Skip to content

Instantly share code, notes, and snippets.

@dmontagu
Last active May 25, 2019 23:48
Show Gist options
  • Save dmontagu/0a8b823c2c5dec3954405a921028f7dd to your computer and use it in GitHub Desktop.
Save dmontagu/0a8b823c2c5dec3954405a921028f7dd to your computer and use it in GitHub Desktop.
Pydantic benchmark line-profiled
Full output on cython branch:
-----------------------------
pydantic time=6.347s, success=50.60%
pydantic time=7.167s, success=50.60%
pydantic time=8.733s, success=50.60%
pydantic time=6.832s, success=50.60%
pydantic time=7.747s, success=50.60%
pydantic best=6.347s, avg=7.365s, stdev=0.919s
pydantic best=211.579μs/iter avg=245.504μs/iter stdev=30.618μs/iter
Timer unit: 1e-06 s
Total time: 36.6847 s
File: pydantic/benchmarks/run.py
Function: run_tests at line 149
Line # Hits Time Per Hit % Time Line Contents
==============================================================
149 def run_tests(tests: List[Type]):
150 1 43.0 43.0 0.0 json_path = THIS_DIR / 'cases.json'
151 1 31.0 31.0 0.0 if not json_path.exists():
152 print('generating test cases...')
153 cases = [generate_case() for _ in range(2000)]
154 with json_path.open('w') as f:
155 json.dump(cases, f, indent=2, sort_keys=True)
156 else:
157 1 91.0 91.0 0.0 with json_path.open() as f:
158 1 64371.0 64371.0 0.2 cases = json.load(f)
159 1 28.0 28.0 0.0 repeats = int(os.getenv('BENCHMARK_REPEATS', '5'))
160 1 1.0 1.0 0.0 results = []
161 1 2.0 2.0 0.0 csv_results = []
162 2 3.0 1.5 0.0 for test_class in tests:
163 1 1.0 1.0 0.0 times = []
164 1 2.0 2.0 0.0 p = test_class.package
165 6 12.0 2.0 0.0 for i in range(repeats):
166 5 9.0 1.8 0.0 count, pass_count = 0, 0
167 5 30.0 6.0 0.0 start = datetime.now()
168 5 26.0 5.2 0.0 test = test_class(True)
169 20 37.0 1.9 0.0 for i in range(3):
170 30015 45920.0 1.5 0.1 for case in cases:
171 30000 36470104.0 1215.7 99.4 passed, result = test.validate(case)
172 30000 55220.0 1.8 0.2 count += 1
173 30000 47280.0 1.6 0.1 pass_count += passed
174 5 63.0 12.6 0.0 time = (datetime.now() - start).total_seconds()
175 5 10.0 2.0 0.0 success = pass_count / count * 100
176 5 202.0 40.4 0.0 print(f'{p:>40} time={time:0.3f}s, success={success:0.2f}%')
177 5 14.0 2.8 0.0 times.append(time)
178 1 657.0 657.0 0.0 print(f'{p:>40} best={min(times):0.3f}s, avg={mean(times):0.3f}s, stdev={stdev(times):0.3f}s')
179 1 2.0 2.0 0.0 model_count = repeats * 3 * len(cases)
180 1 114.0 114.0 0.0 avg = mean(times) / model_count * 1e6
181 1 379.0 379.0 0.0 sd = stdev(times) / model_count * 1e6
182 1 8.0 8.0 0.0 results.append(f'{p:>40} best={min(times) / model_count * 1e6:0.3f}μs/iter '
183 f'avg={avg:0.3f}μs/iter stdev={sd:0.3f}μs/iter')
184 1 2.0 2.0 0.0 csv_results.append([p, avg, sd])
185 1 10.0 10.0 0.0 print()
186 2 2.0 1.0 0.0 for r in results:
187 1 6.0 6.0 0.0 print(r)
188 1 15.0 15.0 0.0 if 'SAVE' in os.environ:
189 csv_file = StringIO()
190 csv_writer = csv.writer(csv_file)
191 first_avg = None
192 for p, avg, sd in sorted(csv_results, key=itemgetter(1)):
193 if first_avg:
194 relative = f'{avg / first_avg:0.1f}x slower'
195 else:
196 relative = ''
197 first_avg = avg
198 csv_writer.writerow([p, relative, f'{avg:0.1f}μs', f'{sd:0.3f}μs'])
199 p = Path(THIS_DIR / '../docs/benchmarks.csv')
200 print(f'saving results to {p}')
201 p.write_text(csv_file.getvalue())
Total time: 36.2438 s
File: pydantic/benchmarks/test_pydantic.py
Function: validate at line 53
Line # Hits Time Per Hit % Time Line Contents
==============================================================
53 def validate(self, data):
54 30000 13931.0 0.5 0.0 try:
55 30000 35611362.0 1187.0 98.3 return True, self.model(**data)
56 14820 15806.0 1.1 0.0 except ValidationError as e:
57 14820 602737.0 40.7 1.7 return False, str(e)
Total time: 8.9698 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 202
Line # Hits Time Per Hit % Time Line Contents
==============================================================
202 1178985 8969804.0 7.6 100.0 return lambda cls, v, values, field, config: validator(v)
Total time: 0.32665 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 206
Line # Hits Time Per Hit % Time Line Contents
==============================================================
206 58710 326650.0 5.6 100.0 return lambda cls, v, values, field, config: validator(v, field=field)
Total time: 1.05909 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 214
Line # Hits Time Per Hit % Time Line Contents
==============================================================
214 159330 1059089.0 6.6 100.0 return lambda cls, v, values, field, config: validator(v, field=field, config=config)
Total time: 1.80439 s
File: pydantic/pydantic/datetime_parse.py
Function: parse_datetime at line 139
Line # Hits Time Per Hit % Time Line Contents
==============================================================
139 def parse_datetime(value: Union[datetime, StrIntFloat]) -> datetime:
140 """
141 Parse a datetime/int/float/string and return a datetime.datetime.
142
143 This function supports time zone offsets. When the input contains one,
144 the output uses a timezone with a fixed offset from UTC.
145
146 Raise ValueError if the input is well formatted but not a valid datetime.
147 Raise ValueError if the input isn't well formatted.
148 """
149 30000 43897.0 1.5 2.4 if isinstance(value, datetime):
150 return value
151
152 30000 382451.0 12.7 21.2 number = get_numeric(value)
153 30000 29223.0 1.0 1.6 if number is not None:
154 return from_unix_seconds(number)
155
156 30000 235176.0 7.8 13.0 match = datetime_re.match(cast(str, value))
157 30000 29546.0 1.0 1.6 if not match:
158 raise errors.DateTimeError()
159
160 30000 99635.0 3.3 5.5 kw = match.groupdict()
161 30000 35429.0 1.2 2.0 if kw['microsecond']:
162 kw['microsecond'] = kw['microsecond'].ljust(6, '0')
163
164 30000 38811.0 1.3 2.2 tzinfo_str = kw.pop('tzinfo')
165 30000 29548.0 1.0 1.6 if tzinfo_str == 'Z':
166 tzinfo = timezone.utc
167 30000 26438.0 0.9 1.5 elif tzinfo_str is not None:
168 offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0
169 offset = 60 * int(tzinfo_str[1:3]) + offset_mins
170 if tzinfo_str[0] == '-':
171 offset = -offset
172 tzinfo = timezone(timedelta(minutes=offset))
173 else:
174 30000 24569.0 0.8 1.4 tzinfo = None
175
176 30000 228746.0 7.6 12.7 kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
177 30000 32779.0 1.1 1.8 kw_['tzinfo'] = tzinfo
178
179 30000 273113.0 9.1 15.1 with change_exception(errors.DateTimeError, ValueError):
180 30000 295030.0 9.8 16.4 return datetime(**kw_) # type: ignore
Total time: 26.0323 s
File: pydantic/pydantic/main.py
Function: __init__ at line 221
Line # Hits Time Per Hit % Time Line Contents
==============================================================
221 def __init__(self, **data: Any) -> None:
222 133245 73015.0 0.5 0.3 if TYPE_CHECKING: # pragma: no cover
223 self.__values__: Dict[str, Any] = {}
224 self.__fields_set__: 'SetStr' = set()
225 133245 25706724.0 192.9 98.7 values, fields_set, _ = parse_model(self, data)
226 117150 158198.0 1.4 0.6 object.__setattr__(self, '__values__', values)
227 117150 94338.0 0.8 0.4 object.__setattr__(self, '__fields_set__', fields_set)
Total time: 18.4985 s
File: pydantic/pydantic/main.py
Function: validate at line 413
Line # Hits Time Per Hit % Time Line Contents
==============================================================
413 @classmethod
414 def validate(cls: Type['Model'], value: Union['DictStrAny', 'Model']) -> 'Model':
415 103245 86499.0 0.8 0.5 if isinstance(value, dict):
416 103245 18411991.0 178.3 99.5 return cls(**value)
417 elif isinstance(value, cls):
418 return value.copy()
419 else:
420 with change_exception(DictError, TypeError, ValueError):
421 return cls(**dict(value)) # type: ignore
Total time: 0.130548 s
File: pydantic/pydantic/types.py
Function: validate at line 144
Line # Hits Time Per Hit % Time Line Contents
==============================================================
144 @classmethod
145 def validate(cls, value: str) -> str:
146 75795 51430.0 0.7 39.4 if cls.curtail_length and len(value) > cls.curtail_length:
147 value = value[: cls.curtail_length]
148
149 75795 48743.0 0.6 37.3 if cls.regex:
150 if not cls.regex.match(value):
151 raise errors.StrRegexError(pattern=cls.regex.pattern)
152
153 75795 30375.0 0.4 23.3 return value
Total time: 0.351456 s
File: pydantic/pydantic/types.py
Function: constr_length_validator at line 629
Line # Hits Time Per Hit % Time Line Contents
==============================================================
629 def constr_length_validator(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
630 79665 69432.0 0.9 19.8 v_len = len(v)
631
632 79665 60986.0 0.8 17.4 min_length = field.type_.min_length or config.min_anystr_length # type: ignore
633 79665 49105.0 0.6 14.0 if min_length is not None and v_len < min_length:
634 240 2215.0 9.2 0.6 raise errors.AnyStrMinLengthError(limit_value=min_length)
635
636 79425 51255.0 0.6 14.6 max_length = field.type_.max_length or config.max_anystr_length # type: ignore
637 79425 51205.0 0.6 14.6 if max_length is not None and v_len > max_length:
638 3630 32920.0 9.1 9.4 raise errors.AnyStrMaxLengthError(limit_value=max_length)
639
640 75795 34338.0 0.5 9.8 return v
Total time: 0.133752 s
File: pydantic/pydantic/types.py
Function: constr_strip_whitespace at line 643
Line # Hits Time Per Hit % Time Line Contents
==============================================================
643 def constr_strip_whitespace(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
644 79665 62219.0 0.8 46.5 strip_whitespace = field.type_.strip_whitespace or config.anystr_strip_whitespace # type: ignore
645 79665 39084.0 0.5 29.2 if strip_whitespace:
646 v = v.strip()
647
648 79665 32449.0 0.4 24.3 return v
Total time: 20.9474 s
File: pydantic/fields.py
Function: validate at line 267
Line # Hits Time Per Hit % Time Line Contents
==============================================================
267 def validate(
268 self, v: Any, values: Dict[str, Any], *, loc: 'LocType', cls: Optional['ModelOrDc'] = None
269 ) -> 'ValidateReturn':
270 774270 416122.0 0.5 2.0 if self.allow_none and not self.validate_always and v is None:
271 12450 5395.0 0.4 0.0 return None, None
272
273 761820 289390.0 0.4 1.4 loc = loc if isinstance(loc, tuple) else (loc,)
274
275 761820 322689.0 0.4 1.5 if v is not None and self.parse_json:
276 v, error = self._validate_json(v, loc)
277 if error:
278 return v, error
279
280 761820 267501.0 0.4 1.3 errors: Optional['ErrorList'] = None
281 761820 311815.0 0.4 1.5 if self.whole_pre_validators:
282 v, errors = self._apply_validators(v, values, loc, cls, self.whole_pre_validators)
283 if errors:
284 return v, errors
285
286 761820 510978.0 0.7 2.4 if self.shape is Shape.SINGLETON:
287 731820 17140549.0 23.4 81.8 v, errors = self._validate_singleton(v, values, loc, cls)
288 30000 21263.0 0.7 0.1 elif self.shape is Shape.MAPPING:
289 v, errors = self._validate_mapping(v, values, loc, cls)
290 30000 19867.0 0.7 0.1 elif self.shape is Shape.TUPLE:
291 v, errors = self._validate_tuple(v, values, loc, cls)
292 else:
293 # sequence, list, tuple, set, generator
294 30000 1003391.0 33.4 4.8 v, errors = self._validate_sequence_like(v, values, loc, cls)
295
296 761820 335088.0 0.4 1.6 if not errors and self.whole_post_validators:
297 v, errors = self._apply_validators(v, values, loc, cls, self.whole_post_validators)
298 761820 303304.0 0.4 1.4 return v, errors
Total time: 18.278 s
File: pydantic/fields.py
Function: _validate_singleton at line 407
Line # Hits Time Per Hit % Time Line Contents
==============================================================
407 def _validate_singleton(
408 self, v: Any, values: Dict[str, Any], loc: 'LocType', cls: Optional['ModelOrDc']
409 ) -> 'ValidateReturn':
410 805065 384619.0 0.5 2.1 if self.sub_fields:
411 errors = []
412 for field in self.sub_fields:
413 value, error = field.validate(v, values, loc=loc, cls=cls)
414 if error:
415 errors.append(error)
416 else:
417 return value, None
418 return v, errors
419 else:
420 805065 17893342.0 22.2 97.9 return self._apply_validators(v, values, loc, cls, self.validators)
Total time: 14.7918 s
File: pydantic/fields.py
Function: _apply_validators at line 422
Line # Hits Time Per Hit % Time Line Contents
==============================================================
422 def _apply_validators(
423 self, v: Any, values: Dict[str, Any], loc: 'LocType', cls: Optional['ModelOrDc'], validators: 'ValidatorsList'
424 ) -> 'ValidateReturn':
425 2187810 920126.0 0.4 6.2 for validator in validators:
426 1397025 1028795.0 0.7 7.0 get_line_profiler().add_function(validator) # just adds lambdas
427 # The added lambdas are from class_validators.py lines 202, 206, 214 (see that file's line 198)
428 1397025 545188.0 0.4 3.7 try:
429 1397025 11902918.0 8.5 80.5 v = validator(cls, v, values, self, self.model_config)
430 14280 20968.0 1.5 0.1 except (ValueError, TypeError) as exc:
431 14280 72789.0 5.1 0.5 return v, ErrorWrapper(exc, loc=loc, config=self.model_config)
432 790785 301055.0 0.4 2.0 return v, None
Total time: 29.2752 s
File: pydantic/parse.py
Function: parse_model at line 37
Line # Hits Time Per Hit % Time Line Contents
==============================================================
37 def parse_model( # noqa: C901 (ignore complexity)
38 model: Union['BaseModel', Type['BaseModel']],
39 input_data: 'DictStrAny',
40 raise_exc: bool = True,
41 cls: 'ModelOrDc' = None,
42 ) -> Tuple['DictStrAny', 'SetStr', Optional[ValidationError]]:
43 """
44 validate data against a model.
45 """
46 133245 107999.0 0.8 0.4 values = {}
47 133245 66082.0 0.5 0.2 errors = []
48 # input_data names, possibly alias
49 133245 73858.0 0.6 0.3 names_used = set()
50 # field names, never aliases
51 133245 77625.0 0.6 0.3 fields_set = set()
52 133245 77971.0 0.6 0.3 config = model.__config__
53 133245 123935.0 0.9 0.4 check_extra = config.extra is not Extra.ignore
54
55 133245 82103.0 0.6 0.3 for name, field in model.__fields__.items():
56 799470 460635.0 0.6 1.6 if type(field.type_) == ForwardRef:
57 raise ConfigError(
58 f'field "{field.name}" not yet prepared so type is still a ForwardRef, '
59 f'you might need to call {model.__class__.__name__}.update_forward_refs().'
60 )
61
62 799470 551927.0 0.7 1.9 value = input_data.get(field.alias, _missing)
63 799470 327377.0 0.4 1.1 using_name = False
64 799470 336394.0 0.4 1.1 if value is _missing and config.allow_population_by_alias and field.alt_alias:
65 value = input_data.get(field.name, _missing)
66 using_name = True
67
68 799470 343603.0 0.4 1.2 if value is _missing:
69 25200 16435.0 0.7 0.1 if field.required:
70 5820 57500.0 9.9 0.2 errors.append(ErrorWrapper(MissingError(), loc=field.alias, config=model.__config__))
71 5820 3612.0 0.6 0.0 continue
72 19380 153271.0 7.9 0.5 value = deepcopy(field.default)
73 19380 17232.0 0.9 0.1 if not model.__config__.validate_all and not field.validate_always:
74 19380 9527.0 0.5 0.0 values[name] = value
75 19380 8953.0 0.5 0.0 continue
76 else:
77 774270 477415.0 0.6 1.6 fields_set.add(name)
78 774270 329243.0 0.4 1.1 if check_extra:
79 275460 148200.0 0.5 0.5 names_used.add(field.name if using_name else field.alias)
80
81 774270 23755947.0 30.7 81.1 v_, errors_ = field.validate(value, values, loc=field.alias, cls=cls or model.__class__) # type: ignore
82 774270 418027.0 0.5 1.4 if isinstance(errors_, ErrorWrapper):
83 13005 8909.0 0.7 0.0 errors.append(errors_)
84 761265 317434.0 0.4 1.1 elif isinstance(errors_, list):
85 1245 891.0 0.7 0.0 errors.extend(errors_)
86 else:
87 760020 455734.0 0.6 1.6 values[name] = v_
88
89 133245 62109.0 0.5 0.2 if check_extra:
90 30000 118488.0 3.9 0.4 extra = input_data.keys() - names_used
91 30000 18360.0 0.6 0.1 if extra:
92 fields_set |= extra
93 if config.extra is Extra.allow:
94 for f in extra:
95 values[f] = input_data[f]
96 else:
97 for f in sorted(extra):
98 errors.append(ErrorWrapper(ExtraError(), loc=f, config=config))
99
100 133245 56371.0 0.4 0.2 if not raise_exc:
101 return values, fields_set, ValidationError(errors) if errors else None
102
103 133245 63516.0 0.5 0.2 if errors:
104 16095 68167.0 4.2 0.2 raise ValidationError(errors)
105 117150 80334.0 0.7 0.3 return values, fields_set, None
Total time: 0.286555 s
File: pydantic/validators.py
Function: not_none_validator at line 42
Line # Hits Time Per Hit % Time Line Contents
==============================================================
42 def not_none_validator(v: Any) -> Any:
43 302085 144334.0 0.5 50.4 if v is None:
44 3960 23423.0 5.9 8.2 raise errors.NoneIsNotAllowedError()
45 298125 118798.0 0.4 41.5 return v
Total time: 0.27822 s
File: pydantic/validators.py
Function: str_validator at line 53
Line # Hits Time Per Hit % Time Line Contents
==============================================================
53 def str_validator(v: Any) -> Optional[str]:
54 298125 180131.0 0.6 64.7 if type(v) == str or v is None:
55 298125 98089.0 0.3 35.3 return v
56 elif isinstance(v, str):
57 if isinstance(v, Enum):
58 return v.value
59 else:
60 return v
61 elif isinstance(v, (bytes, bytearray)):
62 return v.decode()
63 elif isinstance(v, (float, int, Decimal)):
64 # is there anything else we want to add here? If you think so, create an issue.
65 return str(v)
66 else:
67 raise errors.StrError()
Total time: 0.641086 s
File: pydantic/validators.py
Function: int_validator at line 96
Line # Hits Time Per Hit % Time Line Contents
==============================================================
96 def int_validator(v: Any) -> int:
97 206490 113053.0 0.5 17.6 if isinstance(v, int) and not isinstance(v, bool):
98 176490 59966.0 0.3 9.4 return v
99
100 30000 296106.0 9.9 46.2 with change_exception(errors.IntegerError, TypeError, ValueError):
101 30000 171961.0 5.7 26.8 return int(v)
Total time: 0.122023 s
File: pydantic/validators.py
Function: float_validator at line 104
Line # Hits Time Per Hit % Time Line Contents
==============================================================
104 def float_validator(v: Any) -> float:
105 163245 69505.0 0.4 57.0 if isinstance(v, float):
106 163245 52518.0 0.3 43.0 return v
107
108 with change_exception(errors.FloatError, TypeError, ValueError):
109 return float(v)
Total time: 0.033397 s
File: pydantic/validators.py
Function: number_multiple_validator at line 112
Line # Hits Time Per Hit % Time Line Contents
==============================================================
112 def number_multiple_validator(v: 'Number', field: 'Field') -> 'Number':
113 28710 12600.0 0.4 37.7 field_type: ConstrainedNumber = field.type_ # type: ignore
114 28710 11818.0 0.4 35.4 if field_type.multiple_of is not None and v % field_type.multiple_of != 0: # type: ignore
115 raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of)
116
117 28710 8979.0 0.3 26.9 return v
Total time: 0.089658 s
File: pydantic/validators.py
Function: number_size_validator at line 120
Line # Hits Time Per Hit % Time Line Contents
==============================================================
120 def number_size_validator(v: 'Number', field: 'Field') -> 'Number':
121 30000 14069.0 0.5 15.7 field_type: ConstrainedNumber = field.type_ # type: ignore
122 30000 18160.0 0.6 20.3 if field_type.gt is not None and not v > field_type.gt:
123 1290 10871.0 8.4 12.1 raise errors.NumberNotGtError(limit_value=field_type.gt)
124 28710 13198.0 0.5 14.7 elif field_type.ge is not None and not v >= field_type.ge:
125 raise errors.NumberNotGeError(limit_value=field_type.ge)
126
127 28710 12220.0 0.4 13.6 if field_type.lt is not None and not v < field_type.lt:
128 raise errors.NumberNotLtError(limit_value=field_type.lt)
129 28710 11285.0 0.4 12.6 if field_type.le is not None and not v <= field_type.le:
130 raise errors.NumberNotLeError(limit_value=field_type.le)
131
132 28710 9855.0 0.3 11.0 return v
Only last "layer" of functions output on cython branch (rebuilt):
-----------------------------------------------------------------
pydantic time=2.390s, success=50.60%
pydantic time=2.360s, success=50.60%
pydantic time=2.356s, success=50.60%
pydantic time=2.362s, success=50.60%
pydantic time=2.382s, success=50.60%
pydantic best=2.356s, avg=2.370s, stdev=0.015s
pydantic best=78.526μs/iter avg=78.998μs/iter stdev=0.501μs/iter
Timer unit: 1e-06 s
Total time: 1.35921 s
File: pydantic/pydantic/datetime_parse.py
Function: parse_datetime at line 139
Line # Hits Time Per Hit % Time Line Contents
==============================================================
139 def parse_datetime(value: Union[datetime, StrIntFloat]) -> datetime:
140 """
141 Parse a datetime/int/float/string and return a datetime.datetime.
142
143 This function supports time zone offsets. When the input contains one,
144 the output uses a timezone with a fixed offset from UTC.
145
146 Raise ValueError if the input is well formatted but not a valid datetime.
147 Raise ValueError if the input isn't well formatted.
148 """
149 30000 35065.0 1.2 2.6 if isinstance(value, datetime):
150 return value
151
152 30000 267460.0 8.9 19.7 number = get_numeric(value)
153 30000 24521.0 0.8 1.8 if number is not None:
154 return from_unix_seconds(number)
155
156 30000 161104.0 5.4 11.9 match = datetime_re.match(cast(str, value))
157 30000 24395.0 0.8 1.8 if not match:
158 raise errors.DateTimeError()
159
160 30000 66960.0 2.2 4.9 kw = match.groupdict()
161 30000 28583.0 1.0 2.1 if kw['microsecond']:
162 kw['microsecond'] = kw['microsecond'].ljust(6, '0')
163
164 30000 33135.0 1.1 2.4 tzinfo_str = kw.pop('tzinfo')
165 30000 25899.0 0.9 1.9 if tzinfo_str == 'Z':
166 tzinfo = timezone.utc
167 30000 21819.0 0.7 1.6 elif tzinfo_str is not None:
168 offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0
169 offset = 60 * int(tzinfo_str[1:3]) + offset_mins
170 if tzinfo_str[0] == '-':
171 offset = -offset
172 tzinfo = timezone(timedelta(minutes=offset))
173 else:
174 30000 21797.0 0.7 1.6 tzinfo = None
175
176 30000 184802.0 6.2 13.6 kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
177 30000 27140.0 0.9 2.0 kw_['tzinfo'] = tzinfo
178
179 30000 211138.0 7.0 15.5 with change_exception(errors.DateTimeError, ValueError):
180 30000 225396.0 7.5 16.6 return datetime(**kw_) # type: ignore
Total time: 4.57487 s
File: pydantic/pydantic/main.py
Function: validate at line 413
Line # Hits Time Per Hit % Time Line Contents
==============================================================
413 @classmethod
414 def validate(cls: Type['Model'], value: Union['DictStrAny', 'Model']) -> 'Model':
415 103245 75794.0 0.7 1.7 if isinstance(value, dict):
416 103245 4499081.0 43.6 98.3 return cls(**value)
417 elif isinstance(value, cls):
418 return value.copy()
419 else:
420 with change_exception(DictError, TypeError, ValueError):
421 return cls(**dict(value)) # type: ignore
Total time: 0.102269 s
File: pydantic/pydantic/types.py
Function: validate at line 144
Line # Hits Time Per Hit % Time Line Contents
==============================================================
144 @classmethod
145 def validate(cls, value: str) -> str:
146 75795 38268.0 0.5 37.4 if cls.curtail_length and len(value) > cls.curtail_length:
147 value = value[: cls.curtail_length]
148
149 75795 35379.0 0.5 34.6 if cls.regex:
150 if not cls.regex.match(value):
151 raise errors.StrRegexError(pattern=cls.regex.pattern)
152
153 75795 28622.0 0.4 28.0 return value
Total time: 0.30178 s
File: pydantic/pydantic/types.py
Function: constr_length_validator at line 629
Line # Hits Time Per Hit % Time Line Contents
==============================================================
629 def constr_length_validator(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
630 79665 57998.0 0.7 19.2 v_len = len(v)
631
632 79665 52897.0 0.7 17.5 min_length = field.type_.min_length or config.min_anystr_length # type: ignore
633 79665 43675.0 0.5 14.5 if min_length is not None and v_len < min_length:
634 240 1488.0 6.2 0.5 raise errors.AnyStrMinLengthError(limit_value=min_length)
635
636 79425 46118.0 0.6 15.3 max_length = field.type_.max_length or config.max_anystr_length # type: ignore
637 79425 46699.0 0.6 15.5 if max_length is not None and v_len > max_length:
638 3630 20717.0 5.7 6.9 raise errors.AnyStrMaxLengthError(limit_value=max_length)
639
640 75795 32188.0 0.4 10.7 return v
Total time: 0.118638 s
File: pydantic/pydantic/types.py
Function: constr_strip_whitespace at line 643
Line # Hits Time Per Hit % Time Line Contents
==============================================================
643 def constr_strip_whitespace(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
644 79665 52725.0 0.7 44.4 strip_whitespace = field.type_.strip_whitespace or config.anystr_strip_whitespace # type: ignore
645 79665 35205.0 0.4 29.7 if strip_whitespace:
646 v = v.strip()
647
648 79665 30708.0 0.4 25.9 return v
Total time: 0.192056 s
File: pydantic/validators.py
Function: not_none_validator at line 42
Line # Hits Time Per Hit % Time Line Contents
==============================================================
42 def not_none_validator(v: Any) -> Any:
43 302085 97435.0 0.3 50.7 if v is None:
44 3960 14558.0 3.7 7.6 raise errors.NoneIsNotAllowedError()
45 298125 80063.0 0.3 41.7 return v
Total time: 0.175338 s
File: pydantic/validators.py
Function: str_validator at line 53
Line # Hits Time Per Hit % Time Line Contents
==============================================================
53 def str_validator(v: Any) -> Optional[str]:
54 298125 96370.0 0.3 55.0 if type(v) == str or v is None:
55 298125 78968.0 0.3 45.0 return v
56 elif isinstance(v, str):
57 if isinstance(v, Enum):
58 return v.value
59 else:
60 return v
61 elif isinstance(v, (bytes, bytearray)):
62 return v.decode()
63 elif isinstance(v, (float, int, Decimal)):
64 # is there anything else we want to add here? If you think so, create an issue.
65 return str(v)
66 else:
67 raise errors.StrError()
Total time: 0.463655 s
File: pydantic/validators.py
Function: int_validator at line 96
Line # Hits Time Per Hit % Time Line Contents
==============================================================
96 def int_validator(v: Any) -> int:
97 206490 87733.0 0.4 18.9 if isinstance(v, int) and not isinstance(v, bool):
98 176490 49375.0 0.3 10.6 return v
99
100 30000 210534.0 7.0 45.4 with change_exception(errors.IntegerError, TypeError, ValueError):
101 30000 116013.0 3.9 25.0 return int(v)
Total time: 0.101566 s
File: pydantic/validators.py
Function: float_validator at line 104
Line # Hits Time Per Hit % Time Line Contents
==============================================================
104 def float_validator(v: Any) -> float:
105 163245 56418.0 0.3 55.5 if isinstance(v, float):
106 163245 45148.0 0.3 44.5 return v
107
108 with change_exception(errors.FloatError, TypeError, ValueError):
109 return float(v)
Total time: 0.029538 s
File: pydantic/validators.py
Function: number_multiple_validator at line 112
Line # Hits Time Per Hit % Time Line Contents
==============================================================
112 def number_multiple_validator(v: 'Number', field: 'Field') -> 'Number':
113 28710 11334.0 0.4 38.4 field_type: ConstrainedNumber = field.type_ # type: ignore
114 28710 9891.0 0.3 33.5 if field_type.multiple_of is not None and v % field_type.multiple_of != 0: # type: ignore
115 raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of)
116
117 28710 8313.0 0.3 28.1 return v
Total time: 0.08339 s
File: pydantic/validators.py
Function: number_size_validator at line 120
Line # Hits Time Per Hit % Time Line Contents
==============================================================
120 def number_size_validator(v: 'Number', field: 'Field') -> 'Number':
121 30000 13196.0 0.4 15.8 field_type: ConstrainedNumber = field.type_ # type: ignore
122 30000 16044.0 0.5 19.2 if field_type.gt is not None and not v > field_type.gt:
123 1290 7594.0 5.9 9.1 raise errors.NumberNotGtError(limit_value=field_type.gt)
124 28710 10729.0 0.4 12.9 elif field_type.ge is not None and not v >= field_type.ge:
125 raise errors.NumberNotGeError(limit_value=field_type.ge)
126
127 28710 10116.0 0.4 12.1 if field_type.lt is not None and not v < field_type.lt:
128 raise errors.NumberNotLtError(limit_value=field_type.lt)
129 28710 17292.0 0.6 20.7 if field_type.le is not None and not v <= field_type.le:
130 raise errors.NumberNotLeError(limit_value=field_type.le)
131
132 28710 8419.0 0.3 10.1 return v
Full output on master branch:
-----------------------------
pydantic time=12.307s, success=50.60%
pydantic time=12.382s, success=50.60%
pydantic time=11.954s, success=50.60%
pydantic time=11.702s, success=50.60%
pydantic time=12.395s, success=50.60%
pydantic best=11.702s, avg=12.148s, stdev=0.307s
pydantic best=390.063μs/iter avg=404.935μs/iter stdev=10.241μs/iter
Timer unit: 1e-06 s
Total time: 60.6283 s
File: pydantic/benchmarks/run.py
Function: run_tests at line 149
Line # Hits Time Per Hit % Time Line Contents
==============================================================
149 def run_tests(tests: List[Type]):
150 1 49.0 49.0 0.0 json_path = THIS_DIR / 'cases.json'
151 1 34.0 34.0 0.0 if not json_path.exists():
152 print('generating test cases...')
153 cases = [generate_case() for _ in range(2000)]
154 with json_path.open('w') as f:
155 json.dump(cases, f, indent=2, sort_keys=True)
156 else:
157 1 95.0 95.0 0.0 with json_path.open() as f:
158 1 62785.0 62785.0 0.1 cases = json.load(f)
159 1 25.0 25.0 0.0 repeats = int(os.getenv('BENCHMARK_REPEATS', '5'))
160 1 1.0 1.0 0.0 results = []
161 1 1.0 1.0 0.0 csv_results = []
162 2 4.0 2.0 0.0 for test_class in tests:
163 1 1.0 1.0 0.0 times = []
164 1 2.0 2.0 0.0 p = test_class.package
165 6 11.0 1.8 0.0 for i in range(repeats):
166 5 6.0 1.2 0.0 count, pass_count = 0, 0
167 5 27.0 5.4 0.0 start = datetime.now()
168 5 29.0 5.8 0.0 test = test_class(True)
169 20 36.0 1.8 0.0 for i in range(3):
170 30015 39068.0 1.3 0.1 for case in cases:
171 30000 60434256.0 2014.5 99.7 passed, result = test.validate(case)
172 30000 48534.0 1.6 0.1 count += 1
173 30000 42018.0 1.4 0.1 pass_count += passed
174 5 75.0 15.0 0.0 time = (datetime.now() - start).total_seconds()
175 5 12.0 2.4 0.0 success = pass_count / count * 100
176 5 168.0 33.6 0.0 print(f'{p:>40} time={time:0.3f}s, success={success:0.2f}%')
177 5 9.0 1.8 0.0 times.append(time)
178 1 582.0 582.0 0.0 print(f'{p:>40} best={min(times):0.3f}s, avg={mean(times):0.3f}s, stdev={stdev(times):0.3f}s')
179 1 2.0 2.0 0.0 model_count = repeats * 3 * len(cases)
180 1 100.0 100.0 0.0 avg = mean(times) / model_count * 1e6
181 1 331.0 331.0 0.0 sd = stdev(times) / model_count * 1e6
182 1 7.0 7.0 0.0 results.append(f'{p:>40} best={min(times) / model_count * 1e6:0.3f}μs/iter '
183 f'avg={avg:0.3f}μs/iter stdev={sd:0.3f}μs/iter')
184 1 2.0 2.0 0.0 csv_results.append([p, avg, sd])
185 1 6.0 6.0 0.0 print()
186 2 3.0 1.5 0.0 for r in results:
187 1 5.0 5.0 0.0 print(r)
188 1 16.0 16.0 0.0 if 'SAVE' in os.environ:
189 csv_file = StringIO()
190 csv_writer = csv.writer(csv_file)
191 first_avg = None
192 for p, avg, sd in sorted(csv_results, key=itemgetter(1)):
193 if first_avg:
194 relative = f'{avg / first_avg:0.1f}x slower'
195 else:
196 relative = ''
197 first_avg = avg
198 csv_writer.writerow([p, relative, f'{avg:0.1f}μs', f'{sd:0.3f}μs'])
199 p = Path(THIS_DIR / '../docs/benchmarks.csv')
200 print(f'saving results to {p}')
201 p.write_text(csv_file.getvalue())
Total time: 60.2448 s
File: pydantic/benchmarks/test_pydantic.py
Function: validate at line 53
Line # Hits Time Per Hit % Time Line Contents
==============================================================
53 def validate(self, data):
54 30000 14928.0 0.5 0.0 try:
55 30000 59591597.0 1986.4 98.9 return True, self.model(**data)
56 14820 15881.0 1.1 0.0 except ValidationError as e:
57 14820 622425.0 42.0 1.0 return False, str(e)
Total time: 11.6536 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 202
Line # Hits Time Per Hit % Time Line Contents
==============================================================
202 1178985 11653613.0 9.9 100.0 return lambda cls, v, values, field, config: validator(v)
Total time: 0.390685 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 206
Line # Hits Time Per Hit % Time Line Contents
==============================================================
206 58710 390685.0 6.7 100.0 return lambda cls, v, values, field, config: validator(v, field=field)
Total time: 3.56107 s
File: pydantic/pydantic/class_validators.py
Function: <lambda> at line 214
Line # Hits Time Per Hit % Time Line Contents
==============================================================
214 596250 3561067.0 6.0 100.0 return lambda cls, v, values, field, config: validator(v, field=field, config=config)
Total time: 1.65067 s
File: pydantic/pydantic/datetime_parse.py
Function: parse_datetime at line 139
Line # Hits Time Per Hit % Time Line Contents
==============================================================
139 def parse_datetime(value: Union[datetime, StrIntFloat]) -> datetime:
140 """
141 Parse a datetime/int/float/string and return a datetime.datetime.
142
143 This function supports time zone offsets. When the input contains one,
144 the output uses a timezone with a fixed offset from UTC.
145
146 Raise ValueError if the input is well formatted but not a valid datetime.
147 Raise ValueError if the input isn't well formatted.
148 """
149 30000 60334.0 2.0 3.7 if isinstance(value, datetime):
150 return value
151
152 30000 316207.0 10.5 19.2 number = get_numeric(value)
153 30000 26116.0 0.9 1.6 if number is not None:
154 return from_unix_seconds(number)
155
156 30000 180445.0 6.0 10.9 match = datetime_re.match(cast(str, value))
157 30000 26376.0 0.9 1.6 if not match:
158 raise errors.DateTimeError()
159
160 30000 82864.0 2.8 5.0 kw = match.groupdict()
161 30000 29587.0 1.0 1.8 if kw['microsecond']:
162 kw['microsecond'] = kw['microsecond'].ljust(6, '0')
163
164 30000 35600.0 1.2 2.2 tzinfo_str = kw.pop('tzinfo')
165 30000 27440.0 0.9 1.7 if tzinfo_str == 'Z':
166 tzinfo = timezone.utc
167 30000 22895.0 0.8 1.4 elif tzinfo_str is not None:
168 offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0
169 offset = 60 * int(tzinfo_str[1:3]) + offset_mins
170 if tzinfo_str[0] == '-':
171 offset = -offset
172 tzinfo = timezone(timedelta(minutes=offset))
173 else:
174 30000 22300.0 0.7 1.4 tzinfo = None
175
176 30000 198638.0 6.6 12.0 kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
177 30000 26687.0 0.9 1.6 kw_['tzinfo'] = tzinfo
178
179 30000 238436.0 7.9 14.4 with change_exception(errors.DateTimeError, ValueError):
180 30000 356750.0 11.9 21.6 return datetime(**kw_) # type: ignore
Total time: 30.968 s
File: pydantic/pydantic/fields.py
Function: validate at line 271
Line # Hits Time Per Hit % Time Line Contents
==============================================================
271 def validate(
272 self, v: Any, values: Dict[str, Any], *, loc: 'LocType', cls: Optional['ModelOrDc'] = None
273 ) -> 'ValidateReturn':
274 774270 534705.0 0.7 1.7 if self.allow_none and not self.validate_always and v is None:
275 12450 6744.0 0.5 0.0 return None, None
276
277 761820 641225.0 0.8 2.1 loc = loc if isinstance(loc, tuple) else (loc,)
278
279 761820 514757.0 0.7 1.7 if v is not None and self.parse_json:
280 v, error = self._validate_json(v, loc)
281 if error:
282 return v, error
283
284 761820 393910.0 0.5 1.3 errors: Optional['ErrorList'] = None
285 761820 455050.0 0.6 1.5 if self.whole_pre_validators:
286 v, errors = self._apply_validators(v, values, loc, cls, self.whole_pre_validators)
287 if errors:
288 return v, errors
289
290 761820 704593.0 0.9 2.3 if self.shape is Shape.SINGLETON:
291 731820 25010557.0 34.2 80.8 v, errors = self._validate_singleton(v, values, loc, cls)
292 30000 25431.0 0.8 0.1 elif self.shape is Shape.MAPPING:
293 v, errors = self._validate_mapping(v, values, loc, cls)
294 30000 24942.0 0.8 0.1 elif self.shape is Shape.TUPLE:
295 v, errors = self._validate_tuple(v, values, loc, cls)
296 else:
297 # sequence, list, tuple, set, generator
298 30000 1691135.0 56.4 5.5 v, errors = self._validate_sequence_like(v, values, loc, cls)
299
300 761820 529107.0 0.7 1.7 if not errors and self.whole_post_validators:
301 v, errors = self._apply_validators(v, values, loc, cls, self.whole_post_validators)
302 761820 435795.0 0.6 1.4 return v, errors
Total time: 27.5416 s
File: pydantic/pydantic/fields.py
Function: _validate_singleton at line 411
Line # Hits Time Per Hit % Time Line Contents
==============================================================
411 def _validate_singleton(
412 self, v: Any, values: Dict[str, Any], loc: 'LocType', cls: Optional['ModelOrDc']
413 ) -> 'ValidateReturn':
414 805065 441474.0 0.5 1.6 if self.sub_fields:
415 errors = []
416 for field in self.sub_fields:
417 value, error = field.validate(v, values, loc=loc, cls=cls)
418 if error:
419 errors.append(error)
420 else:
421 return value, None
422 return v, errors
423 else:
424 805065 27100161.0 33.7 98.4 return self._apply_validators(v, values, loc, cls, self.validators)
Total time: 22.3984 s
File: pydantic/pydantic/fields.py
Function: _apply_validators at line 426
Line # Hits Time Per Hit % Time Line Contents
==============================================================
426 def _apply_validators(
427 self, v: Any, values: Dict[str, Any], loc: 'LocType', cls: Optional['ModelOrDc'], validators: 'ValidatorsList'
428 ) -> 'ValidateReturn':
429 2624730 1480360.0 0.6 6.6 for validator in validators:
430 1833945 1543719.0 0.8 6.9 get_line_profiler().add_function(validator) # just adds lambdas
431 # The added lambdas are from class_validators.py lines 202, 206, 214 (see that file's line 198)
432 1833945 812147.0 0.4 3.6 try:
433 1833945 17856009.0 9.7 79.7 v = validator(cls, v, values, self, self.model_config)
434 14280 16763.0 1.2 0.1 except (ValueError, TypeError) as exc:
435 14280 273711.0 19.2 1.2 return v, ErrorWrapper(exc, loc=loc, config=self.model_config)
436 790785 415709.0 0.5 1.9 return v, None
Total time: 46.9821 s
File: pydantic/pydantic/main.py
Function: __init__ at line 231
Line # Hits Time Per Hit % Time Line Contents
==============================================================
231 def __init__(self, **data: Any) -> None:
232 133245 71478.0 0.5 0.2 if TYPE_CHECKING: # pragma: no cover
233 self.__values__: Dict[str, Any] = {}
234 self.__fields_set__: 'SetStr' = set()
235 133245 46680707.0 350.3 99.4 values, fields_set, _ = validate_model(self, data)
236 117150 139681.0 1.2 0.3 object.__setattr__(self, '__values__', values)
237 117150 90223.0 0.8 0.2 object.__setattr__(self, '__fields_set__', fields_set)
Total time: 35.7694 s
File: pydantic/pydantic/main.py
Function: validate at line 423
Line # Hits Time Per Hit % Time Line Contents
==============================================================
423 @classmethod
424 def validate(cls: Type['Model'], value: Union['DictStrAny', 'Model']) -> 'Model':
425 103245 76633.0 0.7 0.2 if isinstance(value, dict):
426 103245 35692744.0 345.7 99.8 return cls(**value)
427 elif isinstance(value, cls):
428 return value.copy()
429 else:
430 with change_exception(DictError, TypeError, ValueError):
431 return cls(**dict(value)) # type: ignore
Total time: 45.8329 s
File: pydantic/pydantic/main.py
Function: validate_model at line 570
Line # Hits Time Per Hit % Time Line Contents
==============================================================
570 def validate_model( # noqa: C901 (ignore complexity)
571 model: Union[BaseModel, Type[BaseModel]], input_data: 'DictStrAny', raise_exc: bool = True, cls: 'ModelOrDc' = None
572 ) -> Tuple['DictStrAny', 'SetStr', Optional[ValidationError]]:
573 """
574 validate data against a model.
575 """
576 133245 132484.0 1.0 0.3 values = {}
577 133245 120764.0 0.9 0.3 errors = []
578 # input_data names, possibly alias
579 133245 242812.0 1.8 0.5 names_used = set()
580 # field names, never aliases
581 133245 224687.0 1.7 0.5 fields_set = set()
582 133245 134154.0 1.0 0.3 config = model.__config__
583 133245 417987.0 3.1 0.9 check_extra = config.extra is not Extra.ignore
584
585 932715 991986.0 1.1 2.2 for name, field in model.__fields__.items():
586 799470 912165.0 1.1 2.0 if type(field.type_) == ForwardRef:
587 raise ConfigError(
588 f'field "{field.name}" not yet prepared so type is still a ForwardRef, '
589 f'you might need to call {model.__class__.__name__}.update_forward_refs().'
590 )
591
592 799470 947139.0 1.2 2.1 value = input_data.get(field.alias, _missing)
593 799470 658311.0 0.8 1.4 using_name = False
594 799470 725421.0 0.9 1.6 if value is _missing and config.allow_population_by_alias and field.alt_alias:
595 value = input_data.get(field.name, _missing)
596 using_name = True
597
598 799470 697492.0 0.9 1.5 if value is _missing:
599 25200 24714.0 1.0 0.1 if field.required:
600 5820 150386.0 25.8 0.3 errors.append(ErrorWrapper(MissingError(), loc=field.alias, config=model.__config__))
601 5820 5704.0 1.0 0.0 continue
602 19380 135717.0 7.0 0.3 value = deepcopy(field.default)
603 19380 24035.0 1.2 0.1 if not model.__config__.validate_all and not field.validate_always:
604 19380 19348.0 1.0 0.0 values[name] = value
605 19380 16344.0 0.8 0.0 continue
606 else:
607 774270 817193.0 1.1 1.8 fields_set.add(name)
608 774270 676364.0 0.9 1.5 if check_extra:
609 275460 330176.0 1.2 0.7 names_used.add(field.name if using_name else field.alias)
610
611 774270 34265013.0 44.3 74.8 v_, errors_ = field.validate(value, values, loc=field.alias, cls=cls or model.__class__) # type: ignore
612 774270 894026.0 1.2 2.0 if isinstance(errors_, ErrorWrapper):
613 13005 15919.0 1.2 0.0 errors.append(errors_)
614 761265 813576.0 1.1 1.8 elif isinstance(errors_, list):
615 1245 1628.0 1.3 0.0 errors.extend(errors_)
616 else:
617 760020 764923.0 1.0 1.7 values[name] = v_
618
619 133245 122193.0 0.9 0.3 if check_extra:
620 30000 117963.0 3.9 0.3 extra = input_data.keys() - names_used
621 30000 30160.0 1.0 0.1 if extra:
622 fields_set |= extra
623 if config.extra is Extra.allow:
624 for f in extra:
625 values[f] = input_data[f]
626 else:
627 for f in sorted(extra):
628 errors.append(ErrorWrapper(ExtraError(), loc=f, config=config))
629
630 133245 120810.0 0.9 0.3 if not raise_exc:
631 return values, fields_set, ValidationError(errors) if errors else None
632
633 133245 126492.0 0.9 0.3 if errors:
634 16095 46711.0 2.9 0.1 raise ValidationError(errors)
635 117150 108092.0 0.9 0.2 return values, fields_set, None
Total time: 0.114953 s
File: pydantic/pydantic/types.py
Function: validate at line 146
Line # Hits Time Per Hit % Time Line Contents
==============================================================
146 @classmethod
147 def validate(cls, value: str) -> str:
148 75795 48233.0 0.6 42.0 if cls.curtail_length and len(value) > cls.curtail_length:
149 value = value[: cls.curtail_length]
150
151 75795 37275.0 0.5 32.4 if cls.regex:
152 if not cls.regex.match(value):
153 raise errors.StrRegexError(pattern=cls.regex.pattern)
154
155 75795 29445.0 0.4 25.6 return value
Total time: 0.27713 s
File: pydantic/pydantic/validators.py
Function: not_none_validator at line 28
Line # Hits Time Per Hit % Time Line Contents
==============================================================
28 def not_none_validator(v: Any) -> Any:
29 302085 153932.0 0.5 55.5 if v is None:
30 3960 20052.0 5.1 7.2 raise errors.NoneIsNotAllowedError()
31 298125 103146.0 0.3 37.2 return v
Total time: 0.377421 s
File: pydantic/pydantic/validators.py
Function: str_validator at line 39
Line # Hits Time Per Hit % Time Line Contents
==============================================================
39 def str_validator(v: Any) -> str:
40 298125 250271.0 0.8 66.3 if isinstance(v, (str, NoneType)): # type: ignore
41 298125 127150.0 0.4 33.7 return v
42 elif isinstance(v, (bytes, bytearray)):
43 return v.decode()
44 elif isinstance(v, (float, int, Decimal)):
45 # is there anything else we want to add here? If you think so, create an issue.
46 return str(v)
47 else:
48 raise errors.StrError()
Total time: 0.746154 s
File: pydantic/pydantic/validators.py
Function: int_validator at line 77
Line # Hits Time Per Hit % Time Line Contents
==============================================================
77 def int_validator(v: Any) -> int:
78 206490 198595.0 1.0 26.6 if not isinstance(v, bool) and isinstance(v, int):
79 176490 79141.0 0.4 10.6 return v
80
81 30000 281582.0 9.4 37.7 with change_exception(errors.IntegerError, TypeError, ValueError):
82 30000 186836.0 6.2 25.0 return int(v)
Total time: 0.174489 s
File: pydantic/pydantic/validators.py
Function: float_validator at line 85
Line # Hits Time Per Hit % Time Line Contents
==============================================================
85 def float_validator(v: Any) -> float:
86 163245 108581.0 0.7 62.2 if isinstance(v, float):
87 163245 65908.0 0.4 37.8 return v
88
89 with change_exception(errors.FloatError, TypeError, ValueError):
90 return float(v)
Total time: 0.061112 s
File: pydantic/pydantic/validators.py
Function: number_multiple_validator at line 93
Line # Hits Time Per Hit % Time Line Contents
==============================================================
93 def number_multiple_validator(v: 'Number', field: 'Field') -> 'Number':
94 28710 34935.0 1.2 57.2 field_type = cast('ConstrainedNumber', field.type_)
95 28710 15157.0 0.5 24.8 if field_type.multiple_of is not None and v % field_type.multiple_of != 0: # type: ignore
96 raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of)
97
98 28710 11020.0 0.4 18.0 return v
Total time: 0.134011 s
File: pydantic/pydantic/validators.py
Function: number_size_validator at line 101
Line # Hits Time Per Hit % Time Line Contents
==============================================================
101 def number_size_validator(v: 'Number', field: 'Field') -> 'Number':
102 30000 41308.0 1.4 30.8 field_type = cast('ConstrainedNumber', field.type_)
103 30000 27218.0 0.9 20.3 if field_type.gt is not None and not v > field_type.gt:
104 1290 9497.0 7.4 7.1 raise errors.NumberNotGtError(limit_value=field_type.gt)
105 28710 15688.0 0.5 11.7 elif field_type.ge is not None and not v >= field_type.ge:
106 raise errors.NumberNotGeError(limit_value=field_type.ge)
107
108 28710 14612.0 0.5 10.9 if field_type.lt is not None and not v < field_type.lt:
109 raise errors.NumberNotLtError(limit_value=field_type.lt)
110 28710 13973.0 0.5 10.4 if field_type.le is not None and not v <= field_type.le:
111 raise errors.NumberNotLeError(limit_value=field_type.le)
112
113 28710 11715.0 0.4 8.7 return v
Total time: 1.23868 s
File: pydantic/pydantic/validators.py
Function: anystr_length_validator at line 129
Line # Hits Time Per Hit % Time Line Contents
==============================================================
129 def anystr_length_validator(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
130 298125 176380.0 0.6 14.2 v_len = len(v)
131
132 298125 311834.0 1.0 25.2 min_length = getattr(field.type_, 'min_length', config.min_anystr_length)
133 298125 161325.0 0.5 13.0 if min_length is not None and v_len < min_length:
134 240 2619.0 10.9 0.2 raise errors.AnyStrMinLengthError(limit_value=min_length)
135
136 297885 279888.0 0.9 22.6 max_length = getattr(field.type_, 'max_length', config.max_anystr_length)
137 297885 151702.0 0.5 12.2 if max_length is not None and v_len > max_length:
138 3630 31430.0 8.7 2.5 raise errors.AnyStrMaxLengthError(limit_value=max_length)
139
140 294255 123498.0 0.4 10.0 return v
Total time: 0.606503 s
File: pydantic/pydantic/validators.py
Function: anystr_strip_whitespace at line 143
Line # Hits Time Per Hit % Time Line Contents
==============================================================
143 def anystr_strip_whitespace(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
144 298125 373010.0 1.3 61.5 strip_whitespace = getattr(field.type_, 'strip_whitespace', config.anystr_strip_whitespace)
145 298125 126165.0 0.4 20.8 if strip_whitespace:
146 v = v.strip()
147
148 298125 107328.0 0.4 17.7 return v
Only last "layer" of functions output on master branch:
-------------------------------------------------------
pydantic time=4.412s, success=50.60%
pydantic time=4.516s, success=50.60%
pydantic time=4.501s, success=50.60%
pydantic time=4.476s, success=50.60%
pydantic time=4.477s, success=50.60%
pydantic best=4.412s, avg=4.476s, stdev=0.040s
pydantic best=147.058μs/iter avg=149.212μs/iter stdev=1.333μs/iter
Timer unit: 1e-06 s
Total time: 1.41706 s
File: pydantic/pydantic/datetime_parse.py
Function: parse_datetime at line 139
Line # Hits Time Per Hit % Time Line Contents
==============================================================
139 def parse_datetime(value: Union[datetime, StrIntFloat]) -> datetime:
140 """
141 Parse a datetime/int/float/string and return a datetime.datetime.
142
143 This function supports time zone offsets. When the input contains one,
144 the output uses a timezone with a fixed offset from UTC.
145
146 Raise ValueError if the input is well formatted but not a valid datetime.
147 Raise ValueError if the input isn't well formatted.
148 """
149 30000 33653.0 1.1 2.4 if isinstance(value, datetime):
150 return value
151
152 30000 282550.0 9.4 19.9 number = get_numeric(value)
153 30000 24813.0 0.8 1.8 if number is not None:
154 return from_unix_seconds(number)
155
156 30000 158066.0 5.3 11.2 match = datetime_re.match(cast(str, value))
157 30000 25795.0 0.9 1.8 if not match:
158 raise errors.DateTimeError()
159
160 30000 72533.0 2.4 5.1 kw = match.groupdict()
161 30000 30746.0 1.0 2.2 if kw['microsecond']:
162 kw['microsecond'] = kw['microsecond'].ljust(6, '0')
163
164 30000 36102.0 1.2 2.5 tzinfo_str = kw.pop('tzinfo')
165 30000 27285.0 0.9 1.9 if tzinfo_str == 'Z':
166 tzinfo = timezone.utc
167 30000 22741.0 0.8 1.6 elif tzinfo_str is not None:
168 offset_mins = int(tzinfo_str[-2:]) if len(tzinfo_str) > 3 else 0
169 offset = 60 * int(tzinfo_str[1:3]) + offset_mins
170 if tzinfo_str[0] == '-':
171 offset = -offset
172 tzinfo = timezone(timedelta(minutes=offset))
173 else:
174 30000 22922.0 0.8 1.6 tzinfo = None
175
176 30000 175511.0 5.9 12.4 kw_: Dict[str, Union[int, timezone]] = {k: int(v) for k, v in kw.items() if v is not None}
177 30000 26931.0 0.9 1.9 kw_['tzinfo'] = tzinfo
178
179 30000 215625.0 7.2 15.2 with change_exception(errors.DateTimeError, ValueError):
180 30000 261783.0 8.7 18.5 return datetime(**kw_) # type: ignore
Total time: 11.7748 s
File: pydantic/pydantic/main.py
Function: validate at line 423
Line # Hits Time Per Hit % Time Line Contents
==============================================================
423 @classmethod
424 def validate(cls: Type['Model'], value: Union['DictStrAny', 'Model']) -> 'Model':
425 103245 68490.0 0.7 0.6 if isinstance(value, dict):
426 103245 11706284.0 113.4 99.4 return cls(**value)
427 elif isinstance(value, cls):
428 return value.copy()
429 else:
430 with change_exception(DictError, TypeError, ValueError):
431 return cls(**dict(value)) # type: ignore
Total time: 0.105743 s
File: pydantic/pydantic/types.py
Function: validate at line 146
Line # Hits Time Per Hit % Time Line Contents
==============================================================
146 @classmethod
147 def validate(cls, value: str) -> str:
148 75795 40696.0 0.5 38.5 if cls.curtail_length and len(value) > cls.curtail_length:
149 value = value[: cls.curtail_length]
150
151 75795 36606.0 0.5 34.6 if cls.regex:
152 if not cls.regex.match(value):
153 raise errors.StrRegexError(pattern=cls.regex.pattern)
154
155 75795 28441.0 0.4 26.9 return value
Total time: 0.303975 s
File: pydantic/pydantic/validators.py
Function: not_none_validator at line 28
Line # Hits Time Per Hit % Time Line Contents
==============================================================
28 def not_none_validator(v: Any) -> Any:
29 302085 125627.0 0.4 41.3 if v is None:
30 3960 83772.0 21.2 27.6 raise errors.NoneIsNotAllowedError()
31 298125 94576.0 0.3 31.1 return v
Total time: 0.316406 s
File: pydantic/pydantic/validators.py
Function: str_validator at line 39
Line # Hits Time Per Hit % Time Line Contents
==============================================================
39 def str_validator(v: Any) -> str:
40 298125 206865.0 0.7 65.4 if isinstance(v, (str, NoneType)): # type: ignore
41 298125 109541.0 0.4 34.6 return v
42 elif isinstance(v, (bytes, bytearray)):
43 return v.decode()
44 elif isinstance(v, (float, int, Decimal)):
45 # is there anything else we want to add here? If you think so, create an issue.
46 return str(v)
47 else:
48 raise errors.StrError()
Total time: 0.633337 s
File: pydantic/pydantic/validators.py
Function: int_validator at line 77
Line # Hits Time Per Hit % Time Line Contents
==============================================================
77 def int_validator(v: Any) -> int:
78 206490 170508.0 0.8 26.9 if not isinstance(v, bool) and isinstance(v, int):
79 176490 67546.0 0.4 10.7 return v
80
81 30000 242029.0 8.1 38.2 with change_exception(errors.IntegerError, TypeError, ValueError):
82 30000 153254.0 5.1 24.2 return int(v)
Total time: 0.156316 s
File: pydantic/pydantic/validators.py
Function: float_validator at line 85
Line # Hits Time Per Hit % Time Line Contents
==============================================================
85 def float_validator(v: Any) -> float:
86 163245 98141.0 0.6 62.8 if isinstance(v, float):
87 163245 58175.0 0.4 37.2 return v
88
89 with change_exception(errors.FloatError, TypeError, ValueError):
90 return float(v)
Total time: 0.049485 s
File: pydantic/pydantic/validators.py
Function: number_multiple_validator at line 93
Line # Hits Time Per Hit % Time Line Contents
==============================================================
93 def number_multiple_validator(v: 'Number', field: 'Field') -> 'Number':
94 28710 25596.0 0.9 51.7 field_type = cast('ConstrainedNumber', field.type_)
95 28710 13260.0 0.5 26.8 if field_type.multiple_of is not None and v % field_type.multiple_of != 0: # type: ignore
96 raise errors.NumberNotMultipleError(multiple_of=field_type.multiple_of)
97
98 28710 10629.0 0.4 21.5 return v
Total time: 0.123027 s
File: pydantic/pydantic/validators.py
Function: number_size_validator at line 101
Line # Hits Time Per Hit % Time Line Contents
==============================================================
101 def number_size_validator(v: 'Number', field: 'Field') -> 'Number':
102 30000 36365.0 1.2 29.6 field_type = cast('ConstrainedNumber', field.type_)
103 30000 25133.0 0.8 20.4 if field_type.gt is not None and not v > field_type.gt:
104 1290 7575.0 5.9 6.2 raise errors.NumberNotGtError(limit_value=field_type.gt)
105 28710 14729.0 0.5 12.0 elif field_type.ge is not None and not v >= field_type.ge:
106 raise errors.NumberNotGeError(limit_value=field_type.ge)
107
108 28710 14053.0 0.5 11.4 if field_type.lt is not None and not v < field_type.lt:
109 raise errors.NumberNotLtError(limit_value=field_type.lt)
110 28710 13675.0 0.5 11.1 if field_type.le is not None and not v <= field_type.le:
111 raise errors.NumberNotLeError(limit_value=field_type.le)
112
113 28710 11497.0 0.4 9.3 return v
Total time: 1.14471 s
File: pydantic/pydantic/validators.py
Function: anystr_length_validator at line 129
Line # Hits Time Per Hit % Time Line Contents
==============================================================
129 def anystr_length_validator(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
130 298125 161344.0 0.5 14.1 v_len = len(v)
131
132 298125 290901.0 1.0 25.4 min_length = getattr(field.type_, 'min_length', config.min_anystr_length)
133 298125 141083.0 0.5 12.3 if min_length is not None and v_len < min_length:
134 240 1642.0 6.8 0.1 raise errors.AnyStrMinLengthError(limit_value=min_length)
135
136 297885 268956.0 0.9 23.5 max_length = getattr(field.type_, 'max_length', config.max_anystr_length)
137 297885 143572.0 0.5 12.5 if max_length is not None and v_len > max_length:
138 3630 22062.0 6.1 1.9 raise errors.AnyStrMaxLengthError(limit_value=max_length)
139
140 294255 115148.0 0.4 10.1 return v
Total time: 0.547554 s
File: pydantic/pydantic/validators.py
Function: anystr_strip_whitespace at line 143
Line # Hits Time Per Hit % Time Line Contents
==============================================================
143 def anystr_strip_whitespace(v: 'StrBytes', field: 'Field', config: 'BaseConfig') -> 'StrBytes':
144 298125 331283.0 1.1 60.5 strip_whitespace = getattr(field.type_, 'strip_whitespace', config.anystr_strip_whitespace)
145 298125 116094.0 0.4 21.2 if strip_whitespace:
146 v = v.strip()
147
148 298125 100177.0 0.3 18.3 return v
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment