Coverage for /pythoncovmergedfiles/medio/medio/src/pydantic/pydantic/fields.py: 40%
291 statements
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-27 07:38 +0000
« prev ^ index » next coverage.py v7.2.3, created at 2023-04-27 07:38 +0000
1"""
2Defining fields on models.
3"""
4from __future__ import annotations as _annotations
6import dataclasses
7import inspect
8import sys
9import typing
10from copy import copy
11from dataclasses import Field as DataclassField
12from typing import Any
13from warnings import warn
15import annotated_types
16import typing_extensions
18from . import types
19from ._internal import _decorators, _fields, _forward_ref, _internal_dataclass, _repr, _typing_extra, _utils
20from ._internal._fields import Undefined
21from ._internal._generics import replace_types
22from .errors import PydanticUserError
24if typing.TYPE_CHECKING:
25 from pydantic_core import core_schema as _core_schema
27 from ._internal._repr import ReprArgs
30class FieldInfo(_repr.Representation):
31 """
32 Hold information about a field.
34 FieldInfo is used for any field definition whether or not the `Field()` function is explicitly used.
36 Attributes:
37 annotation (type): The type annotation of the field.
38 default (Any): The default value of the field.
39 default_factory (callable): The factory function used to construct the default value of the field.
40 alias (str): The alias name of the field.
41 alias_priority (int): The priority of the field's alias.
42 validation_alias (str): The validation alias name of the field.
43 serialization_alias (str): The serialization alias name of the field.
44 title (str): The title of the field.
45 description (str): The description of the field.
46 examples (List[str]): List of examples of the field.
47 exclude (bool): Whether or not to exclude the field from the model schema.
48 include (bool): Whether or not to include the field in the model schema.
49 metadata (Dict[str, Any]): Dictionary of metadata constraints.
50 repr (bool): Whether or not to include the field in representation of the model.
51 discriminator (bool): Whether or not to include the field in the "discriminator" schema property of the model.
52 json_schema_extra (Dict[str, Any]): Dictionary of extra JSON schema properties.
53 init_var (bool): Whether or not the field should be included in the constructor of the model.
54 kw_only (bool): Whether or not the field should be a keyword-only argument in the constructor of the model.
55 validate_default (bool): Whether or not to validate the default value of the field.
56 frozen (bool): Whether or not the field is frozen.
57 final (bool): Whether or not the field is final.
58 """
60 # TODO: Need to add attribute annotations
62 __slots__ = (
63 'annotation',
64 'default',
65 'default_factory',
66 'alias',
67 'alias_priority',
68 'validation_alias',
69 'serialization_alias',
70 'title',
71 'description',
72 'examples',
73 'exclude',
74 'include',
75 'metadata',
76 'repr',
77 'discriminator',
78 'json_schema_extra',
79 'init_var',
80 'kw_only',
81 'validate_default',
82 'frozen',
83 'final',
84 )
86 # used to convert kwargs to metadata/constraints,
87 # None has a special meaning - these items are collected into a `PydanticGeneralMetadata`
88 metadata_lookup: dict[str, typing.Callable[[Any], Any] | None] = {
89 'gt': annotated_types.Gt,
90 'ge': annotated_types.Ge,
91 'lt': annotated_types.Lt,
92 'le': annotated_types.Le,
93 'multiple_of': annotated_types.MultipleOf,
94 'strict': types.Strict,
95 'min_length': annotated_types.MinLen,
96 'max_length': annotated_types.MaxLen,
97 'pattern': None,
98 'allow_inf_nan': None,
99 'max_digits': None,
100 'decimal_places': None,
101 }
103 def __init__(self, **kwargs: Any) -> None:
104 # TODO: This is a good place to add migration warnings; we should use overload for type-hinting the signature
105 self.annotation, annotation_metadata = self._extract_metadata(kwargs.get('annotation'))
107 default = kwargs.pop('default', Undefined)
108 if default is Ellipsis:
109 self.default = Undefined
110 else:
111 self.default = default
113 self.default_factory = kwargs.get('default_factory')
115 if self.default is not Undefined and self.default_factory is not None:
116 raise TypeError('cannot specify both default and default_factory')
118 self.alias = kwargs.get('alias')
119 self.alias_priority = kwargs.get('alias_priority') or 2 if self.alias is not None else None
120 self.title = kwargs.get('title')
121 self.validation_alias = kwargs.get('validation_alias', None)
122 self.serialization_alias = kwargs.get('serialization_alias', None)
123 self.description = kwargs.get('description')
124 self.examples = kwargs.get('examples')
125 self.exclude = kwargs.get('exclude')
126 self.include = kwargs.get('include')
127 self.metadata = self._collect_metadata(kwargs) + annotation_metadata
128 self.discriminator = kwargs.get('discriminator')
129 self.repr = kwargs.get('repr', True)
130 self.json_schema_extra = kwargs.get('json_schema_extra')
131 self.validate_default = kwargs.get('validate_default', None)
132 self.frozen = kwargs.get('frozen', None)
133 self.final = kwargs.get('final', None)
134 # currently only used on dataclasses
135 self.init_var = kwargs.get('init_var', None)
136 self.kw_only = kwargs.get('kw_only', None)
138 @classmethod
139 def from_field(cls, default: Any = Undefined, **kwargs: Any) -> FieldInfo:
140 """
141 Create a new `FieldInfo` object with the `Field` function.
143 Args:
144 default (Any): The default value for the field. Defaults to Undefined.
145 **kwargs: Additional arguments dictionary.
147 Raises:
148 TypeError: If 'annotation' is passed as a keyword argument.
150 Returns:
151 FieldInfo: A new FieldInfo object with the given parameters.
153 Examples:
154 This is how you can create a field with default value like this:
156 ```python
157 import pydantic
159 class MyModel(pydantic.BaseModel):
160 foo: int = pydantic.Field(4, ...)
161 ```
162 """
163 # TODO: This is a good place to add migration warnings; should we use overload for type-hinting the signature?
164 if 'annotation' in kwargs:
165 raise TypeError('"annotation" is not permitted as a Field keyword argument')
166 return cls(default=default, **kwargs)
168 @classmethod
169 def from_annotation(cls, annotation: type[Any] | _forward_ref.PydanticForwardRef) -> FieldInfo:
170 """
171 Creates a `FieldInfo` instance from a bare annotation.
173 Args:
174 annotation (Union[type[Any], _forward_ref.PydanticForwardRef]): An annotation object.
176 Returns:
177 FieldInfo: An instance of the field metadata.
179 Examples:
180 This is how you can create a field from a bare annotation like this:
182 ```python
183 import pydantic
184 class MyModel(pydantic.BaseModel):
185 foo: int # <-- like this
186 ```
188 We also account for the case where the annotation can be an instance of `Annotated` and where
189 one of the (not first) arguments in `Annotated` are an instance of `FieldInfo`, e.g.:
191 ```python
192 import pydantic, annotated_types, typing
194 class MyModel(pydantic.BaseModel):
195 foo: typing.Annotated[int, annotated_types.Gt(42)]
196 bar: typing.Annotated[int, Field(gt=42)]
197 ```
199 """
200 final = False
201 if _typing_extra.is_finalvar(annotation):
202 final = True
203 if annotation is not typing_extensions.Final:
204 annotation = typing_extensions.get_args(annotation)[0]
206 if _typing_extra.is_annotated(annotation):
207 first_arg, *extra_args = typing_extensions.get_args(annotation)
208 if _typing_extra.is_finalvar(first_arg):
209 final = True
210 field_info = cls._find_field_info_arg(extra_args)
211 if field_info:
212 new_field_info = copy(field_info)
213 new_field_info.annotation = first_arg
214 new_field_info.final = final
215 new_field_info.metadata += [a for a in extra_args if not isinstance(a, FieldInfo)]
216 return new_field_info
218 return cls(annotation=annotation, final=final)
220 @classmethod
221 def from_annotated_attribute(cls, annotation: type[Any], default: Any) -> FieldInfo:
222 """
223 Create `FieldInfo` from an annotation with a default value.
225 Args:
226 annotation (type[Any]): The type annotation of the field.
227 default (Any): The default value of the field.
229 Returns:
230 FieldInfo: A field object with the passed values.
232 Examples:
233 ```python
234 import pydantic, annotated_types, typing
236 class MyModel(pydantic.BaseModel):
237 foo: int = 4 # <-- like this
238 bar: typing.Annotated[int, annotated_types.Gt(4)] = 4 # <-- or this
239 spam: typing.Annotated[int, pydantic.Field(gt=4)] = 4 # <-- or this
240 ```
241 """
242 final = False
243 if _typing_extra.is_finalvar(annotation):
244 final = True
245 if annotation is not typing_extensions.Final:
246 annotation = typing_extensions.get_args(annotation)[0]
248 if isinstance(default, cls):
249 default.annotation, annotation_metadata = cls._extract_metadata(annotation)
250 default.metadata += annotation_metadata
251 default.final = final
252 return default
253 elif isinstance(default, dataclasses.Field):
254 init_var = False
255 if annotation is dataclasses.InitVar:
256 if sys.version_info < (3, 8):
257 raise RuntimeError('InitVar is not supported in Python 3.7 as type information is lost')
259 init_var = True
260 annotation = Any
261 elif isinstance(annotation, dataclasses.InitVar):
262 init_var = True
263 annotation = annotation.type
264 pydantic_field = cls._from_dataclass_field(default)
265 pydantic_field.annotation, annotation_metadata = cls._extract_metadata(annotation)
266 pydantic_field.metadata += annotation_metadata
267 pydantic_field.final = final
268 pydantic_field.init_var = init_var
269 pydantic_field.kw_only = getattr(default, 'kw_only', None)
270 return pydantic_field
271 else:
272 if _typing_extra.is_annotated(annotation):
273 first_arg, *extra_args = typing_extensions.get_args(annotation)
274 field_info = cls._find_field_info_arg(extra_args)
275 if field_info is not None:
276 if not field_info.is_required():
277 raise TypeError('Default may not be specified twice on the same field')
278 new_field_info = copy(field_info)
279 new_field_info.default = default
280 new_field_info.annotation = first_arg
281 new_field_info.metadata += [a for a in extra_args if not isinstance(a, FieldInfo)]
282 return new_field_info
284 return cls(annotation=annotation, default=default, final=final)
286 @classmethod
287 def _from_dataclass_field(cls, dc_field: DataclassField[Any]) -> FieldInfo:
288 """
289 Return a new `FieldInfo` instance from a `dataclasses.Field` instance.
291 Args:
292 dc_field (dataclasses.Field): The `dataclasses.Field` instance to convert.
294 Returns:
295 FieldInfo: The corresponding `FieldInfo` instance.
297 Raises:
298 TypeError: If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs.
299 """
300 default = dc_field.default
301 if default is dataclasses.MISSING:
302 default = Undefined
304 if dc_field.default_factory is dataclasses.MISSING:
305 default_factory: typing.Callable[[], Any] | None = None
306 else:
307 default_factory = dc_field.default_factory
309 # use the `Field` function so in correct kwargs raise the correct `TypeError`
310 field = Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field.metadata)
312 field.annotation, annotation_metadata = cls._extract_metadata(dc_field.type)
313 field.metadata += annotation_metadata
314 return field
316 @classmethod
317 def _extract_metadata(cls, annotation: type[Any] | None) -> tuple[type[Any] | None, list[Any]]:
318 """Tries to extract metadata/constraints from an annotation if it uses `Annotated`.
320 Args:
321 annotation (type[Any] | None): The type hint annotation for which metadata has to be extracted.
323 Returns:
324 tuple[type[Any] | None, list[Any]]: A tuple containing the extracted metadata type and the list
325 of extra arguments.
327 Raises:
328 TypeError: If a `Field` is used twice on the same field.
329 """
330 if annotation is not None:
331 if _typing_extra.is_annotated(annotation):
332 first_arg, *extra_args = typing_extensions.get_args(annotation)
333 if cls._find_field_info_arg(extra_args):
334 raise TypeError('Field may not be used twice on the same field')
335 return first_arg, list(extra_args)
337 return annotation, []
339 @staticmethod
340 def _find_field_info_arg(args: Any) -> FieldInfo | None:
341 """
342 Find an instance of `FieldInfo` in the provided arguments.
344 Args:
345 args (Any): The argument list to search for `FieldInfo`.
347 Returns:
348 FieldInfo | None: An instance of `FieldInfo` if found, otherwise `None`.
349 """
350 return next((a for a in args if isinstance(a, FieldInfo)), None)
352 @classmethod
353 def _collect_metadata(cls, kwargs: dict[str, Any]) -> list[Any]:
354 """
355 Collect annotations from kwargs.
357 The return type is actually `annotated_types.BaseMetadata | PydanticMetadata`,
358 but it gets combined with `list[Any]` from `Annotated[T, ...]`, hence types.
360 Args:
361 kwargs (dict[str, Any]): Keyword arguments passed to the function.
363 Returns:
364 list[Any]: A list of metadata objects - a combination of `annotated_types.BaseMetadata` and
365 `PydanticMetadata`.
366 """
367 metadata: list[Any] = []
368 general_metadata = {}
369 for key, value in list(kwargs.items()):
370 try:
371 marker = cls.metadata_lookup[key]
372 except KeyError:
373 continue
375 del kwargs[key]
376 if value is not None:
377 if marker is None:
378 general_metadata[key] = value
379 else:
380 metadata.append(marker(value))
381 if general_metadata:
382 metadata.append(_fields.PydanticGeneralMetadata(**general_metadata))
383 return metadata
385 def get_default(self, *, call_default_factory: bool = False) -> Any:
386 """
387 Get the default value.
389 We expose an option for whether to call the default_factory (if present), as calling it may
390 result in side effects that we want to avoid. However, there are times when it really should
391 be called (namely, when instantiating a model via `model_construct`).
393 Args:
394 call_default_factory (bool, optional): Whether to call the default_factory or not. Defaults to False.
396 Returns:
397 Any: The default value, calling the default factory if requested or `None` if not set.
398 """
399 if self.default_factory is None:
400 return _utils.smart_deepcopy(self.default)
401 elif call_default_factory:
402 return self.default_factory()
403 else:
404 return None
406 def is_required(self) -> bool:
407 """Check if the argument is required.
409 Returns:
410 bool: `True` if the argument is required, `False` otherwise.
411 """
412 return self.default is Undefined and self.default_factory is None
414 def rebuild_annotation(self) -> Any:
415 """
416 Rebuild the original annotation for use in signatures.
417 """
418 if not self.metadata:
419 return self.annotation
420 else:
421 return typing_extensions._AnnotatedAlias(self.annotation, self.metadata)
423 def apply_typevars_map(self, typevars_map: dict[Any, Any] | None, types_namespace: dict[str, Any] | None) -> None:
424 """
425 Apply a typevars_map to the annotation.
427 This is used when analyzing parametrized generic types to replace typevars with their concrete types.
429 See pydantic._internal._generics.replace_types for more details.
430 """
431 annotation = _typing_extra.eval_type_lenient(self.annotation, types_namespace, None)
432 self.annotation = replace_types(annotation, typevars_map)
434 def __repr_args__(self) -> ReprArgs:
435 yield 'annotation', _repr.PlainRepr(_repr.display_as_type(self.annotation))
436 yield 'required', self.is_required()
438 for s in self.__slots__:
439 if s == 'annotation':
440 continue
441 elif s == 'metadata' and not self.metadata:
442 continue
443 elif s == 'repr' and self.repr is True:
444 continue
445 elif s == 'final':
446 continue
447 if s == 'frozen' and self.frozen is False:
448 continue
449 if s == 'validation_alias' and self.validation_alias == self.alias:
450 continue
451 if s == 'serialization_alias' and self.serialization_alias == self.alias:
452 continue
453 if s == 'default_factory' and self.default_factory is not None:
454 yield 'default_factory', _repr.PlainRepr(_repr.display_as_type(self.default_factory))
455 else:
456 value = getattr(self, s)
457 if value is not None and value is not Undefined:
458 yield s, value
461@_internal_dataclass.slots_dataclass
462class AliasPath:
463 path: list[int | str]
465 def __init__(self, first_arg: str, *args: str | int) -> None:
466 self.path = [first_arg] + list(args)
468 def convert_to_aliases(self) -> list[str | int]:
469 return self.path
472@_internal_dataclass.slots_dataclass
473class AliasChoices:
474 choices: list[str | AliasPath]
476 def __init__(self, *args: str | AliasPath) -> None:
477 self.choices = list(args)
479 def convert_to_aliases(self) -> list[list[str | int]]:
480 aliases: list[list[str | int]] = []
481 for c in self.choices:
482 if isinstance(c, AliasPath):
483 aliases.append(c.convert_to_aliases())
484 else:
485 aliases.append([c])
486 return aliases
489def Field( # noqa C901
490 default: Any = Undefined,
491 *,
492 default_factory: typing.Callable[[], Any] | None = None,
493 alias: str | None = None,
494 alias_priority: int | None = None,
495 validation_alias: str | AliasPath | AliasChoices | None = None,
496 serialization_alias: str | None = None,
497 title: str | None = None,
498 description: str | None = None,
499 examples: list[Any] | None = None,
500 exclude: typing.AbstractSet[int | str] | typing.Mapping[int | str, Any] | Any = None,
501 include: typing.AbstractSet[int | str] | typing.Mapping[int | str, Any] | Any = None,
502 gt: float | None = None,
503 ge: float | None = None,
504 lt: float | None = None,
505 le: float | None = None,
506 multiple_of: float | None = None,
507 allow_inf_nan: bool | None = None,
508 max_digits: int | None = None,
509 decimal_places: int | None = None,
510 min_items: int | None = None,
511 max_items: int | None = None,
512 min_length: int | None = None,
513 max_length: int | None = None,
514 frozen: bool = False,
515 pattern: str | None = None,
516 discriminator: str | None = None,
517 repr: bool = True,
518 strict: bool | None = None,
519 json_schema_extra: dict[str, Any] | None = None,
520 validate_default: bool | None = None,
521 const: bool | None = None,
522 unique_items: bool | None = None,
523 allow_mutation: bool = True,
524 regex: str | None = None,
525 **extra: Any,
526) -> Any:
527 """
528 Create a field for objects that can be configured.
530 Used to provide extra information about a field, either for the model schema or complex validation. Some arguments
531 apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`.
533 Args:
534 default (Any, optional): default value if the field is not set.
535 default_factory (callable, optional): A callable to generate the default value like :func:`~datetime.utcnow`.
536 alias (str, optional): an alternative name for the attribute.
537 alias_priority (int, optional): priority of the alias. This defines which alias should be used in serialization.
538 validation_alias (str, list of str, list of list of str, optional): 'whitelist' validation step. The field
539 will be the single one allowed by the alias or set of aliases defined.
540 serialization_alias (str, optional): 'blacklist' validation step. The vanilla field will be the single one of
541 the alias' or set of aliases' fields and all the other fields will be ignored at serialization time.
542 title (str, optional): human-readable title.
543 description (str, optional): human-readable description.
544 examples (list[Any], optional): An example value for this field.
545 exclude (Union[AbstractSet[Union[str, int]], Mapping[Union[str, int], Any], Any]):
546 Parameters that should be excluded from the field. If `None`, default
547 Pydantic behaviors are used.
548 include (Union[AbstractSet[Union[str, int]], Mapping[Union[str, int], Any], Any]):
549 Parameters that should be included in the field. If `None`, default
550 Pydantic behaviors are used.
551 gt (float, optional): Greater than. If set, value must be greater than this. Only applicable to numbers.
552 ge (float, optional): Greater than or equal. If set, value must be
553 greater than or equal to this. Only applicable to numbers.
554 lt (float, optional): Less than. If set, value must be
555 less than this. Only applicable to numbers.
556 le (float, optional): Less than or equal. If set, value must be
557 less than or equal to this. Only applicable to numbers.
558 multiple_of (float, optional): Value must be a multiple of this. Only applicable to numbers.
559 allow_inf_nan (bool, optional): Allow `inf`, `-inf`, `nan`. Only applicable to numbers.
560 max_digits (int, optional): Maximum number of allow digits for strings.
561 decimal_places (int, optional): Maximum number decimal places allowed for numbers.
562 min_items (int, optional): Minimum number of items in a collection.
563 max_items (int, optional): Maximum number of items in a collection.
564 min_length (int, optional): Minimum length for strings.
565 max_length (int, optional): Maximum length for strings.
566 frozen (bool, optional): Store the value as a frozen object if is mutable.
567 pattern (str, optional): Pattern for strings.
568 discriminator (str, optional): Codename for discriminating a field among others of the same type.
569 repr (bool, optional): If `True` (the default), return a string representation of the field.
570 strict (bool, optional): If `True` (the default is `None`), the field should be validated strictly.
571 json_schema_extra (dict[str, Any]): Any other additional JSON schema data for the schema property.
572 validate_default (bool, optional): Run validation that isn't only checking existence of defaults. This is
573 `True` by default.
574 const (bool, optional): Value is always the same literal object. This is typically a singleton object,
575 such as `True` or `None`.
576 unique_items (bool, optional): Require that collection items be unique.
577 allow_mutation (bool, optional): If `False`, the dataclass will be frozen (made immutable).
578 regex (str, optional): Regular expression pattern that the field must match against.
581 Returns:
582 Any: return the generated field object.
583 """
584 # Check deprecated & removed params of V1.
585 # This has to be removed deprecation period over.
586 if const:
587 raise PydanticUserError('`const` is removed. use `Literal` instead', code='deprecated_kwargs')
588 if min_items:
589 warn('`min_items` is deprecated and will be removed. use `min_length` instead', DeprecationWarning)
590 if min_length is None:
591 min_length = min_items
592 if max_items:
593 warn('`max_items` is deprecated and will be removed. use `max_length` instead', DeprecationWarning)
594 if max_length is None:
595 max_length = max_items
596 if unique_items:
597 raise PydanticUserError(
598 (
599 '`unique_items` is removed, use `Set` instead'
600 '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)'
601 ),
602 code='deprecated_kwargs',
603 )
604 if allow_mutation is False:
605 warn('`allow_mutation` is deprecated and will be removed. use `frozen` instead', DeprecationWarning)
606 frozen = True
607 if regex:
608 raise PydanticUserError('`regex` is removed. use `Pattern` instead', code='deprecated_kwargs')
609 if extra:
610 warn(
611 'Extra keyword arguments on `Field` is deprecated and will be removed. use `json_schema_extra` instead',
612 DeprecationWarning,
613 )
614 if not json_schema_extra:
615 json_schema_extra = extra
617 converted_validation_alias: str | list[str | int] | list[list[str | int]] | None = None
618 if validation_alias:
619 if not isinstance(validation_alias, (str, AliasChoices, AliasPath)):
620 raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`')
622 if isinstance(validation_alias, (AliasChoices, AliasPath)):
623 converted_validation_alias = validation_alias.convert_to_aliases()
624 else:
625 converted_validation_alias = validation_alias
627 if serialization_alias is None and isinstance(alias, str):
628 serialization_alias = alias
630 return FieldInfo.from_field(
631 default,
632 default_factory=default_factory,
633 alias=alias,
634 alias_priority=alias_priority,
635 validation_alias=converted_validation_alias or alias,
636 serialization_alias=serialization_alias,
637 title=title,
638 description=description,
639 examples=examples,
640 exclude=exclude,
641 include=include,
642 gt=gt,
643 ge=ge,
644 lt=lt,
645 le=le,
646 multiple_of=multiple_of,
647 allow_inf_nan=allow_inf_nan,
648 max_digits=max_digits,
649 decimal_places=decimal_places,
650 min_items=min_items,
651 max_items=max_items,
652 min_length=min_length,
653 max_length=max_length,
654 frozen=frozen,
655 pattern=pattern,
656 discriminator=discriminator,
657 repr=repr,
658 json_schema_extra=json_schema_extra,
659 strict=strict,
660 validate_default=validate_default,
661 )
664class ModelPrivateAttr(_repr.Representation):
665 """A descriptor for private attributes in class models.
667 Attributes:
668 default (Any): The default value of the attribute if not provided.
669 default_factory (typing.Callable[[], Any]): A callable function that generates the default value of the
670 attribute if not provided.
671 """
673 __slots__ = 'default', 'default_factory'
675 def __init__(self, default: Any = Undefined, *, default_factory: typing.Callable[[], Any] | None = None) -> None:
676 self.default = default
677 self.default_factory = default_factory
679 def __set_name__(self, cls: type[Any], name: str) -> None:
680 """
681 preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487
682 """
683 if self.default is not Undefined:
684 try:
685 set_name = getattr(self.default, '__set_name__')
686 except AttributeError:
687 pass
688 else:
689 if callable(set_name):
690 set_name(cls, name)
692 def get_default(self) -> Any:
693 """Returns the default value for the object.
695 If `self.default_factory` is `None`, the method will return a deep copy of the `self.default` object.
696 If `self.default_factory` is not `None`, it will call `self.default_factory` and return the value returned.
698 Returns:
699 Any: The default value of the object.
700 """
701 return _utils.smart_deepcopy(self.default) if self.default_factory is None else self.default_factory()
703 def __eq__(self, other: Any) -> bool:
704 return isinstance(other, self.__class__) and (self.default, self.default_factory) == (
705 other.default,
706 other.default_factory,
707 )
710def PrivateAttr(
711 default: Any = Undefined,
712 *,
713 default_factory: typing.Callable[[], Any] | None = None,
714) -> Any:
715 """
716 Indicates that attribute is only used internally and never mixed with regular fields.
718 Private attributes are not checked by Pydantic, so it's up to you to maintain their accuracy.
720 Private attributes are stored in the model `__slots__`.
722 Args:
723 default (Any): The attribute's default value. Defaults to Undefined.
724 default_factory (typing.Callable[[], Any], optional): Callable that will be
725 called when a default value is needed for this attribute.
726 If both `default` and `default_factory` are set, an error will be raised.
728 Returns:
729 Any: An instance of `ModelPrivateAttr` class.
731 Raises:
732 ValueError: If both `default` and `default_factory` are set.
733 """
734 if default is not Undefined and default_factory is not None:
735 raise TypeError('cannot specify both default and default_factory')
737 return ModelPrivateAttr(
738 default,
739 default_factory=default_factory,
740 )
743@_internal_dataclass.slots_dataclass
744class ComputedFieldInfo:
745 """
746 A container for data from `@computed_field` so that we can access it
747 while building the pydantic-core schema.
748 """
750 decorator_repr: typing.ClassVar[str] = '@computed_field'
751 wrapped_property: property
752 json_return_type: _core_schema.JsonReturnTypes | None
753 alias: str | None
754 title: str | None
755 description: str | None
756 repr: bool
759# this should really be `property[T], cached_proprety[T]` but property is not generic unlike cached_property
760# See https://github.com/python/typing/issues/985 and linked issues
761PropertyT = typing.TypeVar('PropertyT')
764@typing.overload
765def computed_field(
766 *,
767 json_return_type: _core_schema.JsonReturnTypes | None = None,
768 alias: str | None = None,
769 title: str | None = None,
770 description: str | None = None,
771 repr: bool = True,
772) -> typing.Callable[[PropertyT], PropertyT]:
773 ...
776@typing.overload
777def computed_field(__func: PropertyT) -> PropertyT:
778 ...
781def computed_field(
782 __f: PropertyT | None = None,
783 *,
784 alias: str | None = None,
785 title: str | None = None,
786 description: str | None = None,
787 repr: bool = True,
788 json_return_type: _core_schema.JsonReturnTypes | None = None,
789) -> PropertyT | typing.Callable[[PropertyT], PropertyT]:
790 """
791 Decorate to include `property` and `cached_property` when serialising models.
793 If applied to functions not yet decorated with `@property` or `@cached_property`, the function is
794 automatically wrapped with `property`.
796 Args:
797 __f: the function to wrap.
798 alias: alias to use when serializing this computed field, only used when `by_alias=True`
799 title: Title to used when including this computed field in JSON Schema, currently unused waiting for #4697
800 description: Description to used when including this computed field in JSON Schema, defaults to the functions
801 docstring, currently unused waiting for #4697
802 repr: whether to include this computed field in model repr
803 json_return_type: optional return for serialization logic to expect when serialising to JSON, if included
804 this must be correct, otherwise a `TypeError` is raised
806 Returns:
807 A proxy wrapper for the property.
808 """
810 def dec(f: Any) -> Any:
811 nonlocal description
812 if description is None and f.__doc__:
813 description = inspect.cleandoc(f.__doc__)
815 # if the function isn't already decorated with `@property` (or another descriptor), then we wrap it now
816 f = _decorators.ensure_property(f)
817 dec_info = ComputedFieldInfo(f, json_return_type, alias, title, description, repr)
818 return _decorators.PydanticDescriptorProxy(f, dec_info)
820 if __f is None:
821 return dec
822 else:
823 return dec(__f)