Coverage for pydantic/fields.py: 100.00%
625 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 13:26 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-08-15 13:26 +0000
1import copy 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
2import re 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
3from collections import Counter as CollectionCounter, defaultdict, deque 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
4from collections.abc import Callable, Hashable as CollectionsHashable, Iterable as CollectionsIterable 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
5from typing import ( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
6 TYPE_CHECKING,
7 Any,
8 Counter,
9 DefaultDict,
10 Deque,
11 Dict,
12 ForwardRef,
13 FrozenSet,
14 Generator,
15 Iterable,
16 Iterator,
17 List,
18 Mapping,
19 Optional,
20 Pattern,
21 Sequence,
22 Set,
23 Tuple,
24 Type,
25 TypeVar,
26 Union,
27)
29from typing_extensions import Annotated, Final 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
31from pydantic import errors as errors_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
32from pydantic.class_validators import Validator, make_generic_validator, prep_validators 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
33from pydantic.error_wrappers import ErrorWrapper 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
34from pydantic.errors import ConfigError, InvalidDiscriminator, MissingDiscriminator, NoneIsNotAllowedError 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
35from pydantic.types import Json, JsonWrapper 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
36from pydantic.typing import ( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
37 NoArgAnyCallable,
38 convert_generics,
39 display_as_type,
40 get_args,
41 get_origin,
42 is_finalvar,
43 is_literal_type,
44 is_new_type,
45 is_none_type,
46 is_typeddict,
47 is_typeddict_special,
48 is_union,
49 new_type_supertype,
50)
51from pydantic.utils import ( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
52 PyObjectStr,
53 Representation,
54 ValueItems,
55 get_discriminator_alias_and_values,
56 get_unique_discriminator_alias,
57 lenient_isinstance,
58 lenient_issubclass,
59 sequence_like,
60 smart_deepcopy,
61)
62from pydantic.validators import constant_validator, dict_validator, find_validators, validate_json 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
64Required: Any = Ellipsis 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
66T = TypeVar('T') 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
69class UndefinedType: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
70 def __repr__(self) -> str: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
71 return 'PydanticUndefined' 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
73 def __copy__(self: T) -> T: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
74 return self 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
76 def __reduce__(self) -> str: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
77 return 'Undefined' 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
79 def __deepcopy__(self: T, _: Any) -> T: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
80 return self 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
83Undefined = UndefinedType() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
85if TYPE_CHECKING: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
86 from pydantic.class_validators import ValidatorsList
87 from pydantic.config import BaseConfig
88 from pydantic.error_wrappers import ErrorList
89 from pydantic.types import ModelOrDc
90 from pydantic.typing import AbstractSetIntStr, MappingIntStrAny, ReprArgs
92 ValidateReturn = Tuple[Optional[Any], Optional[ErrorList]]
93 LocStr = Union[Tuple[Union[int, str], ...], str]
94 BoolUndefined = Union[bool, UndefinedType]
97class FieldInfo(Representation): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
98 """
99 Captures extra information about a field.
100 """
102 __slots__ = ( 1abcdefghijklmnopqrstPQRSTUuvwxyzABCD
103 'default',
104 'default_factory',
105 'alias',
106 'alias_priority',
107 'title',
108 'description',
109 'exclude',
110 'include',
111 'const',
112 'gt',
113 'ge',
114 'lt',
115 'le',
116 'multiple_of',
117 'allow_inf_nan',
118 'max_digits',
119 'decimal_places',
120 'min_items',
121 'max_items',
122 'unique_items',
123 'min_length',
124 'max_length',
125 'allow_mutation',
126 'repr',
127 'regex',
128 'discriminator',
129 'extra',
130 )
132 # field constraints with the default value, it's also used in update_from_config below
133 __field_constraints__ = { 1abcdefghijklmnopqrstPQRSTUuvwxyzABCD
134 'min_length': None,
135 'max_length': None,
136 'regex': None,
137 'gt': None,
138 'lt': None,
139 'ge': None,
140 'le': None,
141 'multiple_of': None,
142 'allow_inf_nan': None,
143 'max_digits': None,
144 'decimal_places': None,
145 'min_items': None,
146 'max_items': None,
147 'unique_items': None,
148 'allow_mutation': True,
149 }
151 def __init__(self, default: Any = Undefined, **kwargs: Any) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
152 self.default = default 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
153 self.default_factory = kwargs.pop('default_factory', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
154 self.alias = kwargs.pop('alias', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
155 self.alias_priority = kwargs.pop('alias_priority', 2 if self.alias is not None else None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
156 self.title = kwargs.pop('title', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
157 self.description = kwargs.pop('description', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
158 self.exclude = kwargs.pop('exclude', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
159 self.include = kwargs.pop('include', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
160 self.const = kwargs.pop('const', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
161 self.gt = kwargs.pop('gt', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
162 self.ge = kwargs.pop('ge', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
163 self.lt = kwargs.pop('lt', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
164 self.le = kwargs.pop('le', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
165 self.multiple_of = kwargs.pop('multiple_of', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
166 self.allow_inf_nan = kwargs.pop('allow_inf_nan', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
167 self.max_digits = kwargs.pop('max_digits', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
168 self.decimal_places = kwargs.pop('decimal_places', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
169 self.min_items = kwargs.pop('min_items', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
170 self.max_items = kwargs.pop('max_items', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
171 self.unique_items = kwargs.pop('unique_items', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
172 self.min_length = kwargs.pop('min_length', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
173 self.max_length = kwargs.pop('max_length', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
174 self.allow_mutation = kwargs.pop('allow_mutation', True) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
175 self.regex = kwargs.pop('regex', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
176 self.discriminator = kwargs.pop('discriminator', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
177 self.repr = kwargs.pop('repr', True) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
178 self.extra = kwargs 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
180 def __repr_args__(self) -> 'ReprArgs': 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
181 field_defaults_to_hide: Dict[str, Any] = { 1abcdefghijklmnopqrstuvwxyzABCD
182 'repr': True,
183 **self.__field_constraints__,
184 }
186 attrs = ((s, getattr(self, s)) for s in self.__slots__) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
187 return [(a, v) for a, v in attrs if v != field_defaults_to_hide.get(a, None)] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
189 def get_constraints(self) -> Set[str]: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
190 """
191 Gets the constraints set on the field by comparing the constraint value with its default value
193 :return: the constraints set on field_info
194 """
195 return {attr for attr, default in self.__field_constraints__.items() if getattr(self, attr) != default} 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
197 def update_from_config(self, from_config: Dict[str, Any]) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
198 """
199 Update this FieldInfo based on a dict from get_field_info, only fields which have not been set are dated.
200 """
201 for attr_name, value in from_config.items(): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
202 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
203 current_value = getattr(self, attr_name) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
204 except AttributeError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
205 # attr_name is not an attribute of FieldInfo, it should therefore be added to extra
206 # (except if extra already has this value!)
207 self.extra.setdefault(attr_name, value) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
208 else:
209 if current_value is self.__field_constraints__.get(attr_name, None): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
210 setattr(self, attr_name, value) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
211 elif attr_name == 'exclude': 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
212 self.exclude = ValueItems.merge(value, current_value) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
213 elif attr_name == 'include': 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
214 self.include = ValueItems.merge(value, current_value, intersect=True) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
216 def _validate(self) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
217 if self.default is not Undefined and self.default_factory is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
218 raise ValueError('cannot specify both default and default_factory') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
221def Field( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
222 default: Any = Undefined,
223 *,
224 default_factory: Optional[NoArgAnyCallable] = None,
225 alias: Optional[str] = None,
226 title: Optional[str] = None,
227 description: Optional[str] = None,
228 exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None,
229 include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None,
230 const: Optional[bool] = None,
231 gt: Optional[float] = None,
232 ge: Optional[float] = None,
233 lt: Optional[float] = None,
234 le: Optional[float] = None,
235 multiple_of: Optional[float] = None,
236 allow_inf_nan: Optional[bool] = None,
237 max_digits: Optional[int] = None,
238 decimal_places: Optional[int] = None,
239 min_items: Optional[int] = None,
240 max_items: Optional[int] = None,
241 unique_items: Optional[bool] = None,
242 min_length: Optional[int] = None,
243 max_length: Optional[int] = None,
244 allow_mutation: bool = True,
245 regex: Optional[str] = None,
246 discriminator: Optional[str] = None,
247 repr: bool = True,
248 **extra: Any,
249) -> Any:
250 """
251 Used to provide extra information about a field, either for the model schema or complex validation. Some arguments
252 apply only to number fields (``int``, ``float``, ``Decimal``) and some apply only to ``str``.
254 :param default: since this is replacing the field’s default, its first argument is used
255 to set the default, use ellipsis (``...``) to indicate the field is required
256 :param default_factory: callable that will be called when a default value is needed for this field
257 If both `default` and `default_factory` are set, an error is raised.
258 :param alias: the public name of the field
259 :param title: can be any string, used in the schema
260 :param description: can be any string, used in the schema
261 :param exclude: exclude this field while dumping.
262 Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method.
263 :param include: include this field while dumping.
264 Takes same values as the ``include`` and ``exclude`` arguments on the ``.dict`` method.
265 :param const: this field is required and *must* take it's default value
266 :param gt: only applies to numbers, requires the field to be "greater than". The schema
267 will have an ``exclusiveMinimum`` validation keyword
268 :param ge: only applies to numbers, requires the field to be "greater than or equal to". The
269 schema will have a ``minimum`` validation keyword
270 :param lt: only applies to numbers, requires the field to be "less than". The schema
271 will have an ``exclusiveMaximum`` validation keyword
272 :param le: only applies to numbers, requires the field to be "less than or equal to". The
273 schema will have a ``maximum`` validation keyword
274 :param multiple_of: only applies to numbers, requires the field to be "a multiple of". The
275 schema will have a ``multipleOf`` validation keyword
276 :param allow_inf_nan: only applies to numbers, allows the field to be NaN or infinity (+inf or -inf),
277 which is a valid Python float. Default True, set to False for compatibility with JSON.
278 :param max_digits: only applies to Decimals, requires the field to have a maximum number
279 of digits within the decimal. It does not include a zero before the decimal point or trailing decimal zeroes.
280 :param decimal_places: only applies to Decimals, requires the field to have at most a number of decimal places
281 allowed. It does not include trailing decimal zeroes.
282 :param min_items: only applies to lists, requires the field to have a minimum number of
283 elements. The schema will have a ``minItems`` validation keyword
284 :param max_items: only applies to lists, requires the field to have a maximum number of
285 elements. The schema will have a ``maxItems`` validation keyword
286 :param unique_items: only applies to lists, requires the field not to have duplicated
287 elements. The schema will have a ``uniqueItems`` validation keyword
288 :param min_length: only applies to strings, requires the field to have a minimum length. The
289 schema will have a ``minLength`` validation keyword
290 :param max_length: only applies to strings, requires the field to have a maximum length. The
291 schema will have a ``maxLength`` validation keyword
292 :param allow_mutation: a boolean which defaults to True. When False, the field raises a TypeError if the field is
293 assigned on an instance. The BaseModel Config must set validate_assignment to True
294 :param regex: only applies to strings, requires the field match against a regular expression
295 pattern string. The schema will have a ``pattern`` validation keyword
296 :param discriminator: only useful with a (discriminated a.k.a. tagged) `Union` of sub models with a common field.
297 The `discriminator` is the name of this common field to shorten validation and improve generated schema
298 :param repr: show this field in the representation
299 :param **extra: any additional keyword arguments will be added as is to the schema
300 """
301 field_info = FieldInfo( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
302 default,
303 default_factory=default_factory,
304 alias=alias,
305 title=title,
306 description=description,
307 exclude=exclude,
308 include=include,
309 const=const,
310 gt=gt,
311 ge=ge,
312 lt=lt,
313 le=le,
314 multiple_of=multiple_of,
315 allow_inf_nan=allow_inf_nan,
316 max_digits=max_digits,
317 decimal_places=decimal_places,
318 min_items=min_items,
319 max_items=max_items,
320 unique_items=unique_items,
321 min_length=min_length,
322 max_length=max_length,
323 allow_mutation=allow_mutation,
324 regex=regex,
325 discriminator=discriminator,
326 repr=repr,
327 **extra,
328 )
329 field_info._validate() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
330 return field_info 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
333# used to be an enum but changed to int's for small performance improvement as less access overhead
334SHAPE_SINGLETON = 1 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
335SHAPE_LIST = 2 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
336SHAPE_SET = 3 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
337SHAPE_MAPPING = 4 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
338SHAPE_TUPLE = 5 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
339SHAPE_TUPLE_ELLIPSIS = 6 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
340SHAPE_SEQUENCE = 7 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
341SHAPE_FROZENSET = 8 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
342SHAPE_ITERABLE = 9 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
343SHAPE_GENERIC = 10 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
344SHAPE_DEQUE = 11 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
345SHAPE_DICT = 12 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
346SHAPE_DEFAULTDICT = 13 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
347SHAPE_COUNTER = 14 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
348SHAPE_NAME_LOOKUP = { 1abcdefghijklmnopqrstPQRSTUuvwxyzABCD
349 SHAPE_LIST: 'List[{}]',
350 SHAPE_SET: 'Set[{}]',
351 SHAPE_TUPLE_ELLIPSIS: 'Tuple[{}, ...]',
352 SHAPE_SEQUENCE: 'Sequence[{}]',
353 SHAPE_FROZENSET: 'FrozenSet[{}]',
354 SHAPE_ITERABLE: 'Iterable[{}]',
355 SHAPE_DEQUE: 'Deque[{}]',
356 SHAPE_DICT: 'Dict[{}]',
357 SHAPE_DEFAULTDICT: 'DefaultDict[{}]',
358 SHAPE_COUNTER: 'Counter[{}]',
359}
361MAPPING_LIKE_SHAPES: Set[int] = {SHAPE_DEFAULTDICT, SHAPE_DICT, SHAPE_MAPPING, SHAPE_COUNTER} 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
364class ModelField(Representation): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
365 __slots__ = ( 1abcdefghijklmnopqrstPQRSTUuvwxyzABCD
366 'type_',
367 'outer_type_',
368 'annotation',
369 'sub_fields',
370 'sub_fields_mapping',
371 'key_field',
372 'validators',
373 'pre_validators',
374 'post_validators',
375 'default',
376 'default_factory',
377 'required',
378 'final',
379 'model_config',
380 'name',
381 'alias',
382 'has_alias',
383 'field_info',
384 'discriminator_key',
385 'discriminator_alias',
386 'validate_always',
387 'allow_none',
388 'shape',
389 'class_validators',
390 'parse_json',
391 )
393 def __init__( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
394 self,
395 *,
396 name: str,
397 type_: Type[Any],
398 class_validators: Optional[Dict[str, Validator]],
399 model_config: Type['BaseConfig'],
400 default: Any = None,
401 default_factory: Optional[NoArgAnyCallable] = None,
402 required: 'BoolUndefined' = Undefined,
403 final: bool = False,
404 alias: Optional[str] = None,
405 field_info: Optional[FieldInfo] = None,
406 ) -> None:
407 self.name: str = name 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
408 self.has_alias: bool = alias is not None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
409 self.alias: str = alias if alias is not None else name 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
410 self.annotation = type_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
411 self.type_: Any = convert_generics(type_) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
412 self.outer_type_: Any = type_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
413 self.class_validators = class_validators or {} 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
414 self.default: Any = default 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
415 self.default_factory: Optional[NoArgAnyCallable] = default_factory 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
416 self.required: 'BoolUndefined' = required 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
417 self.final: bool = final 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
418 self.model_config = model_config 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
419 self.field_info: FieldInfo = field_info or FieldInfo(default) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
420 self.discriminator_key: Optional[str] = self.field_info.discriminator 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
421 self.discriminator_alias: Optional[str] = self.discriminator_key 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
423 self.allow_none: bool = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
424 self.validate_always: bool = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
425 self.sub_fields: Optional[List[ModelField]] = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
426 self.sub_fields_mapping: Optional[Dict[str, 'ModelField']] = None # used for discriminated union 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
427 self.key_field: Optional[ModelField] = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
428 self.validators: 'ValidatorsList' = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
429 self.pre_validators: Optional['ValidatorsList'] = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
430 self.post_validators: Optional['ValidatorsList'] = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
431 self.parse_json: bool = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
432 self.shape: int = SHAPE_SINGLETON 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
433 self.model_config.prepare_field(self) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
434 self.prepare() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
436 def get_default(self) -> Any: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
437 return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
439 @staticmethod 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
440 def _get_field_info( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
441 field_name: str, annotation: Any, value: Any, config: Type['BaseConfig']
442 ) -> Tuple[FieldInfo, Any]:
443 """
444 Get a FieldInfo from a root typing.Annotated annotation, value, or config default.
446 The FieldInfo may be set in typing.Annotated or the value, but not both. If neither contain
447 a FieldInfo, a new one will be created using the config.
449 :param field_name: name of the field for use in error messages
450 :param annotation: a type hint such as `str` or `Annotated[str, Field(..., min_length=5)]`
451 :param value: the field's assigned value
452 :param config: the model's config object
453 :return: the FieldInfo contained in the `annotation`, the value, or a new one from the config.
454 """
455 field_info_from_config = config.get_field_info(field_name) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
457 field_info = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
458 if get_origin(annotation) is Annotated: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
459 field_infos = [arg for arg in get_args(annotation)[1:] if isinstance(arg, FieldInfo)] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
460 if len(field_infos) > 1: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
461 raise ValueError(f'cannot specify multiple `Annotated` `Field`s for {field_name!r}') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
462 field_info = next(iter(field_infos), None) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
463 if field_info is not None: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
464 field_info = copy.copy(field_info) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
465 field_info.update_from_config(field_info_from_config) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
466 if field_info.default not in (Undefined, Required): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
467 raise ValueError(f'`Field` default cannot be set in `Annotated` for {field_name!r}') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
468 if value is not Undefined and value is not Required: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
469 # check also `Required` because of `validate_arguments` that sets `...` as default value
470 field_info.default = value 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
472 if isinstance(value, FieldInfo): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
473 if field_info is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
474 raise ValueError(f'cannot specify `Annotated` and value `Field`s together for {field_name!r}') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
475 field_info = value 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
476 field_info.update_from_config(field_info_from_config) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
477 elif field_info is None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
478 field_info = FieldInfo(value, **field_info_from_config) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
479 value = None if field_info.default_factory is not None else field_info.default 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
480 field_info._validate() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
481 return field_info, value 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
483 @classmethod 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
484 def infer( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
485 cls,
486 *,
487 name: str,
488 value: Any,
489 annotation: Any,
490 class_validators: Optional[Dict[str, Validator]],
491 config: Type['BaseConfig'],
492 ) -> 'ModelField':
493 from pydantic.schema import get_annotation_from_field_info 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
495 field_info, value = cls._get_field_info(name, annotation, value, config) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
496 required: 'BoolUndefined' = Undefined 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
497 if value is Required: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
498 required = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
499 value = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
500 elif value is not Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
501 required = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
502 annotation = get_annotation_from_field_info(annotation, field_info, name, config.validate_assignment) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
504 return cls( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
505 name=name,
506 type_=annotation,
507 alias=field_info.alias,
508 class_validators=class_validators,
509 default=value,
510 default_factory=field_info.default_factory,
511 required=required,
512 model_config=config,
513 field_info=field_info,
514 )
516 def set_config(self, config: Type['BaseConfig']) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
517 self.model_config = config 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
518 info_from_config = config.get_field_info(self.name) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
519 config.prepare_field(self) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
520 new_alias = info_from_config.get('alias') 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
521 new_alias_priority = info_from_config.get('alias_priority') or 0 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
522 if new_alias and new_alias_priority >= (self.field_info.alias_priority or 0): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
523 self.field_info.alias = new_alias 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
524 self.field_info.alias_priority = new_alias_priority 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
525 self.alias = new_alias 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
526 new_exclude = info_from_config.get('exclude') 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
527 if new_exclude is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
528 self.field_info.exclude = ValueItems.merge(self.field_info.exclude, new_exclude) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
529 new_include = info_from_config.get('include') 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
530 if new_include is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
531 self.field_info.include = ValueItems.merge(self.field_info.include, new_include, intersect=True) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
533 @property 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
534 def alt_alias(self) -> bool: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
535 return self.name != self.alias 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
537 def prepare(self) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
538 """
539 Prepare the field but inspecting self.default, self.type_ etc.
541 Note: this method is **not** idempotent (because _type_analysis is not idempotent),
542 e.g. calling it it multiple times may modify the field and configure it incorrectly.
543 """
544 self._set_default_and_type() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
545 if self.type_.__class__ is ForwardRef or self.type_.__class__ is DeferredType: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
546 # self.type_ is currently a ForwardRef and there's nothing we can do now,
547 # user will need to call model.update_forward_refs()
548 return 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
550 self._type_analysis() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
551 if self.required is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
552 self.required = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
553 if self.default is Undefined and self.default_factory is None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
554 self.default = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
555 self.populate_validators() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
557 def _set_default_and_type(self) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
558 """
559 Set the default value, infer the type if needed and check if `None` value is valid.
560 """
561 if self.default_factory is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
562 if self.type_ is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
563 raise errors_.ConfigError( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
564 f'you need to set the type of field {self.name!r} when using `default_factory`'
565 )
566 return 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
568 default_value = self.get_default() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
570 if default_value is not None and self.type_ is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
571 self.type_ = default_value.__class__ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
572 self.outer_type_ = self.type_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
573 self.annotation = self.type_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
575 if self.type_ is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
576 raise errors_.ConfigError(f'unable to infer type for attribute "{self.name}"') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
578 if self.required is False and default_value is None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
579 self.allow_none = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
581 def _type_analysis(self) -> None: # noqa: C901 (ignore complexity) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
582 # typing interface is horrible, we have to do some ugly checks
583 if lenient_issubclass(self.type_, JsonWrapper): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
584 self.type_ = self.type_.inner_type 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
585 self.parse_json = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
586 elif lenient_issubclass(self.type_, Json): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
587 self.type_ = Any 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
588 self.parse_json = True 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
589 elif isinstance(self.type_, TypeVar): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
590 if self.type_.__bound__: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
591 self.type_ = self.type_.__bound__ 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
592 elif self.type_.__constraints__: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
593 self.type_ = Union[self.type_.__constraints__] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
594 else:
595 self.type_ = Any 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
596 elif is_new_type(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
597 self.type_ = new_type_supertype(self.type_) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
599 if self.type_ is Any or self.type_ is object: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
600 if self.required is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
601 self.required = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
602 self.allow_none = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
603 return 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
604 elif self.type_ is Pattern or self.type_ is re.Pattern: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
605 # python 3.7 only, Pattern is a typing object but without sub fields
606 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
607 elif is_literal_type(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
608 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
609 elif is_typeddict(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
610 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
612 if is_finalvar(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
613 self.final = True 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
615 if self.type_ is Final: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
616 self.type_ = Any 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
617 else:
618 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
620 self._type_analysis() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
621 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
623 origin = get_origin(self.type_) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
625 if origin is Annotated or is_typeddict_special(origin): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
626 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
627 self._type_analysis() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
628 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
630 if self.discriminator_key is not None and not is_union(origin): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
631 raise TypeError('`discriminator` can only be used with `Union` type with more than one variant') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
633 # add extra check for `collections.abc.Hashable` for python 3.10+ where origin is not `None`
634 if origin is None or origin is CollectionsHashable: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
635 # field is not "typing" object eg. Union, Dict, List etc.
636 # allow None for virtual superclasses of NoneType, e.g. Hashable
637 if isinstance(self.type_, type) and isinstance(None, self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
638 self.allow_none = True 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
639 return 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
640 elif origin is Callable: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
641 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
642 elif is_union(origin): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
643 types_ = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
644 for type_ in get_args(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
645 if is_none_type(type_) or type_ is Any or type_ is object: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
646 if self.required is Undefined: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
647 self.required = False 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
648 self.allow_none = True 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
649 if is_none_type(type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
650 continue 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
651 types_.append(type_) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
653 if len(types_) == 1: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
654 # Optional[]
655 self.type_ = types_[0] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
656 # this is the one case where the "outer type" isn't just the original type
657 self.outer_type_ = self.type_ 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
658 # re-run to correctly interpret the new self.type_
659 self._type_analysis() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
660 else:
661 self.sub_fields = [self._create_sub_type(t, f'{self.name}_{display_as_type(t)}') for t in types_] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
663 if self.discriminator_key is not None: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
664 self.prepare_discriminated_union_sub_fields() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
665 return 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
666 elif issubclass(origin, Tuple): # type: ignore 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
667 # origin == Tuple without item type
668 args = get_args(self.type_) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
669 if not args: # plain tuple 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
670 self.type_ = Any 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
671 self.shape = SHAPE_TUPLE_ELLIPSIS 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
672 elif len(args) == 2 and args[1] is Ellipsis: # e.g. Tuple[int, ...] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
673 self.type_ = args[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
674 self.shape = SHAPE_TUPLE_ELLIPSIS 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
675 self.sub_fields = [self._create_sub_type(args[0], f'{self.name}_0')] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
676 elif args == ((),): # Tuple[()] means empty tuple 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
677 self.shape = SHAPE_TUPLE 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
678 self.type_ = Any 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
679 self.sub_fields = [] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
680 else:
681 self.shape = SHAPE_TUPLE 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
682 self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(args)] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
683 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
684 elif issubclass(origin, List): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
685 # Create self validators
686 get_validators = getattr(self.type_, '__get_validators__', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
687 if get_validators: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
688 self.class_validators.update( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
689 {f'list_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
690 )
692 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
693 self.shape = SHAPE_LIST 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
694 elif issubclass(origin, Set): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
695 # Create self validators
696 get_validators = getattr(self.type_, '__get_validators__', None) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
697 if get_validators: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
698 self.class_validators.update( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
699 {f'set_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
700 )
702 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
703 self.shape = SHAPE_SET 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
704 elif issubclass(origin, FrozenSet): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
705 # Create self validators
706 get_validators = getattr(self.type_, '__get_validators__', None) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
707 if get_validators: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
708 self.class_validators.update( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
709 {f'frozenset_{i}': Validator(validator, pre=True) for i, validator in enumerate(get_validators())}
710 )
712 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
713 self.shape = SHAPE_FROZENSET 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
714 elif issubclass(origin, Deque): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
715 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
716 self.shape = SHAPE_DEQUE 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
717 elif issubclass(origin, Sequence): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
718 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
719 self.shape = SHAPE_SEQUENCE 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
720 # priority to most common mapping: dict
721 elif origin is dict or origin is Dict: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
722 self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
723 self.type_ = get_args(self.type_)[1] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
724 self.shape = SHAPE_DICT 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
725 elif issubclass(origin, DefaultDict): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
726 self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
727 self.type_ = get_args(self.type_)[1] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
728 self.shape = SHAPE_DEFAULTDICT 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
729 elif issubclass(origin, Counter): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
730 self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
731 self.type_ = int 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
732 self.shape = SHAPE_COUNTER 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
733 elif issubclass(origin, Mapping): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
734 self.key_field = self._create_sub_type(get_args(self.type_)[0], 'key_' + self.name, for_keys=True) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
735 self.type_ = get_args(self.type_)[1] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
736 self.shape = SHAPE_MAPPING 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
737 # Equality check as almost everything inherits form Iterable, including str
738 # check for Iterable and CollectionsIterable, as it could receive one even when declared with the other
739 elif origin in {Iterable, CollectionsIterable}: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
740 self.type_ = get_args(self.type_)[0] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
741 self.shape = SHAPE_ITERABLE 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
742 self.sub_fields = [self._create_sub_type(self.type_, f'{self.name}_type')] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
743 elif issubclass(origin, Type): # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
744 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
745 elif hasattr(origin, '__get_validators__') or self.model_config.arbitrary_types_allowed: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
746 # Is a Pydantic-compatible generic that handles itself
747 # or we have arbitrary_types_allowed = True
748 self.shape = SHAPE_GENERIC 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
749 self.sub_fields = [self._create_sub_type(t, f'{self.name}_{i}') for i, t in enumerate(get_args(self.type_))] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
750 self.type_ = origin 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
751 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
752 else:
753 raise TypeError(f'Fields of type "{origin}" are not supported.') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
755 # type_ has been refined eg. as the type of a List and sub_fields needs to be populated
756 self.sub_fields = [self._create_sub_type(self.type_, '_' + self.name)] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
758 def prepare_discriminated_union_sub_fields(self) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
759 """
760 Prepare the mapping <discriminator key> -> <ModelField> and update `sub_fields`
761 Note that this process can be aborted if a `ForwardRef` is encountered
762 """
763 assert self.discriminator_key is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
765 if self.type_.__class__ is DeferredType: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
766 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
768 assert self.sub_fields is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
769 sub_fields_mapping: Dict[str, 'ModelField'] = {} 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
770 all_aliases: Set[str] = set() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
772 for sub_field in self.sub_fields: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
773 t = sub_field.type_ 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
774 if t.__class__ is ForwardRef: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
775 # Stopping everything...will need to call `update_forward_refs`
776 return 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
778 alias, discriminator_values = get_discriminator_alias_and_values(t, self.discriminator_key) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
779 all_aliases.add(alias) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
780 for discriminator_value in discriminator_values: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
781 sub_fields_mapping[discriminator_value] = sub_field 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
783 self.sub_fields_mapping = sub_fields_mapping 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
784 self.discriminator_alias = get_unique_discriminator_alias(all_aliases, self.discriminator_key) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
786 def _create_sub_type(self, type_: Type[Any], name: str, *, for_keys: bool = False) -> 'ModelField': 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
787 if for_keys: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
788 class_validators = None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
789 else:
790 # validators for sub items should not have `each_item` as we want to check only the first sublevel
791 class_validators = { 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
792 k: Validator(
793 func=v.func,
794 pre=v.pre,
795 each_item=False,
796 always=v.always,
797 check_fields=v.check_fields,
798 skip_on_failure=v.skip_on_failure,
799 )
800 for k, v in self.class_validators.items()
801 if v.each_item
802 }
804 field_info, _ = self._get_field_info(name, type_, None, self.model_config) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
806 return self.__class__( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
807 type_=type_,
808 name=name,
809 class_validators=class_validators,
810 model_config=self.model_config,
811 field_info=field_info,
812 )
814 def populate_validators(self) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
815 """
816 Prepare self.pre_validators, self.validators, and self.post_validators based on self.type_'s __get_validators__
817 and class validators. This method should be idempotent, e.g. it should be safe to call multiple times
818 without mis-configuring the field.
819 """
820 self.validate_always = getattr(self.type_, 'validate_always', False) or any( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
821 v.always for v in self.class_validators.values()
822 )
824 class_validators_ = self.class_validators.values() 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
825 if not self.sub_fields or self.shape == SHAPE_GENERIC: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
826 get_validators = getattr(self.type_, '__get_validators__', None) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
827 v_funcs = ( 1abcdefghijklmnopqrstPQRSTUuvwxyzABCD
828 *[v.func for v in class_validators_ if v.each_item and v.pre],
829 *(get_validators() if get_validators else list(find_validators(self.type_, self.model_config))),
830 *[v.func for v in class_validators_ if v.each_item and not v.pre],
831 )
832 self.validators = prep_validators(v_funcs) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
834 self.pre_validators = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
835 self.post_validators = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
837 if self.field_info and self.field_info.const: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
838 self.post_validators.append(make_generic_validator(constant_validator)) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
840 if class_validators_: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
841 self.pre_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and v.pre) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
842 self.post_validators += prep_validators(v.func for v in class_validators_ if not v.each_item and not v.pre) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
844 if self.parse_json: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
845 self.pre_validators.append(make_generic_validator(validate_json)) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
847 self.pre_validators = self.pre_validators or None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
848 self.post_validators = self.post_validators or None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
850 def validate( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
851 self, v: Any, values: Dict[str, Any], *, loc: 'LocStr', cls: Optional['ModelOrDc'] = None
852 ) -> 'ValidateReturn':
853 assert self.type_.__class__ is not DeferredType 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
855 if self.type_.__class__ is ForwardRef: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
856 assert cls is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
857 raise ConfigError( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
858 f'field "{self.name}" not yet prepared so type is still a ForwardRef, '
859 f'you might need to call {cls.__name__}.update_forward_refs().'
860 )
862 errors: Optional['ErrorList']
863 if self.pre_validators: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
864 v, errors = self._apply_validators(v, values, loc, cls, self.pre_validators) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
865 if errors: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
866 return v, errors 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
868 if v is None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
869 if is_none_type(self.type_): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
870 # keep validating
871 pass 1JKabcdefghijLMklmnopqrstNOuvwxyzABCD
872 elif self.allow_none: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
873 if self.post_validators: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
874 return self._apply_validators(v, values, loc, cls, self.post_validators) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
875 else:
876 return None, None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
877 else:
878 return v, ErrorWrapper(NoneIsNotAllowedError(), loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
880 if self.shape == SHAPE_SINGLETON: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
881 v, errors = self._validate_singleton(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
882 elif self.shape in MAPPING_LIKE_SHAPES: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
883 v, errors = self._validate_mapping_like(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
884 elif self.shape == SHAPE_TUPLE: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
885 v, errors = self._validate_tuple(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
886 elif self.shape == SHAPE_ITERABLE: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
887 v, errors = self._validate_iterable(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
888 elif self.shape == SHAPE_GENERIC: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
889 v, errors = self._apply_validators(v, values, loc, cls, self.validators) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
890 else:
891 # sequence, list, set, generator, tuple with ellipsis, frozen set
892 v, errors = self._validate_sequence_like(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
894 if not errors and self.post_validators: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
895 v, errors = self._apply_validators(v, values, loc, cls, self.post_validators) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
896 return v, errors 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
898 def _validate_sequence_like( # noqa: C901 (ignore complexity) 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
899 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
900 ) -> 'ValidateReturn':
901 """
902 Validate sequence-like containers: lists, tuples, sets and generators
903 Note that large if-else blocks are necessary to enable Cython
904 optimization, which is why we disable the complexity check above.
905 """
906 if not sequence_like(v): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
907 e: errors_.PydanticTypeError
908 if self.shape == SHAPE_LIST: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
909 e = errors_.ListError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
910 elif self.shape in (SHAPE_TUPLE, SHAPE_TUPLE_ELLIPSIS): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
911 e = errors_.TupleError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
912 elif self.shape == SHAPE_SET: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
913 e = errors_.SetError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
914 elif self.shape == SHAPE_FROZENSET: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
915 e = errors_.FrozenSetError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
916 else:
917 e = errors_.SequenceError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
918 return v, ErrorWrapper(e, loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
920 loc = loc if isinstance(loc, tuple) else (loc,) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
921 result = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
922 errors: List[ErrorList] = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
923 for i, v_ in enumerate(v): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
924 v_loc = *loc, i 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
925 r, ee = self._validate_singleton(v_, values, v_loc, cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
926 if ee: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
927 errors.append(ee) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
928 else:
929 result.append(r) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
931 if errors: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
932 return v, errors 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
934 converted: Union[List[Any], Set[Any], FrozenSet[Any], Tuple[Any, ...], Iterator[Any], Deque[Any]] = result 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
936 if self.shape == SHAPE_SET: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
937 converted = set(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
938 elif self.shape == SHAPE_FROZENSET: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
939 converted = frozenset(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
940 elif self.shape == SHAPE_TUPLE_ELLIPSIS: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
941 converted = tuple(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
942 elif self.shape == SHAPE_DEQUE: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
943 converted = deque(result, maxlen=getattr(v, 'maxlen', None)) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
944 elif self.shape == SHAPE_SEQUENCE: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
945 if isinstance(v, tuple): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
946 converted = tuple(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
947 elif isinstance(v, set): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
948 converted = set(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
949 elif isinstance(v, Generator): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
950 converted = iter(result) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
951 elif isinstance(v, deque): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
952 converted = deque(result, maxlen=getattr(v, 'maxlen', None)) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
953 return converted, None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
955 def _validate_iterable( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
956 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
957 ) -> 'ValidateReturn':
958 """
959 Validate Iterables.
961 This intentionally doesn't validate values to allow infinite generators.
962 """
964 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
965 iterable = iter(v) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
966 except TypeError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
967 return v, ErrorWrapper(errors_.IterableError(), loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
968 return iterable, None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
970 def _validate_tuple( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
971 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
972 ) -> 'ValidateReturn':
973 e: Optional[Exception] = None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
974 if not sequence_like(v): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
975 e = errors_.TupleError() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
976 else:
977 actual_length, expected_length = len(v), len(self.sub_fields) # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
978 if actual_length != expected_length: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
979 e = errors_.TupleLengthError(actual_length=actual_length, expected_length=expected_length) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
981 if e: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
982 return v, ErrorWrapper(e, loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
984 loc = loc if isinstance(loc, tuple) else (loc,) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
985 result = [] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
986 errors: List[ErrorList] = [] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
987 for i, (v_, field) in enumerate(zip(v, self.sub_fields)): # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
988 v_loc = *loc, i 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
989 r, ee = field.validate(v_, values, loc=v_loc, cls=cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
990 if ee: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
991 errors.append(ee) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
992 else:
993 result.append(r) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
995 if errors: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
996 return v, errors 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
997 else:
998 return tuple(result), None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1000 def _validate_mapping_like( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
1001 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
1002 ) -> 'ValidateReturn':
1003 try: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1004 v_iter = dict_validator(v) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1005 except TypeError as exc: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1006 return v, ErrorWrapper(exc, loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1008 loc = loc if isinstance(loc, tuple) else (loc,) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1009 result, errors = {}, [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1010 for k, v_ in v_iter.items(): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1011 v_loc = *loc, '__key__' 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1012 key_result, key_errors = self.key_field.validate(k, values, loc=v_loc, cls=cls) # type: ignore 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1013 if key_errors: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1014 errors.append(key_errors) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1015 continue 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1017 v_loc = *loc, k 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1018 value_result, value_errors = self._validate_singleton(v_, values, v_loc, cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1019 if value_errors: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1020 errors.append(value_errors) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1021 continue 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1023 result[key_result] = value_result 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1024 if errors: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1025 return v, errors 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1026 elif self.shape == SHAPE_DICT: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1027 return result, None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1028 elif self.shape == SHAPE_DEFAULTDICT: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1029 return defaultdict(self.type_, result), None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1030 elif self.shape == SHAPE_COUNTER: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1031 return CollectionCounter(result), None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1032 else:
1033 return self._get_mapping_value(v, result), None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1035 def _get_mapping_value(self, original: T, converted: Dict[Any, Any]) -> Union[T, Dict[Any, Any]]: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1036 """
1037 When type is `Mapping[KT, KV]` (or another unsupported mapping), we try to avoid
1038 coercing to `dict` unwillingly.
1039 """
1040 original_cls = original.__class__ 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1042 if original_cls == dict or original_cls == Dict: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1043 return converted 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1044 elif original_cls in {defaultdict, DefaultDict}: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1045 return defaultdict(self.type_, converted) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1046 else:
1047 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1048 # Counter, OrderedDict, UserDict, ...
1049 return original_cls(converted) # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1050 except TypeError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1051 raise RuntimeError(f'Could not convert dictionary to {original_cls.__name__!r}') from None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1053 def _validate_singleton( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
1054 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
1055 ) -> 'ValidateReturn':
1056 if self.sub_fields: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1057 if self.discriminator_key is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1058 return self._validate_discriminated_union(v, values, loc, cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1060 errors = [] 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1062 if self.model_config.smart_union and is_union(get_origin(self.type_)): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1063 # 1st pass: check if the value is an exact instance of one of the Union types
1064 # (e.g. to avoid coercing a bool into an int)
1065 for field in self.sub_fields: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1066 if v.__class__ is field.outer_type_: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1067 return v, None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1069 # 2nd pass: check if the value is an instance of any subclass of the Union types
1070 for field in self.sub_fields: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1071 # This whole logic will be improved later on to support more complex `isinstance` checks
1072 # It will probably be done once a strict mode is added and be something like:
1073 # ```
1074 # value, error = field.validate(v, values, strict=True)
1075 # if error is None:
1076 # return value, None
1077 # ```
1078 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1079 if isinstance(v, field.outer_type_): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1080 return v, None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1081 except TypeError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1082 # compound type
1083 if lenient_isinstance(v, get_origin(field.outer_type_)): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1084 value, error = field.validate(v, values, loc=loc, cls=cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1085 if not error: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1086 return value, None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1088 # 1st pass by default or 3rd pass with `smart_union` enabled:
1089 # check if the value can be coerced into one of the Union types
1090 for field in self.sub_fields: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1091 value, error = field.validate(v, values, loc=loc, cls=cls) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1092 if error: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1093 errors.append(error) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1094 else:
1095 return value, None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1096 return v, errors 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1097 else:
1098 return self._apply_validators(v, values, loc, cls, self.validators) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1100 def _validate_discriminated_union( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
1101 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc']
1102 ) -> 'ValidateReturn':
1103 assert self.discriminator_key is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1104 assert self.discriminator_alias is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1106 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1107 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1108 discriminator_value = v[self.discriminator_alias] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1109 except KeyError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1110 if self.model_config.allow_population_by_field_name: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1111 discriminator_value = v[self.discriminator_key] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1112 else:
1113 raise 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1114 except KeyError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1115 return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1116 except TypeError: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1117 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1118 # BaseModel or dataclass
1119 discriminator_value = getattr(v, self.discriminator_key) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1120 except (AttributeError, TypeError): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1121 return v, ErrorWrapper(MissingDiscriminator(discriminator_key=self.discriminator_key), loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1123 if self.sub_fields_mapping is None: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1124 assert cls is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1125 raise ConfigError( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1126 f'field "{self.name}" not yet prepared so type is still a ForwardRef, '
1127 f'you might need to call {cls.__name__}.update_forward_refs().'
1128 )
1130 try: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1131 sub_field = self.sub_fields_mapping[discriminator_value] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1132 except (KeyError, TypeError): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1133 # KeyError: `discriminator_value` is not in the dictionary.
1134 # TypeError: `discriminator_value` is unhashable.
1135 assert self.sub_fields_mapping is not None 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1136 return v, ErrorWrapper( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1137 InvalidDiscriminator(
1138 discriminator_key=self.discriminator_key,
1139 discriminator_value=discriminator_value,
1140 allowed_values=list(self.sub_fields_mapping),
1141 ),
1142 loc,
1143 )
1144 else:
1145 if not isinstance(loc, tuple): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1146 loc = (loc,) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1147 return sub_field.validate(v, values, loc=(*loc, display_as_type(sub_field.type_)), cls=cls) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1149 def _apply_validators( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
1150 self, v: Any, values: Dict[str, Any], loc: 'LocStr', cls: Optional['ModelOrDc'], validators: 'ValidatorsList'
1151 ) -> 'ValidateReturn':
1152 for validator in validators: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1153 try: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1154 v = validator(cls, v, values, self, self.model_config) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1155 except (ValueError, TypeError, AssertionError) as exc: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1156 return v, ErrorWrapper(exc, loc) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1157 return v, None 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1159 def is_complex(self) -> bool: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1160 """
1161 Whether the field is "complex" eg. env variables should be parsed as JSON.
1162 """
1163 from pydantic.main import BaseModel 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1165 return ( 1abcdefghijklmnopqrstEFGHIuvwxyzABCD
1166 self.shape != SHAPE_SINGLETON
1167 or hasattr(self.type_, '__pydantic_model__')
1168 or lenient_issubclass(self.type_, (BaseModel, list, set, frozenset, dict))
1169 )
1171 def _type_display(self) -> PyObjectStr: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1172 t = display_as_type(self.type_) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1174 if self.shape in MAPPING_LIKE_SHAPES: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1175 t = f'Mapping[{display_as_type(self.key_field.type_)}, {t}]' # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1176 elif self.shape == SHAPE_TUPLE: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1177 t = 'Tuple[{}]'.format(', '.join(display_as_type(f.type_) for f in self.sub_fields)) # type: ignore 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1178 elif self.shape == SHAPE_GENERIC: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1179 assert self.sub_fields 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1180 t = '{}[{}]'.format( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1181 display_as_type(self.type_), ', '.join(display_as_type(f.type_) for f in self.sub_fields)
1182 )
1183 elif self.shape != SHAPE_SINGLETON: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1184 t = SHAPE_NAME_LOOKUP[self.shape].format(t) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1186 if self.allow_none and (self.shape != SHAPE_SINGLETON or not self.sub_fields): 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1187 t = f'Optional[{t}]' 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1188 return PyObjectStr(t) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1190 def __repr_args__(self) -> 'ReprArgs': 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1191 args = [('name', self.name), ('type', self._type_display()), ('required', self.required)] 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1193 if not self.required: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1194 if self.default_factory is not None: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1195 args.append(('default_factory', f'<function {self.default_factory.__name__}>')) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1196 else:
1197 args.append(('default', self.default)) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1199 if self.alt_alias: 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1200 args.append(('alias', self.alias)) 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1201 return args 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1204class ModelPrivateAttr(Representation): 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1205 __slots__ = ('default', 'default_factory') 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1207 def __init__(self, default: Any = Undefined, *, default_factory: Optional[NoArgAnyCallable] = None) -> None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1208 self.default = default 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1209 self.default_factory = default_factory 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1211 def get_default(self) -> Any: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1212 return smart_deepcopy(self.default) if self.default_factory is None else self.default_factory() 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1214 def __eq__(self, other: Any) -> bool: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1215 return isinstance(other, self.__class__) and (self.default, self.default_factory) == ( 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1216 other.default,
1217 other.default_factory,
1218 )
1221def PrivateAttr( 1abcdefghijklmnopqrstEFGHPQRSTUIuvwxyzABCD
1222 default: Any = Undefined,
1223 *,
1224 default_factory: Optional[NoArgAnyCallable] = None,
1225) -> Any:
1226 """
1227 Indicates that attribute is only used internally and never mixed with regular fields.
1229 Types or values of private attrs are not checked by pydantic and it's up to you to keep them relevant.
1231 Private attrs are stored in model __slots__.
1233 :param default: the attribute’s default value
1234 :param default_factory: callable that will be called when a default value is needed for this attribute
1235 If both `default` and `default_factory` are set, an error is raised.
1236 """
1237 if default is not Undefined and default_factory is not None: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1238 raise ValueError('cannot specify both default and default_factory') 1JKabcdefghijLMklmnopqrstEFGHINOuvwxyzABCD
1240 return ModelPrivateAttr( 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1241 default,
1242 default_factory=default_factory,
1243 )
1246class DeferredType: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1247 """
1248 Used to postpone field preparation, while creating recursive generic models.
1249 """
1252def is_finalvar_with_default_val(type_: Type[Any], val: Any) -> bool: 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD
1253 return is_finalvar(type_) and val is not Undefined and not isinstance(val, FieldInfo) 1JKabcdefghijLMklmnopqrstEFGHPQRSTUINOuvwxyzABCD