Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pydantic/fields.py: 61%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Defining fields on models."""
3from __future__ import annotations as _annotations
5import dataclasses
6import inspect
7import re
8import sys
9from collections.abc import Callable, Mapping
10from copy import copy
11from dataclasses import Field as DataclassField
12from functools import cached_property
13from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Literal, TypeVar, cast, final, overload
14from warnings import warn
16import annotated_types
17import typing_extensions
18from pydantic_core import MISSING, PydanticUndefined
19from typing_extensions import Self, TypeAlias, TypedDict, Unpack, deprecated
20from typing_inspection import typing_objects
21from typing_inspection.introspection import UNKNOWN, AnnotationSource, ForbiddenQualifier, Qualifier, inspect_annotation
23from . import types
24from ._internal import _decorators, _fields, _generics, _internal_dataclass, _repr, _typing_extra, _utils
25from ._internal._namespace_utils import GlobalsNamespace, MappingNamespace
26from .aliases import AliasChoices, AliasGenerator, AliasPath
27from .config import JsonDict
28from .errors import PydanticForbiddenQualifier, PydanticUserError
29from .json_schema import PydanticJsonSchemaWarning
30from .warnings import PydanticDeprecatedSince20
32if TYPE_CHECKING:
33 from ._internal._config import ConfigWrapper
34 from ._internal._repr import ReprArgs
37__all__ = 'Field', 'FieldInfo', 'PrivateAttr', 'computed_field'
40_Unset: Any = PydanticUndefined
42if sys.version_info >= (3, 13):
43 import warnings
45 Deprecated: TypeAlias = warnings.deprecated | deprecated
46else:
47 Deprecated: TypeAlias = deprecated
50class _FromFieldInfoInputs(TypedDict, total=False):
51 """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.from_field`."""
53 # TODO PEP 747: use TypeForm:
54 annotation: type[Any] | None
55 default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None
56 alias: str | None
57 alias_priority: int | None
58 validation_alias: str | AliasPath | AliasChoices | None
59 serialization_alias: str | None
60 title: str | None
61 field_title_generator: Callable[[str, FieldInfo], str] | None
62 description: str | None
63 examples: list[Any] | None
64 exclude: bool | None
65 exclude_if: Callable[[Any], bool] | None
66 gt: annotated_types.SupportsGt | None
67 ge: annotated_types.SupportsGe | None
68 lt: annotated_types.SupportsLt | None
69 le: annotated_types.SupportsLe | None
70 multiple_of: float | None
71 strict: bool | None
72 min_length: int | None
73 max_length: int | None
74 pattern: str | re.Pattern[str] | None
75 allow_inf_nan: bool | None
76 max_digits: int | None
77 decimal_places: int | None
78 union_mode: Literal['smart', 'left_to_right'] | None
79 discriminator: str | types.Discriminator | None
80 deprecated: Deprecated | str | bool | None
81 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
82 frozen: bool | None
83 validate_default: bool | None
84 repr: bool
85 init: bool | None
86 init_var: bool | None
87 kw_only: bool | None
88 coerce_numbers_to_str: bool | None
89 fail_fast: bool | None
92class _FieldInfoInputs(_FromFieldInfoInputs, total=False):
93 """This class exists solely to add type checking for the `**kwargs` in `FieldInfo.__init__`."""
95 default: Any
98class _FieldInfoAsDict(TypedDict, closed=True):
99 # TODO PEP 747: use TypeForm:
100 annotation: Any
101 metadata: list[Any]
102 attributes: dict[str, Any]
105@final
106class FieldInfo(_repr.Representation):
107 """This class holds information about a field.
109 `FieldInfo` is used for any field definition regardless of whether the [`Field()`][pydantic.fields.Field]
110 function is explicitly used.
112 !!! warning
113 The `FieldInfo` class is meant to expose information about a field in a Pydantic model or dataclass.
114 `FieldInfo` instances shouldn't be instantiated directly, nor mutated.
116 If you need to derive a new model from another one and are willing to alter `FieldInfo` instances,
117 refer to this [dynamic model example](../examples/dynamic_models.md).
119 Attributes:
120 annotation: The type annotation of the field.
121 default: The default value of the field.
122 default_factory: A callable to generate the default value. The callable can either take 0 arguments
123 (in which case it is called as is) or a single argument containing the already validated data.
124 alias: The alias name of the field.
125 alias_priority: The priority of the field's alias.
126 validation_alias: The validation alias of the field.
127 serialization_alias: The serialization alias of the field.
128 title: The title of the field.
129 field_title_generator: A callable that takes a field name and returns title for it.
130 description: The description of the field.
131 examples: List of examples of the field.
132 exclude: Whether to exclude the field from the model serialization.
133 exclude_if: A callable that determines whether to exclude a field during serialization based on its value.
134 discriminator: Field name or Discriminator for discriminating the type in a tagged union.
135 deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
136 or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
137 json_schema_extra: A dict or callable to provide extra JSON schema properties.
138 frozen: Whether the field is frozen.
139 validate_default: Whether to validate the default value of the field.
140 repr: Whether to include the field in representation of the model.
141 init: Whether the field should be included in the constructor of the dataclass.
142 init_var: Whether the field should _only_ be included in the constructor of the dataclass, and not stored.
143 kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass.
144 metadata: The metadata list. Contains all the data that isn't expressed as direct `FieldInfo` attributes, including:
146 * Type-specific constraints, such as `gt` or `min_length` (these are converted to metadata classes such as `annotated_types.Gt`).
147 * Any other arbitrary object used within [`Annotated`][typing.Annotated] metadata
148 (e.g. [custom types handlers](../concepts/types.md#as-an-annotation) or any object not recognized by Pydantic).
149 """
151 # TODO PEP 747: use TypeForm:
152 annotation: type[Any] | None
153 default: Any
154 default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None
155 alias: str | None
156 alias_priority: int | None
157 validation_alias: str | AliasPath | AliasChoices | None
158 serialization_alias: str | None
159 title: str | None
160 field_title_generator: Callable[[str, FieldInfo], str] | None
161 description: str | None
162 examples: list[Any] | None
163 exclude: bool | None
164 exclude_if: Callable[[Any], bool] | None
165 discriminator: str | types.Discriminator | None
166 deprecated: Deprecated | str | bool | None
167 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
168 frozen: bool | None
169 validate_default: bool | None
170 repr: bool
171 init: bool | None
172 init_var: bool | None
173 kw_only: bool | None
174 metadata: list[Any]
176 __slots__ = (
177 'annotation',
178 'default',
179 'default_factory',
180 'alias',
181 'alias_priority',
182 'validation_alias',
183 'serialization_alias',
184 'title',
185 'field_title_generator',
186 'description',
187 'examples',
188 'exclude',
189 'exclude_if',
190 'discriminator',
191 'deprecated',
192 'json_schema_extra',
193 'frozen',
194 'validate_default',
195 'repr',
196 'init',
197 'init_var',
198 'kw_only',
199 'metadata',
200 '_attributes_set',
201 '_qualifiers',
202 '_complete',
203 '_original_assignment',
204 '_original_annotation',
205 '_final',
206 )
208 # used to convert kwargs to metadata/constraints,
209 # None has a special meaning - these items are collected into a `PydanticGeneralMetadata`
210 metadata_lookup: ClassVar[dict[str, Callable[[Any], Any] | None]] = {
211 'strict': types.Strict,
212 'gt': annotated_types.Gt,
213 'ge': annotated_types.Ge,
214 'lt': annotated_types.Lt,
215 'le': annotated_types.Le,
216 'multiple_of': annotated_types.MultipleOf,
217 'min_length': annotated_types.MinLen,
218 'max_length': annotated_types.MaxLen,
219 'pattern': None,
220 'allow_inf_nan': None,
221 'max_digits': None,
222 'decimal_places': None,
223 'union_mode': None,
224 'coerce_numbers_to_str': None,
225 'fail_fast': types.FailFast,
226 }
228 def __init__(self, **kwargs: Unpack[_FieldInfoInputs]) -> None:
229 """This class should generally not be initialized directly; instead, use the `pydantic.fields.Field` function
230 or one of the constructor classmethods.
232 See the signature of `pydantic.fields.Field` for more details about the expected arguments.
233 """
234 # Tracking the explicitly set attributes is necessary to correctly merge `Field()` functions
235 # (e.g. with `Annotated[int, Field(alias='a'), Field(alias=None)]`, even though `None` is the default value,
236 # we need to track that `alias=None` was explicitly set):
237 self._attributes_set = {k: v for k, v in kwargs.items() if v is not _Unset and k not in self.metadata_lookup}
238 kwargs = {k: _DefaultValues.get(k) if v is _Unset else v for k, v in kwargs.items()} # type: ignore
239 self.annotation = kwargs.get('annotation')
241 # Note: in theory, the second `pop()` arguments are not required below, as defaults are already set from `_DefaultsValues`.
242 default = kwargs.pop('default', PydanticUndefined)
243 if default is Ellipsis:
244 self.default = PydanticUndefined
245 self._attributes_set.pop('default', None)
246 else:
247 self.default = default
249 self.default_factory = kwargs.pop('default_factory', None)
251 if self.default is not PydanticUndefined and self.default_factory is not None:
252 raise TypeError('cannot specify both default and default_factory')
254 self.alias = kwargs.pop('alias', None)
255 self.validation_alias = kwargs.pop('validation_alias', None)
256 self.serialization_alias = kwargs.pop('serialization_alias', None)
257 alias_is_set = any(alias is not None for alias in (self.alias, self.validation_alias, self.serialization_alias))
258 self.alias_priority = kwargs.pop('alias_priority', None) or 2 if alias_is_set else None
259 self.title = kwargs.pop('title', None)
260 self.field_title_generator = kwargs.pop('field_title_generator', None)
261 self.description = kwargs.pop('description', None)
262 self.examples = kwargs.pop('examples', None)
263 self.exclude = kwargs.pop('exclude', None)
264 self.exclude_if = kwargs.pop('exclude_if', None)
265 self.discriminator = kwargs.pop('discriminator', None)
266 # For compatibility with FastAPI<=0.110.0, we preserve the existing value if it is not overridden
267 self.deprecated = kwargs.pop('deprecated', getattr(self, 'deprecated', None))
268 self.repr = kwargs.pop('repr', True)
269 self.json_schema_extra = kwargs.pop('json_schema_extra', None)
270 self.validate_default = kwargs.pop('validate_default', None)
271 self.frozen = kwargs.pop('frozen', None)
272 # currently only used on dataclasses
273 self.init = kwargs.pop('init', None)
274 self.init_var = kwargs.pop('init_var', None)
275 self.kw_only = kwargs.pop('kw_only', None)
277 self.metadata = self._collect_metadata(kwargs) # type: ignore
279 # Private attributes:
280 self._qualifiers: set[Qualifier] = set()
281 # Used to rebuild FieldInfo instances:
282 self._complete = True
283 self._original_annotation: Any = PydanticUndefined
284 self._original_assignment: Any = PydanticUndefined
285 # Used to track whether the `FieldInfo` instance represents the data about a field (and is exposed in `model_fields`/`__pydantic_fields__`),
286 # or if it is the result of the `Field()` function being used as metadata in an `Annotated` type/as an assignment
287 # (not an ideal pattern, see https://github.com/pydantic/pydantic/issues/11122):
288 self._final = False
290 @staticmethod
291 def from_field(default: Any = PydanticUndefined, **kwargs: Unpack[_FromFieldInfoInputs]) -> FieldInfo:
292 """Create a new `FieldInfo` object with the `Field` function.
294 Args:
295 default: The default value for the field. Defaults to Undefined.
296 **kwargs: Additional arguments dictionary.
298 Raises:
299 TypeError: If 'annotation' is passed as a keyword argument.
301 Returns:
302 A new FieldInfo object with the given parameters.
304 Example:
305 This is how you can create a field with default value like this:
307 ```python
308 import pydantic
310 class MyModel(pydantic.BaseModel):
311 foo: int = pydantic.Field(4)
312 ```
313 """
314 if 'annotation' in kwargs:
315 raise TypeError('"annotation" is not permitted as a Field keyword argument')
316 return FieldInfo(default=default, **kwargs)
318 @staticmethod
319 def from_annotation(annotation: type[Any], *, _source: AnnotationSource = AnnotationSource.ANY) -> FieldInfo:
320 """Creates a `FieldInfo` instance from a bare annotation.
322 This function is used internally to create a `FieldInfo` from a bare annotation like this:
324 ```python
325 import pydantic
327 class MyModel(pydantic.BaseModel):
328 foo: int # <-- like this
329 ```
331 We also account for the case where the annotation can be an instance of `Annotated` and where
332 one of the (not first) arguments in `Annotated` is an instance of `FieldInfo`, e.g.:
334 ```python
335 from typing import Annotated
337 import annotated_types
339 import pydantic
341 class MyModel(pydantic.BaseModel):
342 foo: Annotated[int, annotated_types.Gt(42)]
343 bar: Annotated[int, pydantic.Field(gt=42)]
344 ```
346 Args:
347 annotation: An annotation object.
349 Returns:
350 An instance of the field metadata.
351 """
352 try:
353 inspected_ann = inspect_annotation(
354 annotation,
355 annotation_source=_source,
356 unpack_type_aliases='skip',
357 )
358 except ForbiddenQualifier as e:
359 raise PydanticForbiddenQualifier(e.qualifier, annotation)
361 # TODO check for classvar and error?
363 # No assigned value, this happens when using a bare `Final` qualifier (also for other
364 # qualifiers, but they shouldn't appear here). In this case we infer the type as `Any`
365 # because we don't have any assigned value.
366 type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type
367 final = 'final' in inspected_ann.qualifiers
368 metadata = inspected_ann.metadata
370 attr_overrides = {'annotation': type_expr}
371 if final:
372 attr_overrides['frozen'] = True
373 field_info = FieldInfo._construct(metadata, **attr_overrides)
374 field_info._qualifiers = inspected_ann.qualifiers
375 field_info._final = True
376 return field_info
378 @staticmethod
379 def from_annotated_attribute(
380 annotation: type[Any], default: Any, *, _source: AnnotationSource = AnnotationSource.ANY
381 ) -> FieldInfo:
382 """Create `FieldInfo` from an annotation with a default value.
384 This is used in cases like the following:
386 ```python
387 from typing import Annotated
389 import annotated_types
391 import pydantic
393 class MyModel(pydantic.BaseModel):
394 foo: int = 4 # <-- like this
395 bar: Annotated[int, annotated_types.Gt(4)] = 4 # <-- or this
396 spam: Annotated[int, pydantic.Field(gt=4)] = 4 # <-- or this
397 ```
399 Args:
400 annotation: The type annotation of the field.
401 default: The default value of the field.
403 Returns:
404 A field object with the passed values.
405 """
406 if annotation is not MISSING and annotation is default:
407 raise PydanticUserError(
408 'Error when building FieldInfo from annotated attribute. '
409 "Make sure you don't have any field name clashing with a type annotation.",
410 code='unevaluable-type-annotation',
411 )
413 try:
414 inspected_ann = inspect_annotation(
415 annotation,
416 annotation_source=_source,
417 unpack_type_aliases='skip',
418 )
419 except ForbiddenQualifier as e:
420 raise PydanticForbiddenQualifier(e.qualifier, annotation)
422 # TODO check for classvar and error?
424 # TODO infer from the default, this can be done in v3 once we treat final fields with
425 # a default as proper fields and not class variables:
426 type_expr: Any = Any if inspected_ann.type is UNKNOWN else inspected_ann.type
427 final = 'final' in inspected_ann.qualifiers
428 metadata = inspected_ann.metadata
430 # HACK 1: the order in which the metadata is merged is inconsistent; we need to prepend
431 # metadata from the assignment at the beginning of the metadata. Changing this is only
432 # possible in v3 (at least). See https://github.com/pydantic/pydantic/issues/10507
433 prepend_metadata: list[Any] | None = None
434 attr_overrides = {'annotation': type_expr}
435 if final:
436 attr_overrides['frozen'] = True
438 # HACK 2: FastAPI is subclassing `FieldInfo` and historically expected the actual
439 # instance's type to be preserved when constructing new models with its subclasses as assignments.
440 # This code is never reached by Pydantic itself, and in an ideal world this shouldn't be necessary.
441 if not metadata and isinstance(default, FieldInfo) and type(default) is not FieldInfo:
442 field_info = default._copy()
443 field_info._attributes_set.update(attr_overrides)
444 for k, v in attr_overrides.items():
445 setattr(field_info, k, v)
446 return field_info
448 if isinstance(default, FieldInfo):
449 default_copy = default._copy() # Copy unnecessary when we remove HACK 1.
450 prepend_metadata = default_copy.metadata
451 default_copy.metadata = []
452 metadata = metadata + [default_copy]
453 elif isinstance(default, dataclasses.Field):
454 from_field = FieldInfo._from_dataclass_field(default)
455 prepend_metadata = from_field.metadata # Unnecessary when we remove HACK 1.
456 from_field.metadata = []
457 metadata = metadata + [from_field]
458 if 'init_var' in inspected_ann.qualifiers:
459 attr_overrides['init_var'] = True
460 if (init := getattr(default, 'init', None)) is not None:
461 attr_overrides['init'] = init
462 if (kw_only := getattr(default, 'kw_only', None)) is not None:
463 attr_overrides['kw_only'] = kw_only
464 else:
465 # `default` is the actual default value
466 attr_overrides['default'] = default
468 field_info = FieldInfo._construct(
469 prepend_metadata + metadata if prepend_metadata is not None else metadata, **attr_overrides
470 )
471 field_info._qualifiers = inspected_ann.qualifiers
472 field_info._final = True
473 return field_info
475 @classmethod
476 def _construct(cls, metadata: list[Any], **attr_overrides: Any) -> Self:
477 """Construct the final `FieldInfo` instance, by merging the possibly existing `FieldInfo` instances from the metadata.
479 With the following example:
481 ```python {test="skip" lint="skip"}
482 class Model(BaseModel):
483 f: Annotated[int, Gt(1), Field(description='desc', lt=2)]
484 ```
486 `metadata` refers to the metadata elements of the `Annotated` form. This metadata is iterated over from left to right:
488 - If the element is a `Field()` function (which is itself a `FieldInfo` instance), the field attributes (such as
489 `description`) are saved to be set on the final `FieldInfo` instance.
490 On the other hand, some kwargs (such as `lt`) are stored as `metadata` (see `FieldInfo.__init__()`, calling
491 `FieldInfo._collect_metadata()`). In this case, the final metadata list is extended with the one from this instance.
492 - Else, the element is considered as a single metadata object, and is appended to the final metadata list.
494 Args:
495 metadata: The list of metadata elements to merge together. If the `FieldInfo` instance to be constructed is for
496 a field with an assigned `Field()`, this `Field()` assignment should be added as the last element of the
497 provided metadata.
498 **attr_overrides: Extra attributes that should be set on the final merged `FieldInfo` instance.
500 Returns:
501 The final merged `FieldInfo` instance.
502 """
503 merged_metadata: list[Any] = []
504 merged_kwargs: dict[str, Any] = {}
506 for meta in metadata:
507 if isinstance(meta, FieldInfo):
508 merged_metadata.extend(meta.metadata)
510 new_js_extra: JsonDict | None = None
511 current_js_extra = meta.json_schema_extra
512 if current_js_extra is not None and 'json_schema_extra' in merged_kwargs:
513 # We need to merge `json_schema_extra`'s:
514 existing_js_extra = merged_kwargs['json_schema_extra']
515 if isinstance(existing_js_extra, dict):
516 if isinstance(current_js_extra, dict):
517 new_js_extra = {
518 **existing_js_extra,
519 **current_js_extra,
520 }
521 elif callable(current_js_extra):
522 warn(
523 'Composing `dict` and `callable` type `json_schema_extra` is not supported. '
524 'The `callable` type is being ignored. '
525 "If you'd like support for this behavior, please open an issue on pydantic.",
526 UserWarning,
527 )
528 elif callable(existing_js_extra) and isinstance(current_js_extra, dict):
529 warn(
530 'Composing `dict` and `callable` type `json_schema_extra` is not supported. '
531 'The `callable` type is being ignored. '
532 "If you'd like support for this behavior, please open an issue on pydantic.",
533 UserWarning,
534 )
536 # HACK: It is common for users to define "make model partial" (or similar) utilities, that
537 # convert all model fields to be optional (i.e. have a default value). To do so, they mutate
538 # each `FieldInfo` instance from `model_fields` to set a `default`, and use `create_model()`
539 # with `Annotated[<orig_type> | None, mutated_field_info]`` as an annotation. However, such
540 # mutations (by doing simple assignments) are only accidentally working, because we also
541 # need to track attributes explicitly set in `_attributes_set` (relying on default values for
542 # each attribute is *not* enough, for instance with `Annotated[int, Field(alias='a'), Field(alias=None)]`
543 # the resulting `FieldInfo` should have `alias=None`).
544 # To mitigate this, we add a special case when a "final" `FieldInfo` instance (that is an instance coming
545 # from `model_fields`) is used in annotated metadata (or assignment). In this case, we assume *all* attributes
546 # were explicitly set, and as such we use all of them (and this will correctly pick up the mutations).
547 # In theory, this shouldn't really be supported, you are only supposed to use the `Field()` function, not
548 # a `FieldInfo` instance directly (granted, `Field()` returns a `FieldInfo`, see
549 # https://github.com/pydantic/pydantic/issues/11122):
550 if meta._final:
551 merged_kwargs.update({attr: getattr(meta, attr) for attr in _Attrs})
552 else:
553 merged_kwargs.update(meta._attributes_set)
555 if new_js_extra is not None:
556 merged_kwargs['json_schema_extra'] = new_js_extra
557 elif typing_objects.is_deprecated(meta):
558 merged_kwargs['deprecated'] = meta
559 else:
560 merged_metadata.append(meta)
562 merged_kwargs.update(attr_overrides)
563 merged_field_info = cls(**merged_kwargs)
564 merged_field_info.metadata = merged_metadata
565 return merged_field_info
567 @staticmethod
568 @typing_extensions.deprecated(
569 "The 'merge_field_infos()' method is deprecated and will be removed in a future version. "
570 'If you relied on this method, please open an issue in the Pydantic issue tracker.',
571 category=None,
572 )
573 def merge_field_infos(*field_infos: FieldInfo, **overrides: Any) -> FieldInfo:
574 """Merge `FieldInfo` instances keeping only explicitly set attributes.
576 Later `FieldInfo` instances override earlier ones.
578 Returns:
579 FieldInfo: A merged FieldInfo instance.
580 """
581 if len(field_infos) == 1:
582 # No merging necessary, but we still need to make a copy and apply the overrides
583 field_info = field_infos[0]._copy()
584 field_info._attributes_set.update(overrides)
586 default_override = overrides.pop('default', PydanticUndefined)
587 if default_override is Ellipsis:
588 default_override = PydanticUndefined
589 if default_override is not PydanticUndefined:
590 field_info.default = default_override
592 for k, v in overrides.items():
593 setattr(field_info, k, v)
594 return field_info # type: ignore
596 merged_field_info_kwargs: dict[str, Any] = {}
597 metadata = {}
598 for field_info in field_infos:
599 attributes_set = field_info._attributes_set.copy()
601 try:
602 json_schema_extra = attributes_set.pop('json_schema_extra')
603 existing_json_schema_extra = merged_field_info_kwargs.get('json_schema_extra')
605 if existing_json_schema_extra is None:
606 merged_field_info_kwargs['json_schema_extra'] = json_schema_extra
607 if isinstance(existing_json_schema_extra, dict):
608 if isinstance(json_schema_extra, dict):
609 merged_field_info_kwargs['json_schema_extra'] = {
610 **existing_json_schema_extra,
611 **json_schema_extra,
612 }
613 if callable(json_schema_extra):
614 warn(
615 'Composing `dict` and `callable` type `json_schema_extra` is not supported.'
616 'The `callable` type is being ignored.'
617 "If you'd like support for this behavior, please open an issue on pydantic.",
618 PydanticJsonSchemaWarning,
619 )
620 elif callable(json_schema_extra):
621 # if ever there's a case of a callable, we'll just keep the last json schema extra spec
622 merged_field_info_kwargs['json_schema_extra'] = json_schema_extra
623 except KeyError:
624 pass
626 # later FieldInfo instances override everything except json_schema_extra from earlier FieldInfo instances
627 merged_field_info_kwargs.update(attributes_set)
629 for x in field_info.metadata:
630 if not isinstance(x, FieldInfo):
631 metadata[type(x)] = x
633 merged_field_info_kwargs.update(overrides)
634 field_info = FieldInfo(**merged_field_info_kwargs)
635 field_info.metadata = list(metadata.values())
636 return field_info
638 @staticmethod
639 def _from_dataclass_field(dc_field: DataclassField[Any]) -> FieldInfo:
640 """Return a new `FieldInfo` instance from a `dataclasses.Field` instance.
642 Args:
643 dc_field: The `dataclasses.Field` instance to convert.
645 Returns:
646 The corresponding `FieldInfo` instance.
648 Raises:
649 TypeError: If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs.
650 """
651 default = dc_field.default
652 if default is dataclasses.MISSING:
653 default = _Unset
655 if dc_field.default_factory is dataclasses.MISSING:
656 default_factory = _Unset
657 else:
658 default_factory = dc_field.default_factory
660 # use the `Field` function so in correct kwargs raise the correct `TypeError`
661 dc_field_metadata = {k: v for k, v in dc_field.metadata.items() if k in _FIELD_ARG_NAMES}
662 if sys.version_info >= (3, 14) and dc_field.doc is not None:
663 dc_field_metadata['description'] = dc_field.doc
664 return Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field_metadata) # pyright: ignore[reportCallIssue]
666 @staticmethod
667 def _collect_metadata(kwargs: dict[str, Any]) -> list[Any]:
668 """Collect annotations from kwargs.
670 Args:
671 kwargs: Keyword arguments passed to the function.
673 Returns:
674 A list of metadata objects - a combination of `annotated_types.BaseMetadata` and
675 `PydanticMetadata`.
676 """
677 metadata: list[Any] = []
678 general_metadata = {}
679 for key, value in list(kwargs.items()):
680 try:
681 marker = FieldInfo.metadata_lookup[key]
682 except KeyError:
683 continue
685 del kwargs[key]
686 if value is not None:
687 if marker is None:
688 general_metadata[key] = value
689 else:
690 metadata.append(marker(value))
691 if general_metadata:
692 metadata.append(_fields.pydantic_general_metadata(**general_metadata))
693 return metadata
695 @property
696 def deprecation_message(self) -> str | None:
697 """The deprecation message to be emitted, or `None` if not set."""
698 if self.deprecated is None:
699 return None
700 if isinstance(self.deprecated, bool):
701 return 'deprecated' if self.deprecated else None
702 return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message
704 @property
705 def default_factory_takes_validated_data(self) -> bool | None:
706 """Whether the provided default factory callable has a validated data parameter.
708 Returns `None` if no default factory is set.
709 """
710 if self.default_factory is not None:
711 return _fields.takes_validated_data_argument(self.default_factory)
713 @overload
714 def get_default(
715 self, *, call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None
716 ) -> Any: ...
718 @overload
719 def get_default(self, *, call_default_factory: Literal[False] = ...) -> Any: ...
721 def get_default(self, *, call_default_factory: bool = False, validated_data: dict[str, Any] | None = None) -> Any:
722 """Get the default value.
724 We expose an option for whether to call the default_factory (if present), as calling it may
725 result in side effects that we want to avoid. However, there are times when it really should
726 be called (namely, when instantiating a model via `model_construct`).
728 Args:
729 call_default_factory: Whether to call the default factory or not.
730 validated_data: The already validated data to be passed to the default factory.
732 Returns:
733 The default value, calling the default factory if requested or `None` if not set.
734 """
735 if self.default_factory is None:
736 return _utils.smart_deepcopy(self.default)
737 elif call_default_factory:
738 if self.default_factory_takes_validated_data:
739 fac = cast('Callable[[dict[str, Any]], Any]', self.default_factory)
740 if validated_data is None:
741 raise ValueError(
742 "The default factory requires the 'validated_data' argument, which was not provided when calling 'get_default'."
743 )
744 return fac(validated_data)
745 else:
746 fac = cast('Callable[[], Any]', self.default_factory)
747 return fac()
748 else:
749 return None
751 def is_required(self) -> bool:
752 """Check if the field is required (i.e., does not have a default value or factory).
754 Returns:
755 `True` if the field is required, `False` otherwise.
756 """
757 return self.default is PydanticUndefined and self.default_factory is None
759 def rebuild_annotation(self) -> Any:
760 """Attempts to rebuild the original annotation for use in function signatures.
762 If metadata is present, it adds it to the original annotation using
763 `Annotated`. Otherwise, it returns the original annotation as-is.
765 Note that because the metadata has been flattened, the original annotation
766 may not be reconstructed exactly as originally provided, e.g. if the original
767 type had unrecognized annotations, or was annotated with a call to `pydantic.Field`.
769 Returns:
770 The rebuilt annotation.
771 """
772 if not self.metadata:
773 return self.annotation
774 else:
775 # Annotated arguments must be a tuple
776 return Annotated[(self.annotation, *self.metadata)] # type: ignore
778 def apply_typevars_map(
779 self,
780 typevars_map: Mapping[TypeVar, Any] | None,
781 globalns: GlobalsNamespace | None = None,
782 localns: MappingNamespace | None = None,
783 ) -> None:
784 """Apply a `typevars_map` to the annotation.
786 This method is used when analyzing parametrized generic types to replace typevars with their concrete types.
788 This method applies the `typevars_map` to the annotation in place.
790 Args:
791 typevars_map: A dictionary mapping type variables to their concrete types.
792 globalns: The globals namespace to use during type annotation evaluation.
793 localns: The locals namespace to use during type annotation evaluation.
795 See Also:
796 pydantic._internal._generics.replace_types is used for replacing the typevars with
797 their concrete types.
798 """
799 annotation = _generics.replace_types(self.annotation, typevars_map)
800 annotation, evaluated = _typing_extra.try_eval_type(annotation, globalns, localns)
801 self.annotation = annotation
802 if not evaluated:
803 self._complete = False
804 self._original_annotation = self.annotation
806 def asdict(self) -> _FieldInfoAsDict:
807 """Return a dictionary representation of the `FieldInfo` instance.
809 The returned value is a dictionary with three items:
811 * `annotation`: The type annotation of the field.
812 * `metadata`: The metadata list.
813 * `attributes`: A mapping of the remaining `FieldInfo` attributes to their values (e.g. `alias`, `title`).
814 """
815 return {
816 'annotation': self.annotation,
817 'metadata': self.metadata,
818 'attributes': {attr: getattr(self, attr) for attr in _Attrs},
819 }
821 def _copy(self) -> Self:
822 """Return a copy of the `FieldInfo` instance."""
823 # Note: we can't define a custom `__copy__()`, as `FieldInfo` is being subclassed
824 # by some third-party libraries with extra attributes defined (and as `FieldInfo`
825 # is slotted, we can't make a copy of the `__dict__`).
826 copied = copy(self)
827 for attr_name in ('metadata', '_attributes_set', '_qualifiers'):
828 # Apply "deep-copy" behavior on collections attributes:
829 value = getattr(copied, attr_name).copy()
830 setattr(copied, attr_name, value)
832 return copied
834 def __repr_args__(self) -> ReprArgs:
835 yield 'annotation', _repr.PlainRepr(_repr.display_as_type(self.annotation))
836 yield 'required', self.is_required()
838 for s in self.__slots__:
839 # TODO: properly make use of the protocol (https://rich.readthedocs.io/en/stable/pretty.html#rich-repr-protocol)
840 # By yielding a three-tuple:
841 if s in (
842 'annotation',
843 '_attributes_set',
844 '_qualifiers',
845 '_complete',
846 '_original_assignment',
847 '_original_annotation',
848 '_final',
849 ):
850 continue
851 elif s == 'metadata' and not self.metadata:
852 continue
853 elif s == 'repr' and self.repr is True:
854 continue
855 if s == 'frozen' and self.frozen is False:
856 continue
857 if s == 'validation_alias' and self.validation_alias == self.alias:
858 continue
859 if s == 'serialization_alias' and self.serialization_alias == self.alias:
860 continue
861 if s == 'default' and self.default is not PydanticUndefined:
862 yield 'default', self.default
863 elif s == 'default_factory' and self.default_factory is not None:
864 yield 'default_factory', _repr.PlainRepr(_repr.display_as_type(self.default_factory))
865 else:
866 value = getattr(self, s)
867 if value is not None and value is not PydanticUndefined:
868 yield s, value
871class _EmptyKwargs(TypedDict):
872 """This class exists solely to ensure that type checking warns about passing `**extra` in `Field`."""
875_Attrs = {
876 'default': ...,
877 'default_factory': None,
878 'alias': None,
879 'alias_priority': None,
880 'validation_alias': None,
881 'serialization_alias': None,
882 'title': None,
883 'field_title_generator': None,
884 'description': None,
885 'examples': None,
886 'exclude': None,
887 'exclude_if': None,
888 'discriminator': None,
889 'deprecated': None,
890 'json_schema_extra': None,
891 'frozen': None,
892 'validate_default': None,
893 'repr': True,
894 'init': None,
895 'init_var': None,
896 'kw_only': None,
897}
899_DefaultValues = {
900 **_Attrs,
901 'kw_only': None,
902 'pattern': None,
903 'strict': None,
904 'gt': None,
905 'ge': None,
906 'lt': None,
907 'le': None,
908 'multiple_of': None,
909 'allow_inf_nan': None,
910 'max_digits': None,
911 'decimal_places': None,
912 'min_length': None,
913 'max_length': None,
914 'coerce_numbers_to_str': None,
915}
918_T = TypeVar('_T')
921# NOTE: Actual return type is 'FieldInfo', but we want to help type checkers
922# to understand the magic that happens at runtime with the following overloads:
923@overload # type hint the return value as `Any` to avoid type checking regressions when using `...`.
924def Field(
925 default: ellipsis, # noqa: F821 # TODO: use `_typing_extra.EllipsisType` when we drop Py3.9
926 *,
927 alias: str | None = _Unset,
928 alias_priority: int | None = _Unset,
929 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
930 serialization_alias: str | None = _Unset,
931 title: str | None = _Unset,
932 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
933 description: str | None = _Unset,
934 examples: list[Any] | None = _Unset,
935 exclude: bool | None = _Unset,
936 exclude_if: Callable[[Any], bool] | None = _Unset,
937 discriminator: str | types.Discriminator | None = _Unset,
938 deprecated: Deprecated | str | bool | None = _Unset,
939 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
940 frozen: bool | None = _Unset,
941 validate_default: bool | None = _Unset,
942 repr: bool = _Unset,
943 init: bool | None = _Unset,
944 init_var: bool | None = _Unset,
945 kw_only: bool | None = _Unset,
946 pattern: str | re.Pattern[str] | None = _Unset,
947 strict: bool | None = _Unset,
948 coerce_numbers_to_str: bool | None = _Unset,
949 gt: annotated_types.SupportsGt | None = _Unset,
950 ge: annotated_types.SupportsGe | None = _Unset,
951 lt: annotated_types.SupportsLt | None = _Unset,
952 le: annotated_types.SupportsLe | None = _Unset,
953 multiple_of: float | None = _Unset,
954 allow_inf_nan: bool | None = _Unset,
955 max_digits: int | None = _Unset,
956 decimal_places: int | None = _Unset,
957 min_length: int | None = _Unset,
958 max_length: int | None = _Unset,
959 union_mode: Literal['smart', 'left_to_right'] = _Unset,
960 fail_fast: bool | None = _Unset,
961 **extra: Unpack[_EmptyKwargs],
962) -> Any: ...
963@overload # `default` argument set, validate_default=True (no type checking on the default value)
964def Field(
965 default: Any,
966 *,
967 alias: str | None = _Unset,
968 alias_priority: int | None = _Unset,
969 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
970 serialization_alias: str | None = _Unset,
971 title: str | None = _Unset,
972 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
973 description: str | None = _Unset,
974 examples: list[Any] | None = _Unset,
975 exclude: bool | None = _Unset,
976 exclude_if: Callable[[Any], bool] | None = _Unset,
977 discriminator: str | types.Discriminator | None = _Unset,
978 deprecated: Deprecated | str | bool | None = _Unset,
979 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
980 frozen: bool | None = _Unset,
981 validate_default: Literal[True],
982 repr: bool = _Unset,
983 init: bool | None = _Unset,
984 init_var: bool | None = _Unset,
985 kw_only: bool | None = _Unset,
986 pattern: str | re.Pattern[str] | None = _Unset,
987 strict: bool | None = _Unset,
988 coerce_numbers_to_str: bool | None = _Unset,
989 gt: annotated_types.SupportsGt | None = _Unset,
990 ge: annotated_types.SupportsGe | None = _Unset,
991 lt: annotated_types.SupportsLt | None = _Unset,
992 le: annotated_types.SupportsLe | None = _Unset,
993 multiple_of: float | None = _Unset,
994 allow_inf_nan: bool | None = _Unset,
995 max_digits: int | None = _Unset,
996 decimal_places: int | None = _Unset,
997 min_length: int | None = _Unset,
998 max_length: int | None = _Unset,
999 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1000 fail_fast: bool | None = _Unset,
1001 **extra: Unpack[_EmptyKwargs],
1002) -> Any: ...
1003@overload # `default` argument set, validate_default=False or unset
1004def Field(
1005 default: _T,
1006 *,
1007 alias: str | None = _Unset,
1008 alias_priority: int | None = _Unset,
1009 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1010 serialization_alias: str | None = _Unset,
1011 title: str | None = _Unset,
1012 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1013 description: str | None = _Unset,
1014 examples: list[Any] | None = _Unset,
1015 exclude: bool | None = _Unset,
1016 # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However,
1017 # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise
1018 # `a: int = Field(default_factory=str)` results in a false negative).
1019 exclude_if: Callable[[Any], bool] | None = _Unset,
1020 discriminator: str | types.Discriminator | None = _Unset,
1021 deprecated: Deprecated | str | bool | None = _Unset,
1022 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1023 frozen: bool | None = _Unset,
1024 validate_default: Literal[False] = ...,
1025 repr: bool = _Unset,
1026 init: bool | None = _Unset,
1027 init_var: bool | None = _Unset,
1028 kw_only: bool | None = _Unset,
1029 pattern: str | re.Pattern[str] | None = _Unset,
1030 strict: bool | None = _Unset,
1031 coerce_numbers_to_str: bool | None = _Unset,
1032 gt: annotated_types.SupportsGt | None = _Unset,
1033 ge: annotated_types.SupportsGe | None = _Unset,
1034 lt: annotated_types.SupportsLt | None = _Unset,
1035 le: annotated_types.SupportsLe | None = _Unset,
1036 multiple_of: float | None = _Unset,
1037 allow_inf_nan: bool | None = _Unset,
1038 max_digits: int | None = _Unset,
1039 decimal_places: int | None = _Unset,
1040 min_length: int | None = _Unset,
1041 max_length: int | None = _Unset,
1042 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1043 fail_fast: bool | None = _Unset,
1044 **extra: Unpack[_EmptyKwargs],
1045) -> _T: ...
1046@overload # `default_factory` argument set, validate_default=True (no type checking on the default value)
1047def Field( # pyright: ignore[reportOverlappingOverload]
1048 *,
1049 default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any],
1050 alias: str | None = _Unset,
1051 alias_priority: int | None = _Unset,
1052 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1053 serialization_alias: str | None = _Unset,
1054 title: str | None = _Unset,
1055 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1056 description: str | None = _Unset,
1057 examples: list[Any] | None = _Unset,
1058 exclude: bool | None = _Unset,
1059 exclude_if: Callable[[Any], bool] | None = _Unset,
1060 discriminator: str | types.Discriminator | None = _Unset,
1061 deprecated: Deprecated | str | bool | None = _Unset,
1062 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1063 frozen: bool | None = _Unset,
1064 validate_default: Literal[True],
1065 repr: bool = _Unset,
1066 init: bool | None = _Unset,
1067 init_var: bool | None = _Unset,
1068 kw_only: bool | None = _Unset,
1069 pattern: str | re.Pattern[str] | None = _Unset,
1070 strict: bool | None = _Unset,
1071 coerce_numbers_to_str: bool | None = _Unset,
1072 gt: annotated_types.SupportsGt | None = _Unset,
1073 ge: annotated_types.SupportsGe | None = _Unset,
1074 lt: annotated_types.SupportsLt | None = _Unset,
1075 le: annotated_types.SupportsLe | None = _Unset,
1076 multiple_of: float | None = _Unset,
1077 allow_inf_nan: bool | None = _Unset,
1078 max_digits: int | None = _Unset,
1079 decimal_places: int | None = _Unset,
1080 min_length: int | None = _Unset,
1081 max_length: int | None = _Unset,
1082 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1083 fail_fast: bool | None = _Unset,
1084 **extra: Unpack[_EmptyKwargs],
1085) -> Any: ...
1086@overload # `default_factory` argument set, validate_default=False or unset
1087def Field(
1088 *,
1089 default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T],
1090 alias: str | None = _Unset,
1091 alias_priority: int | None = _Unset,
1092 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1093 serialization_alias: str | None = _Unset,
1094 title: str | None = _Unset,
1095 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1096 description: str | None = _Unset,
1097 examples: list[Any] | None = _Unset,
1098 exclude: bool | None = _Unset,
1099 # NOTE: to get proper type checking on `exclude_if`'s argument, we could use `_T` instead of `Any`. However,
1100 # this requires (at least for pyright) adding an additional overload where `exclude_if` is required (otherwise
1101 # `a: int = Field(default_factory=str)` results in a false negative).
1102 exclude_if: Callable[[Any], bool] | None = _Unset,
1103 discriminator: str | types.Discriminator | None = _Unset,
1104 deprecated: Deprecated | str | bool | None = _Unset,
1105 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1106 frozen: bool | None = _Unset,
1107 validate_default: Literal[False] | None = _Unset,
1108 repr: bool = _Unset,
1109 init: bool | None = _Unset,
1110 init_var: bool | None = _Unset,
1111 kw_only: bool | None = _Unset,
1112 pattern: str | re.Pattern[str] | None = _Unset,
1113 strict: bool | None = _Unset,
1114 coerce_numbers_to_str: bool | None = _Unset,
1115 gt: annotated_types.SupportsGt | None = _Unset,
1116 ge: annotated_types.SupportsGe | None = _Unset,
1117 lt: annotated_types.SupportsLt | None = _Unset,
1118 le: annotated_types.SupportsLe | None = _Unset,
1119 multiple_of: float | None = _Unset,
1120 allow_inf_nan: bool | None = _Unset,
1121 max_digits: int | None = _Unset,
1122 decimal_places: int | None = _Unset,
1123 min_length: int | None = _Unset,
1124 max_length: int | None = _Unset,
1125 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1126 fail_fast: bool | None = _Unset,
1127 **extra: Unpack[_EmptyKwargs],
1128) -> _T: ...
1129@overload
1130def Field( # No default set
1131 *,
1132 alias: str | None = _Unset,
1133 alias_priority: int | None = _Unset,
1134 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1135 serialization_alias: str | None = _Unset,
1136 title: str | None = _Unset,
1137 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1138 description: str | None = _Unset,
1139 examples: list[Any] | None = _Unset,
1140 exclude: bool | None = _Unset,
1141 exclude_if: Callable[[Any], bool] | None = _Unset,
1142 discriminator: str | types.Discriminator | None = _Unset,
1143 deprecated: Deprecated | str | bool | None = _Unset,
1144 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1145 frozen: bool | None = _Unset,
1146 validate_default: bool | None = _Unset,
1147 repr: bool = _Unset,
1148 init: bool | None = _Unset,
1149 init_var: bool | None = _Unset,
1150 kw_only: bool | None = _Unset,
1151 pattern: str | re.Pattern[str] | None = _Unset,
1152 strict: bool | None = _Unset,
1153 coerce_numbers_to_str: bool | None = _Unset,
1154 gt: annotated_types.SupportsGt | None = _Unset,
1155 ge: annotated_types.SupportsGe | None = _Unset,
1156 lt: annotated_types.SupportsLt | None = _Unset,
1157 le: annotated_types.SupportsLe | None = _Unset,
1158 multiple_of: float | None = _Unset,
1159 allow_inf_nan: bool | None = _Unset,
1160 max_digits: int | None = _Unset,
1161 decimal_places: int | None = _Unset,
1162 min_length: int | None = _Unset,
1163 max_length: int | None = _Unset,
1164 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1165 fail_fast: bool | None = _Unset,
1166 **extra: Unpack[_EmptyKwargs],
1167) -> Any: ...
1168def Field( # noqa: C901
1169 default: Any = PydanticUndefined,
1170 *,
1171 default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any] | None = _Unset,
1172 alias: str | None = _Unset,
1173 alias_priority: int | None = _Unset,
1174 validation_alias: str | AliasPath | AliasChoices | None = _Unset,
1175 serialization_alias: str | None = _Unset,
1176 title: str | None = _Unset,
1177 field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset,
1178 description: str | None = _Unset,
1179 examples: list[Any] | None = _Unset,
1180 exclude: bool | None = _Unset,
1181 exclude_if: Callable[[Any], bool] | None = _Unset,
1182 discriminator: str | types.Discriminator | None = _Unset,
1183 deprecated: Deprecated | str | bool | None = _Unset,
1184 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset,
1185 frozen: bool | None = _Unset,
1186 validate_default: bool | None = _Unset,
1187 repr: bool = _Unset,
1188 init: bool | None = _Unset,
1189 init_var: bool | None = _Unset,
1190 kw_only: bool | None = _Unset,
1191 pattern: str | re.Pattern[str] | None = _Unset,
1192 strict: bool | None = _Unset,
1193 coerce_numbers_to_str: bool | None = _Unset,
1194 gt: annotated_types.SupportsGt | None = _Unset,
1195 ge: annotated_types.SupportsGe | None = _Unset,
1196 lt: annotated_types.SupportsLt | None = _Unset,
1197 le: annotated_types.SupportsLe | None = _Unset,
1198 multiple_of: float | None = _Unset,
1199 allow_inf_nan: bool | None = _Unset,
1200 max_digits: int | None = _Unset,
1201 decimal_places: int | None = _Unset,
1202 min_length: int | None = _Unset,
1203 max_length: int | None = _Unset,
1204 union_mode: Literal['smart', 'left_to_right'] = _Unset,
1205 fail_fast: bool | None = _Unset,
1206 **extra: Unpack[_EmptyKwargs],
1207) -> Any:
1208 """!!! abstract "Usage Documentation"
1209 [Fields](../concepts/fields.md)
1211 Create a field for objects that can be configured.
1213 Used to provide extra information about a field, either for the model schema or complex validation. Some arguments
1214 apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`.
1216 Note:
1217 - Any `_Unset` objects will be replaced by the corresponding value defined in the `_DefaultValues` dictionary. If a key for the `_Unset` object is not found in the `_DefaultValues` dictionary, it will default to `None`
1219 Args:
1220 default: Default value if the field is not set.
1221 default_factory: A callable to generate the default value. The callable can either take 0 arguments
1222 (in which case it is called as is) or a single argument containing the already validated data.
1223 alias: The name to use for the attribute when validating or serializing by alias.
1224 This is often used for things like converting between snake and camel case.
1225 alias_priority: Priority of the alias. This affects whether an alias generator is used.
1226 validation_alias: Like `alias`, but only affects validation, not serialization.
1227 serialization_alias: Like `alias`, but only affects serialization, not validation.
1228 title: Human-readable title.
1229 field_title_generator: A callable that takes a field name and returns title for it.
1230 description: Human-readable description.
1231 examples: Example values for this field.
1232 exclude: Whether to exclude the field from the model serialization.
1233 exclude_if: A callable that determines whether to exclude a field during serialization based on its value.
1234 discriminator: Field name or Discriminator for discriminating the type in a tagged union.
1235 deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
1236 or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
1237 json_schema_extra: A dict or callable to provide extra JSON schema properties.
1238 frozen: Whether the field is frozen. If true, attempts to change the value on an instance will raise an error.
1239 validate_default: If `True`, apply validation to the default value every time you create an instance.
1240 Otherwise, for performance reasons, the default value of the field is trusted and not validated.
1241 repr: A boolean indicating whether to include the field in the `__repr__` output.
1242 init: Whether the field should be included in the constructor of the dataclass.
1243 (Only applies to dataclasses.)
1244 init_var: Whether the field should _only_ be included in the constructor of the dataclass.
1245 (Only applies to dataclasses.)
1246 kw_only: Whether the field should be a keyword-only argument in the constructor of the dataclass.
1247 (Only applies to dataclasses.)
1248 coerce_numbers_to_str: Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode).
1249 strict: If `True`, strict validation is applied to the field.
1250 See [Strict Mode](../concepts/strict_mode.md) for details.
1251 gt: Greater than. If set, value must be greater than this. Only applicable to numbers.
1252 ge: Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers.
1253 lt: Less than. If set, value must be less than this. Only applicable to numbers.
1254 le: Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers.
1255 multiple_of: Value must be a multiple of this. Only applicable to numbers.
1256 min_length: Minimum length for iterables.
1257 max_length: Maximum length for iterables.
1258 pattern: Pattern for strings (a regular expression).
1259 allow_inf_nan: Allow `inf`, `-inf`, `nan`. Only applicable to float and [`Decimal`][decimal.Decimal] numbers.
1260 max_digits: Maximum number of allow digits for strings.
1261 decimal_places: Maximum number of decimal places allowed for numbers.
1262 union_mode: The strategy to apply when validating a union. Can be `smart` (the default), or `left_to_right`.
1263 See [Union Mode](../concepts/unions.md#union-modes) for details.
1264 fail_fast: If `True`, validation will stop on the first error. If `False`, all validation errors will be collected.
1265 This option can be applied only to iterable types (list, tuple, set, and frozenset).
1266 extra: (Deprecated) Extra fields that will be included in the JSON schema.
1268 !!! warning Deprecated
1269 The `extra` kwargs is deprecated. Use `json_schema_extra` instead.
1271 Returns:
1272 A new [`FieldInfo`][pydantic.fields.FieldInfo]. The return annotation is `Any` so `Field` can be used on
1273 type-annotated fields without causing a type error.
1274 """
1275 # Check deprecated and removed params from V1. This logic should eventually be removed.
1276 const = extra.pop('const', None) # type: ignore
1277 if const is not None:
1278 raise PydanticUserError('`const` is removed, use `Literal` instead', code='removed-kwargs')
1280 min_items = extra.pop('min_items', None) # type: ignore
1281 if min_items is not None:
1282 warn(
1283 '`min_items` is deprecated and will be removed, use `min_length` instead',
1284 PydanticDeprecatedSince20,
1285 stacklevel=2,
1286 )
1287 if min_length in (None, _Unset):
1288 min_length = min_items # type: ignore
1290 max_items = extra.pop('max_items', None) # type: ignore
1291 if max_items is not None:
1292 warn(
1293 '`max_items` is deprecated and will be removed, use `max_length` instead',
1294 PydanticDeprecatedSince20,
1295 stacklevel=2,
1296 )
1297 if max_length in (None, _Unset):
1298 max_length = max_items # type: ignore
1300 unique_items = extra.pop('unique_items', None) # type: ignore
1301 if unique_items is not None:
1302 raise PydanticUserError(
1303 (
1304 '`unique_items` is removed, use `Set` instead'
1305 '(this feature is discussed in https://github.com/pydantic/pydantic-core/issues/296)'
1306 ),
1307 code='removed-kwargs',
1308 )
1310 allow_mutation = extra.pop('allow_mutation', None) # type: ignore
1311 if allow_mutation is not None:
1312 warn(
1313 '`allow_mutation` is deprecated and will be removed. use `frozen` instead',
1314 PydanticDeprecatedSince20,
1315 stacklevel=2,
1316 )
1317 if allow_mutation is False:
1318 frozen = True
1320 regex = extra.pop('regex', None) # type: ignore
1321 if regex is not None:
1322 raise PydanticUserError('`regex` is removed. use `pattern` instead', code='removed-kwargs')
1324 if extra:
1325 warn(
1326 'Using extra keyword arguments on `Field` is deprecated and will be removed.'
1327 ' Use `json_schema_extra` instead.'
1328 f' (Extra keys: {", ".join(k.__repr__() for k in extra.keys())})',
1329 PydanticDeprecatedSince20,
1330 stacklevel=2,
1331 )
1332 if not json_schema_extra or json_schema_extra is _Unset:
1333 json_schema_extra = extra # type: ignore
1335 if (
1336 validation_alias
1337 and validation_alias is not _Unset
1338 and not isinstance(validation_alias, (str, AliasChoices, AliasPath))
1339 ):
1340 raise TypeError('Invalid `validation_alias` type. it should be `str`, `AliasChoices`, or `AliasPath`')
1342 if serialization_alias in (_Unset, None) and isinstance(alias, str):
1343 serialization_alias = alias
1345 if validation_alias in (_Unset, None):
1346 validation_alias = alias
1348 include = extra.pop('include', None) # type: ignore
1349 if include is not None:
1350 warn(
1351 '`include` is deprecated and does nothing. It will be removed, use `exclude` instead',
1352 PydanticDeprecatedSince20,
1353 stacklevel=2,
1354 )
1356 return FieldInfo.from_field(
1357 default,
1358 default_factory=default_factory,
1359 alias=alias,
1360 alias_priority=alias_priority,
1361 validation_alias=validation_alias,
1362 serialization_alias=serialization_alias,
1363 title=title,
1364 field_title_generator=field_title_generator,
1365 description=description,
1366 examples=examples,
1367 exclude=exclude,
1368 exclude_if=exclude_if,
1369 discriminator=discriminator,
1370 deprecated=deprecated,
1371 json_schema_extra=json_schema_extra,
1372 frozen=frozen,
1373 pattern=pattern,
1374 validate_default=validate_default,
1375 repr=repr,
1376 init=init,
1377 init_var=init_var,
1378 kw_only=kw_only,
1379 coerce_numbers_to_str=coerce_numbers_to_str,
1380 strict=strict,
1381 gt=gt,
1382 ge=ge,
1383 lt=lt,
1384 le=le,
1385 multiple_of=multiple_of,
1386 min_length=min_length,
1387 max_length=max_length,
1388 allow_inf_nan=allow_inf_nan,
1389 max_digits=max_digits,
1390 decimal_places=decimal_places,
1391 union_mode=union_mode,
1392 fail_fast=fail_fast,
1393 )
1396_FIELD_ARG_NAMES = set(inspect.signature(Field).parameters)
1397_FIELD_ARG_NAMES.remove('extra') # do not include the varkwargs parameter
1400class ModelPrivateAttr(_repr.Representation):
1401 """A descriptor for private attributes in class models.
1403 !!! warning
1404 You generally shouldn't be creating `ModelPrivateAttr` instances directly, instead use
1405 `pydantic.fields.PrivateAttr`. (This is similar to `FieldInfo` vs. `Field`.)
1407 Attributes:
1408 default: The default value of the attribute if not provided.
1409 default_factory: A callable function that generates the default value of the
1410 attribute if not provided.
1411 """
1413 __slots__ = ('default', 'default_factory')
1415 def __init__(self, default: Any = PydanticUndefined, *, default_factory: Callable[[], Any] | None = None) -> None:
1416 if default is Ellipsis:
1417 self.default = PydanticUndefined
1418 else:
1419 self.default = default
1420 self.default_factory = default_factory
1422 if not TYPE_CHECKING:
1423 # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access
1425 def __getattr__(self, item: str) -> Any:
1426 """This function improves compatibility with custom descriptors by ensuring delegation happens
1427 as expected when the default value of a private attribute is a descriptor.
1428 """
1429 if item in {'__get__', '__set__', '__delete__'}:
1430 if hasattr(self.default, item):
1431 return getattr(self.default, item)
1432 raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')
1434 def __set_name__(self, cls: type[Any], name: str) -> None:
1435 """Preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487."""
1436 default = self.default
1437 if default is PydanticUndefined:
1438 return
1439 set_name = getattr(default, '__set_name__', None)
1440 if callable(set_name):
1441 set_name(cls, name)
1443 def get_default(self) -> Any:
1444 """Retrieve the default value of the object.
1446 If `self.default_factory` is `None`, the method will return a deep copy of the `self.default` object.
1448 If `self.default_factory` is not `None`, it will call `self.default_factory` and return the value returned.
1450 Returns:
1451 The default value of the object.
1452 """
1453 return _utils.smart_deepcopy(self.default) if self.default_factory is None else self.default_factory()
1455 def __eq__(self, other: Any) -> bool:
1456 return isinstance(other, self.__class__) and (self.default, self.default_factory) == (
1457 other.default,
1458 other.default_factory,
1459 )
1462# NOTE: Actual return type is 'ModelPrivateAttr', but we want to help type checkers
1463# to understand the magic that happens at runtime.
1464@overload # `default` argument set
1465def PrivateAttr(
1466 default: _T,
1467 *,
1468 init: Literal[False] = False,
1469) -> _T: ...
1470@overload # `default_factory` argument set
1471def PrivateAttr(
1472 *,
1473 default_factory: Callable[[], _T],
1474 init: Literal[False] = False,
1475) -> _T: ...
1476@overload # No default set
1477def PrivateAttr(
1478 *,
1479 init: Literal[False] = False,
1480) -> Any: ...
1481def PrivateAttr(
1482 default: Any = PydanticUndefined,
1483 *,
1484 default_factory: Callable[[], Any] | None = None,
1485 init: Literal[False] = False,
1486) -> Any:
1487 """!!! abstract "Usage Documentation"
1488 [Private Model Attributes](../concepts/models.md#private-model-attributes)
1490 Indicates that an attribute is intended for private use and not handled during normal validation/serialization.
1492 Private attributes are not validated by Pydantic, so it's up to you to ensure they are used in a type-safe manner.
1494 Private attributes are stored in `__private_attributes__` on the model.
1496 Args:
1497 default: The attribute's default value. Defaults to Undefined.
1498 default_factory: Callable that will be
1499 called when a default value is needed for this attribute.
1500 If both `default` and `default_factory` are set, an error will be raised.
1501 init: Whether the attribute should be included in the constructor of the dataclass. Always `False`.
1503 Returns:
1504 An instance of [`ModelPrivateAttr`][pydantic.fields.ModelPrivateAttr] class.
1506 Raises:
1507 ValueError: If both `default` and `default_factory` are set.
1508 """
1509 if default is not PydanticUndefined and default_factory is not None:
1510 raise TypeError('cannot specify both default and default_factory')
1512 return ModelPrivateAttr(
1513 default,
1514 default_factory=default_factory,
1515 )
1518@dataclasses.dataclass(**_internal_dataclass.slots_true)
1519class ComputedFieldInfo:
1520 """A container for data from `@computed_field` so that we can access it while building the pydantic-core schema.
1522 Attributes:
1523 decorator_repr: A class variable representing the decorator string, '@computed_field'.
1524 wrapped_property: The wrapped computed field property.
1525 return_type: The type of the computed field property's return value.
1526 alias: The alias of the property to be used during serialization.
1527 alias_priority: The priority of the alias. This affects whether an alias generator is used.
1528 title: Title of the computed field to include in the serialization JSON schema.
1529 field_title_generator: A callable that takes a field name and returns title for it.
1530 description: Description of the computed field to include in the serialization JSON schema.
1531 deprecated: A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport,
1532 or a boolean. If `True`, a default deprecation message will be emitted when accessing the field.
1533 examples: Example values of the computed field to include in the serialization JSON schema.
1534 json_schema_extra: A dict or callable to provide extra JSON schema properties.
1535 repr: A boolean indicating whether to include the field in the __repr__ output.
1536 """
1538 decorator_repr: ClassVar[str] = '@computed_field'
1539 wrapped_property: property
1540 return_type: Any
1541 alias: str | None
1542 alias_priority: int | None
1543 title: str | None
1544 field_title_generator: Callable[[str, ComputedFieldInfo], str] | None
1545 description: str | None
1546 deprecated: Deprecated | str | bool | None
1547 examples: list[Any] | None
1548 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None
1549 repr: bool
1551 @property
1552 def deprecation_message(self) -> str | None:
1553 """The deprecation message to be emitted, or `None` if not set."""
1554 if self.deprecated is None:
1555 return None
1556 if isinstance(self.deprecated, bool):
1557 return 'deprecated' if self.deprecated else None
1558 return self.deprecated if isinstance(self.deprecated, str) else self.deprecated.message
1560 def _update_from_config(self, config_wrapper: ConfigWrapper, name: str) -> None:
1561 """Update the instance from the configuration set on the class this computed field belongs to."""
1562 title_generator = self.field_title_generator or config_wrapper.field_title_generator
1563 if title_generator is not None and self.title is None:
1564 self.title = title_generator(name, self)
1565 if config_wrapper.alias_generator is not None:
1566 self._apply_alias_generator(config_wrapper.alias_generator, name)
1568 def _apply_alias_generator(self, alias_generator: Callable[[str], str] | AliasGenerator, name: str) -> None:
1569 """Apply an alias generator to aliases if appropriate.
1571 Args:
1572 alias_generator: A callable that takes a string and returns a string, or an `AliasGenerator` instance.
1573 name: The name of the computed field from which to generate the alias.
1574 """
1575 # Apply an alias_generator if
1576 # 1. An alias is not specified
1577 # 2. An alias is specified, but the priority is <= 1
1579 if self.alias_priority is None or self.alias_priority <= 1 or self.alias is None:
1580 alias, _, serialization_alias = None, None, None
1582 if isinstance(alias_generator, AliasGenerator):
1583 alias, _, serialization_alias = alias_generator.generate_aliases(name)
1584 elif callable(alias_generator):
1585 alias = alias_generator(name)
1587 # if priority is not set, we set to 1
1588 # which supports the case where the alias_generator from a child class is used
1589 # to generate an alias for a field in a parent class
1590 if self.alias_priority is None or self.alias_priority <= 1:
1591 self.alias_priority = 1
1593 # if the priority is 1, then we set the aliases to the generated alias
1594 # note that we use the serialization_alias with priority over alias, as computed_field
1595 # aliases are used for serialization only (not validation)
1596 if self.alias_priority == 1:
1597 self.alias = _utils.get_first_not_none(serialization_alias, alias)
1600def _wrapped_property_is_private(property_: cached_property | property) -> bool: # type: ignore
1601 """Returns true if provided property is private, False otherwise."""
1602 wrapped_name: str = ''
1604 if isinstance(property_, property):
1605 wrapped_name = getattr(property_.fget, '__name__', '')
1606 elif isinstance(property_, cached_property): # type: ignore
1607 wrapped_name = getattr(property_.func, '__name__', '') # type: ignore
1609 return wrapped_name.startswith('_') and not wrapped_name.startswith('__')
1612# this should really be `property[T], cached_property[T]` but property is not generic unlike cached_property
1613# See https://github.com/python/typing/issues/985 and linked issues
1614PropertyT = TypeVar('PropertyT')
1617@overload
1618def computed_field(func: PropertyT, /) -> PropertyT: ...
1621@overload
1622def computed_field(
1623 *,
1624 alias: str | None = None,
1625 alias_priority: int | None = None,
1626 title: str | None = None,
1627 field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None,
1628 description: str | None = None,
1629 deprecated: Deprecated | str | bool | None = None,
1630 examples: list[Any] | None = None,
1631 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None,
1632 repr: bool = True,
1633 return_type: Any = PydanticUndefined,
1634) -> Callable[[PropertyT], PropertyT]: ...
1637def computed_field(
1638 func: PropertyT | None = None,
1639 /,
1640 *,
1641 alias: str | None = None,
1642 alias_priority: int | None = None,
1643 title: str | None = None,
1644 field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None,
1645 description: str | None = None,
1646 deprecated: Deprecated | str | bool | None = None,
1647 examples: list[Any] | None = None,
1648 json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None,
1649 repr: bool | None = None,
1650 return_type: Any = PydanticUndefined,
1651) -> PropertyT | Callable[[PropertyT], PropertyT]:
1652 """!!! abstract "Usage Documentation"
1653 [The `computed_field` decorator](../concepts/fields.md#the-computed_field-decorator)
1655 Decorator to include `property` and `cached_property` when serializing models or dataclasses.
1657 This is useful for fields that are computed from other fields, or for fields that are expensive to compute and should be cached.
1659 ```python
1660 from pydantic import BaseModel, computed_field
1662 class Rectangle(BaseModel):
1663 width: int
1664 length: int
1666 @computed_field
1667 @property
1668 def area(self) -> int:
1669 return self.width * self.length
1671 print(Rectangle(width=3, length=2).model_dump())
1672 #> {'width': 3, 'length': 2, 'area': 6}
1673 ```
1675 If applied to functions not yet decorated with `@property` or `@cached_property`, the function is
1676 automatically wrapped with `property`. Although this is more concise, you will lose IntelliSense in your IDE,
1677 and confuse static type checkers, thus explicit use of `@property` is recommended.
1679 !!! warning "Mypy Warning"
1680 Even with the `@property` or `@cached_property` applied to your function before `@computed_field`,
1681 mypy may throw a `Decorated property not supported` error.
1682 See [mypy issue #1362](https://github.com/python/mypy/issues/1362), for more information.
1683 To avoid this error message, add `# type: ignore[prop-decorator]` to the `@computed_field` line.
1685 [pyright](https://github.com/microsoft/pyright) supports `@computed_field` without error.
1687 ```python
1688 import random
1690 from pydantic import BaseModel, computed_field
1692 class Square(BaseModel):
1693 width: float
1695 @computed_field
1696 def area(self) -> float: # converted to a `property` by `computed_field`
1697 return round(self.width**2, 2)
1699 @area.setter
1700 def area(self, new_area: float) -> None:
1701 self.width = new_area**0.5
1703 @computed_field(alias='the magic number', repr=False)
1704 def random_number(self) -> int:
1705 return random.randint(0, 1_000)
1707 square = Square(width=1.3)
1709 # `random_number` does not appear in representation
1710 print(repr(square))
1711 #> Square(width=1.3, area=1.69)
1713 print(square.random_number)
1714 #> 3
1716 square.area = 4
1718 print(square.model_dump_json(by_alias=True))
1719 #> {"width":2.0,"area":4.0,"the magic number":3}
1720 ```
1722 !!! warning "Overriding with `computed_field`"
1723 You can't override a field from a parent class with a `computed_field` in the child class.
1724 `mypy` complains about this behavior if allowed, and `dataclasses` doesn't allow this pattern either.
1725 See the example below:
1727 ```python
1728 from pydantic import BaseModel, computed_field
1730 class Parent(BaseModel):
1731 a: str
1733 try:
1735 class Child(Parent):
1736 @computed_field
1737 @property
1738 def a(self) -> str:
1739 return 'new a'
1741 except TypeError as e:
1742 print(e)
1743 '''
1744 Field 'a' of class 'Child' overrides symbol of same name in a parent class. This override with a computed_field is incompatible.
1745 '''
1746 ```
1748 Private properties decorated with `@computed_field` have `repr=False` by default.
1750 ```python
1751 from functools import cached_property
1753 from pydantic import BaseModel, computed_field
1755 class Model(BaseModel):
1756 foo: int
1758 @computed_field
1759 @cached_property
1760 def _private_cached_property(self) -> int:
1761 return -self.foo
1763 @computed_field
1764 @property
1765 def _private_property(self) -> int:
1766 return -self.foo
1768 m = Model(foo=1)
1769 print(repr(m))
1770 #> Model(foo=1)
1771 ```
1773 Args:
1774 func: the function to wrap.
1775 alias: alias to use when serializing this computed field, only used when `by_alias=True`
1776 alias_priority: priority of the alias. This affects whether an alias generator is used
1777 title: Title to use when including this computed field in JSON Schema
1778 field_title_generator: A callable that takes a field name and returns title for it.
1779 description: Description to use when including this computed field in JSON Schema, defaults to the function's
1780 docstring
1781 deprecated: A deprecation message (or an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport).
1782 to be emitted when accessing the field. Or a boolean. This will automatically be set if the property is decorated with the
1783 `deprecated` decorator.
1784 examples: Example values to use when including this computed field in JSON Schema
1785 json_schema_extra: A dict or callable to provide extra JSON schema properties.
1786 repr: whether to include this computed field in model repr.
1787 Default is `False` for private properties and `True` for public properties.
1788 return_type: optional return for serialization logic to expect when serializing to JSON, if included
1789 this must be correct, otherwise a `TypeError` is raised.
1790 If you don't include a return type Any is used, which does runtime introspection to handle arbitrary
1791 objects.
1793 Returns:
1794 A proxy wrapper for the property.
1795 """
1797 def dec(f: Any) -> Any:
1798 nonlocal description, deprecated, return_type, alias_priority
1799 unwrapped = _decorators.unwrap_wrapped_function(f)
1801 if description is None and unwrapped.__doc__:
1802 description = inspect.cleandoc(unwrapped.__doc__)
1804 if deprecated is None and hasattr(unwrapped, '__deprecated__'):
1805 deprecated = unwrapped.__deprecated__
1807 # if the function isn't already decorated with `@property` (or another descriptor), then we wrap it now
1808 f = _decorators.ensure_property(f)
1809 alias_priority = (alias_priority or 2) if alias is not None else None
1811 if repr is None:
1812 repr_: bool = not _wrapped_property_is_private(property_=f)
1813 else:
1814 repr_ = repr
1816 dec_info = ComputedFieldInfo(
1817 f,
1818 return_type,
1819 alias,
1820 alias_priority,
1821 title,
1822 field_title_generator,
1823 description,
1824 deprecated,
1825 examples,
1826 json_schema_extra,
1827 repr_,
1828 )
1829 return _decorators.PydanticDescriptorProxy(f, dec_info)
1831 if func is None:
1832 return dec
1833 else:
1834 return dec(func)