# Pydantic Validation (Latest) > Data validation using Python type hints Pydantic is the most widely used data validation library for Python. Fast and extensible, Pydantic plays nicely with your linters/IDE/brain. Define how data should be in pure, canonical Python 3.9+; validate it with Pydantic. --- # [Aliases](https://pydantic.dev/docs/validation/latest/api/pydantic/aliases/) # Aliases Support for alias configurations. ## AliasPath Usage Documentation [`AliasPath` and `AliasChoices`](/docs/validation/latest/concepts/alias#aliaspath-and-aliaschoices) A data class used by `validation_alias` as a convenience to create aliases. ### Attributes #### path A list of string or integer aliases. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] ### Methods #### convert\_to\_aliases ```python def convert_to_aliases() -> list[str | int] ``` Converts arguments to a list of string or integer aliases. ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] -- The list of aliases. #### search\_dict\_for\_path ```python def search_dict_for_path(d: dict) -> Any ``` Searches a dictionary for the path specified by the alias. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The value at the specified path, or `PydanticUndefined` if the path is not found. ## AliasChoices Usage Documentation [`AliasPath` and `AliasChoices`](/docs/validation/latest/concepts/alias#aliaspath-and-aliaschoices) A data class used by `validation_alias` as a convenience to create aliases. ### Attributes #### choices A list containing a string or `AliasPath`. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath)\] ### Methods #### convert\_to\_aliases ```python def convert_to_aliases() -> list[list[str | int]] ``` Converts arguments to a list of lists containing string or integer aliases. ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] -- The list of aliases. ## AliasGenerator Usage Documentation [Using an `AliasGenerator`](/docs/validation/latest/concepts/alias#using-an-aliasgenerator) A data class used by `alias_generator` as a convenience to create various aliases. ### Attributes #### alias A callable that takes a field name and returns an alias for it. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### validation\_alias A callable that takes a field name and returns a validation alias for it. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath) | [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### serialization\_alias A callable that takes a field name and returns a serialization alias for it. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) ### Methods #### generate\_aliases ```python def generate_aliases( field_name: str, ) -> tuple[str | None, str | AliasPath | AliasChoices | None, str | None] ``` Generate `alias`, `validation_alias`, and `serialization_alias` for a field. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath) | [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) | [`None`](https://docs.python.org/3/library/constants.html#None), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)\] -- A tuple of three aliases - validation, alias, and serialization. --- # [Annotated Handlers](https://pydantic.dev/docs/validation/latest/api/pydantic/annotated_handlers/) # Annotated Handlers Type annotations to use with `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__`. ## GetJsonSchemaHandler Handler to call into the next JSON schema generation function. ### Attributes #### mode Json schema mode, can be `validation` or `serialization`. **Type:** `JsonSchemaMode` ### Methods #### resolve\_ref\_schema ```python def resolve_ref_schema(maybe_ref_json_schema: JsonSchemaValue) -> JsonSchemaValue ``` Get the real schema for a `{"$ref": ...}` schema. If the schema given is not a `$ref` schema, it will be returned as is. This means you don't have to check before calling this function. ##### Returns `JsonSchemaValue` -- A JsonSchemaValue that has no `$ref`. ##### Parameters **`maybe_ref_json_schema`** : `JsonSchemaValue` A JsonSchemaValue which may be a `$ref` schema. ##### Raises - `LookupError` -- If the ref is not found. ## GetCoreSchemaHandler Handler to call into the next CoreSchema schema generation function. ### Attributes #### field\_name Get the name of the closest field to this validator. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) ### Methods #### generate\_schema ```python def generate_schema(source_type: Any) -> core_schema.CoreSchema ``` Generate a schema unrelated to the current context. Use this function if e.g. you are handling schema generation for a sequence and want to generate a schema for its items. Otherwise, you may end up doing something like applying a `min_length` constraint that was intended for the sequence itself to its items! ##### Returns `core_schema.CoreSchema` -- The `pydantic-core` CoreSchema generated. ##### Parameters **`source_type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The input type. #### resolve\_ref\_schema ```python def resolve_ref_schema( maybe_ref_schema: core_schema.CoreSchema, ) -> core_schema.CoreSchema ``` Get the real schema for a `definition-ref` schema. If the schema given is not a `definition-ref` schema, it will be returned as is. This means you don't have to check before calling this function. ##### Returns `core_schema.CoreSchema` -- A concrete `CoreSchema`. ##### Parameters **`maybe_ref_schema`** : `core_schema.CoreSchema` A `CoreSchema`, `ref`\-based or not. ##### Raises - `LookupError` -- If the `ref` is not found. --- # [BaseModel](https://pydantic.dev/docs/validation/latest/api/pydantic/base_model/) # BaseModel Pydantic models are simply classes which inherit from `BaseModel` and define fields as annotated attributes. ## BaseModel Usage Documentation [Models](/docs/validation/latest/concepts/models) A base class for creating Pydantic models. ### Attributes #### \_\_class\_vars\_\_ The names of the class variables defined on the model. **Type:** [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] #### \_\_private\_attributes\_\_ Metadata about the private attributes of the model. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ModelPrivateAttr`\] #### \_\_signature\_\_ The synthesized `__init__` [`Signature`](https://docs.python.org/3/library/inspect.html#inspect.Signature) of the model. **Type:** `Signature` #### \_\_pydantic\_complete\_\_ Whether model building is completed, or if there are still undefined fields. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### \_\_pydantic\_core\_schema\_\_ The core schema of the model. **Type:** `CoreSchema` #### \_\_pydantic\_custom\_init\_\_ Whether the model has a custom `__init__` function. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### \_\_pydantic\_decorators\_\_ Metadata containing the decorators defined on the model. This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1. **Type:** `_decorators.DecoratorInfos` #### \_\_pydantic\_generic\_metadata\_\_ A dictionary containing metadata about generic Pydantic models. The `origin` and `args` items map to the [`__origin__`](https://docs.python.org/3/library/stdtypes.html#genericalias.__origin__) and [`__args__`](https://docs.python.org/3/library/stdtypes.html#genericalias.__args__) attributes of [generic aliases](https://docs.python.org/3/library/stdtypes.html#types-genericalias), and the `parameter` item maps to the `__parameter__` attribute of generic classes. **Type:** `_generics.PydanticGenericMetadata` #### \_\_pydantic\_parent\_namespace\_\_ Parent namespace of the model, used for automatic rebuilding of models. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### \_\_pydantic\_post\_init\_\_ The name of the post-init method for the model, if defined. **Type:** [`None`](https://docs.python.org/3/library/constants.html#None) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['model\_post\_init'\] #### \_\_pydantic\_root\_model\_\_ Whether the model is a [`RootModel`](/docs/validation/latest/api/pydantic/root_model/#pydantic.root_model.RootModel). **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### \_\_pydantic\_serializer\_\_ The `pydantic-core` `SchemaSerializer` used to dump instances of the model. **Type:** `SchemaSerializer` #### \_\_pydantic\_validator\_\_ The `pydantic-core` `SchemaValidator` used to validate instances of the model. **Type:** `SchemaValidator` | `PluggableSchemaValidator` #### \_\_pydantic\_fields\_\_ A dictionary of field names and their corresponding [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) objects. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `FieldInfo`\] #### \_\_pydantic\_computed\_fields\_\_ A dictionary of computed field names and their corresponding [`ComputedFieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.ComputedFieldInfo) objects. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ComputedFieldInfo`\] #### \_\_pydantic\_extra\_\_ A dictionary containing extra values, if [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) is set to `'allow'`. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### \_\_pydantic\_fields\_set\_\_ The names of fields explicitly set during instantiation. **Type:** [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] #### \_\_pydantic\_private\_\_ Values of private attributes set on the model instance. **Type:** [`Dict`](https://docs.python.org/3/library/typing.html#typing.Dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) ### Methods #### \_\_init\_\_ ```python def __init__(data: Any = {}) -> None ``` Raises [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) if the input data cannot be validated to form a valid model. `self` is explicitly positional-only to allow `self` as a field name. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### model\_fields `@classmethod` ```python def model_fields(cls) -> dict[str, FieldInfo] ``` A mapping of field names to their respective [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instances. Caution Accessing this attribute from a model instance is deprecated, and will not work in Pydantic V3. Instead, you should access this attribute from the model class. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `FieldInfo`\] #### model\_computed\_fields `@classmethod` ```python def model_computed_fields(cls) -> dict[str, ComputedFieldInfo] ``` A mapping of computed field names to their respective [`ComputedFieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.ComputedFieldInfo) instances. Caution Accessing this attribute from a model instance is deprecated, and will not work in Pydantic V3. Instead, you should access this attribute from the model class. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ComputedFieldInfo`\] #### model\_construct `@classmethod` ```python def model_construct(cls, _fields_set: set[str] | None = None, values: Any = {}) -> Self ``` Creates a new instance of the `Model` class with validated data. Creates a new model setting `__dict__` and `__pydantic_fields_set__` from trusted or pre-validated data. Default values are respected, but no other validation is performed. Note `model_construct()` generally respects the `model_config.extra` setting on the provided model. That is, if `model_config.extra == 'allow'`, then all extra passed values are added to the model instance's `__dict__` and `__pydantic_extra__` fields. If `model_config.extra == 'ignore'` (the default), then all extra passed values are ignored. Because no validation is performed with a call to `model_construct()`, having `model_config.extra == 'forbid'` does not result in an error if extra values are passed, but they will be ignored. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- A new instance of the `Model` class with validated data. ##### Parameters **`_fields_set`** : [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of field names that were originally explicitly set during instantiation. If provided, this is directly used for the [`model_fields_set`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields_set) attribute. Otherwise, the field names from the `values` argument will be used. **`values`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `{}` Trusted or pre-validated data dictionary. #### model\_copy ```python def model_copy(update: Mapping[str, Any] | None = None, deep: bool = False) -> Self ``` Usage Documentation [`model_copy`](/docs/validation/latest/concepts/models#model-copy) Returns a copy of the model. Note The underlying instance's [`__dict__`](https://docs.python.org/3/reference/datamodel.html#object.__dict__) attribute is copied. This might have unexpected side effects if you store anything in it, on top of the model fields (e.g. the value of [cached properties](https://docs.python.org/3/library/functools.html#functools.cached_property)). ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- New model instance. ##### Parameters **`update`** : [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Values to change/add in the new model. Note: the data is not validated before creating the new model. You should trust this data. **`deep`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Set to `True` to make a deep copy of the model. #### model\_dump ```python def model_dump( mode: Literal['json', 'python'] | str = 'python', include: IncEx | None = None, exclude: IncEx | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, ) -> dict[str, Any] ``` Usage Documentation [`model_dump`](/docs/validation/latest/concepts/serialization#python-mode) Generate a dictionary representation of the model, optionally specifying which fields to include or exclude. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- A dictionary representation of the model. ##### Parameters **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['json', 'python'\] | [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `'python'` The mode in which `to_python` should run. If mode is 'json', the output will only contain JSON serializable types. If mode is 'python', the output may contain non-JSON-serializable Python objects. **`include`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to include in the output. **`exclude`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to exclude from the output. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the serializer. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias in the dictionary key if defined. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have not been explicitly set. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are set to their default value. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If True, dumped values should be valid as input for non-idempotent types such as Json\[T\]. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. #### model\_dump\_json ```python def model_dump_json( indent: int | None = None, ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, context: Any | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, ) -> str ``` Usage Documentation [`model_dump_json`](/docs/validation/latest/concepts/serialization#json-mode) Generates a JSON representation of the model using Pydantic's `to_json` method. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- A JSON string representation of the model. ##### Parameters **`indent`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Indentation to use in the JSON output. If None is passed, the output will be compact. **`ensure_ascii`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. If `False` (the default), these characters will be output as-is. **`include`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Field(s) to include in the JSON output. **`exclude`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Field(s) to exclude from the JSON output. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the serializer. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to serialize using field aliases. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have not been explicitly set. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are set to their default value. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If True, dumped values should be valid as input for non-idempotent types such as Json\[T\]. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. #### model\_json\_schema `@classmethod` ```python def model_json_schema( cls, by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE, schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, mode: JsonSchemaMode = 'validation', union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', ) -> dict[str, Any] ``` Generates a JSON schema for a model class. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- The JSON schema for the given model class. ##### Parameters **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use attribute aliases or not. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The reference template. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` To override the logic used to generate the JSON schema, as a subclass of `GenerateJsonSchema` with your desired modifications **`mode`** : `JsonSchemaMode` _Default:_ `'validation'` The mode in which to generate the schema. #### model\_parametrized\_name `@classmethod` ```python def model_parametrized_name(cls, params: tuple[type[Any], ...]) -> str ``` Compute the class name for parametrizations of generic classes. This method can be overridden to achieve a custom naming scheme for generic BaseModels. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- String representing the new class where `params` are passed to `cls` as type variables. ##### Parameters **`params`** : [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], ...\] Tuple of types of the class. Given a generic class `Model` with 2 type variables and a concrete model `Model[str, int]`, the value `(str, int)` would be passed to `params`. ##### Raises - `TypeError` -- Raised when trying to generate concrete names for non-generic models. #### model\_post\_init ```python def model_post_init(context: Any) -> None ``` Override this method to perform additional initialization after `__init__` and `model_construct`. This is useful if you want to do some validation that requires the entire model to be initialized. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### model\_rebuild `@classmethod` ```python def model_rebuild( cls, force: bool = False, raise_errors: bool = True, _parent_namespace_depth: int = 2, _types_namespace: MappingNamespace | None = None, ) -> bool | None ``` Try to rebuild the pydantic-core schema for the model. This may be necessary when one of the annotations is a ForwardRef which could not be resolved during the initial attempt to build the schema, and automatic rebuilding fails. ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- Returns `None` if the schema is already "complete" and rebuilding was not required. [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. ##### Parameters **`force`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to force the rebuilding of the model schema, defaults to `False`. **`raise_errors`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to raise errors, defaults to `True`. **`_parent_namespace_depth`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `2` The depth level of the parent namespace, defaults to 2. **`_types_namespace`** : `MappingNamespace` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The types namespace, defaults to `None`. #### model\_validate `@classmethod` ```python def model_validate( cls, obj: Any, strict: bool | None = None, extra: ExtraValues | None = None, from_attributes: bool | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None, ) -> Self ``` Validate a pydantic model instance. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- The validated model instance. ##### Parameters **`obj`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The object to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to enforce types strictly. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to extract data from object attributes. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the validator. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If the object could not be validated. #### model\_validate\_json `@classmethod` ```python def model_validate_json( cls, json_data: str | bytes | bytearray, strict: bool | None = None, extra: ExtraValues | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None, ) -> Self ``` Usage Documentation [JSON Parsing](/docs/validation/latest/concepts/json#json-parsing) Validate the given JSON data against the Pydantic model. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- The validated Pydantic model. ##### Parameters **`json_data`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) | [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) The JSON data to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to enforce types strictly. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Extra variables to pass to the validator. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If `json_data` is not a JSON string or the object could not be validated. #### model\_validate\_strings `@classmethod` ```python def model_validate_strings( cls, obj: Any, strict: bool | None = None, extra: ExtraValues | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None, ) -> Self ``` Validate the given object with string data against the Pydantic model. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- The validated Pydantic model. ##### Parameters **`obj`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The object containing string data to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to enforce types strictly. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Extra variables to pass to the validator. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ## create\_model ```python def create_model( model_name: str, __config__: ConfigDict | None = None, __doc__: str | None = None, __base__: None = None, __module__: str = __name__, __validators__: dict[str, Callable[..., Any]] | None = None, __cls_kwargs__: dict[str, Any] | None = None, __qualname__: str | None = None, field_definitions: Any | tuple[Any, Any] = {}, ) -> type[BaseModel] def create_model( model_name: str, __config__: ConfigDict | None = None, __doc__: str | None = None, __base__: type[ModelT] | tuple[type[ModelT], ...], __module__: str = __name__, __validators__: dict[str, Callable[..., Any]] | None = None, __cls_kwargs__: dict[str, Any] | None = None, __qualname__: str | None = None, field_definitions: Any | tuple[Any, Any] = {}, ) -> type[ModelT] ``` Usage Documentation [Dynamic Model Creation](/docs/validation/latest/concepts/models#dynamic-model-creation) Dynamically creates and returns a new Pydantic model, in other words, `create_model` dynamically creates a subclass of [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). Caution This function may execute arbitrary code contained in field annotations, if string references need to be evaluated. See [Security implications of introspecting annotations](https://docs.python.org/3/library/annotationlib.html#annotationlib-security) for more information. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[`ModelT`\] -- The new [model](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). ### Parameters **`model_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name of the newly created model. **`__config__`** : [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The configuration of the new model. **`__doc__`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The docstring of the new model. **`__base__`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`ModelT`\] | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[`ModelT`\], ...\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The base class or classes for the new model. **`__module__`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the module that the model belongs to; if `None`, the value is taken from `sys._getframe(1)` **`__validators__`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A dictionary of methods that validate fields. The keys are the names of the validation methods to be added to the model, and the values are the validation methods themselves. You can read more about functional validators [here](https://docs.pydantic.dev/2.9/concepts/validators/#field-validators). **`__cls_kwargs__`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A dictionary of keyword arguments for class creation, such as `metaclass`. **`__qualname__`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The qualified name of the newly created model. **`**field_definitions`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] _Default:_ `{}` Field definitions of the new model. Either: - a single element, representing the type annotation of the field. - a two-tuple, the first element being the type and the second element the assigned value (either a default or the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function). ### Raises - `PydanticUserError` -- If `__base__` and `__config__` are both passed. --- # [Configuration](https://pydantic.dev/docs/validation/latest/api/pydantic/config/) # Configuration Configuration for Pydantic models. ## ConfigDict **Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) A TypedDict for configuring Pydantic behaviour. ### Attributes #### title The title for the generated JSON schema, defaults to the model's name **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### model\_title\_generator A callable that takes a model class and returns the title for it. Defaults to `None`. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`type`](https://docs.python.org/3/glossary.html#term-type)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### field\_title\_generator A callable that takes a field's name and info and returns title for it. Defaults to `None`. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `FieldInfo` | `ComputedFieldInfo`\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### str\_to\_lower Whether to convert all characters to lowercase for str types. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_to\_upper Whether to convert all characters to uppercase for str types. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_strip\_whitespace Whether to strip leading and trailing whitespace for str types. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_min\_length The minimum length for str types. Defaults to `None`. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) #### str\_max\_length The maximum length for str types. Defaults to `None`. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### extra Whether to ignore, allow, or forbid extra data during model initialization. Defaults to `'ignore'`. Three configuration values are available: - `'ignore'`: Providing extra data is ignored (the default): ```python from pydantic import BaseModel, ConfigDict class User(BaseModel): model_config = ConfigDict(extra='ignore') # (1) name: str user = User(name='John Doe', age=20) # (2) print(user) #> name='John Doe' ``` This is the default behaviour. The `age` argument is ignored. - `'forbid'`: Providing extra data is not permitted, and a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) will be raised if this is the case: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: int model_config = ConfigDict(extra='forbid') try: Model(x=1, y='a') except ValidationError as exc: print(exc) """ 1 validation error for Model y Extra inputs are not permitted [type=extra_forbidden, input_value='a', input_type=str] """ ``` - `'allow'`: Providing extra data is allowed and stored in the `__pydantic_extra__` dictionary attribute: ```python from pydantic import BaseModel, ConfigDict class Model(BaseModel): x: int model_config = ConfigDict(extra='allow') m = Model(x=1, y='a') assert m.__pydantic_extra__ == {'y': 'a'} ``` By default, no validation will be applied to these extra items, but you can set a type for the values by overriding the type annotation for `__pydantic_extra__`: ```python from pydantic import BaseModel, ConfigDict, Field, ValidationError class Model(BaseModel): __pydantic_extra__: dict[str, int] = Field(init=False) # (1) x: int model_config = ConfigDict(extra='allow') try: Model(x=1, y='a') except ValidationError as exc: print(exc) """ 1 validation error for Model y Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] """ m = Model(x=1, y='2') assert m.x == 1 assert m.y == 2 assert m.model_dump() == {'x': 1, 'y': 2} assert m.__pydantic_extra__ == {'y': 2} ``` The `= Field(init=False)` does not have any effect at runtime, but prevents the `__pydantic_extra__` field from being included as a parameter to the model's `__init__` method by type checkers. As well as specifying an `extra` configuration value on the model, you can also provide it as an argument to the validation methods. This will override any `extra` configuration value set on the model: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: int model_config = ConfigDict(extra="allow") try: # Override model config and forbid extra fields just this time Model.model_validate({"x": 1, "y": 2}, extra="forbid") except ValidationError as exc: print(exc) """ 1 validation error for Model y Extra inputs are not permitted [type=extra_forbidden, input_value=2, input_type=int] """ ``` **Type:** `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) #### frozen Whether models are faux-immutable, i.e. whether `__setattr__` is allowed, and also generates a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the attributes are hashable. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### populate\_by\_name Whether an aliased field may be populated by its name as given by the model attribute, as well as the alias. Defaults to `False`. Caution `populate_by_name` usage is not recommended in v2.11+ and will be deprecated in v3. Instead, you should use the [`validate_by_name`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_name) configuration setting. When `validate_by_name=True` and `validate_by_alias=True`, this is strictly equivalent to the previous behavior of `populate_by_name=True`. In v2.11, we also introduced a [`validate_by_alias`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_alias) setting that introduces more fine grained control for validation behavior. Here's how you might go about using the new settings to achieve the same behavior: ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): model_config = ConfigDict(validate_by_name=True, validate_by_alias=True) my_field: str = Field(alias='my_alias') # (1) m = Model(my_alias='foo') # (2) print(m) #> my_field='foo' m = Model(my_field='foo') # (3) print(m) #> my_field='foo' ``` The field `'my_field'` has an alias `'my_alias'`. The model is populated by the alias `'my_alias'`. The model is populated by the attribute name `'my_field'`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### use\_enum\_values Whether to populate models with the `value` property of enums, rather than the raw enum. This may be useful if you want to serialize `model.model_dump()` later. Defaults to `False`. Note If you have an `Optional[Enum]` value that you set a default for, you need to use `validate_default=True` for said Field to ensure that the `use_enum_values` flag takes effect on the default, as extracting an enum's value occurs during validation, not serialization. ```python from enum import Enum from typing import Optional from pydantic import BaseModel, ConfigDict, Field class SomeEnum(Enum): FOO = 'foo' BAR = 'bar' BAZ = 'baz' class SomeModel(BaseModel): model_config = ConfigDict(use_enum_values=True) some_enum: SomeEnum another_enum: Optional[SomeEnum] = Field( default=SomeEnum.FOO, validate_default=True ) model1 = SomeModel(some_enum=SomeEnum.BAR) print(model1.model_dump()) #> {'some_enum': 'bar', 'another_enum': 'foo'} model2 = SomeModel(some_enum=SomeEnum.BAR, another_enum=SomeEnum.BAZ) print(model2.model_dump()) #> {'some_enum': 'bar', 'another_enum': 'baz'} ``` **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### validate\_assignment Whether to validate the data when the model is changed. Defaults to `False`. The default behavior of Pydantic is to validate the data when the model is created. In case the user changes the data after the model is created, the model is _not_ revalidated. ```python from pydantic import BaseModel class User(BaseModel): name: str user = User(name='John Doe') # (1) print(user) #> name='John Doe' user.name = 123 # (1) print(user) #> name=123 ``` The validation happens only when the model is created. The validation does not happen when the data is changed. In case you want to revalidate the model when the data is changed, you can use `validate_assignment=True`: ```python from pydantic import BaseModel, ValidationError class User(BaseModel, validate_assignment=True): # (1) name: str user = User(name='John Doe') # (2) print(user) #> name='John Doe' try: user.name = 123 # (3) except ValidationError as e: print(e) ''' 1 validation error for User name Input should be a valid string [type=string_type, input_value=123, input_type=int] ''' ``` You can either use class keyword arguments, or `model_config` to set `validate_assignment=True`. The validation happens when the model is created. The validation _also_ happens when the data is changed. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### arbitrary\_types\_allowed Whether arbitrary types are allowed for field types. Defaults to `False`. ```python from pydantic import BaseModel, ConfigDict, ValidationError # This is not a pydantic model, it's an arbitrary class class Pet: def __init__(self, name: str): self.name = name class Model(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) pet: Pet owner: str pet = Pet(name='Hedwig') # A simple check of instance type is used to validate the data model = Model(owner='Harry', pet=pet) print(model) #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry' print(model.pet) #> <__main__.Pet object at 0x0123456789ab> print(model.pet.name) #> Hedwig print(type(model.pet)) #> try: # If the value is not an instance of the type, it's invalid Model(owner='Harry', pet='Hedwig') except ValidationError as e: print(e) ''' 1 validation error for Model pet Input should be an instance of Pet [type=is_instance_of, input_value='Hedwig', input_type=str] ''' # Nothing in the instance of the arbitrary type is checked # Here name probably should have been a str, but it's not validated pet2 = Pet(name=42) model2 = Model(owner='Harry', pet=pet2) print(model2) #> pet=<__main__.Pet object at 0x0123456789ab> owner='Harry' print(model2.pet) #> <__main__.Pet object at 0x0123456789ab> print(model2.pet.name) #> 42 print(type(model2.pet)) #> ``` **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### from\_attributes Whether to build models and look up discriminators of tagged unions using python object attributes. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### loc\_by\_alias Whether to use the actual key provided in the data (e.g. alias) for error `loc`s rather than the field's name. Defaults to `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### alias\_generator A callable that takes a field name and returns an alias for it or an instance of [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator). Defaults to `None`. When using a callable, the alias generator is used for both validation and serialization. If you want to use different alias generators for validation and serialization, you can use [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator) instead. If data source field names do not match your code style (e.g. CamelCase fields), you can automatically generate aliases using `alias_generator`. Here's an example with a basic callable: ```python from pydantic import BaseModel, ConfigDict from pydantic.alias_generators import to_pascal class Voice(BaseModel): model_config = ConfigDict(alias_generator=to_pascal) name: str language_code: str voice = Voice(Name='Filiz', LanguageCode='tr-TR') print(voice.language_code) #> tr-TR print(voice.model_dump(by_alias=True)) #> {'Name': 'Filiz', 'LanguageCode': 'tr-TR'} ``` If you want to use different alias generators for validation and serialization, you can use [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator). ```python from pydantic import AliasGenerator, BaseModel, ConfigDict from pydantic.alias_generators import to_camel, to_pascal class Athlete(BaseModel): first_name: str last_name: str sport: str model_config = ConfigDict( alias_generator=AliasGenerator( validation_alias=to_camel, serialization_alias=to_pascal, ) ) athlete = Athlete(firstName='John', lastName='Doe', sport='track') print(athlete.model_dump(by_alias=True)) #> {'FirstName': 'John', 'LastName': 'Doe', 'Sport': 'track'} ``` **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator) | [`None`](https://docs.python.org/3/library/constants.html#None) #### ignored\_types A tuple of types that may occur as values of class attributes without annotations. This is typically used for custom descriptors (classes that behave like `property`). If an attribute is set on a class without an annotation and has a type that is not in this tuple (or otherwise recognized by _pydantic_), an error will be raised. Defaults to `()`. **Type:** [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`type`](https://docs.python.org/3/glossary.html#term-type), ...\] #### allow\_inf\_nan Whether to allow infinity (`+inf` an `-inf`) and NaN values to float and decimal fields. Defaults to `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### json\_schema\_extra A dict or callable to provide extra JSON schema properties. Defaults to `None`. **Type:** `JsonDict` | `JsonSchemaExtraCallable` | [`None`](https://docs.python.org/3/library/constants.html#None) #### json\_encoders A `dict` of custom JSON encoders for specific types. Defaults to `None`. ⚠ Deprecated in v2 This configuration option is a carryover from v1. We originally planned to remove it in v2 but didn't have a 1:1 replacement so we are keeping it for now. It is still deprecated and will likely be removed in the future. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[[`object`](https://docs.python.org/3/glossary.html#term-object)\], `JsonEncoder`\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### strict Whether strict validation is applied to all fields on the model. By default, Pydantic attempts to coerce values to the correct type, when possible. There are situations in which you may want to disable this behavior, and instead raise an error if a value's type does not match the field's type annotation. To configure strict mode for all fields on a model, you can set `strict=True` on the model. ```python from pydantic import BaseModel, ConfigDict class Model(BaseModel): model_config = ConfigDict(strict=True) name: str age: int ``` See [Strict Mode](/docs/validation/latest/concepts/strict_mode) for more details. See the [Conversion Table](/docs/validation/latest/concepts/conversion_table) for more details on how Pydantic converts data in both strict and lax modes. ✦ New in v2 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### revalidate\_instances When and how to revalidate models and dataclasses during validation. Can be one of: - `'never'`: will _not_ revalidate models and dataclasses during validation - `'always'`: will revalidate models and dataclasses during validation - `'subclass-instances'`: will revalidate models and dataclasses during validation if the instance is a subclass of the model or dataclass The default is `'never'` (no revalidation). This configuration only affects _the current model_ it is applied on, and does _not_ propagate to the models referenced in fields. ```python from pydantic import BaseModel class User(BaseModel, revalidate_instances='never'): # (1) name: str class Transaction(BaseModel): user: User my_user = User(name='John') t = Transaction(user=my_user) my_user.name = 1 # (2) t = Transaction(user=my_user) # (3) print(t) #> user=User(name=1) ``` This is the default behavior. The assignment is _not_ validated, unless you set [`validate_assignment`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_assignment) in the configuration. Since `revalidate_instances` is set to `'never'`, the user instance is not revalidated. Here is an example demonstrating the behavior of `'subclass-instances'`: ```python from pydantic import BaseModel class User(BaseModel, revalidate_instances='subclass-instances'): name: str class SubUser(User): age: int class Transaction(BaseModel): user: User my_user = User(name='John') my_user.name = 1 # (1) t = Transaction(user=my_user) # (2) print(t) #> user=User(name=1) my_sub_user = SubUser(name='John', age=20) t = Transaction(user=my_sub_user) print(t) # (3) #> user=User(name='John') ``` The assignment is _not_ validated, unless you set [`validate_assignment`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_assignment) in the configuration. Because `my_user` is a "direct" instance of `User`, it is _not_ being revalidated. It would have been the case if `revalidate_instances` was set to `'always'`. Because `my_sub_user` is an instance of a `User` subclass, it is being revalidated. In this case, Pydantic coerces `my_sub_user` to the defined `User` class defined on `Transaction`. If one of its fields had an invalid value, a validation error would have been raised. ✦ New in v2 **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['always', 'never', 'subclass-instances'\] #### ser\_json\_timedelta The format of JSON serialized timedeltas. Accepts the string values of `'iso8601'` and `'float'`. Defaults to `'iso8601'`. - `'iso8601'` will serialize timedeltas to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations). - `'float'` will serialize timedeltas to the total number of seconds. ↻ Changed in v2.12 It is now recommended to use the [`ser_json_temporal`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.ser_json_temporal) setting. `ser_json_timedelta` will be deprecated in v3. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'float'\] #### ser\_json\_temporal The format of JSON serialized temporal types from the [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) module. This includes: - [`datetime.datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) - [`datetime.date`](https://docs.python.org/3/library/datetime.html#datetime.date) - [`datetime.time`](https://docs.python.org/3/library/datetime.html#datetime.time) - [`datetime.timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) Can be one of: - `'iso8601'` will serialize date-like types to [ISO 8601 text format](https://en.wikipedia.org/wiki/ISO_8601#Durations). - `'milliseconds'` will serialize date-like types to a floating point number of milliseconds since the epoch. - `'seconds'` will serialize date-like types to a floating point number of seconds since the epoch. Defaults to `'iso8601'`. ✦ New in v2.12 This setting replaces [`ser_json_timedelta`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.ser_json_timedelta), which will be deprecated in v3. `ser_json_temporal` adds more configurability for the other temporal types. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'seconds', 'milliseconds'\] #### val\_temporal\_unit The unit to assume for validating numeric input for datetime-like types ([`datetime.datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) and [`datetime.date`](https://docs.python.org/3/library/datetime.html#datetime.date)). Can be one of: - `'seconds'` will validate date or time numeric inputs as seconds since the [epoch](https://en.wikipedia.org/wiki/Unix_time). - `'milliseconds'` will validate date or time numeric inputs as milliseconds since the [epoch](https://en.wikipedia.org/wiki/Unix_time). - `'infer'` will infer the unit from the string numeric input on unix time as: - seconds since the [epoch](https://en.wikipedia.org/wiki/Unix_time) if $-2^{10} <= v <= 2^{10}$ - milliseconds since the [epoch](https://en.wikipedia.org/wiki/Unix_time) (if $v < -2^{10}$ or $v > 2^{10}$). Defaults to `'infer'`. ✦ New in v2.12 **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['seconds', 'milliseconds', 'infer'\] #### ser\_json\_bytes The encoding of JSON serialized bytes. Defaults to `'utf8'`. Set equal to `val_json_bytes` to get back an equal value after serialization round trip. - `'utf8'` will serialize bytes to UTF-8 strings. - `'base64'` will serialize bytes to URL safe base64 strings. - `'hex'` will serialize bytes to hexadecimal strings. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] #### val\_json\_bytes ✦ New in v2.9 The encoding of JSON serialized bytes to decode. Defaults to `'utf8'`. Set equal to `ser_json_bytes` to get back an equal value after serialization round trip. - `'utf8'` will deserialize UTF-8 strings to bytes. - `'base64'` will deserialize URL safe base64 strings to bytes. - `'hex'` will deserialize hexadecimal strings to bytes. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] #### ser\_json\_inf\_nan The encoding of JSON serialized infinity and NaN float values. Defaults to `'null'`. - `'null'` will serialize infinity and NaN values as `null`. - `'constants'` will serialize infinity and NaN values as `Infinity` and `NaN`. - `'strings'` will serialize infinity as string `"Infinity"` and NaN as string `"NaN"`. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['null', 'constants', 'strings'\] #### validate\_default Whether to validate default values during validation. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### validate\_return Whether to validate the return value from call validators. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### protected\_namespaces A tuple of strings and/or regex patterns that prevent models from having fields with names that conflict with its existing members/methods. Strings are matched on a prefix basis. For instance, with `'dog'`, having a field named `'dog_name'` will be disallowed. Regex patterns are matched on the entire field name. For instance, with the pattern `'^dog, having a field named` 'dog' `will be disallowed,`, having a field named �IC1� will be disallowed, but `'dog_name'` will be accepted. Defaults to `('model_validate', 'model_dump')`. This default is used to prevent collisions with the existing (and possibly future) [validation](/docs/validation/latest/concepts/models#validating-data) and [serialization](/docs/validation/latest/concepts/serialization#serializing-data) methods. ```python import warnings from pydantic import BaseModel warnings.filterwarnings('error') # Raise warnings as errors try: class Model(BaseModel): model_dump_something: str except UserWarning as e: print(e) ''' Field 'model_dump_something' in 'Model' conflicts with protected namespace 'model_dump'. You may be able to solve this by setting the 'protected_namespaces' configuration to ('model_validate',). ''' ``` You can customize this behavior using the `protected_namespaces` setting: ```python import re import warnings from pydantic import BaseModel, ConfigDict with warnings.catch_warnings(record=True) as caught_warnings: warnings.simplefilter('always') # Catch all warnings class Model(BaseModel): safe_field: str also_protect_field: str protect_this: str model_config = ConfigDict( protected_namespaces=( 'protect_me_', 'also_protect_', re.compile('^protect_this$'), ) ) for warning in caught_warnings: print(f'{warning.message}') ''' Field 'also_protect_field' in 'Model' conflicts with protected namespace 'also_protect_'. You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', re.compile('^protect_this$'))`. Field 'protect_this' in 'Model' conflicts with protected namespace 're.compile('^protect_this$')'. You may be able to solve this by setting the 'protected_namespaces' configuration to ('protect_me_', 'also_protect_')`. ''' ``` While Pydantic will only emit a warning when an item is in a protected namespace but does not actually have a collision, an error _is_ raised if there is an actual collision with an existing attribute: ```python from pydantic import BaseModel, ConfigDict try: class Model(BaseModel): model_validate: str model_config = ConfigDict(protected_namespaces=('model_',)) except ValueError as e: print(e) ''' Field 'model_validate' conflicts with member > of protected namespace 'model_'. ''' ``` ↻ Changed in v2.10 The default protected namespaces was changed from `('model_',)` to `('model_validate', 'model_dump')`, to allow for fields like `model_id`, `model_name` to be used. **Type:** [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Pattern`](https://docs.python.org/3/library/typing.html#typing.Pattern)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], ...\] #### hide\_input\_in\_errors Whether to hide inputs when printing errors. Defaults to `False`. Pydantic shows the input value and type when it raises `ValidationError` during the validation. ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): a: str try: Model(a=123) except ValidationError as e: print(e) ''' 1 validation error for Model a Input should be a valid string [type=string_type, input_value=123, input_type=int] ''' ``` You can hide the input value and type by setting the `hide_input_in_errors` config to `True`. ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): a: str model_config = ConfigDict(hide_input_in_errors=True) try: Model(a=123) except ValidationError as e: print(e) ''' 1 validation error for Model a Input should be a valid string [type=string_type] ''' ``` **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### defer\_build Whether to defer model validator and serializer construction until the first model validation. Defaults to False. This can be useful to avoid the overhead of building models which are only used nested within other models, or when you want to manually define type namespace via [`Model.model_rebuild(_types_namespace=...)`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild). ↻ Changed in v2.10 The setting also applies to [Pydantic dataclasses](/docs/validation/latest/concepts/dataclasses) and [type adapters](/docs/validation/latest/concepts/type_adapter). **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### plugin\_settings A `dict` of settings for plugins. Defaults to `None`. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`object`](https://docs.python.org/3/glossary.html#term-object)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### schema\_generator The `GenerateSchema` class to use during core schema generation. ⚠ Deprecated in v2.10 The `GenerateSchema` class is private and highly subject to change. **Type:** [`type`](https://docs.python.org/3/glossary.html#term-type)\[`_GenerateSchema`\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### json\_schema\_serialization\_defaults\_required Whether fields with default values should be marked as required in the serialization schema. Defaults to `False`. This ensures that the serialization schema will reflect the fact a field with a default will always be present when serializing the model, even though it is not required for validation. However, there are scenarios where this may be undesirable -- in particular, if you want to share the schema between validation and serialization, and don't mind fields with defaults being marked as not required during serialization. See [#7209](https://github.com/pydantic/pydantic/issues/7209) for more details. ```python from pydantic import BaseModel, ConfigDict class Model(BaseModel): a: str = 'a' model_config = ConfigDict(json_schema_serialization_defaults_required=True) print(Model.model_json_schema(mode='validation')) ''' { 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}}, 'title': 'Model', 'type': 'object', } ''' print(Model.model_json_schema(mode='serialization')) ''' { 'properties': {'a': {'default': 'a', 'title': 'A', 'type': 'string'}}, 'required': ['a'], 'title': 'Model', 'type': 'object', } ''' ``` ✦ New in v2.4 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### json\_schema\_mode\_override If not `None`, the specified mode will be used to generate the JSON schema regardless of what `mode` was passed to the function call. Defaults to `None`. This provides a way to force the JSON schema generation to reflect a specific mode, e.g., to always use the validation schema. It can be useful when using frameworks (such as FastAPI) that may generate different schemas for validation and serialization that must both be referenced from the same schema; when this happens, we automatically append `-Input` to the definition reference for the validation schema and `-Output` to the definition reference for the serialization schema. By specifying a `json_schema_mode_override` though, this prevents the conflict between the validation and serialization schemas (since both will use the specified schema), and so prevents the suffixes from being added to the definition references. ```python from pydantic import BaseModel, ConfigDict, Json class Model(BaseModel): a: Json[int] # requires a string to validate, but will dump an int print(Model.model_json_schema(mode='serialization')) ''' { 'properties': {'a': {'title': 'A', 'type': 'integer'}}, 'required': ['a'], 'title': 'Model', 'type': 'object', } ''' class ForceInputModel(Model): # the following ensures that even with mode='serialization', we # will get the schema that would be generated for validation. model_config = ConfigDict(json_schema_mode_override='validation') print(ForceInputModel.model_json_schema(mode='serialization')) ''' { 'properties': { 'a': { 'contentMediaType': 'application/json', 'contentSchema': {'type': 'integer'}, 'title': 'A', 'type': 'string', } }, 'required': ['a'], 'title': 'ForceInputModel', 'type': 'object', } ''' ``` ✦ New in v2.4 **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['validation', 'serialization', [`None`](https://docs.python.org/3/library/constants.html#None)\] #### coerce\_numbers\_to\_str If `True`, enables automatic coercion of any `Number` type to `str` in "lax" (non-strict) mode. Defaults to `False`. Pydantic doesn't allow number types (`int`, `float`, `Decimal`) to be coerced as type `str` by default. ```python from decimal import Decimal from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): value: str try: print(Model(value=42)) except ValidationError as e: print(e) ''' 1 validation error for Model value Input should be a valid string [type=string_type, input_value=42, input_type=int] ''' class Model(BaseModel): model_config = ConfigDict(coerce_numbers_to_str=True) value: str repr(Model(value=42).value) #> "42" repr(Model(value=42.13).value) #> "42.13" repr(Model(value=Decimal('42.13')).value) #> "42.13" ``` **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### regex\_engine The regex engine to be used for pattern validation. Defaults to `'rust-regex'`. - `'rust-regex'` uses the [`regex`](https://docs.rs/regex) Rust crate, which is non-backtracking and therefore more DDoS resistant, but does not support all regex features. - `'python-re'` use the [`re`](https://docs.python.org/3/library/re.html#module-re) module, which supports all regex features, but may be slower. Note If you use a compiled regex pattern, the `'python-re'` engine will be used regardless of this setting. This is so that flags such as [`re.IGNORECASE`](https://docs.python.org/3/library/re.html#re.IGNORECASE) are respected. ```python from pydantic import BaseModel, ConfigDict, Field, ValidationError class Model(BaseModel): model_config = ConfigDict(regex_engine='python-re') value: str = Field(pattern=r'^abc(?=def)') print(Model(value='abcdef').value) #> abcdef try: print(Model(value='abxyzcdef')) except ValidationError as e: print(e) ''' 1 validation error for Model value String should match pattern '^abc(?=def)' [type=string_pattern_mismatch, input_value='abxyzcdef', input_type=str] ''' ``` ✦ New in v2.5 **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['rust-regex', 'python-re'\] #### validation\_error\_cause If `True`, Python exceptions that were part of a validation failure will be shown as an exception group as a cause. Can be useful for debugging. Defaults to `False`. ✦ New in v2.5 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### use\_attribute\_docstrings Whether docstrings of attributes (bare string literals immediately following the attribute declaration) should be used for field descriptions. Defaults to `False`. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): model_config = ConfigDict(use_attribute_docstrings=True) x: str """ Example of an attribute docstring """ y: int = Field(description="Description in Field") """ Description in Field overrides attribute docstring """ print(Model.model_fields["x"].description) # > Example of an attribute docstring print(Model.model_fields["y"].description) # > Description in Field ``` This requires the source code of the class to be available at runtime (and so won't work in the interactive interpreter shell). Usage with `TypedDict` and stdlib dataclasses Due to current limitations, attribute docstrings detection may not work as expected when using [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) and stdlib dataclasses, in particular when: - inheritance is being used. - multiple classes have the same name in the same source file (unless Python 3.13 or greater is used). ✦ New in v2.7 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### cache\_strings Whether to cache strings to avoid constructing new Python objects. Defaults to True. Enabling this setting should significantly improve validation performance while increasing memory usage slightly. - `True` or `'all'` (the default): cache all strings - `'keys'`: cache only dictionary keys - `False` or `'none'`: no caching Note `True` or `'all'` is required to cache strings during general validation because validators don't know if they're in a key or a value. Tip If repeated strings are rare, it's recommended to use `'keys'` or `'none'` to reduce memory usage, as the performance difference is minimal if repeated strings are rare. ✦ New in v2.7 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['all', 'keys', 'none'\] #### validate\_by\_alias Whether an aliased field may be populated by its alias. Defaults to `True`. Here's an example of disabling validation by alias: ```py from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): model_config = ConfigDict(validate_by_name=True, validate_by_alias=False) my_field: str = Field(validation_alias='my_alias') # (1) m = Model(my_field='foo') # (2) print(m) #> my_field='foo' ``` The field `'my_field'` has an alias `'my_alias'`. The model can only be populated by the attribute name `'my_field'`. Caution You cannot set both `validate_by_alias` and `validate_by_name` to `False`. This would make it impossible to populate an attribute. See [usage errors](/docs/validation/latest/errors/usage_errors#validate-by-alias-and-name-false) for an example. If you set `validate_by_alias` to `False`, under the hood, Pydantic dynamically sets `validate_by_name` to `True` to ensure that validation can still occur. ✦ New in v2.11 This setting was introduced in conjunction with [`validate_by_name`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_name) to empower users with more fine grained validation control. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### validate\_by\_name Whether an aliased field may be populated by its name as given by the model attribute. Defaults to `False`. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): model_config = ConfigDict(validate_by_name=True, validate_by_alias=True) my_field: str = Field(validation_alias='my_alias') # (1) m = Model(my_alias='foo') # (2) print(m) #> my_field='foo' m = Model(my_field='foo') # (3) print(m) #> my_field='foo' ``` The field `'my_field'` has an alias `'my_alias'`. The model is populated by the alias `'my_alias'`. The model is populated by the attribute name `'my_field'`. Caution You cannot set both `validate_by_alias` and `validate_by_name` to `False`. This would make it impossible to populate an attribute. See [usage errors](/docs/validation/latest/errors/usage_errors#validate-by-alias-and-name-false) for an example. ✦ New in v2.11 This setting was introduced in conjunction with [`validate_by_alias`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_alias) to empower users with more fine grained validation control. It is an alternative to [`populate_by_name`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.populate_by_name), that enables validation by name **and** by alias. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### serialize\_by\_alias Whether an aliased field should be serialized by its alias. Defaults to `False`. Note: In v2.11, `serialize_by_alias` was introduced to address the [popular request](https://github.com/pydantic/pydantic/issues/8379) for consistency with alias behavior for validation and serialization settings. In v3, the default value is expected to change to `True` for consistency with the validation default. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): model_config = ConfigDict(serialize_by_alias=True) my_field: str = Field(serialization_alias='my_alias') # (1) m = Model(my_field='foo') print(m.model_dump()) # (2) #> {'my_alias': 'foo'} ``` The field `'my_field'` has an alias `'my_alias'`. The model is serialized using the alias `'my_alias'` for the `'my_field'` attribute. ✦ New in v2.11 This setting was introduced to address the [popular request](https://github.com/pydantic/pydantic/issues/8379) for consistency with alias behavior for validation and serialization. In v3, the default value is expected to change to `True` for consistency with the validation default. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### url\_preserve\_empty\_path Whether to preserve empty URL paths when validating values for a URL type. Defaults to `False`. ```python from pydantic import AnyUrl, BaseModel, ConfigDict class Model(BaseModel): model_config = ConfigDict(url_preserve_empty_path=True) url: AnyUrl m = Model(url='http://example.com') print(m.url) #> http://example.com ``` ✦ New in v2.12 **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### polymorphic\_serialization Whether to use polymorphic serialization for subclasses of the model or Pydantic dataclass. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ## with\_config ```python def with_config(config: ConfigDict) -> Callable[[_TypeT], _TypeT] def with_config(config: ConfigDict) -> Callable[[_TypeT], _TypeT] def with_config(config: Unpack[ConfigDict] = {}) -> Callable[[_TypeT], _TypeT] ``` Usage Documentation [Configuration with other types](/docs/validation/latest/concepts/config#configuration-on-other-supported-types) A convenience decorator to set a [Pydantic configuration](/docs/validation/latest/api/pydantic/config) on a `TypedDict` or a `dataclass` from the standard library. Although the configuration can be set using the `__pydantic_config__` attribute, it does not play well with type checkers, especially with `TypedDict`. Usage ```python from typing_extensions import TypedDict from pydantic import ConfigDict, TypeAdapter, with_config @with_config(ConfigDict(str_to_lower=True)) class TD(TypedDict): x: str ta = TypeAdapter(TD) print(ta.validate_python({'x': 'ABC'})) #> {'x': 'abc'} ``` ⚠ Deprecated in v2.11, removed in v3 Passing `config` as a keyword argument. ↻ Changed in v2.11 Keyword arguments can be provided directly instead of a config dictionary. ### Returns [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_TypeT`\], `_TypeT`\] ## ExtraValues **Default:** `Literal['allow', 'ignore', 'forbid']` Alias generators for converting between different capitalization conventions. ## to\_pascal ```python def to_pascal(snake: str) -> str ``` Convert a snake\_case string to PascalCase. ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The PascalCase string. ### Parameters **`snake`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The string to convert. ## to\_camel ```python def to_camel(snake: str) -> str ``` Convert a snake\_case string to camelCase. ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The converted camelCase string. ### Parameters **`snake`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The string to convert. ## to\_snake ```python def to_snake(camel: str) -> str ``` Convert a PascalCase, camelCase, or kebab-case string to snake\_case. ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The converted string in snake\_case. ### Parameters **`camel`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The string to convert. --- # [Pydantic Dataclasses](https://pydantic.dev/docs/validation/latest/api/pydantic/dataclasses/) # Pydantic Dataclasses Provide an enhanced dataclass that performs validation. ## dataclass ```python def dataclass( init: Literal[False] = False, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool = False, config: ConfigDict | type[object] | None = None, validate_on_init: bool | None = None, kw_only: bool = ..., slots: bool = ..., ) -> Callable[[type[_T]], type[PydanticDataclass]] def dataclass( _cls: type[_T], init: Literal[False] = False, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool | None = None, config: ConfigDict | type[object] | None = None, validate_on_init: bool | None = None, kw_only: bool = ..., slots: bool = ..., ) -> type[PydanticDataclass] def dataclass( init: Literal[False] = False, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool | None = None, config: ConfigDict | type[object] | None = None, validate_on_init: bool | None = None, ) -> Callable[[type[_T]], type[PydanticDataclass]] def dataclass( _cls: type[_T], init: Literal[False] = False, repr: bool = True, eq: bool = True, order: bool = False, unsafe_hash: bool = False, frozen: bool | None = None, config: ConfigDict | type[object] | None = None, validate_on_init: bool | None = None, ) -> type[PydanticDataclass] ``` Usage Documentation [`dataclasses`](/docs/validation/latest/concepts/dataclasses) A decorator used to create a Pydantic-enhanced dataclass, similar to the standard Python `dataclass`, but with added validation. This function should be used similarly to `dataclasses.dataclass`. ### Returns [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[`_T`\]\], [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\]\] | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\] -- A decorator that accepts a class as its argument and returns a Pydantic `dataclass`. ### Parameters **`_cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`_T`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The target `dataclass`. **`init`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\[[`False`](https://docs.python.org/3/library/constants.html#False)\] _Default:_ `False` Included for signature compatibility with `dataclasses.dataclass`, and is passed through to `dataclasses.dataclass` when appropriate. If specified, must be set to `False`, as pydantic inserts its own `__init__` function. **`repr`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` A boolean indicating whether to include the field in the `__repr__` output. **`eq`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Determines if a `__eq__` method should be generated for the class. **`order`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Determines if comparison magic methods should be generated, such as `__lt__`, but not `__eq__`. **`unsafe_hash`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Determines if a `__hash__` method should be included in the class, as in `dataclasses.dataclass`. **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines if the generated class should be a 'frozen' `dataclass`, which does not allow its attributes to be modified after it has been initialized. If not set, the value from the provided `config` argument will be used (and will default to `False` otherwise). **`config`** : [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) | [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`object`](https://docs.python.org/3/glossary.html#term-object)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The Pydantic config to use for the `dataclass`. **`validate_on_init`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A deprecated parameter included for backwards compatibility; in V2, all Pydantic dataclasses are validated on init. **`kw_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Determines if `__init__` method parameters must be specified by keyword only. Defaults to `False`. **`slots`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Determines if the generated class should be a 'slots' `dataclass`, which does not allow the addition of new attributes after instantiation. ### Raises - `AssertionError` -- Raised if `init` is not `False` or `validate_on_init` is `False`. ## rebuild\_dataclass ```python def rebuild_dataclass( cls: type[PydanticDataclass], force: bool = False, raise_errors: bool = True, _parent_namespace_depth: int = 2, _types_namespace: MappingNamespace | None = None, ) -> bool | None ``` Try to rebuild the pydantic-core schema for the dataclass. This may be necessary when one of the annotations is a ForwardRef which could not be resolved during the initial attempt to build the schema, and automatic rebuilding fails. This is analogous to `BaseModel.model_rebuild`. ### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- Returns `None` if the schema is already "complete" and rebuilding was not required. [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\] The class to rebuild the pydantic-core schema for. **`force`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to force the rebuilding of the schema, defaults to `False`. **`raise_errors`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to raise errors, defaults to `True`. **`_parent_namespace_depth`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `2` The depth level of the parent namespace, defaults to 2. **`_types_namespace`** : `MappingNamespace` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The types namespace, defaults to `None`. ## is\_pydantic\_dataclass ```python def is_pydantic_dataclass(class_: type[Any]) -> TypeGuard[type[PydanticDataclass]] ``` Whether a class is a pydantic dataclass. ### Returns [`TypeGuard`](https://docs.python.org/3/library/typing.html#typing.TypeGuard)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\]\] -- `True` if the class is a pydantic dataclass, `False` otherwise. ### Parameters **`class_`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The class. --- # [Errors](https://pydantic.dev/docs/validation/latest/api/pydantic/errors/) # Errors Pydantic-specific errors. ## PydanticErrorMixin A mixin class for common functionality shared by all Pydantic-specific errors. ### Attributes #### message A message describing the error. #### code An optional error code from PydanticErrorCodes enum. ## PydanticUserError **Bases:** `PydanticErrorMixin`, [`RuntimeError`](https://docs.python.org/3/library/exceptions.html#RuntimeError) An error raised due to incorrect use of Pydantic. ## PydanticUndefinedAnnotation **Bases:** `PydanticErrorMixin`, [`NameError`](https://docs.python.org/3/library/exceptions.html#NameError) A subclass of `NameError` raised when handling undefined annotations during `CoreSchema` generation. ### Attributes #### name Name of the error. #### message Description of the error. ### Methods #### from\_name\_error `@classmethod` ```python def from_name_error(cls, name_error: NameError) -> Self ``` Convert a `NameError` to a `PydanticUndefinedAnnotation` error. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- Converted `PydanticUndefinedAnnotation` error. ##### Parameters **`name_error`** : [`NameError`](https://docs.python.org/3/library/exceptions.html#NameError) `NameError` to be converted. ## PydanticImportError **Bases:** `PydanticErrorMixin`, [`ImportError`](https://docs.python.org/3/library/exceptions.html#ImportError) An error raised when an import fails due to module changes between V1 and V2. ### Attributes #### message Description of the error. ## PydanticSchemaGenerationError **Bases:** [`PydanticUserError`](/docs/validation/latest/api/pydantic/errors/#pydantic.errors.PydanticUserError) An error raised during failures to generate a `CoreSchema` for some type. ### Attributes #### message Description of the error. ## PydanticInvalidForJsonSchema **Bases:** [`PydanticUserError`](/docs/validation/latest/api/pydantic/errors/#pydantic.errors.PydanticUserError) An error raised during failures to generate a JSON schema for some `CoreSchema`. ### Attributes #### message Description of the error. ## PydanticForbiddenQualifier **Bases:** [`PydanticUserError`](/docs/validation/latest/api/pydantic/errors/#pydantic.errors.PydanticUserError) An error raised if a forbidden type qualifier is found in a type annotation. --- # [Experimental](https://pydantic.dev/docs/validation/latest/api/pydantic/experimental/) # Experimental ## Pipeline API Experimental pipeline API functionality. Be careful with this API, it's subject to change. ## \_Pipeline **Bases:** `Generic[_InT, _OutT]` Abstract representation of a chain of validation, transformation, and parsing steps. ### Methods #### transform ```python def transform(func: Callable[[_OutT], _NewOutT]) -> _Pipeline[_InT, _NewOutT] ``` Transform the output of the previous step. If used as the first step in a pipeline, the type of the field is used. That is, the transformation is applied to after the value is parsed to the field's type. ##### Returns `_Pipeline`\[`_InT`, `_NewOutT`\] #### validate\_as ```python def validate_as(tp: type[_NewOutT], strict: bool = False) -> _Pipeline[_InT, _NewOutT] def validate_as(tp: ellipsis, strict: bool = False) -> _Pipeline[_InT, Any] def validate_as(tp: Any, strict: bool = ...) -> _Pipeline[_InT, Any] ``` Validate / parse the input into a new type. If no type is provided, the type of the field is used. Types are parsed in Pydantic's `lax` mode by default, but you can enable `strict` mode by passing `strict=True`. ##### Returns `_Pipeline`\[`_InT`, [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] #### validate\_as\_deferred ```python def validate_as_deferred( func: Callable[[], type[_NewOutT]], ) -> _Pipeline[_InT, _NewOutT] ``` Parse the input into a new type, deferring resolution of the type until the current class is fully defined. This is useful when you need to reference the class in it's own type annotations. ##### Returns `_Pipeline`\[`_InT`, `_NewOutT`\] #### constrain ```python def constrain(constraint: annotated_types.Ge) -> _Pipeline[_InT, _NewOutGe] def constrain(constraint: annotated_types.Gt) -> _Pipeline[_InT, _NewOutGt] def constrain(constraint: annotated_types.Le) -> _Pipeline[_InT, _NewOutLe] def constrain(constraint: annotated_types.Lt) -> _Pipeline[_InT, _NewOutLt] def constrain(constraint: annotated_types.Len) -> _Pipeline[_InT, _NewOutLen] def constrain(constraint: annotated_types.MultipleOf) -> _Pipeline[_InT, _NewOutT] def constrain(constraint: annotated_types.Timezone) -> _Pipeline[_InT, _NewOutDatetime] def constrain(constraint: annotated_types.Predicate) -> _Pipeline[_InT, _OutT] def constrain(constraint: annotated_types.Interval) -> _Pipeline[_InT, _NewOutInterval] def constrain(constraint: _Eq) -> _Pipeline[_InT, _OutT] def constrain(constraint: _NotEq) -> _Pipeline[_InT, _OutT] def constrain(constraint: _In) -> _Pipeline[_InT, _OutT] def constrain(constraint: _NotIn) -> _Pipeline[_InT, _OutT] def constrain(constraint: Pattern[str]) -> _Pipeline[_InT, _NewOutT] ``` Constrain a value to meet a certain condition. We support most conditions from `annotated_types`, as well as regular expressions. Most of the time you'll be calling a shortcut method like `gt`, `lt`, `len`, etc so you don't need to call this directly. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### predicate ```python def predicate(func: Callable[[_NewOutT], bool]) -> _Pipeline[_InT, _NewOutT] ``` Constrain a value to meet a certain predicate. ##### Returns `_Pipeline`\[`_InT`, `_NewOutT`\] #### gt ```python def gt(gt: _NewOutGt) -> _Pipeline[_InT, _NewOutGt] ``` Constrain a value to be greater than a certain value. ##### Returns `_Pipeline`\[`_InT`, `_NewOutGt`\] #### lt ```python def lt(lt: _NewOutLt) -> _Pipeline[_InT, _NewOutLt] ``` Constrain a value to be less than a certain value. ##### Returns `_Pipeline`\[`_InT`, `_NewOutLt`\] #### ge ```python def ge(ge: _NewOutGe) -> _Pipeline[_InT, _NewOutGe] ``` Constrain a value to be greater than or equal to a certain value. ##### Returns `_Pipeline`\[`_InT`, `_NewOutGe`\] #### le ```python def le(le: _NewOutLe) -> _Pipeline[_InT, _NewOutLe] ``` Constrain a value to be less than or equal to a certain value. ##### Returns `_Pipeline`\[`_InT`, `_NewOutLe`\] #### len ```python def len(min_len: int, max_len: int | None = None) -> _Pipeline[_InT, _NewOutLen] ``` Constrain a value to have a certain length. ##### Returns `_Pipeline`\[`_InT`, `_NewOutLen`\] #### multiple\_of ```python def multiple_of(multiple_of: _NewOutDiv) -> _Pipeline[_InT, _NewOutDiv] def multiple_of(multiple_of: _NewOutMod) -> _Pipeline[_InT, _NewOutMod] ``` Constrain a value to be a multiple of a certain number. ##### Returns `_Pipeline`\[`_InT`, [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] #### eq ```python def eq(value: _OutT) -> _Pipeline[_InT, _OutT] ``` Constrain a value to be equal to a certain value. ##### Returns `_Pipeline`\[`_InT`, `_OutT`\] #### not\_eq ```python def not_eq(value: _OutT) -> _Pipeline[_InT, _OutT] ``` Constrain a value to not be equal to a certain value. ##### Returns `_Pipeline`\[`_InT`, `_OutT`\] #### in\_ ```python def in_(values: Container[_OutT]) -> _Pipeline[_InT, _OutT] ``` Constrain a value to be in a certain set. ##### Returns `_Pipeline`\[`_InT`, `_OutT`\] #### not\_in ```python def not_in(values: Container[_OutT]) -> _Pipeline[_InT, _OutT] ``` Constrain a value to not be in a certain set. ##### Returns `_Pipeline`\[`_InT`, `_OutT`\] #### otherwise ```python def otherwise( other: _Pipeline[_OtherIn, _OtherOut], ) -> _Pipeline[_InT | _OtherIn, _OutT | _OtherOut] ``` Combine two validation chains, returning the result of the first chain if it succeeds, and the second chain if it fails. ##### Returns `_Pipeline`\[`_InT` | `_OtherIn`, `_OutT` | `_OtherOut`\] #### then ```python def then(other: _Pipeline[_OutT, _OtherOut]) -> _Pipeline[_InT, _OtherOut] ``` Pipe the result of one validation chain into another. ##### Returns `_Pipeline`\[`_InT`, `_OtherOut`\] ## Arguments schema API Experimental module exposing a function to generate a core schema that validates callable arguments. ## generate\_arguments\_schema ```python def generate_arguments_schema( func: Callable[..., Any], schema_type: Literal['arguments', 'arguments-v3'] = 'arguments-v3', parameters_callback: Callable[[int, str, Any], Literal['skip'] | None] | None = None, config: ConfigDict | None = None, ) -> CoreSchema ``` Generate the schema for the arguments of a function. ### Returns `CoreSchema` -- The generated schema. ### Parameters **`func`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The function to generate the schema for. **`schema_type`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['arguments', 'arguments-v3'\] _Default:_ `'arguments-v3'` The type of schema to generate. **`parameters_callback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`int`](https://docs.python.org/3/library/functions.html#int), [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['skip'\] | [`None`](https://docs.python.org/3/library/constants.html#None)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable that will be invoked for each parameter. The callback should take three required arguments: the index, the name and the type annotation (or [`Parameter.empty`](https://docs.python.org/3/library/inspect.html#inspect.Parameter.empty) if not annotated) of the parameter. The callback can optionally return `'skip'`, so that the parameter gets excluded from the resulting schema. **`config`** : [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The configuration to use. --- # [Fields](https://pydantic.dev/docs/validation/latest/api/pydantic/fields/) # Fields Defining fields on models. ## FieldInfo **Bases:** `Representation` This class holds information about a field. `FieldInfo` is used for any field definition regardless of whether the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function is explicitly used. Caution The `FieldInfo` class is meant to expose information about a field in a Pydantic model or dataclass. `FieldInfo` instances shouldn't be instantiated directly, nor mutated. If you need to derive a new model from another one and are willing to alter `FieldInfo` instances, refer to this [dynamic model example](/docs/validation/latest/examples/dynamic_models). ### Attributes #### annotation The type annotation of the field. **Type:** [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### default The default value of the field. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### default\_factory A callable to generate the default value. The callable can either take 0 arguments (in which case it is called as is) or a single argument containing the already validated data. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### alias The alias name of the field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### alias\_priority The priority of the field's alias. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### validation\_alias The validation alias of the field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath) | [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) | [`None`](https://docs.python.org/3/library/constants.html#None) #### serialization\_alias The serialization alias of the field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### title The title of the field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### field\_title\_generator A callable that takes a field name and returns title for it. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `FieldInfo`\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### description The description of the field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### examples List of examples of the field. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### exclude Whether to exclude the field from the model serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### exclude\_if A callable that determines whether to exclude a field during serialization based on its value. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### discriminator Field name or Discriminator for discriminating the type in a tagged union. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`types.Discriminator`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Discriminator) | [`None`](https://docs.python.org/3/library/constants.html#None) #### deprecated A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. **Type:** `Deprecated` | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### json\_schema\_extra A dict or callable to provide extra JSON schema properties. **Type:** `JsonDict` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`JsonDict`\], [`None`](https://docs.python.org/3/library/constants.html#None)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### frozen Whether the field is frozen. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### validate\_default Whether to validate the default value of the field. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### repr Whether to include the field in representation of the model. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### init Whether the field should be included in the constructor of the dataclass. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### init\_var Whether the field should _only_ be included in the constructor of the dataclass, and not stored. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### kw\_only Whether the field should be a keyword-only argument in the constructor of the dataclass. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### metadata The metadata list. Contains all the data that isn't expressed as direct `FieldInfo` attributes, including: - Type-specific constraints, such as `gt` or `min_length` (these are converted to metadata classes such as `annotated_types.Gt`). - Any other arbitrary object used within [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata (e.g. [custom types handlers](/docs/validation/latest/concepts/types#as-an-annotation) or any object not recognized by Pydantic). **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] ### Methods #### \_construct `@classmethod` ```python def _construct(cls, metadata: list[Any], attr_overrides: Any = {}) -> Self ``` Construct the final `FieldInfo` instance, by merging the possibly existing `FieldInfo` instances from the metadata. With the following example: ```python class Model(BaseModel): f: Annotated[int, Gt(1), Field(description='desc', lt=2)] ``` `metadata` refers to the metadata elements of the `Annotated` form. This metadata is iterated over from left to right: - If the element is a `Field()` function (which is itself a `FieldInfo` instance), the field attributes (such as `description`) are saved to be set on the final `FieldInfo` instance. On the other hand, some kwargs (such as `lt`) are stored as `metadata` (see `FieldInfo.__init__()`, calling `FieldInfo._collect_metadata()`). In this case, the final metadata list is extended with the one from this instance. - Else, the element is considered as a single metadata object, and is appended to the final metadata list. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- The final merged `FieldInfo` instance. ##### Parameters **`metadata`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The list of metadata elements to merge together. If the `FieldInfo` instance to be constructed is for a field with an assigned `Field()`, this `Field()` assignment should be added as the last element of the provided metadata. **`**attr_overrides`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `{}` Extra attributes that should be set on the final merged `FieldInfo` instance. #### \_from\_dataclass\_field `@staticmethod` ```python def _from_dataclass_field(dc_field: DataclassField[Any]) -> FieldInfo ``` Return a new `FieldInfo` instance from a `dataclasses.Field` instance. ##### Returns `FieldInfo` -- The corresponding `FieldInfo` instance. ##### Parameters **`dc_field`** : `DataclassField`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The `dataclasses.Field` instance to convert. ##### Raises - `TypeError` -- If any of the `FieldInfo` kwargs does not match the `dataclass.Field` kwargs. #### \_collect\_metadata `@staticmethod` ```python def _collect_metadata(kwargs: dict[str, Any]) -> list[Any] ``` Collect annotations from kwargs. ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- A list of metadata objects - a combination of `annotated_types.BaseMetadata` and `PydanticMetadata`. ##### Parameters **`kwargs`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] Keyword arguments passed to the function. #### get\_default ```python def get_default( call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None, ) -> Any def get_default(call_default_factory: Literal[False] = ...) -> Any ``` Get the default value. We expose an option for whether to call the default\_factory (if present), as calling it may result in side effects that we want to avoid. However, there are times when it really should be called (namely, when instantiating a model via `model_construct`). ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The default value, calling the default factory if requested or `PydanticUndefined` if not set. ##### Parameters **`call_default_factory`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to call the default factory or not. **`validated_data`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The already validated data to be passed to the default factory. #### is\_required ```python def is_required() -> bool ``` Check if the field is required (i.e., does not have a default value or factory). ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- `True` if the field is required, `False` otherwise. #### asdict ```python def asdict() -> _FieldInfoAsDict ``` Return a dictionary representation of the `FieldInfo` instance. The returned value is a dictionary with three items: - `annotation`: The type annotation of the field. - `metadata`: The metadata list. - `attributes`: A mapping of the remaining `FieldInfo` attributes to their values (e.g. `alias`, `title`). ##### Returns `_FieldInfoAsDict` #### \_copy ```python def _copy() -> Self ``` Return a copy of the `FieldInfo` instance. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) ## ModelPrivateAttr **Bases:** `Representation` A descriptor for private attributes in class models. Caution You generally shouldn't be creating `ModelPrivateAttr` instances directly, instead use `pydantic.fields.PrivateAttr`. (This is similar to `FieldInfo` vs. `Field`.) ### Attributes #### default The default value of the attribute if not provided. #### default\_factory A callable to generate the default value. The callable can either take 0 arguments (in which case it is called as is) or a single argument containing the validated data (the model's [`__dict__`](https://docs.python.org/3/reference/datamodel.html#object.__dict__)) and the already initialized private attributes. ### Methods #### \_\_getattr\_\_ ```python def __getattr__(item: str) -> Any ``` This function improves compatibility with custom descriptors by ensuring delegation happens as expected when the default value of a private attribute is a descriptor. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### \_\_set\_name\_\_ ```python def __set_name__(cls: type[Any], name: str) -> None ``` Preserve `__set_name__` protocol defined in [https://peps.python.org/pep-0487](https://peps.python.org/pep-0487). ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### get\_default ```python def get_default( call_default_factory: Literal[True], validated_data: dict[str, Any] | None = None, ) -> Any def get_default(call_default_factory: Literal[False] = ...) -> Any ``` Get the default value. We expose an option for whether to call the default\_factory (if present), as calling it may result in side effects that we want to avoid. However, there are times when it really should be called (namely, when instantiating a model via `model_construct`). ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The default value, calling the default factory if requested or `None` if not set. ##### Parameters **`call_default_factory`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to call the default factory or not. **`validated_data`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The already validated data to be passed to the default factory. ## ComputedFieldInfo A container for data from `@computed_field` so that we can access it while building the pydantic-core schema. ### Attributes #### decorator\_repr A class variable representing the decorator string, '@computed\_field'. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### wrapped\_property The wrapped computed field property. **Type:** [`property`](https://docs.python.org/3/library/functions.html#property) #### return\_type The type of the computed field property's return value. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### alias The alias of the property to be used during serialization. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### alias\_priority The priority of the alias. This affects whether an alias generator is used. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### title Title of the computed field to include in the serialization JSON schema. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### field\_title\_generator A callable that takes a field name and returns title for it. **Type:** [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ComputedFieldInfo`\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### description Description of the computed field to include in the serialization JSON schema. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### deprecated A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. **Type:** `Deprecated` | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### examples Example values of the computed field to include in the serialization JSON schema. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### json\_schema\_extra A dict or callable to provide extra JSON schema properties. **Type:** `JsonDict` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`JsonDict`\], [`None`](https://docs.python.org/3/library/constants.html#None)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### repr A boolean indicating whether to include the field in the **repr** output. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ### Methods #### \_update\_from\_config ```python def _update_from_config(config_wrapper: ConfigWrapper, name: str) -> None ``` Update the instance from the configuration set on the class this computed field belongs to. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### \_apply\_alias\_generator ```python def _apply_alias_generator( alias_generator: Callable[[str], str] | AliasGenerator, name: str, ) -> None ``` Apply an alias generator to aliases if appropriate. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) ##### Parameters **`alias_generator`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator) A callable that takes a string and returns a string, or an `AliasGenerator` instance. **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name of the computed field from which to generate the alias. ## Field ```python def Field( default: ellipsis, alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: bool | None = _Unset, repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> Any def Field( default: Any, alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: Literal[True], repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> Any def Field( default: _T, alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: Literal[False] = ..., repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> _T def Field( default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any], alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: Literal[True], repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> Any def Field( default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T], alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: Literal[False] | None = _Unset, repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> _T def Field( alias: str | None = _Unset, alias_priority: int | None = _Unset, validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, field_title_generator: Callable[[str, FieldInfo], str] | None = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, exclude_if: Callable[[Any], bool] | None = _Unset, discriminator: str | types.Discriminator | None = _Unset, deprecated: Deprecated | str | bool | None = _Unset, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = _Unset, frozen: bool | None = _Unset, validate_default: bool | None = _Unset, repr: bool = _Unset, init: bool | None = _Unset, init_var: bool | None = _Unset, kw_only: bool | None = _Unset, pattern: str | re.Pattern[str] | None = _Unset, strict: bool | None = _Unset, coerce_numbers_to_str: bool | None = _Unset, gt: annotated_types.SupportsGt | None = _Unset, ge: annotated_types.SupportsGe | None = _Unset, lt: annotated_types.SupportsLt | None = _Unset, le: annotated_types.SupportsLe | None = _Unset, multiple_of: float | None = _Unset, allow_inf_nan: bool | None = _Unset, max_digits: int | None = _Unset, decimal_places: int | None = _Unset, min_length: int | None = _Unset, max_length: int | None = _Unset, union_mode: Literal['smart', 'left_to_right'] = _Unset, fail_fast: bool | None = _Unset, extra: Unpack[_EmptyKwargs] = {}, ) -> Any ``` Usage Documentation [Fields](/docs/validation/latest/concepts/fields) Create a field for objects that can be configured. Used to provide extra information about a field, either for the model schema or complex validation. Some arguments apply only to number fields (`int`, `float`, `Decimal`) and some apply only to `str`. ### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- A new [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo). The return annotation is `Any` so `Field` can be used on type-annotated fields without causing a type error. ### Parameters **`default`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` Default value if the field is not set. **`default_factory`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` A callable to generate the default value. The callable can either take 0 arguments (in which case it is called as is) or a single argument containing the already validated data. **`alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` The name to use for the attribute when validating or serializing by alias. This is often used for things like converting between snake and camel case. **`alias_priority`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Priority of the alias. This affects whether an alias generator is used. **`validation_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath) | [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Like `alias`, but only affects validation, not serialization. **`serialization_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Like `alias`, but only affects serialization, not validation. **`title`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Human-readable title. **`field_title_generator`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `FieldInfo`\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` A callable that takes a field name and returns title for it. **`description`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Human-readable description. **`examples`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Example values for this field. **`exclude`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether to exclude the field from the model serialization. **`exclude_if`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` A callable that determines whether to exclude a field during serialization based on its value. **`discriminator`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`types.Discriminator`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Discriminator) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Field name or Discriminator for discriminating the type in a tagged union. **`deprecated`** : `Deprecated` | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` A deprecation message, an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport, or a boolean. If `True`, a default deprecation message will be emitted when accessing the field. **`json_schema_extra`** : `JsonDict` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`JsonDict`\], [`None`](https://docs.python.org/3/library/constants.html#None)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` A dict or callable to provide extra JSON schema properties. **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether the field is frozen. If true, attempts to change the value on an instance will raise an error. **`validate_default`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` If `True`, apply validation to the default value every time you create an instance. Otherwise, for performance reasons, the default value of the field is trusted and not validated. **`repr`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `_Unset` A boolean indicating whether to include the field in the `__repr__` output. **`init`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether the field should be included in the constructor of the dataclass. (Only applies to dataclasses.) **`init_var`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether the field should _only_ be included in the constructor of the dataclass. (Only applies to dataclasses.) **`kw_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether the field should be a keyword-only argument in the constructor of the dataclass. (Only applies to dataclasses.) **`coerce_numbers_to_str`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode). **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` If `True`, strict validation is applied to the field. See [Strict Mode](/docs/validation/latest/concepts/strict_mode) for details. **`gt`** : `annotated_types.SupportsGt` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Greater than. If set, value must be greater than this. Only applicable to numbers. **`ge`** : `annotated_types.SupportsGe` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Greater than or equal. If set, value must be greater than or equal to this. Only applicable to numbers. **`lt`** : `annotated_types.SupportsLt` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Less than. If set, value must be less than this. Only applicable to numbers. **`le`** : `annotated_types.SupportsLe` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Less than or equal. If set, value must be less than or equal to this. Only applicable to numbers. **`multiple_of`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Value must be a multiple of this. Only applicable to numbers. **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Minimum length for iterables. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Maximum length for iterables. **`pattern`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`re.Pattern`](https://docs.python.org/3/library/re.html#re.Pattern)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Pattern for strings (a regular expression). **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Allow `inf`, `-inf`, `nan`. Only applicable to float and [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) numbers. **`max_digits`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Maximum number of allow digits for strings. **`decimal_places`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` Maximum number of decimal places allowed for numbers. **`union_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['smart', 'left\_to\_right'\] _Default:_ `_Unset` The strategy to apply when validating a union. Can be `smart` (the default), or `left_to_right`. See [Union Mode](/docs/validation/latest/concepts/unions#union-modes) for details. **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_Unset` If `True`, validation will stop on the first error. If `False`, all validation errors will be collected. This option can be applied only to iterable types (list, tuple, set, and frozenset). **`extra`** : [`Unpack`](https://docs.python.org/3/library/typing.html#typing.Unpack)\[`_EmptyKwargs`\] _Default:_ `{}` (Deprecated) Extra fields that will be included in the JSON schema. Deprecated The `extra` kwargs is deprecated. Use `json_schema_extra` instead. ## PrivateAttr ```python def PrivateAttr(default: _T, init: Literal[False] = False) -> _T def PrivateAttr( default_factory: Callable[[], _T] | Callable[[dict[str, Any]], _T], init: Literal[False] = False, ) -> _T def PrivateAttr(init: Literal[False] = False) -> Any ``` Usage Documentation [Private Model Attributes](/docs/validation/latest/concepts/models#private-model-attributes) Indicates that an attribute is intended for private use and not handled during normal validation/serialization. Private attributes are not validated by Pydantic, so it's up to you to ensure they are used in a type-safe manner. Private attributes are stored in `__private_attributes__` on the model. ### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- An instance of [`ModelPrivateAttr`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.ModelPrivateAttr) class. ### Parameters **`default`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` The attribute's default value. Defaults to Undefined. **`default_factory`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable to generate the default value. The callable can either take 0 arguments (in which case it is called as is) or a single argument containing the validated data (the model's [`__dict__`](https://docs.python.org/3/reference/datamodel.html#object.__dict__)) and the already initialized private attributes. If both `default` and `default_factory` are set, an error will be raised. **`init`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\[[`False`](https://docs.python.org/3/library/constants.html#False)\] _Default:_ `False` Whether the attribute should be included in the constructor of the dataclass. Always `False`. ### Raises - `ValueError` -- If both `default` and `default_factory` are set. ## computed\_field ```python def computed_field(func: PropertyT) -> PropertyT def computed_field( alias: str | None = None, alias_priority: int | None = None, exclude_if: Callable[[Any], bool] | None = None, title: str | None = None, field_title_generator: Callable[[str, ComputedFieldInfo], str] | None = None, description: str | None = None, deprecated: Deprecated | str | bool | None = None, examples: list[Any] | None = None, json_schema_extra: JsonDict | Callable[[JsonDict], None] | None = None, repr: bool = True, return_type: Any = PydanticUndefined, ) -> Callable[[PropertyT], PropertyT] ``` Usage Documentation [The `computed_field` decorator](/docs/validation/latest/concepts/fields#the-computed_field-decorator) Decorator to include `property` and `cached_property` when serializing models or dataclasses. This is useful for fields that are computed from other fields, or for fields that are expensive to compute and should be cached. ```python from pydantic import BaseModel, computed_field class Rectangle(BaseModel): width: int length: int @computed_field @property def area(self) -> int: return self.width * self.length print(Rectangle(width=3, length=2).model_dump()) #> {'width': 3, 'length': 2, 'area': 6} ``` If applied to functions not yet decorated with `@property` or `@cached_property`, the function is automatically wrapped with `property`. Although this is more concise, you will lose IntelliSense in your IDE, and confuse static type checkers, thus explicit use of `@property` is recommended. Mypy Warning Even with the `@property` or `@cached_property` applied to your function before `@computed_field`, mypy may throw a `Decorated property not supported` error. See [mypy issue #1362](https://github.com/python/mypy/issues/1362), for more information. To avoid this error message, add `# type: ignore[prop-decorator]` to the `@computed_field` line. [pyright](https://github.com/microsoft/pyright) supports `@computed_field` without error. ```python import random from pydantic import BaseModel, computed_field class Square(BaseModel): width: float @computed_field def area(self) -> float: # converted to a `property` by `computed_field` return round(self.width**2, 2) @area.setter def area(self, new_area: float) -> None: self.width = new_area**0.5 @computed_field(alias='the magic number', repr=False) def random_number(self) -> int: return random.randint(0, 1_000) square = Square(width=1.3) # `random_number` does not appear in representation print(repr(square)) #> Square(width=1.3, area=1.69) print(square.random_number) #> 3 square.area = 4 print(square.model_dump_json(by_alias=True)) #> {"width":2.0,"area":4.0,"the magic number":3} ``` Overriding with `computed_field` You can't override a field from a parent class with a `computed_field` in the child class. `mypy` complains about this behavior if allowed, and `dataclasses` doesn't allow this pattern either. See the example below: ```python from pydantic import BaseModel, computed_field class Parent(BaseModel): a: str try: class Child(Parent): @computed_field @property def a(self) -> str: return 'new a' except TypeError as e: print(e) ''' Field 'a' of class 'Child' overrides symbol of same name in a parent class. This override with a computed_field is incompatible. ''' ``` Private properties decorated with `@computed_field` have `repr=False` by default. ```python from functools import cached_property from pydantic import BaseModel, computed_field class Model(BaseModel): foo: int @computed_field @cached_property def _private_cached_property(self) -> int: return -self.foo @computed_field @property def _private_property(self) -> int: return -self.foo m = Model(foo=1) print(repr(m)) #> Model(foo=1) ``` ### Returns `PropertyT` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`PropertyT`\], `PropertyT`\] -- A proxy wrapper for the property. ### Parameters **`func`** : `PropertyT` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` the function to wrap. **`alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` alias to use when serializing this computed field, only used when `by_alias=True` **`alias_priority`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` priority of the alias. This affects whether an alias generator is used **`exclude_if`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable that determines whether to exclude this computed field during serialization based on its value. **`title`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Title to use when including this computed field in JSON Schema **`field_title_generator`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ComputedFieldInfo`\], [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable that takes a field name and returns title for it. **`description`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Description to use when including this computed field in JSON Schema, defaults to the function's docstring **`deprecated`** : `Deprecated` | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A deprecation message (or an instance of `warnings.deprecated` or the `typing_extensions.deprecated` backport). to be emitted when accessing the field. Or a boolean. This will automatically be set if the property is decorated with the `deprecated` decorator. **`examples`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Example values to use when including this computed field in JSON Schema **`json_schema_extra`** : `JsonDict` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`JsonDict`\], [`None`](https://docs.python.org/3/library/constants.html#None)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A dict or callable to provide extra JSON schema properties. **`repr`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` whether to include this computed field in model repr. Default is `False` for private properties and `True` for public properties. **`return_type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` optional return for serialization logic to expect when serializing to JSON, if included this must be correct, otherwise a `TypeError` is raised. If you don't include a return type Any is used, which does runtime introspection to handle arbitrary objects. --- # [Functional Serializers](https://pydantic.dev/docs/validation/latest/api/pydantic/functional_serializers/) # Functional Serializers This module contains related classes and functions for serialization. ## PlainSerializer Plain serializers use a function to modify the output of serialization. This is particularly helpful when you want to customize the serialization for annotated types. Consider an input of `list`, which will be serialized into a space-delimited string. ```python from typing import Annotated from pydantic import BaseModel, PlainSerializer CustomStr = Annotated[ list, PlainSerializer(lambda x: ' '.join(x), return_type=str) ] class StudentModel(BaseModel): courses: CustomStr student = StudentModel(courses=['Math', 'Chemistry', 'English']) print(student.model_dump()) #> {'courses': 'Math Chemistry English'} ``` ### Attributes #### func The serializer function. **Type:** `core_schema.SerializerFunction` #### return\_type The return type for the function. If omitted it will be inferred from the type annotation. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### when\_used Determines when this serializer should be used. Accepts a string with values `'always'`, `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'. **Type:** `WhenUsed` ## WrapSerializer Wrap serializers receive the raw inputs along with a handler function that applies the standard serialization logic, and can modify the resulting value before returning it as the final output of serialization. For example, here's a scenario in which a wrap serializer transforms timezones to UTC **and** utilizes the existing `datetime` serialization logic. ```python from datetime import datetime, timezone from typing import Annotated, Any from pydantic import BaseModel, WrapSerializer class EventDatetime(BaseModel): start: datetime end: datetime def convert_to_utc(value: Any, handler, info) -> dict[str, datetime]: # Note that `handler` can actually help serialize the `value` for # further custom serialization in case it's a subclass. partial_result = handler(value, info) if info.mode == 'json': return { k: datetime.fromisoformat(v).astimezone(timezone.utc) for k, v in partial_result.items() } return {k: v.astimezone(timezone.utc) for k, v in partial_result.items()} UTCEventDatetime = Annotated[EventDatetime, WrapSerializer(convert_to_utc)] class EventModel(BaseModel): event_datetime: UTCEventDatetime dt = EventDatetime( start='2024-01-01T07:00:00-08:00', end='2024-01-03T20:00:00+06:00' ) event = EventModel(event_datetime=dt) print(event.model_dump()) ''' { 'event_datetime': { 'start': datetime.datetime( 2024, 1, 1, 15, 0, tzinfo=datetime.timezone.utc ), 'end': datetime.datetime( 2024, 1, 3, 14, 0, tzinfo=datetime.timezone.utc ), } } ''' print(event.model_dump_json()) ''' {"event_datetime":{"start":"2024-01-01T15:00:00Z","end":"2024-01-03T14:00:00Z"}} ''' ``` ### Attributes #### func The serializer function to be wrapped. **Type:** `core_schema.WrapSerializerFunction` #### return\_type The return type for the function. If omitted it will be inferred from the type annotation. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) #### when\_used Determines when this serializer should be used. Accepts a string with values `'always'`, `'unless-none'`, `'json'`, and `'json-unless-none'`. Defaults to 'always'. **Type:** `WhenUsed` ## SerializeAsAny Annotation used to mark a type as having duck-typing serialization behavior. See [usage documentation](/docs/validation/latest/concepts/serialization#serializing-with-duck-typing) for more details. ## field\_serializer ```python def field_serializer( field: str, fields: str = (), mode: Literal['wrap'], return_type: Any = ..., when_used: WhenUsed = ..., check_fields: bool | None = ..., ) -> Callable[[_FieldWrapSerializerT], _FieldWrapSerializerT] def field_serializer( field: str, fields: str = (), mode: Literal['plain'] = ..., return_type: Any = ..., when_used: WhenUsed = ..., check_fields: bool | None = ..., ) -> Callable[[_FieldPlainSerializerT], _FieldPlainSerializerT] ``` Decorator that enables custom field serialization. In the below example, a field of type `set` is used to mitigate duplication. A `field_serializer` is used to serialize the data as a sorted list. ```python from pydantic import BaseModel, field_serializer class StudentModel(BaseModel): name: str = 'Jane' courses: set[str] @field_serializer('courses', when_used='json') def serialize_courses_in_order(self, courses: set[str]): return sorted(courses) student = StudentModel(courses={'Math', 'Chemistry', 'English'}) print(student.model_dump_json()) #> {"name":"Jane","courses":["Chemistry","English","Math"]} ``` See [the usage documentation](/docs/validation/latest/concepts/serialization#serializers) for more information. Four signatures are supported for the decorated serializer: - `(self, value: Any, info: FieldSerializationInfo)` - `(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo)` - `(value: Any, info: SerializationInfo)` - `(value: Any, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)` ### Returns [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_FieldWrapSerializerT`\], `_FieldWrapSerializerT`\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_FieldPlainSerializerT`\], `_FieldPlainSerializerT`\] ### Parameters **`*fields`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `()` The field names the serializer should apply to. **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['plain', 'wrap'\] _Default:_ `'plain'` The serialization mode. - `plain` means the function will be called instead of the default serialization logic, - `wrap` means the function will be called with an argument to optionally call the default serialization logic. **`return_type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` Optional return type for the function, if omitted it will be inferred from the type annotation. **`when_used`** : `WhenUsed` _Default:_ `'always'` Determines the serializer will be used for serialization. **`check_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to check that the fields actually exist on the model. ### Raises - `PydanticUserError` -- - If the decorator is used without any arguments (at least one field name must be provided). - If the provided field names are not strings. ## model\_serializer ```python def model_serializer(f: _ModelPlainSerializerT) -> _ModelPlainSerializerT def model_serializer( mode: Literal['wrap'], when_used: WhenUsed = 'always', return_type: Any = ..., ) -> Callable[[_ModelWrapSerializerT], _ModelWrapSerializerT] def model_serializer( mode: Literal['plain'] = ..., when_used: WhenUsed = 'always', return_type: Any = ..., ) -> Callable[[_ModelPlainSerializerT], _ModelPlainSerializerT] ``` Decorator that enables custom model serialization. This is useful when a model need to be serialized in a customized manner, allowing for flexibility beyond just specific fields. An example would be to serialize temperature to the same temperature scale, such as degrees Celsius. ```python from typing import Literal from pydantic import BaseModel, model_serializer class TemperatureModel(BaseModel): unit: Literal['C', 'F'] value: int @model_serializer() def serialize_model(self): if self.unit == 'F': return {'unit': 'C', 'value': int((self.value - 32) / 1.8)} return {'unit': self.unit, 'value': self.value} temperature = TemperatureModel(unit='F', value=212) print(temperature.model_dump()) #> {'unit': 'C', 'value': 100} ``` Two signatures are supported for `mode='plain'`, which is the default: - `(self)` - `(self, info: SerializationInfo)` And two other signatures for `mode='wrap'`: - `(self, nxt: SerializerFunctionWrapHandler)` - `(self, nxt: SerializerFunctionWrapHandler, info: SerializationInfo)` See [the usage documentation](/docs/validation/latest/concepts/serialization#serializers) for more information. ### Returns `_ModelPlainSerializerT` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_ModelWrapSerializerT`\], `_ModelWrapSerializerT`\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_ModelPlainSerializerT`\], `_ModelPlainSerializerT`\] -- The decorator function. ### Parameters **`f`** : `_ModelPlainSerializerT` | `_ModelWrapSerializerT` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The function to be decorated. **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['plain', 'wrap'\] _Default:_ `'plain'` The serialization mode. - `'plain'` means the function will be called instead of the default serialization logic - `'wrap'` means the function will be called with an argument to optionally call the default serialization logic. **`when_used`** : `WhenUsed` _Default:_ `'always'` Determines when this serializer should be used. **`return_type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` The return type for the function. If omitted it will be inferred from the type annotation. ## FieldPlainSerializer A field serializer method or function in `plain` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'core_schema.SerializerFunction | _Partial'` ## FieldWrapSerializer A field serializer method or function in `wrap` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'core_schema.WrapSerializerFunction | _Partial'` ## FieldSerializer A field serializer method or function. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'FieldPlainSerializer | FieldWrapSerializer'` ## ModelPlainSerializerWithInfo A model serializer method with the `info` argument, in `plain` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[Any, SerializationInfo[Any]], Any]` ## ModelPlainSerializerWithoutInfo A model serializer method without the `info` argument, in `plain` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[Any], Any]` ## ModelPlainSerializer A model serializer method in `plain` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'ModelPlainSerializerWithInfo | ModelPlainSerializerWithoutInfo'` ## ModelWrapSerializerWithInfo A model serializer method with the `info` argument, in `wrap` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo[Any]], Any]` ## ModelWrapSerializerWithoutInfo A model serializer method without the `info` argument, in `wrap` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Callable[[Any, SerializerFunctionWrapHandler], Any]` ## ModelWrapSerializer A model serializer method in `wrap` mode. **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `'ModelWrapSerializerWithInfo | ModelWrapSerializerWithoutInfo'` --- # [Functional Validators](https://pydantic.dev/docs/validation/latest/api/pydantic/functional_validators/) # Functional Validators This module contains related classes and functions for validation. ## AfterValidator Usage Documentation [field _after_ validators](/docs/validation/latest/concepts/validators#field-after-validator) A metadata class that indicates that a validation should be applied **after** the inner validation logic. ### Attributes #### func The validator function. **Type:** `core_schema.NoInfoValidatorFunction` | `core_schema.WithInfoValidatorFunction` ## BeforeValidator Usage Documentation [field _before_ validators](/docs/validation/latest/concepts/validators#field-before-validator) A metadata class that indicates that a validation should be applied **before** the inner validation logic. ### Attributes #### func The validator function. **Type:** `core_schema.NoInfoValidatorFunction` | `core_schema.WithInfoValidatorFunction` #### json\_schema\_input\_type The input type used to generate the appropriate JSON Schema (in validation mode). The actual input type is `Any`. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) ## PlainValidator Usage Documentation [field _plain_ validators](/docs/validation/latest/concepts/validators#field-plain-validator) A metadata class that indicates that a validation should be applied **instead** of the inner validation logic. Note Before v2.9, `PlainValidator` wasn't always compatible with JSON Schema generation for `mode='validation'`. You can now use the `json_schema_input_type` argument to specify the input type of the function to be used in the JSON schema when `mode='validation'` (the default). See the example below for more details. ### Attributes #### func The validator function. **Type:** `core_schema.NoInfoValidatorFunction` | `core_schema.WithInfoValidatorFunction` #### json\_schema\_input\_type The input type used to generate the appropriate JSON Schema (in validation mode). The actual input type is `Any`. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) ## WrapValidator Usage Documentation [field _wrap_ validators](/docs/validation/latest/concepts/validators#field-wrap-validator) A metadata class that indicates that a validation should be applied **around** the inner validation logic. ### Attributes #### func The validator function. **Type:** `core_schema.NoInfoWrapValidatorFunction` | `core_schema.WithInfoWrapValidatorFunction` #### json\_schema\_input\_type The input type used to generate the appropriate JSON Schema (in validation mode). The actual input type is `Any`. **Type:** [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) ```python from datetime import datetime from typing import Annotated from pydantic import BaseModel, ValidationError, WrapValidator def validate_timestamp(v, handler): if v == 'now': # we don't want to bother with further validation, just return the new value return datetime.now() try: return handler(v) except ValidationError: # validation failed, in this case we want to return a default value return datetime(2000, 1, 1) MyTimestamp = Annotated[datetime, WrapValidator(validate_timestamp)] class Model(BaseModel): a: MyTimestamp print(Model(a='now').a) #> 2032-01-02 03:04:05.000006 print(Model(a='invalid').a) #> 2000-01-01 00:00:00 ``` ## ModelWrapValidatorHandler **Bases:** `ValidatorFunctionWrapHandler`, `Protocol[_ModelTypeCo]` `@model_validator` decorated function handler argument type. This is used when `mode='wrap'`. ## ModelWrapValidatorWithoutInfo **Bases:** `Protocol[_ModelType]` A `@model_validator` decorated function signature. This is used when `mode='wrap'` and the function does not have info argument. ## ModelWrapValidator **Bases:** `Protocol[_ModelType]` A `@model_validator` decorated function signature. This is used when `mode='wrap'`. ## FreeModelBeforeValidatorWithoutInfo **Bases:** [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) A `@model_validator` decorated function signature. This is used when `mode='before'` and the function does not have info argument. ## ModelBeforeValidatorWithoutInfo **Bases:** [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) A `@model_validator` decorated function signature. This is used when `mode='before'` and the function does not have info argument. ## FreeModelBeforeValidator **Bases:** [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) A `@model_validator` decorated function signature. This is used when `mode='before'`. ## ModelBeforeValidator **Bases:** [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) A `@model_validator` decorated function signature. This is used when `mode='before'`. ## InstanceOf Generic type for annotating a type that is an instance of a given class. ## SkipValidation If this is applied as an annotation (e.g., via `x: Annotated[int, SkipValidation]`), validation will be skipped. You can also use `SkipValidation[int]` as a shorthand for `Annotated[int, SkipValidation]`. This can be useful if you want to use a type annotation for documentation/IDE/type-checking purposes, and know that it is safe to skip validation for one or more of the fields. Because this converts the validation schema to `any_schema`, subsequent annotation-applied transformations may not have the expected effects. Therefore, when used, this annotation should generally be the final annotation applied to a type. ## ValidateAs A helper class to validate a custom type from a type that is natively supported by Pydantic. ### Constructor Parameters **`from_type`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`_FromTypeT`\] The type natively supported by Pydantic to use to perform validation. **`instantiation_hook`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`_FromTypeT`\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] A callable taking the validated type as an argument, and returning the populated custom type. ## field\_validator ```python def field_validator( field: str, fields: str = (), mode: Literal['wrap'], check_fields: bool | None = ..., json_schema_input_type: Any = ..., ) -> Callable[[_V2WrapValidatorType], _V2WrapValidatorType] def field_validator( field: str, fields: str = (), mode: Literal['before', 'plain'], check_fields: bool | None = ..., json_schema_input_type: Any = ..., ) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType] def field_validator( field: str, fields: str = (), mode: Literal['after'] = ..., check_fields: bool | None = ..., ) -> Callable[[_V2BeforeAfterOrPlainValidatorType], _V2BeforeAfterOrPlainValidatorType] ``` Usage Documentation [field validators](/docs/validation/latest/concepts/validators#field-validators) Decorate methods on the class indicating that they should be used to validate fields. Example usage: ```python from typing import Any from pydantic import ( BaseModel, ValidationError, field_validator, ) class Model(BaseModel): a: str @field_validator('a') @classmethod def ensure_foobar(cls, v: Any): if 'foobar' not in v: raise ValueError('"foobar" not found in a') return v print(repr(Model(a='this is foobar good'))) #> Model(a='this is foobar good') try: Model(a='snap') except ValidationError as exc_info: print(exc_info) ''' 1 validation error for Model a Value error, "foobar" not found in a [type=value_error, input_value='snap', input_type=str] ''' ``` For more in depth examples, see [Field Validators](/docs/validation/latest/concepts/validators#field-validators). ### Returns [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] ### Parameters **`*fields`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `()` The field names the validator should apply to. **`mode`** : `FieldValidatorModes` _Default:_ `'after'` Specifies whether to validate the fields before or after validation. **`check_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to check that the fields actually exist on the model. **`json_schema_input_type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` The input type of the function. This is only used to generate the appropriate JSON Schema (in validation mode) and can only specified when `mode` is either `'before'`, `'plain'` or `'wrap'`. ### Raises - `PydanticUserError` -- - If the decorator is used without any arguments (at least one field name must be provided). - If the provided field names are not strings. - If `json_schema_input_type` is provided with an unsupported `mode`. - If the decorator is applied to an instance method. ## model\_validator ```python def model_validator( mode: Literal['wrap'], ) -> Callable[[_AnyModelWrapValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]] def model_validator( mode: Literal['before'], ) -> Callable[[_AnyModelBeforeValidator], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]] def model_validator( mode: Literal['after'], ) -> Callable[[_AnyModelAfterValidator[_ModelType]], _decorators.PydanticDescriptorProxy[_decorators.ModelValidatorDecoratorInfo]] ``` Usage Documentation [Model Validators](/docs/validation/latest/concepts/validators#model-validators) Decorate model methods for validation purposes. Example usage: ```python from typing_extensions import Self from pydantic import BaseModel, ValidationError, model_validator class Square(BaseModel): width: float height: float @model_validator(mode='after') def verify_square(self) -> Self: if self.width != self.height: raise ValueError('width and height do not match') return self s = Square(width=1, height=1) print(repr(s)) #> Square(width=1.0, height=1.0) try: Square(width=1, height=2) except ValidationError as e: print(e) ''' 1 validation error for Square Value error, width and height do not match [type=value_error, input_value={'width': 1, 'height': 2}, input_type=dict] ''' ``` For more in depth examples, see [Model Validators](/docs/validation/latest/concepts/validators#model-validators). ### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- A decorator that can be used to decorate a function to be used as a model validator. ### Parameters **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['wrap', 'before', 'after'\] A required string literal that specifies the validation mode. It can be one of the following: 'wrap', 'before', or 'after'. ## ModelAfterValidatorWithoutInfo A `@model_validator` decorated function signature. This is used when `mode='after'` and the function does not have info argument. **Default:** `Callable[[_ModelType], _ModelType]` ## ModelAfterValidator A `@model_validator` decorated function signature. This is used when `mode='after'`. **Default:** `Callable[[_ModelType, core_schema.ValidationInfo[Any]], _ModelType]` --- # [JSON Schema](https://pydantic.dev/docs/validation/latest/api/pydantic/json_schema/) # JSON Schema Usage Documentation [JSON Schema](/docs/validation/latest/concepts/json_schema) The `json_schema` module contains classes and functions to allow the way [JSON Schema](https://json-schema.org/) is generated to be customized. In general you shouldn't need to use this module directly; instead, you can use [`BaseModel.model_json_schema`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) and [`TypeAdapter.json_schema`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.json_schema). ## PydanticJsonSchemaWarning **Bases:** [`UserWarning`](https://docs.python.org/3/library/exceptions.html#UserWarning) This class is used to emit warnings produced during JSON schema generation. See the [`GenerateJsonSchema.emit_warning`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema.emit_warning) and [`GenerateJsonSchema.render_warning_message`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema.render_warning_message) methods for more details; these can be overridden to control warning behavior. ## GenerateJsonSchema Usage Documentation [Customizing the JSON Schema Generation Process](/docs/validation/latest/concepts/json_schema#customizing-the-json-schema-generation-process) A class for generating JSON schemas. This class generates JSON schemas based on configured parameters. The default schema dialect is [https://json-schema.org/draft/2020-12/schema](https://json-schema.org/draft/2020-12/schema). The class uses `by_alias` to configure how fields with multiple names are handled and `ref_template` to format reference names. ### Attributes #### schema\_dialect The JSON schema dialect used to generate the schema. See [Declaring a Dialect](https://json-schema.org/understanding-json-schema/reference/schema.html#id4) in the JSON Schema documentation for more information about dialects. #### ignored\_warning\_kinds Warnings to ignore when generating the schema. `self.render_warning_message` will do nothing if its argument `kind` is in `ignored_warning_kinds`; this value can be modified on subclasses to easily control which warnings are emitted. **Type:** [`set`](https://docs.python.org/3/reference/expressions.html#set)\[`JsonSchemaWarningKind`\] #### by\_alias Whether to use field aliases when generating the schema. #### ref\_template The format string used when generating reference names. #### core\_to\_json\_refs A mapping of core refs to JSON refs. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`CoreModeRef`, `JsonRef`\] #### core\_to\_defs\_refs A mapping of core refs to definition refs. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`CoreModeRef`, `DefsRef`\] #### defs\_to\_core\_refs A mapping of definition refs to core refs. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`DefsRef`, `CoreModeRef`\] #### json\_to\_defs\_refs A mapping of JSON refs to definition refs. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`JsonRef`, `DefsRef`\] #### definitions Definitions in the schema. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`DefsRef`, `JsonSchemaValue`\] ### Constructor Parameters **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use field aliases in the generated schemas. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The format string to use when generating reference names. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. ### Methods #### build\_schema\_type\_to\_method ```python def build_schema_type_to_method( ) -> dict[CoreSchemaOrFieldType, Callable[[CoreSchemaOrField], JsonSchemaValue]] ``` Builds a dictionary mapping fields to methods for generating JSON schemas. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`CoreSchemaOrFieldType`, [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`CoreSchemaOrField`\], `JsonSchemaValue`\]\] -- A dictionary containing the mapping of `CoreSchemaOrFieldType` to a handler method. ##### Raises - `TypeError` -- If no method has been defined for generating a JSON schema for a given pydantic core schema type. #### generate\_definitions ```python def generate_definitions( inputs: Sequence[tuple[JsonSchemaKeyT, JsonSchemaMode, core_schema.CoreSchema]], ) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], dict[DefsRef, JsonSchemaValue]] ``` Generates JSON schema definitions from a list of core schemas, pairing the generated definitions with a mapping that links the input keys to the definition references. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`JsonSchemaKeyT`, `JsonSchemaMode`\], `JsonSchemaValue`\], [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`DefsRef`, `JsonSchemaValue`\]\] -- A tuple where: - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have JsonRef references to definitions that are defined in the second returned element.) - The second element is a dictionary whose keys are definition references for the JSON schemas from the first returned element, and whose values are the actual JSON schema definitions. ##### Parameters **`inputs`** : [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`JsonSchemaKeyT`, `JsonSchemaMode`, `core_schema.CoreSchema`\]\] A sequence of tuples, where: - The first element is a JSON schema key type. - The second element is the JSON mode: either 'validation' or 'serialization'. - The third element is a core schema. ##### Raises - `PydanticUserError` -- Raised if the JSON schema generator has already been used to generate a JSON schema. #### generate ```python def generate(schema: CoreSchema, mode: JsonSchemaMode = 'validation') -> JsonSchemaValue ``` Generates a JSON schema for a specified schema in a specified mode. ##### Returns `JsonSchemaValue` -- A JSON schema representing the specified schema. ##### Parameters **`schema`** : `CoreSchema` A Pydantic model. **`mode`** : `JsonSchemaMode` _Default:_ `'validation'` The mode in which to generate the schema. Defaults to 'validation'. ##### Raises - `PydanticUserError` -- If the JSON schema generator has already been used to generate a JSON schema. #### generate\_inner ```python def generate_inner(schema: CoreSchemaOrField) -> JsonSchemaValue ``` Generates a JSON schema for a given core schema. TODO: the nested function definitions here seem like bad practice, I'd like to unpack these in a future PR. It'd be great if we could shorten the call stack a bit for JSON schema generation, and I think there's potential for that here. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `CoreSchemaOrField` The given core schema. #### sort ```python def sort(value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue ``` Override this method to customize the sorting of the JSON schema (e.g., don't sort at all, sort all keys unconditionally, etc.) By default, alphabetically sort the keys in the JSON schema, skipping the 'properties' and 'default' keys to preserve field definition order. This sort is recursive, so it will sort all nested dictionaries as well. ##### Returns `JsonSchemaValue` #### invalid\_schema ```python def invalid_schema(schema: core_schema.InvalidSchema) -> JsonSchemaValue ``` Placeholder - should never be called. ##### Returns `JsonSchemaValue` #### any\_schema ```python def any_schema(schema: core_schema.AnySchema) -> JsonSchemaValue ``` Generates a JSON schema that matches any value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.AnySchema` The core schema. #### none\_schema ```python def none_schema(schema: core_schema.NoneSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches `None`. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.NoneSchema` The core schema. #### bool\_schema ```python def bool_schema(schema: core_schema.BoolSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a bool value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.BoolSchema` The core schema. #### int\_schema ```python def int_schema(schema: core_schema.IntSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches an int value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.IntSchema` The core schema. #### float\_schema ```python def float_schema(schema: core_schema.FloatSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a float value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.FloatSchema` The core schema. #### decimal\_schema ```python def decimal_schema(schema: core_schema.DecimalSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a decimal value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DecimalSchema` The core schema. #### str\_schema ```python def str_schema(schema: core_schema.StringSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a string value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.StringSchema` The core schema. #### bytes\_schema ```python def bytes_schema(schema: core_schema.BytesSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a bytes value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.BytesSchema` The core schema. #### date\_schema ```python def date_schema(schema: core_schema.DateSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a date value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DateSchema` The core schema. #### time\_schema ```python def time_schema(schema: core_schema.TimeSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a time value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TimeSchema` The core schema. #### datetime\_schema ```python def datetime_schema(schema: core_schema.DatetimeSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a datetime value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DatetimeSchema` The core schema. #### timedelta\_schema ```python def timedelta_schema(schema: core_schema.TimedeltaSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a timedelta value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TimedeltaSchema` The core schema. #### literal\_schema ```python def literal_schema(schema: core_schema.LiteralSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a literal value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.LiteralSchema` The core schema. #### missing\_sentinel\_schema ```python def missing_sentinel_schema( schema: core_schema.MissingSentinelSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches the `MISSING` sentinel value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.MissingSentinelSchema` The core schema. #### enum\_schema ```python def enum_schema(schema: core_schema.EnumSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches an Enum value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.EnumSchema` The core schema. #### is\_instance\_schema ```python def is_instance_schema(schema: core_schema.IsInstanceSchema) -> JsonSchemaValue ``` Handles JSON schema generation for a core schema that checks if a value is an instance of a class. Unless overridden in a subclass, this raises an error. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.IsInstanceSchema` The core schema. #### is\_subclass\_schema ```python def is_subclass_schema(schema: core_schema.IsSubclassSchema) -> JsonSchemaValue ``` Handles JSON schema generation for a core schema that checks if a value is a subclass of a class. For backwards compatibility with v1, this does not raise an error, but can be overridden to change this. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.IsSubclassSchema` The core schema. #### callable\_schema ```python def callable_schema(schema: core_schema.CallableSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a callable value. Unless overridden in a subclass, this raises an error. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.CallableSchema` The core schema. #### list\_schema ```python def list_schema(schema: core_schema.ListSchema) -> JsonSchemaValue ``` Returns a schema that matches a list schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ListSchema` The core schema. #### tuple\_positional\_schema ```python def tuple_positional_schema(schema: core_schema.TupleSchema) -> JsonSchemaValue ``` Replaced by `tuple_schema`. ##### Returns `JsonSchemaValue` #### tuple\_variable\_schema ```python def tuple_variable_schema(schema: core_schema.TupleSchema) -> JsonSchemaValue ``` Replaced by `tuple_schema`. ##### Returns `JsonSchemaValue` #### tuple\_schema ```python def tuple_schema(schema: core_schema.TupleSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a tuple schema e.g. `tuple[int, str, bool]` or `tuple[int, ...]`. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TupleSchema` The core schema. #### set\_schema ```python def set_schema(schema: core_schema.SetSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a set schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.SetSchema` The core schema. #### frozenset\_schema ```python def frozenset_schema(schema: core_schema.FrozenSetSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a frozenset schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.FrozenSetSchema` The core schema. #### generator\_schema ```python def generator_schema(schema: core_schema.GeneratorSchema) -> JsonSchemaValue ``` Returns a JSON schema that represents the provided GeneratorSchema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.GeneratorSchema` The schema. #### dict\_schema ```python def dict_schema(schema: core_schema.DictSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a dict schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DictSchema` The core schema. #### function\_before\_schema ```python def function_before_schema( schema: core_schema.BeforeValidatorFunctionSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a function-before schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.BeforeValidatorFunctionSchema` The core schema. #### function\_after\_schema ```python def function_after_schema( schema: core_schema.AfterValidatorFunctionSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a function-after schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.AfterValidatorFunctionSchema` The core schema. #### function\_plain\_schema ```python def function_plain_schema( schema: core_schema.PlainValidatorFunctionSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a function-plain schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.PlainValidatorFunctionSchema` The core schema. #### function\_wrap\_schema ```python def function_wrap_schema( schema: core_schema.WrapValidatorFunctionSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a function-wrap schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.WrapValidatorFunctionSchema` The core schema. #### default\_schema ```python def default_schema(schema: core_schema.WithDefaultSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema with a default value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.WithDefaultSchema` The core schema. #### get\_default\_value ```python def get_default_value(schema: core_schema.WithDefaultSchema) -> Any ``` Get the default value to be used when generating a JSON Schema for a core schema with a default. The default implementation is to use the statically defined default value. This method can be overridden if you want to make use of the default factory. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The default value to use, or [`NoDefault`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.NoDefault) if no default value is available. ##### Parameters **`schema`** : `core_schema.WithDefaultSchema` The `'with-default'` core schema. #### nullable\_schema ```python def nullable_schema(schema: core_schema.NullableSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that allows null values. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.NullableSchema` The core schema. #### union\_schema ```python def union_schema(schema: core_schema.UnionSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that allows values matching any of the given schemas. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.UnionSchema` The core schema. #### get\_union\_of\_schemas ```python def get_union_of_schemas(schemas: list[JsonSchemaValue]) -> JsonSchemaValue ``` Returns the JSON Schema representation for the union of the provided JSON Schemas. The result depends on the configured `'union_format'`. ##### Returns `JsonSchemaValue` -- The JSON Schema representing the union of schemas. ##### Parameters **`schemas`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`JsonSchemaValue`\] The list of JSON Schemas to be included in the union. #### tagged\_union\_schema ```python def tagged_union_schema(schema: core_schema.TaggedUnionSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that allows values matching any of the given schemas, where the schemas are tagged with a discriminator field that indicates which schema should be used to validate the value. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TaggedUnionSchema` The core schema. #### chain\_schema ```python def chain_schema(schema: core_schema.ChainSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a core\_schema.ChainSchema. When generating a schema for validation, we return the validation JSON schema for the first step in the chain. For serialization, we return the serialization JSON schema for the last step in the chain. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ChainSchema` The core schema. #### lax\_or\_strict\_schema ```python def lax_or_strict_schema(schema: core_schema.LaxOrStrictSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that allows values matching either the lax schema or the strict schema. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.LaxOrStrictSchema` The core schema. #### json\_or\_python\_schema ```python def json_or_python_schema(schema: core_schema.JsonOrPythonSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that allows values matching either the JSON schema or the Python schema. The JSON schema is used instead of the Python schema. If you want to use the Python schema, you should override this method. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.JsonOrPythonSchema` The core schema. #### typed\_dict\_schema ```python def typed_dict_schema(schema: core_schema.TypedDictSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a typed dict. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TypedDictSchema` The core schema. #### typed\_dict\_field\_schema ```python def typed_dict_field_schema(schema: core_schema.TypedDictField) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a typed dict field. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.TypedDictField` The core schema. #### dataclass\_field\_schema ```python def dataclass_field_schema(schema: core_schema.DataclassField) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a dataclass field. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DataclassField` The core schema. #### model\_field\_schema ```python def model_field_schema(schema: core_schema.ModelField) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a model field. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ModelField` The core schema. #### computed\_field\_schema ```python def computed_field_schema(schema: core_schema.ComputedField) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a computed field. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ComputedField` The core schema. #### model\_schema ```python def model_schema(schema: core_schema.ModelSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a model. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ModelSchema` The core schema. #### resolve\_ref\_schema ```python def resolve_ref_schema(json_schema: JsonSchemaValue) -> JsonSchemaValue ``` Resolve a JsonSchemaValue to the non-ref schema if it is a $ref schema. ##### Returns `JsonSchemaValue` -- The resolved schema. ##### Parameters **`json_schema`** : `JsonSchemaValue` The schema to resolve. ##### Raises - `RuntimeError` -- If the schema reference can't be found in definitions. #### model\_fields\_schema ```python def model_fields_schema(schema: core_schema.ModelFieldsSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a model's fields. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ModelFieldsSchema` The core schema. #### field\_is\_present ```python def field_is_present(field: CoreSchemaField) -> bool ``` Whether the field should be included in the generated JSON schema. ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- `True` if the field should be included in the generated JSON schema, `False` otherwise. ##### Parameters **`field`** : `CoreSchemaField` The schema for the field itself. #### field\_is\_required ```python def field_is_required( field: core_schema.ModelField | core_schema.DataclassField | core_schema.TypedDictField, total: bool, ) -> bool ``` Whether the field should be marked as required in the generated JSON schema. (Note that this is irrelevant if the field is not present in the JSON schema.). ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- `True` if the field should be marked as required in the generated JSON schema, `False` otherwise. ##### Parameters **`field`** : `core_schema.ModelField` | `core_schema.DataclassField` | `core_schema.TypedDictField` The schema for the field itself. **`total`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) Only applies to `TypedDictField`s. Indicates if the `TypedDict` this field belongs to is total, in which case any fields that don't explicitly specify `required=False` are required. #### dataclass\_args\_schema ```python def dataclass_args_schema(schema: core_schema.DataclassArgsSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a dataclass's constructor arguments. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DataclassArgsSchema` The core schema. #### dataclass\_schema ```python def dataclass_schema(schema: core_schema.DataclassSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a dataclass. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DataclassSchema` The core schema. #### arguments\_schema ```python def arguments_schema(schema: core_schema.ArgumentsSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a function's arguments. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ArgumentsSchema` The core schema. #### kw\_arguments\_schema ```python def kw_arguments_schema( arguments: list[core_schema.ArgumentsParameter], var_kwargs_schema: CoreSchema | None, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a function's keyword arguments. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`arguments`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`core_schema.ArgumentsParameter`\] The core schema. #### p\_arguments\_schema ```python def p_arguments_schema( arguments: list[core_schema.ArgumentsParameter], var_args_schema: CoreSchema | None, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a function's positional arguments. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`arguments`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`core_schema.ArgumentsParameter`\] The core schema. #### get\_argument\_name ```python def get_argument_name( argument: core_schema.ArgumentsParameter | core_schema.ArgumentsV3Parameter, ) -> str ``` Retrieves the name of an argument. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The name of the argument. ##### Parameters **`argument`** : `core_schema.ArgumentsParameter` | `core_schema.ArgumentsV3Parameter` The core schema. #### arguments\_v3\_schema ```python def arguments_v3_schema(schema: core_schema.ArgumentsV3Schema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a function's arguments. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ArgumentsV3Schema` The core schema. #### call\_schema ```python def call_schema(schema: core_schema.CallSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a function call. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.CallSchema` The core schema. #### custom\_error\_schema ```python def custom_error_schema(schema: core_schema.CustomErrorSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a custom error. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.CustomErrorSchema` The core schema. #### json\_schema ```python def json_schema(schema: core_schema.JsonSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a JSON object. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.JsonSchema` The core schema. #### url\_schema ```python def url_schema(schema: core_schema.UrlSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a URL. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.UrlSchema` The core schema. #### multi\_host\_url\_schema ```python def multi_host_url_schema(schema: core_schema.MultiHostUrlSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a URL that can be used with multiple hosts. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.MultiHostUrlSchema` The core schema. #### uuid\_schema ```python def uuid_schema(schema: core_schema.UuidSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a UUID. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.UuidSchema` The core schema. #### definitions\_schema ```python def definitions_schema(schema: core_schema.DefinitionsSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that defines a JSON object with definitions. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DefinitionsSchema` The core schema. #### definition\_ref\_schema ```python def definition_ref_schema( schema: core_schema.DefinitionReferenceSchema, ) -> JsonSchemaValue ``` Generates a JSON schema that matches a schema that references a definition. ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.DefinitionReferenceSchema` The core schema. #### ser\_schema ```python def ser_schema( schema: core_schema.SerSchema | core_schema.IncExSeqSerSchema | core_schema.IncExDictSerSchema, ) -> JsonSchemaValue | None ``` Generates a JSON schema that matches a schema that defines a serialized object. ##### Returns `JsonSchemaValue` | [`None`](https://docs.python.org/3/library/constants.html#None) -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.SerSchema` | `core_schema.IncExSeqSerSchema` | `core_schema.IncExDictSerSchema` The core schema. #### complex\_schema ```python def complex_schema(schema: core_schema.ComplexSchema) -> JsonSchemaValue ``` Generates a JSON schema that matches a complex number. JSON has no standard way to represent complex numbers. Complex number is not a numeric type. Here we represent complex number as strings following the rule defined by Python. For instance, '1+2j' is an accepted complex string. Details can be found in [Python's `complex` documentation](https://docs.python.org/3/library/functions.html#complex). ##### Returns `JsonSchemaValue` -- The generated JSON schema. ##### Parameters **`schema`** : `core_schema.ComplexSchema` The core schema. #### get\_title\_from\_name ```python def get_title_from_name(name: str) -> str ``` Retrieves a title from a name. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The title. ##### Parameters **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name to retrieve a title from. #### field\_title\_should\_be\_set ```python def field_title_should_be_set(schema: CoreSchemaOrField) -> bool ``` Returns true if a field with the given schema should have a title set based on the field name. Intuitively, we want this to return true for schemas that wouldn't otherwise provide their own title (e.g., int, float, str), and false for those that would (e.g., BaseModel subclasses). ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- `True` if the field should have a title set, `False` otherwise. ##### Parameters **`schema`** : `CoreSchemaOrField` The schema to check. #### normalize\_name ```python def normalize_name(name: str) -> str ``` Normalizes a name to be used as a key in a dictionary. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The normalized name. ##### Parameters **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name to normalize. #### get\_defs\_ref ```python def get_defs_ref(core_mode_ref: CoreModeRef) -> DefsRef ``` Override this method to change the way that definitions keys are generated from a core reference. ##### Returns `DefsRef` -- The definitions key. ##### Parameters **`core_mode_ref`** : `CoreModeRef` The core reference. #### get\_cache\_defs\_ref\_schema ```python def get_cache_defs_ref_schema(core_ref: CoreRef) -> tuple[DefsRef, JsonSchemaValue] ``` This method wraps the get\_defs\_ref method with some cache-lookup/population logic, and returns both the produced defs\_ref and the JSON schema that will refer to the right definition. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`DefsRef`, `JsonSchemaValue`\] -- A tuple of the definitions reference and the JSON schema that will refer to it. ##### Parameters **`core_ref`** : `CoreRef` The core reference to get the definitions reference for. #### handle\_ref\_overrides ```python def handle_ref_overrides(json_schema: JsonSchemaValue) -> JsonSchemaValue ``` Remove any sibling keys that are redundant with the referenced schema. ##### Returns `JsonSchemaValue` -- The schema with redundant sibling keys removed. ##### Parameters **`json_schema`** : `JsonSchemaValue` The schema to remove redundant sibling keys from. #### encode\_default ```python def encode_default(dft: Any) -> Any ``` Encode a default value to a JSON-serializable value. This is used to encode default values for fields in the generated JSON schema. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The encoded default value. ##### Parameters **`dft`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The default value to encode. #### update\_with\_validations ```python def update_with_validations( json_schema: JsonSchemaValue, core_schema: CoreSchema, mapping: dict[str, str], ) -> None ``` Update the json\_schema with the corresponding validations specified in the core\_schema, using the provided mapping to translate keys in core\_schema to the appropriate keys for a JSON schema. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) ##### Parameters **`json_schema`** : `JsonSchemaValue` The JSON schema to update. **`core_schema`** : `CoreSchema` The core schema to get the validations from. **`mapping`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] A mapping from core\_schema attribute names to the corresponding JSON schema attribute names. #### get\_json\_ref\_counts ```python def get_json_ref_counts(json_schema: JsonSchemaValue) -> dict[JsonRef, int] ``` Get all values corresponding to the key '$ref' anywhere in the json\_schema. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[`JsonRef`, [`int`](https://docs.python.org/3/library/functions.html#int)\] #### emit\_warning ```python def emit_warning(kind: JsonSchemaWarningKind, detail: str) -> None ``` This method simply emits PydanticJsonSchemaWarnings based on handling in the `warning_message` method. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### render\_warning\_message ```python def render_warning_message(kind: JsonSchemaWarningKind, detail: str) -> str | None ``` This method is responsible for ignoring warnings as desired, and for formatting the warning messages. You can override the value of `ignored_warning_kinds` in a subclass of GenerateJsonSchema to modify what warnings are generated. If you want more control, you can override this method; just return None in situations where you don't want warnings to be emitted. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) -- The formatted warning message, or `None` if no warning should be emitted. ##### Parameters **`kind`** : `JsonSchemaWarningKind` The kind of warning to render. It can be one of the following: - 'skipped-choice': A choice field was skipped because it had no valid choices. - 'non-serializable-default': A default value was skipped because it was not JSON-serializable. **`detail`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) A string with additional details about the warning. ## WithJsonSchema Usage Documentation [`WithJsonSchema` Annotation](/docs/validation/latest/concepts/json_schema#withjsonschema-annotation) An annotation used to override the JSON Schema for a type. This is useful when you want to set a JSON Schema for a type that don't produce any JSON Schemas by default (e.g. [`Callable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable)). If `mode` is set this will only apply to that schema generation mode, allowing you to set different JSON Schemas for validation and serialization. Note If the `WithJsonSchema` annotation is coupled with the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function, the behavior overriding will vary depending on the location: - If the [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata is specified at the "top-level" field, `Field()` metadata arguments (excluding [constraints](/docs/validation/latest/concepts/fields#field-constraints)) such as `title` and `description` will be applied on top of the `WithJsonSchema`, no matter the order: ```python from typing import Annotated from pydantic import BaseModel, Field, WithJsonSchema class Model(BaseModel): field: Annotated[ int, Field(title='My Field'), WithJsonSchema({'type': 'integer', 'extra': 'data'}), ] Model.model_json_schema()['properties']['field'] #> {'type': 'integer', 'extra': 'data', 'title': 'My Field'} ``` - If the [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata is specified on a specific inner type, `WithJsonSchema` will unconditionally override the JSON Schema: ```python from typing import Annotated from pydantic import BaseModel, Field, WithJsonSchema class Model(BaseModel): field: list[ Annotated[ int, Field(title='My Field'), WithJsonSchema({'type': 'integer', 'extra': 'data'}), ] ] Model.model_json_schema()['properties']['field'] #> {'items': {'extra': 'data', 'type': 'integer'}, 'title': 'Field', 'type': 'array'} ``` See also the documentation about [the annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern). ## Examples Add examples to a JSON schema. If the JSON Schema already contains examples, the provided examples will be appended. If `mode` is set this will only apply to that schema generation mode, allowing you to add different examples for validation and serialization. ## SkipJsonSchema Usage Documentation [`SkipJsonSchema` Annotation](/docs/validation/latest/concepts/json_schema#skipjsonschema-annotation) Add this as an annotation on a field to skip generating a JSON schema for that field. ## model\_json\_schema ```python def model_json_schema( cls: type[BaseModel] | type[PydanticDataclass], by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE, union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, mode: JsonSchemaMode = 'validation', ) -> dict[str, Any] ``` Utility function to generate a JSON Schema for a model. ### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- The generated JSON Schema. ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel)\] | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\] The model class to generate a JSON Schema for. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` If `True` (the default), fields will be serialized according to their alias. If `False`, fields will be serialized according to their attribute name. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The template to use for generating JSON Schema references. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` The class to use for generating the JSON Schema. **`mode`** : `JsonSchemaMode` _Default:_ `'validation'` The mode to use for generating the JSON Schema. It can be one of the following: - 'validation': Generate a JSON Schema for validating data. - 'serialization': Generate a JSON Schema for serializing data. ## models\_json\_schema ```python def models_json_schema( models: Sequence[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode]], by_alias: bool = True, title: str | None = None, description: str | None = None, ref_template: str = DEFAULT_REF_TEMPLATE, union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, ) -> tuple[dict[tuple[type[BaseModel] | type[PydanticDataclass], JsonSchemaMode], JsonSchemaValue], JsonSchemaValue] ``` Utility function to generate a JSON Schema for multiple models. ### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[[`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel)\] | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\], `JsonSchemaMode`\], `JsonSchemaValue`\], `JsonSchemaValue`\] -- A tuple where: - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have JsonRef references to definitions that are defined in the second returned element.) - The second element is a JSON schema containing all definitions referenced in the first returned element, along with the optional title and description keys. ### Parameters **`models`** : [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`type`](https://docs.python.org/3/glossary.html#term-type)\[[`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel)\] | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`PydanticDataclass`\], `JsonSchemaMode`\]\] A sequence of tuples of the form (model, mode). **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether field aliases should be used as keys in the generated JSON Schema. **`title`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The title of the generated JSON Schema. **`description`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The description of the generated JSON Schema. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The reference template to use for generating JSON Schema references. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` The schema generator to use for generating the JSON Schema. ## CoreSchemaOrFieldType A type alias for defined schema types that represents a union of `core_schema.CoreSchemaType` and `core_schema.CoreSchemaFieldType`. **Default:** `Literal[core_schema.CoreSchemaType, core_schema.CoreSchemaFieldType]` ## JsonSchemaValue A type alias for a JSON schema value. This is a dictionary of string keys to arbitrary JSON values. **Default:** `dict[str, Any]` ## JsonSchemaMode A type alias that represents the mode of a JSON schema; either 'validation' or 'serialization'. For some types, the inputs to validation differ from the outputs of serialization. For example, computed fields will only be present when serializing, and should not be provided when validating. This flag provides a way to indicate whether you want the JSON schema required for validation inputs, or that will be matched by serialization outputs. **Default:** `Literal['validation', 'serialization']` ## JsonSchemaWarningKind A type alias representing the kinds of warnings that can be emitted during JSON schema generation. See [`GenerateJsonSchema.render_warning_message`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema.render_warning_message) for more details. **Default:** `Literal['skipped-choice', 'non-serializable-default', 'skipped-discriminator']` ## NoDefault A sentinel value used to indicate that no default value should be used when generating a JSON Schema for a core schema with a default value. **Default:** `object()` ## DEFAULT\_REF\_TEMPLATE The default format string used to generate reference names. **Default:** `'#/$defs/{model}'` --- # [Network Types](https://pydantic.dev/docs/validation/latest/api/pydantic/networks/) # Network Types The networks module contains types for common network-related fields. ## UrlConstraints Url constraints. ### Attributes #### max\_length The maximum length of the url. Defaults to `None`. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### allowed\_schemes The allowed schemes. Defaults to `None`. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### host\_required Whether the host is required. Defaults to `None`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### default\_host The default host. Defaults to `None`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### default\_port The default port. Defaults to `None`. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### default\_path The default path. Defaults to `None`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### preserve\_empty\_path Whether to preserve empty URL paths. Defaults to `None`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) ## AnyUrl **Bases:** `_BaseUrl` Base type for all URLs. - Any scheme allowed - Top-level domain (TLD) not required - Host not required Assuming an input URL of `http://samuel:pass@example.com:8000/the/path/?query=here#fragment=is;this=bit`, the types export the following properties: - `scheme`: the URL scheme (`http`), always set. - `host`: the URL host (`example.com`). - `username`: optional username if included (`samuel`). - `password`: optional password if included (`pass`). - `port`: optional port (`8000`). - `path`: optional path (`/the/path/`). - `query`: optional URL query (for example, `GET` arguments or "search string", such as `query=here`). - `fragment`: optional fragment (`fragment=is;this=bit`). ## AnyHttpUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any http or https URL. - TLD not required - Host not required ## HttpUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any http or https URL. - TLD not required - Host not required - Max length 2083 ```python from pydantic import BaseModel, HttpUrl, ValidationError class MyModel(BaseModel): url: HttpUrl m = MyModel(url='http://www.example.com') # (1) print(m.url) #> http://www.example.com/ try: MyModel(url='ftp://invalid.url') except ValidationError as e: print(e) ''' 1 validation error for MyModel url URL scheme should be 'http' or 'https' [type=url_scheme, input_value='ftp://invalid.url', input_type=str] ''' try: MyModel(url='not a url') except ValidationError as e: print(e) ''' 1 validation error for MyModel url Input should be a valid URL, relative URL without a base [type=url_parsing, input_value='not a url', input_type=str] ''' ``` Note: mypy would prefer `m = MyModel(url=HttpUrl('http://www.example.com'))`, but Pydantic will convert the string to an HttpUrl instance anyway. "International domains" (e.g. a URL where the host or TLD includes non-ascii characters) will be encoded via [punycode](https://en.wikipedia.org/wiki/Punycode) (see [this article](https://www.xudongz.com/blog/2017/idn-phishing/) for a good description of why this is important): ```python from pydantic import BaseModel, HttpUrl class MyModel(BaseModel): url: HttpUrl m1 = MyModel(url='http://puny£code.com') print(m1.url) #> http://xn--punycode-eja.com/ m2 = MyModel(url='https://www.аррӏе.com/') print(m2.url) #> https://www.xn--80ak6aa92e.com/ m3 = MyModel(url='https://www.example.珠宝/') print(m3.url) #> https://www.example.xn--pbt977c/ ``` Underscores in Hostnames In Pydantic, underscores are allowed in all parts of a domain except the TLD. Technically this might be wrong - in theory the hostname cannot have underscores, but subdomains can. To explain this; consider the following two cases: - `exam_ple.co.uk`: the hostname is `exam_ple`, which should not be allowed since it contains an underscore. - `foo_bar.example.com` the hostname is `example`, which should be allowed since the underscore is in the subdomain. Without having an exhaustive list of TLDs, it would be impossible to differentiate between these two. Therefore underscores are allowed, but you can always do further validation in a validator if desired. Also, Chrome, Firefox, and Safari all currently accept `http://exam_ple.com` as a URL, so we're in good (or at least big) company. ## AnyWebsocketUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any ws or wss URL. - TLD not required - Host not required ## WebsocketUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any ws or wss URL. - TLD not required - Host not required - Max length 2083 ## FileUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any file URL. - Host not required ## FtpUrl **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept ftp URL. - TLD not required - Host not required ## PostgresDsn **Bases:** `_BaseMultiHostUrl` A type that will accept any Postgres DSN. - User info required - TLD not required - Host required - Supports multiple hosts If further validation is required, these properties can be used by validators to enforce specific behaviour: ```python from pydantic import ( BaseModel, HttpUrl, PostgresDsn, ValidationError, field_validator, ) class MyModel(BaseModel): url: HttpUrl m = MyModel(url='http://www.example.com') # the repr() method for a url will display all properties of the url print(repr(m.url)) #> HttpUrl('http://www.example.com/') print(m.url.scheme) #> http print(m.url.host) #> www.example.com print(m.url.port) #> 80 class MyDatabaseModel(BaseModel): db: PostgresDsn @field_validator('db') def check_db_name(cls, v): assert v.path and len(v.path) > 1, 'database must be provided' return v m = MyDatabaseModel(db='postgres://user:pass@localhost:5432/foobar') print(m.db) #> postgres://user:pass@localhost:5432/foobar try: MyDatabaseModel(db='postgres://user:pass@localhost:5432') except ValidationError as e: print(e) ''' 1 validation error for MyDatabaseModel db Assertion failed, database must be provided assert (None) + where None = PostgresDsn('postgres://user:pass@localhost:5432').path [type=assertion_error, input_value='postgres://user:pass@localhost:5432', input_type=str] ''' ``` ### Attributes #### host The required URL host. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## CockroachDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any Cockroach DSN. - User info required - TLD not required - Host required ### Attributes #### host The required URL host. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## AmqpDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any AMQP DSN. - User info required - TLD not required - Host not required ## RedisDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any Redis DSN. - User info required - TLD not required - Host required (e.g., `rediss://:pass@localhost`) ### Attributes #### host The required URL host. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## MongoDsn **Bases:** `_BaseMultiHostUrl` A type that will accept any MongoDB DSN. - User info not required - Database name not required - Port not required - User info may be passed without user part (e.g., `mongodb://mongodb0.example.com:27017`). Caution If a port isn't specified, the default MongoDB port `27017` will be used. If this behavior is undesirable, you can use the following: ```python from typing import Annotated from pydantic_core import MultiHostUrl from pydantic import UrlConstraints MongoDsnNoDefaultPort = Annotated[ MultiHostUrl, UrlConstraints(allowed_schemes=['mongodb', 'mongodb+srv']), ] ``` ## KafkaDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any Kafka DSN. - User info required - TLD not required - Host not required ## NatsDsn **Bases:** `_BaseMultiHostUrl` A type that will accept any NATS DSN. NATS is a connective technology built for the ever increasingly hyper-connected world. It is a single technology that enables applications to securely communicate across any combination of cloud vendors, on-premise, edge, web and mobile, and devices. More: [https://nats.io](https://nats.io) ## MySQLDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any MySQL DSN. - User info required - TLD not required - Host not required ## MariaDBDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any MariaDB DSN. - User info required - TLD not required - Host not required ## ClickHouseDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any ClickHouse DSN. - User info required - TLD not required - Host not required ## SnowflakeDsn **Bases:** [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) A type that will accept any Snowflake DSN. - User info required - TLD not required - Host required ### Attributes #### host The required URL host. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## EmailStr Validate email addresses. ```python from pydantic import BaseModel, EmailStr class Model(BaseModel): email: EmailStr print(Model(email='contact@mail.com')) #> email='contact@mail.com' ``` ## NameEmail **Bases:** `Representation` Validate a name and email address combination, as specified by [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4). The `NameEmail` has two properties: `name` and `email`. In case the `name` is not provided, it's inferred from the email address. ```python from pydantic import BaseModel, NameEmail class User(BaseModel): email: NameEmail user = User(email='Fred Bloggs ') print(user.email) #> Fred Bloggs print(user.email.name) #> Fred Bloggs user = User(email='fred.bloggs@example.com') print(user.email) #> fred.bloggs print(user.email.name) #> fred.bloggs ``` ## IPvAnyAddress Validate an IPv4 or IPv6 address. ```python from pydantic import BaseModel from pydantic.networks import IPvAnyAddress class IpModel(BaseModel): ip: IPvAnyAddress print(IpModel(ip='127.0.0.1')) #> ip=IPv4Address('127.0.0.1') try: IpModel(ip='http://www.example.com') except ValueError as e: print(e.errors()) ''' [ { 'type': 'ip_any_address', 'loc': ('ip',), 'msg': 'value is not a valid IPv4 or IPv6 address', 'input': 'http://www.example.com', } ] ''' ``` ## IPvAnyInterface Validate an IPv4 or IPv6 interface. ## IPvAnyNetwork Validate an IPv4 or IPv6 network. ## validate\_email ```python def validate_email(value: str) -> tuple[str, str] ``` Email address validation using [email-validator](https://pypi.org/project/email-validator/). ### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str)\] -- A tuple containing the local part of the email (or the name for "pretty" email addresses) and the normalized email. ### Raises - `PydanticCustomError` -- If the email is invalid. ## MAX\_EMAIL\_LENGTH Maximum length for an email. A somewhat arbitrary but very generous number compared to what is allowed by most implementations. **Default:** `2048` --- # [RootModel](https://pydantic.dev/docs/validation/latest/api/pydantic/root_model/) # RootModel RootModel class and type definitions. ## RootModel **Bases:** [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel), `Generic[RootModelRootType]` Usage Documentation [`RootModel` and Custom Root Types](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types) A Pydantic `BaseModel` for the root object of the model. ### Attributes #### root The root object of the model. **Type:** `RootModelRootType` #### \_\_pydantic\_root\_model\_\_ Whether the model is a RootModel. #### \_\_pydantic\_private\_\_ Private fields in the model. #### \_\_pydantic\_extra\_\_ Extra fields in the model. ### Methods #### model\_construct `@classmethod` ```python def model_construct( cls, root: RootModelRootType, _fields_set: set[str] | None = None, ) -> Self ``` Create a new model using the provided root object and update fields set. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) -- The new model. ##### Parameters **`root`** : `RootModelRootType` The root object of the model. **`_fields_set`** : [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The set of fields to be updated. ##### Raises - `NotImplemented` -- If the model is not a subclass of `RootModel`. #### model\_dump ```python def model_dump( mode: Literal['json', 'python'] | str = 'python', include: Any = None, exclude: Any = None, context: dict[str, Any] | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, serialize_as_any: bool = False, ) -> Any ``` This method is included just to get a more accurate return type for type checkers. It is included in this `if TYPE_CHECKING:` block since no override is actually necessary. See the documentation of `BaseModel.model_dump` for more details about the arguments. Generally, this method will have a return type of `RootModelRootType`, assuming that `RootModelRootType` is not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel` subclass, then the return type will likely be `dict[str, Any]`, as `model_dump` calls are recursive. The return type could even be something different, in the case of a custom serializer. Thus, `Any` is used here to catch all of these cases. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) --- # [Standard Library Types](https://pydantic.dev/docs/validation/latest/api/pydantic/standard_library_types/) > Support for common types from the Python standard library. # Standard Library Types This section enumerates the supported built-in and standard library types: the allowed values, the possible constraints, and whether strictness can be configured. See also the [conversion table](/docs/validation/latest/concepts/conversion_table) for a summary of the allowed values for each type. Note Unless specified otherwise, values are serialized as-is, in both Python and JSON modes. ## Booleans Built-in type: [`bool`](https://docs.python.org/3/library/functions.html#bool) ### Validation - A valid [`bool`](https://docs.python.org/3/library/functions.html#bool) instance, i.e. `True` or `False`. - The integers `0` or `1`. - A string, which when converted to lowercase is one of `'0'`, `'off'`, `'f'`, `'false'`, `'n'`, `'no'`, `'1'`, `'on'` `'t'`, `'true'`, `'y'`, `'yes'`. - [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) objects that are valid per the previous rule when decoded to a string. ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only boolean values are valid. Pydantic provides the [`StrictBool`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictBool) type as a convenience to [using the `Strict()` metadata class](/docs/validation/latest/concepts/strict_mode#using-the-strict-metadata-class). ### Example ```python from pydantic import BaseModel, ValidationError class BooleanModel(BaseModel): bool_value: bool print(BooleanModel(bool_value=False)) #> bool_value=False print(BooleanModel(bool_value='False')) #> bool_value=False print(BooleanModel(bool_value=1)) #> bool_value=True try: BooleanModel(bool_value=[]) except ValidationError as e: print(str(e)) """ 1 validation error for BooleanModel bool_value Input should be a valid boolean [type=bool_type, input_value=[], input_type=list] """ ``` ## Strings Built-in type: [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Validation - Strings are accepted as-is. - [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) and [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) are decoded to UTF-8 strings. - [Enums](https://docs.python.org/3/library/enum.html#module-enum) are converted using the [`value`](https://docs.python.org/3/library/enum.html#enum.Enum.value) attribute, by calling [`str()`](https://docs.python.org/3/library/stdtypes.html#str) on it. - If [`coerce_numbers_to_str`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.coerce_numbers_to_str) is set, any number type ([`int`](https://docs.python.org/3/library/functions.html#int), [`float`](https://docs.python.org/3/library/functions.html#float) and [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal)) will be coerced to a string and accepted as-is. ### Constraints Strings support the following constraints: Constraint Description JSON Schema `pattern` A regex pattern that the string must match [`pattern`](https://json-schema.org/understanding-json-schema/reference/string#regexp) keyword (see [note](#pattern-constraint-note) below). `min_length` The minimum length of the string [`minLength`](https://json-schema.org/understanding-json-schema/reference/string#length) keyword `max_length` The maximum length of the string [`maxLength`](https://json-schema.org/understanding-json-schema/reference/string#length) keyword `strip_whitespace` Whether to remove leading and trailing whitespace N/A `to_upper` Whether to convert the string to uppercase N/A `to_lower` Whether to convert the string to lowercase N/A `ascii_only` Whether to allow only ASCII characters N/A These constraints can be provided using the [`StringConstraints`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StringConstraints) metadata type, or using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function (except for `strip_whitespace`, `to_upper`, `to_lower` and `ascii_only`). The [`annotated-types`](https://github.com/annotated-types/annotated-types) library also provides the `MinLen`, `MaxLen` and `Len` metadata types, as well as the `LowerCase`, `UpperCase`, `IsDigit` and `IsAscii` predicates (must be parameterized with `str`, e.g. `LowerCase[str]`). `pattern` constraint By default, Pydantic will use the [`regex`](https://docs.rs/regex) Rust crate to enforce the `pattern` constraint. The regex engine can be controlled using the [`regex_engine`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.regex_engine) configuration value. If a compiled [regular expression object](https://docs.python.org/3/library/re.html#re.Pattern) is used for `pattern`, the Python engine will automatically be used. While the JSON Schema specification [recommends](https://json-schema.org/draft/2020-12/json-schema-core#name-regular-expressions) using patterns valid according to dialect described in [ECMA-262](https://262.ecma-international.org/11.0/index.html#sec-patterns), Pydantic will _not_ enforce it. ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only string values are valid. Pydantic provides the [`StrictStr`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictStr) type as a convenience to [using the `Strict()` metadata class](/docs/validation/latest/concepts/strict_mode#using-the-strict-metadata-class). ### Example ```python from typing import Annotated from pydantic import BaseModel, StringConstraints class StringModel(BaseModel): str_value: str = "" constrained_str_value: Annotated[str, StringConstraints(to_lower=True)] = "" print(StringModel(str_value="test").str_value) #> test print(StringModel(constrained_str_value='TEST').constrained_str_value) #> test ``` ## Bytes Built-in type: [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes). See also: [`ByteSize`](/docs/validation/latest/api/pydantic/types/#pydantic.types.ByteSize). ### Validation - [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) instances are validated as is. - Strings and [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) instances are converted as bytes, following the [`val_json_bytes`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.val_json_bytes) configuration value (despite its name, it applies to both Python and JSON modes). ### Constraints Strings support the following constraints: Constraint Description JSON Schema `min_length` The minimum length of the bytes [`minLength`](https://json-schema.org/understanding-json-schema/reference/string#length) keyword `max_length` The maximum length of the bytes [`maxLength`](https://json-schema.org/understanding-json-schema/reference/string#length) keyword The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) instances are valid. Pydantic provides the [`StrictBytes`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictBytes) type as a convenience to [using the `Strict()` metadata class](/docs/validation/latest/concepts/strict_mode#using-the-strict-metadata-class). In JSON mode, strict mode has no effect. ## Numbers Pydantic supports the following numeric types from the Python standard library: ### Integers Built-in type: [`int`](https://docs.python.org/3/library/functions.html#int). #### Validation - Integers are validated as-is. - Strings and bytes are attempted to be converted to integers and validated as-is (see the [jiter implementation](https://docs.rs/jiter/latest/jiter/enum.NumberInt.html#impl-TryFrom%3C%26%5Bu8%5D%3E-for-NumberInt) for details). - Floats are validated as integers, provided the float input is not infinite or a NaN (not-a-number) and the fractional part is 0. - [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instances, provided they are [finite](https://docs.python.org/3/library/decimal.html#decimal.Decimal.is_finite) and the denominator is 1. - [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) instances, provided they are [integers](https://docs.python.org/3/library/fractions.html#fractions.Fraction.is_integer). - [Enums](https://docs.python.org/3/library/enum.html#module-enum) are converted using the [`value`](https://docs.python.org/3/library/enum.html#enum.Enum.value) attribute. #### Constraints Integers support the following constraints (numbers must be coercible to integers): Constraint Description JSON Schema `le` The value must be less than or equal to this number [`maximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `ge` The value must be greater than or equal to this number [`minimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `lt` The value must be strictly less than this number [`exclusiveMaximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `gt` The value must be strictly greater than this number [`exclusiveMinimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `multiple_of` The value must be a multiple of this number [`multipleOf`](https://json-schema.org/understanding-json-schema/reference/numeric#multiples) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt`, `Gt` and `MultipleOf` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. Pydantic also provides the following types to further constrain the allowed integer values: - [`PositiveInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PositiveInt): Requires the input to be greater than zero. - [`NegativeInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NegativeInt): Requires the input to be less than zero. - [`NonPositiveInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NonPositiveInt): Requires the input to be less than or equal to zero. - [`NonNegativeInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NonNegativeInt): Requires the input to be greater than or equal to zero. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only integer values are valid. Pydantic provides the [`StrictInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictInt) type as a convenience to [using the `Strict()` metadata class](/docs/validation/latest/concepts/strict_mode#using-the-strict-metadata-class). ### Floats Built-in type: [`float`](https://docs.python.org/3/library/functions.html#float). #### Validation - Floats are validated as-is. - String and bytes are attempted to be converted to floats and validated as-is. (see the [Rust implementation](https://doc.rust-lang.org/src/core/num/dec2flt/mod.rs.html) for details). - If the input has a [`__float__()`](https://docs.python.org/3/reference/datamodel.html#object.__float__) method, it will be called to convert the input into a float. If `__float__()` is not defined, it falls back to [`__index__()`](https://docs.python.org/3/reference/datamodel.html#object.__index__). This includes (but not limited to) the [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) and [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) types. #### Constraints Floats support the following constraints: Constraint Description JSON Schema `le` The value must be less than or equal to this number [`maximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `ge` The value must be greater than or equal to this number [`minimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `lt` The value must be strictly less than this number [`exclusiveMaximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `gt` The value must be strictly greater than this number [`exclusiveMinimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `multiple_of` The value must be a multiple of this number [`multipleOf`](https://json-schema.org/understanding-json-schema/reference/numeric#multiples) keyword `allow_inf_nan` Whether to allow NaN (not-a-number) and infinite values N/A These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The [`annotated-types`](https://github.com/annotated-types/annotated-types) library also provides the `Le`, `Ge`, `Lt`, `Gt` and `MultipleOf` metadata types, as well as the `IsFinite`, `IsNotFinite`, `IsNan`, `IsNotNan`, `IsAscii`, `IsInfinite` and `IsNotInfinite` predicates (must be parameterized with `float`, e.g. `IsFinite[float]`). The [`AllowInfNan`](/docs/validation/latest/api/pydantic/types/#pydantic.types.AllowInfNan) type can also be used. Pydantic also provides the following types as convenience aliases: - [`PositiveFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PositiveFloat): Requires the input to be greater than zero. - [`NegativeFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NegativeFloat): Requires the input to be less than zero. - [`NonPositiveFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NonPositiveFloat): Requires the input to be less than or equal to zero. - [`NonNegativeFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NonNegativeFloat): Requires the input to be greater than or equal to zero. - [`FiniteFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.FiniteFloat): Prevents NaN (not-a-number) and infinite values. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only float values and inputs having a [`__float__()`](https://docs.python.org/3/reference/datamodel.html#object.__float__) or [`__index__()`](https://docs.python.org/3/reference/datamodel.html#object.__index__) method are valid. Pydantic provides the [`StrictFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictFloat) type as a convenience to [using the `Strict()` metadata class](/docs/validation/latest/concepts/strict_mode#using-the-strict-metadata-class). ### Integer enums Standard library type: [`enum.IntEnum`](https://docs.python.org/3/library/enum.html#enum.IntEnum). #### Validation - If the [`enum.IntEnum`](https://docs.python.org/3/library/enum.html#enum.IntEnum) type is used directly, any [`enum.IntEnum`](https://docs.python.org/3/library/enum.html#enum.IntEnum) instance is validated as-is - If an [`enum.IntEnum`](https://docs.python.org/3/library/enum.html#enum.IntEnum) subclass is used as a type, any enum member or value that correspond to the enum members values is validated as-is. See [Enums](#enums) for more details. ### Decimals Standard library type: [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal). #### Validation - [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instances are validated as is. - Any value accepted by the [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) constructor. #### Constraints Decimals support the following constraints (numbers must be coercible to decimals): Constraint Description JSON Schema `le` The value must be less than or equal to this number [`maximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `ge` The value must be greater than or equal to this number [`minimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `lt` The value must be strictly less than this number [`exclusiveMaximum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `gt` The value must be strictly greater than this number [`exclusiveMinimum`](https://json-schema.org/understanding-json-schema/reference/numeric#range) keyword `multiple_of` The value must be a multiple of this number [`multipleOf`](https://json-schema.org/understanding-json-schema/reference/numeric#multiples) keyword `allow_inf_nan` Whether to allow NaN (not-a-number) and infinite values N/A `max_digits` The maximum number of decimal digits allowed. The zero before the decimal point and trailing zeros are not counted. [`pattern`](https://json-schema.org/understanding-json-schema/reference/string#regexp) keyword, to describe the string pattern `decimal_places` The maximum number of decimal places allowed. Trailing zeros are not counted. [`pattern`](https://json-schema.org/understanding-json-schema/reference/string#regexp) keyword, to describe the string pattern Note that the JSON Schema [`pattern`](https://json-schema.org/understanding-json-schema/reference/string#regexp) keyword will be specified in the JSON Schema to describe the string pattern in all cases (and can vary if `max_digits` and/or `decimal_places` is specified). These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt`, `Gt` and `MultipleOf` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library and the [`AllowInfNan`](/docs/validation/latest/api/pydantic/types/#pydantic.types.AllowInfNan) type can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instances are accepted. In JSON mode, strict mode has no effect. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. A [serializer](/docs/validation/latest/concepts/serialization#field-plain-serializer) can be used to override this behavior: ```python from decimal import Decimal from typing import Annotated from pydantic import BaseModel, PlainSerializer class Model(BaseModel): f: Annotated[Decimal, PlainSerializer(float, when_used='json')] my_model = Model(f=Decimal('2.1')) print(my_model.model_dump()) # (1) #> {'f': Decimal('2.1')} print(my_model.model_dump_json()) # (2) #> {"f":2.1} ``` In Python mode, `f`remains a [`Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instance. In JSON mode, `f` is serialized as a float. ### Complex numbers ✦ New in v2.9 Built-in type: [`complex`](https://docs.python.org/3/library/functions.html#complex). #### Validation - [`complex`](https://docs.python.org/3/library/functions.html#complex) instances are validated as-is. - In Python mode, data is validated using the [`complex()`](https://docs.python.org/3/library/functions.html#complex) constructor. - In JSON mode, string are validated using the [`complex()`](https://docs.python.org/3/library/functions.html#complex) constructor, numbers (integers and floats) are used as the real part. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`complex`](https://docs.python.org/3/library/functions.html#complex) instances are accepted. In JSON mode, only strings that are accepted by the [`complex()`](https://docs.python.org/3/library/functions.html#complex) constructor are allowed. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`complex`](https://docs.python.org/3/library/functions.html#complex) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. ### Fractions ✦ New in v2.10 Standard library type: [`fractions.Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction). #### Validation - [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) instances are validated as is. - Floats, strings and [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) instances are validated using the [`Fraction()`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) constructor. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`Fraction`](https://docs.python.org/3/library/fractions.html#fractions.Fraction) instances are accepted. In JSON mode, strict mode has no effect. #### Serialization Fractions are serialized as strings, both in [Python](/docs/validation/latest/concepts/serialization#python-mode) and [JSON](/docs/validation/latest/concepts/serialization#json-mode) modes. ## Date and time types Pydantic supports the following [date and time](https://docs.python.org/library/datetime.html#available-types) types from the [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) standard library: ### Datetimes Standard library type: [`datetime.datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime). #### Validation - [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instances are validated as is. - Strings and bytes are validated in two ways: - Strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format (both datetime and date). See the [speedate](https://docs.rs/speedate/) documentation for more details. - Unix timestamps, both as seconds or milliseconds sinch the [epoch](https://en.wikipedia.org/wiki/Unix_time). See the [`val_temporal_unit`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.val_temporal_unit) configuration value for more details. - Integers and floats (or types that can be coerced as integers or floats) are validated as unix timestamps, following the same semantics as strings. - [`datetime.date`](https://docs.python.org/3/library/datetime.html#datetime.date) instances are accepted, and converted to a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instance by setting the [`hour`](https://docs.python.org/3/library/datetime.html#datetime.datetime.hour), [`minute`](https://docs.python.org/3/library/datetime.html#datetime.datetime.minute), [`second`](https://docs.python.org/3/library/datetime.html#datetime.datetime.second) and [`microsecond`](https://docs.python.org/3/library/datetime.html#datetime.datetime.microsecond) attributes to `0`, and the [`tzinfo`](https://docs.python.org/3/library/datetime.html#datetime.datetime.tzinfo) attribute to `None`. Note Named timezone support (as specified in [RFC 9557](https://datatracker.ietf.org/doc/html/rfc9557.html)) can be tracked in [this issue](https://github.com/pydantic/pydantic/issues/12252). #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. #### Constraints Datetimes support the following constraints (constraint values must be coercible to a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instance): Constraint Description JSON Schema `le` The value must be less than or equal to this datetime N/A `ge` The value must be greater than or equal to this datetime N/A `lt` The value must be strictly less than this datetime N/A `gt` The value must be strictly greater than this datetime N/A These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt` and `Gt` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. Pydantic also provides the following types to further constrain the allowed datetime values: - [`AwareDatetime`](/docs/validation/latest/api/pydantic/types/#pydantic.types.AwareDatetime): Requires the input to have a timezone. - [`NaiveDatetime`](/docs/validation/latest/api/pydantic/types/#pydantic.types.NaiveDatetime): Requires the input to _not_ have a timezone. - [`PastDatetime`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PastDatetime): Requires the input to be in the past when validated. - [`FutureDatetime`](/docs/validation/latest/api/pydantic/types/#pydantic.types.FutureDatetime): Requires the input to be in the future when validated. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) instances are accepted. In JSON mode, only strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format (_only_ datetime) or as unix timestamps are accepted. #### Example ```python from datetime import datetime from typing import Annotated from pydantic import AwareDatetime, BaseModel, Field class Event(BaseModel): dt: Annotated[AwareDatetime, Field(gt=datetime(2000, 1, 1))] event = Event(dt='2032-04-23T10:20:30.400+02:30') print(event.model_dump()) """ {'dt': datetime.datetime(2032, 4, 23, 10, 20, 30, 400000, tzinfo=TzInfo(9000))} """ print(event.model_dump_json()) #> {"dt":"2032-04-23T10:20:30.400000+02:30"} ``` ### Dates Standard library type: [`datetime.date`](https://docs.python.org/3/library/datetime.html#datetime.date). #### Validation - [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) instances are validated as is. - Strings and bytes are validated in two ways: - Strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) date format. See the [speedate](https://docs.rs/speedate/) documentation for more details. - Unix timestamps, both as seconds or milliseconds sinch the [epoch](https://en.wikipedia.org/wiki/Unix_time). See the [`val_temporal_unit`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.val_temporal_unit) configuration value for more details. - If the validation fails, the input can be [validated as a datetime](#datetimes) (including as numbers), provided that the time component is 0 and that it is naive. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. #### Constraints Dates support the following constraints (constraint values must be coercible to a [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) instance): Constraint Description JSON Schema `le` The value must be less than or equal to this date N/A `ge` The value must be greater than or equal to this date N/A `lt` The value must be strictly less than this date N/A `gt` The value must be strictly greater than this date N/A These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt` and `Gt` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. Pydantic also provides the following types to further constrain the allowed date values: - [`PastDate`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PastDate): Requires the input to be in the past when validated. - [`FutureDate`](/docs/validation/latest/api/pydantic/types/#pydantic.types.FutureDate): Requires the input to be in the future when validated. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) instances are accepted. In JSON mode, only strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format (_only_ date) or as unix timestamps are accepted. #### Example ```python from datetime import date from pydantic import BaseModel class Birthday(BaseModel): d: date my_birthday = Birthday(d=1679616000.0) print(my_birthday.model_dump()) #> {'d': datetime.date(2023, 3, 24)} print(my_birthday.model_dump_json()) #> {"d":"2023-03-24"} ``` ### Time Standard library type: [`datetime.time`](https://docs.python.org/3/library/datetime.html#datetime.time). #### Validation - [`time`](https://docs.python.org/3/library/datetime.html#datetime.time) instances are validated as is. - Strings and bytes are validated according to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) time format. - Integers and floats (or values that can be coerced to such numbers) are validated as seconds. The value should not exceed 86 399. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`time`](https://docs.python.org/3/library/datetime.html#datetime.time) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. Note Named timezones from the [IANA time zone database](https://www.iana.org/time-zones) (see the [`zoneinfo`](https://docs.python.org/3/library/zoneinfo.html#module-zoneinfo) module) are _not_ serialized with time objects. This is consistent with the [`time.isoformat()`](https://docs.python.org/3/library/datetime.html#datetime.time.isoformat) method. #### Constraints Time support the following constraints (constraint values must be coercible to a [`time`](https://docs.python.org/3/library/datetime.html#datetime.time) instance): Constraint Description JSON Schema `le` The value must be less than or equal to this time N/A `ge` The value must be greater than or equal to this time N/A `lt` The value must be strictly less than this time N/A `gt` The value must be strictly greater than this time N/A These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt` and `Gt` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`time`](https://docs.python.org/3/library/datetime.html#datetime.time) instances are accepted. In JSON mode, only strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format are accepted. #### Example ```python from datetime import time from pydantic import BaseModel class Meeting(BaseModel): t: time m = Meeting(t=time(4, 8, 16)) print(m.model_dump()) #> {'t': datetime.time(4, 8, 16)} print(m.model_dump_json()) #> {"t":"04:08:16"} ``` ### Timedeltas Standard library type: [`datetime.timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta). #### Validation - [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) instances are validated as is. - Strings and bytes are validated according to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) time format. - Integers and floats (or values that can be coerced to such numbers) are validated as seconds. #### Constraints Timedeltas support the following constraints (constraint values must be coercible to a [`timedata`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) instance): | Constraint | Description | JSON Schema | | ---------- | ---------------------------------------------------- -----| ----------- | | `le` | The value must be less than or equal to this timedelta | N/A | | `ge` | The value must be greater than or equal to this timedelta | N/A | | `lt` | The value must be strictly less than this timedelta | N/A | | `gt` | The value must be strictly greater than this timedelta | N/A | These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `Le`, `Ge`, `Lt` and `Gt` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) instances are accepted. In JSON mode, only strings complying to the [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format are accepted. #### Example ```python from datetime import timedelta from pydantic import BaseModel class Model(BaseModel): td: timedelta m = Model(td='P3DT12H30M5S') print(m.model_dump()) #> {'td': datetime.timedelta(days=3, seconds=45005)} print(m.model_dump_json()) #> {"td":"P3DT12H30M5S"} ``` ## Enums Standard library type: [`enum.Enum`](https://docs.python.org/3/library/enum.html#enum.Enum). ### Validation - If the [`enum.Enum`](https://docs.python.org/3/library/enum.html#enum.Enum) type is used directly, any [`enum.Enum`](https://docs.python.org/3/library/enum.html#enum.Enum) instance is validated as-is. - If an [`enum.Enum`](https://docs.python.org/3/library/enum.html#enum.Enum) subclass is used as a type, any enum member or value that correspond to the enum members [values](https://docs.python.org/3/library/enum.html#enum.Enum.value) is validated as-is. ### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), enum instances are serialized as is. The [`use_enum_values`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.use_enum_values) configuration value can be set to use the enum [value](https://docs.python.org/3/library/enum.html#enum.Enum.value) during validation (so that it is also used during serialization). In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), enum instances are serialized using their [value](https://docs.python.org/3/library/enum.html#enum.Enum.value). ### Example ```python from enum import Enum, IntEnum from pydantic import BaseModel, ValidationError class FruitEnum(str, Enum): PEAR = 'pear' BANANA = 'banana' class ToolEnum(IntEnum): SPANNER = 1 WRENCH = 2 class CookingModel(BaseModel): fruit: FruitEnum = FruitEnum.PEAR tool: ToolEnum = ToolEnum.SPANNER print(CookingModel()) #> fruit= tool= print(CookingModel(tool=2, fruit='banana')) #> fruit= tool= try: CookingModel(fruit='other') except ValidationError as e: print(e) """ 1 validation error for CookingModel fruit Input should be 'pear' or 'banana' [type=enum, input_value='other', input_type=str] """ ``` ## None types Supported types: [`None`](https://docs.python.org/3/library/constants.html#None), [`NoneType`](https://docs.python.org/3/library/types.html#types.NoneType) or `Literal[None]` (they are [equivalent](https://typing.readthedocs.io/en/latest/spec/special-types.html#none)). Allows only `None` as a value. ## Generic collection types Pydantic supports a wide variety of generic collection types, both built-ins (such as [`list`](https://docs.python.org/3/glossary.html#term-list)) and abstract base classes from the [`collections.abc`](https://docs.python.org/3/library/collections.abc.html#module-collections.abc) module (such as [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence)). In most cases, it is recommended to make use of the built-in types over the abstract ones. Due to [data coercion](/docs/validation/latest/concepts/models#data-conversion), using [`list`](https://docs.python.org/3/glossary.html#term-list) or [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) will allow most other iterables as input, with better performance. Strictness on collection types When applying [strict mode](/docs/validation/latest/concepts/strict_mode) on collection types, strictness will _not_ apply to the inner types. This may change in the future, see [this issue](https://github.com/pydantic/pydantic/issues/12319). ### Lists Built-in type: [`list`](https://docs.python.org/3/glossary.html#term-list) (deprecated alias: [`typing.List`](https://docs.python.org/3/library/typing.html#typing.List)). #### Validation - Allows [`list`](https://docs.python.org/3/glossary.html#term-list), [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple), [`set`](https://docs.python.org/3/reference/expressions.html#set) and [`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset) instances, or any iterable that is _not_ a [string](https://docs.python.org/3/library/stdtypes.html#str), [bytes](https://docs.python.org/3/library/stdtypes.html#bytes), [bytearray](https://docs.python.org/3/library/stdtypes.html#bytearray), [dict](https://docs.python.org/3/reference/expressions.html#dict) or [mapping](https://docs.python.org/3/glossary.html#term-mapping). Produces a [`list`](https://docs.python.org/3/glossary.html#term-list) instance. - If a generic parameter is provided, the appropriate validation is applied to all items of the list. #### Constraints Lists support the following constraints: Constraint Description JSON Schema `min_length` The list must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The list must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`list`](https://docs.python.org/3/glossary.html#term-list) instances are valid. Strict mode does _not_ apply to the items of the list. The strict constraint must be applied to the parameter type for this to work. #### Example ```python from typing import Optional from pydantic import BaseModel, Field class Model(BaseModel): simple_list: Optional[list[object]] = None list_of_ints: Optional[list[int]] = Field(default=None, strict=True) print(Model(simple_list=('1', '2', '3')).simple_list) #> ['1', '2', '3'] print(Model(list_of_ints=['1', 2, 3]).list_of_ints) #> [1, 2, 3] ``` ### Tuples Built-in type: [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) (deprecated alias: [`typing.Tuple`](https://docs.python.org/3/library/typing.html#typing.Tuple)). Note [Unpacked tuple types](https://typing.python.org/en/latest/spec/generics.html#unpacking-tuple-types) (as specified by [PEP 646](https://peps.python.org/pep-0646/)) are _not_ yet supported, and can be tracked in [this issue](https://github.com/pydantic/pydantic/issues/5952). #### Validation - Allows [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple), [`list`](https://docs.python.org/3/glossary.html#term-list), [`set`](https://docs.python.org/3/reference/expressions.html#set) and [`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset) instances, or any iterable that is _not_ a [string](https://docs.python.org/3/library/stdtypes.html#str), [bytes](https://docs.python.org/3/library/stdtypes.html#bytes), [bytearray](https://docs.python.org/3/library/stdtypes.html#bytearray), [dict](https://docs.python.org/3/reference/expressions.html#dict) or [mapping](https://docs.python.org/3/glossary.html#term-mapping). Produces a [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) instance. - Appropriate validation is applied to items of the tuple, if [element types](https://typing.python.org/en/latest/spec/tuples.html#tuple-type-form) are specified. #### Constraints Lists support the following constraints: Constraint Description JSON Schema `min_length` The tuple must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The tuple must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. Additionally, the [`prefixItems`](https://json-schema.org/understanding-json-schema/reference/array#tupleValidation) JSON Schema keyword may be used depending on the tuple shape. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) instances are valid. Strict mode does _not_ apply to the items of the tuple. The strict constraint must be applied to the parameter types for this to work. #### Example ```python from typing import Optional from pydantic import BaseModel class Model(BaseModel): simple_tuple: Optional[tuple] = None tuple_of_different_types: Optional[tuple[int, float, bool]] = None print(Model(simple_tuple=[1, 2, 3, 4]).simple_tuple) #> (1, 2, 3, 4) print(Model(tuple_of_different_types=[3, 2, 1]).tuple_of_different_types) #> (3, 2.0, True) ``` ### Named tuples Standard library type: [`typing.NamedTuple`](https://docs.python.org/3/library/typing.html#typing.NamedTuple) (and types created by the [`collections.namedtuple()`](https://docs.python.org/3/library/collections.html#collections.namedtuple) factory function - each field will implicitly have the type [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)). #### Validation - Allows [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) and [`list`](https://docs.python.org/3/glossary.html#term-list) instances. Validate each item according to the field definition. - Allows [`dict`](https://docs.python.org/3/reference/expressions.html#dict) instances. Keys must match the named tuple field names, and values are validated according to the field definition. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), named tuples are serialized as tuples. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as arrays. #### Example ```python from typing import NamedTuple from pydantic import BaseModel class Point(NamedTuple): x: int y: int class Model(BaseModel): p: Point model = Model(p=('1', 2)) print(model.model_dump()) #> {'p': (1, 2)} ``` ### Sets Types: [`set`](https://docs.python.org/3/reference/expressions.html#set) (or [`collections.abc.MutableSet`](https://docs.python.org/3/library/collections.abc.html#collections.abc.MutableSet)) and [`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset) (or [`collections.abc.Set`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Set)) (deprecated aliases: [`typing.Set`](https://docs.python.org/3/library/typing.html#typing.Set) and [`typing.FrozenSet`](https://docs.python.org/3/library/typing.html#typing.FrozenSet)). #### Validation - Allows [`set`](https://docs.python.org/3/reference/expressions.html#set), [`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset), [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple) and [`list`](https://docs.python.org/3/glossary.html#term-list) instances, or any iterable that is _not_ a [string](https://docs.python.org/3/library/stdtypes.html#str), [bytes](https://docs.python.org/3/library/stdtypes.html#bytes), [bytearray](https://docs.python.org/3/library/stdtypes.html#bytearray), [dict](https://docs.python.org/3/reference/expressions.html#dict) or [mapping](https://docs.python.org/3/glossary.html#term-mapping). Produces a [`set`](https://docs.python.org/3/reference/expressions.html#set) or [`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset) instance. - If a generic parameter is provided, the appropriate validation is applied to all items of the set/frozenset. #### Constraints Sets support the following constraints: Constraint Description JSON Schema `min_length` The set must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The set must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`set`](https://docs.python.org/3/reference/expressions.html#set)/[`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset) instances are valid. Strict mode does _not_ apply to the items of the set. The strict constraint must be applied to the parameter type for this to work. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), sets are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as arrays. #### Example ```python from typing import Optional from pydantic import BaseModel class Model(BaseModel): simple_set: Optional[set] = None set_of_ints: Optional[frozenset[int]] = None print(Model(simple_set=['1', '2', '3']).simple_set) #> {'1', '2', '3'} print(Model(set_of_ints=['1', '2', '3']).set_of_ints) #> frozenset({1, 2, 3}) ``` #### JSON Schema Pydantic does best effort to sort default values that are [`collections.abc.Set`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Set) instances. ### Deque Standard library type: [`collections.deque`](https://docs.python.org/3/library/collections.html#collections.deque) (deprecated alias: [`typing.Deque`](https://docs.python.org/3/library/typing.html#typing.Deque)). #### Validation Values are first validated as a [list](#lists), and then passed to the [`deque`](https://docs.python.org/3/library/collections.html#collections.deque) constructor. #### Constraints Deques support the following constraints: Constraint Description JSON Schema `min_length` The deque must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The deque must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`deque`](https://docs.python.org/3/library/collections.html#collections.deque) instances are valid. Strict mode does _not_ apply to the items of the deque. The strict constraint must be applied to the parameter type for this to work. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), deques are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as arrays. #### Example ```python from collections import deque from pydantic import BaseModel class Model(BaseModel): deque: deque[int] print(Model(deque=[1, 2, 3]).deque) #> deque([1, 2, 3]) ``` ### Sequences Standard library type: [`collections.abc.Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) (deprecated alias: [`typing.Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)). In most cases, you will want to use the built-in types (such as [list](#lists) or [tuple](#tuples)) as [type coercion](/docs/validation/latest/concepts/models#data-conversion) will apply. The [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) type can be used when you want to preserve the input type during serialization. #### Validation Any [`collections.abc.Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) instance (expect strings and bytes) is accepted. It is converted to a list using the [`list()`](https://docs.python.org/3/glossary.html#term-list) constructor, and then converted back to the original input type. Strings aren't treated as sequences While strings are technically valid sequence instances, this is frequently not intended as is a common source of bugs. As a result, Pydantic will _not_ accept strings and bytes for the [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) type (see example below). #### Constraints Sequences support the following constraints: Constraint Description JSON Schema `min_length` The sequence must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The sequence must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), sequences are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as arrays. #### Example ```python from collections.abc import Sequence from pydantic import BaseModel, ValidationError class Model(BaseModel): sequence_of_strs: Sequence[str] print(Model(sequence_of_strs=['a', 'bc']).sequence_of_strs) #> ['a', 'bc'] print(Model(sequence_of_strs=('a', 'bc')).sequence_of_strs) #> ('a', 'bc') try: Model(sequence_of_strs='abc') except ValidationError as e: print(e) """ 1 validation error for Model sequence_of_strs 'str' instances are not allowed as a Sequence value [type=sequence_str, input_value='abc', input_type=str] """ ``` ### Dictionaries Built-in type: [`dict`](https://docs.python.org/3/reference/expressions.html#dict). #### Validation - [`dict`](https://docs.python.org/3/reference/expressions.html#dict) instances are accepted as is. - [mappings](https://docs.python.org/3/glossary.html#term-mapping) instances are accepted and coerced to a [`dict`](https://docs.python.org/3/reference/expressions.html#dict). - If generic parameters for keys and values are provided, the appropriate validation is applied. #### Constraints Dictionaries support the following constraints: Constraint Description JSON Schema `min_length` The dictionary must have at least this many items [`minItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword `max_length` The dictionary must have at most this many items [`maxItems`](https://json-schema.org/understanding-json-schema/reference/array#length) keyword These constraints can be provided using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. The `MinLen` and `MaxLen` metadata types from the [`annotated-types`](https://github.com/annotated-types/annotated-types) library can also be used. #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`dict`](https://docs.python.org/3/reference/expressions.html#dict) instances are valid. Strict mode does _not_ apply to the keys and values of the dictionaries. The strict constraint must be applied to the parameter types for this to work. #### Example ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: dict[str, int] m = Model(x={'foo': 1}) print(m.model_dump()) #> {'x': {'foo': 1}} try: Model(x='test') except ValidationError as e: print(e) """ 1 validation error for Model x Input should be a valid dictionary [type=dict_type, input_value='test', input_type=str] """ ``` ### Typed dictionaries Standard library type: [`typing.TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) (see also: the [typing specification](https://typing.python.org/en/latest/spec/typeddict.html)). Note Because of runtime limitations, Pydantic will require using the [`TypedDict`](https://typing-extensions.readthedocs.io/en/latest/index.html#typing_extensions.TypedDict) type from [`typing_extensions`](https://typing-extensions.readthedocs.io/en/latest/index.html#module-typing_extensions) when using Python 3.12 and lower. [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) declares a dictionary type that expects all of its instances to have a certain set of keys where each key is associated with a value of a consistent type. This type [supports configuration](/docs/validation/latest/concepts/config#configuration-on-other-supported-types). #### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`dict`](https://docs.python.org/3/reference/expressions.html#dict) instances are valid (unlike mappings in lax mode). Strict mode does _not_ apply to the values of the typed dictionary. The strict constraint must be applied to the value types for this to work. #### Example ```python from typing_extensions import TypedDict from pydantic import TypeAdapter, ValidationError class User(TypedDict): name: str id: int ta = TypeAdapter(User) print(ta.validate_python({'name': 'foo', 'id': 1})) #> {'name': 'foo', 'id': 1} try: ta.validate_python({'name': 'foo'}) except ValidationError as e: print(e) """ 1 validation error for User id Field required [type=missing, input_value={'name': 'foo'}, input_type=dict] """ ``` ### Iterables Standard library type: [`collections.abc.Iterable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Iterable) (deprecated alias: [`typing.Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)). #### Validation Iterables are lazily validated, and wrapped in an internal datastructure that can be iterated over (and will validate the items type while doing so). This means that even if you provide a concrete container such as a list, the validated type will _not_ be of type [`list`](https://docs.python.org/3/glossary.html#term-list). However, Pydantic will ensure that the input value is iterable by getting an [iterator](https://docs.python.org/3/glossary.html#term-iterator) from it (by calling [`iter()`](https://docs.python.org/3/library/functions.html#iter) on the value). It is recommended to use concrete collection types (such as [lists](#lists)) instead, unless you are using an infinite iterator (in which case eagerly validating the input would result in an infinite loop). #### Example ```python from collections.abc import Iterable from pydantic import BaseModel, ValidationError class Model(BaseModel): f: Iterable[str] m = Model(f=[1, 2]) # Validates fine try: next(m.f) except ValidationError as e: print(e) """ 1 validation error for ValidatorIterator 0 Input should be a valid string [type=string_type, input_value=1, input_type=int] """ ``` ## Callable Standard library type: [`collections.abc.Callable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable) (deprecated alias: [`typing.Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)). ### Validation Pydantic only validates that the input is a [callable](https://docs.python.org/3/glossary.html#term-callable) (using the [`callable()`](https://docs.python.org/3/library/functions.html#callable) function). It does _not_ validate the number of parameters or their type, nor the type of the return value. ```python from typing import Callable from pydantic import BaseModel class Foo(BaseModel): callback: Callable[[int], int] m = Foo(callback=lambda x: x) print(m) #> callback= at 0x0123456789ab> ``` ### Serialization Callables are serialized as is. Callables can't be serialized in [JSON mode](/docs/validation/latest/concepts/serialization#json-mode) (a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) is raised). ## IP Addresses Standard library types: - [`ipaddress.IPv4Address`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Address) - [`ipaddress.IPv4Interface`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Interface) - [`ipaddress.IPv4Network`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv4Network) - [`ipaddress.IPv6Address`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Address) - [`ipaddress.IPv6Interface`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Interface) - [`ipaddress.IPv6Network`](https://docs.python.org/3/library/ipaddress.html#ipaddress.IPv6Network) See also: the [`IPvAnyAddress`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.IPvAnyAddress), [`IPvAnyInterface`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.IPvAnyInterface) and [`IPvAnyNetwork`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.IPvAnyNetwork) Pydantic types. ### Validation - Instances are validated as is. - Other input values are passed to the constructor of the relevant address type. ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only the address types are accepted. In JSON mode, strict mode has no effect. ### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), IP addresses are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. ## UUID Standard library type: [`uuid.UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID). ### Validation - [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) instances are validated as is. - Strings and bytes are validated as UUIDs, and casted to a [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) instance. ### Constraints The [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) type supports a `version` constraint. The [`UuidVersion`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UuidVersion) metadata type can be used. Pydantic also provides the following types as convenience aliases: [`UUID1`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID1), [`UUID3`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID3), [`UUID4`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID4), [`UUID5`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID5), [`UUID6`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID6), [`UUID7`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID7), [`UUID8`](/docs/validation/latest/api/pydantic/types/#pydantic.types.UUID8). ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) instances are accepted. In JSON mode, strict mode has no effect. ### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), UUIDs are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. ### Example ```python from typing import Annotated from uuid import UUID from pydantic import BaseModel from pydantic.types import UUID7, UuidVersion class Model(BaseModel): u1: UUID7 u2: Annotated[UUID, UuidVersion(4)] print( Model( u1='01999b2c-8353-749b-8dac-859307fae22b', u2=UUID('125725f3-e1b4-44e3-90c3-1a20eab12da5'), ) ) """ u1=UUID('01999b2c-8353-749b-8dac-859307fae22b') u2=UUID('125725f3-e1b4-44e3-90c3-1a20eab12da5') """ ``` ## Type Built-in type: [`type`](https://docs.python.org/3/glossary.html#term-type) (deprecated alias: [`typing.Type`](https://docs.python.org/3/library/typing.html#typing.Type)). ### Validation Allows any type that is a subclass of the type argument. For instance, with `type[str]`, allows the [`str`](https://docs.python.org/3/library/stdtypes.html#str) class or any [`str`](https://docs.python.org/3/library/stdtypes.html#str) subclass as an input. If no type argument is provided (i.e. `type` is used as an annotation), allow any class. ### Serialization Types are serialized as is. Types can't be serialized in [JSON mode](/docs/validation/latest/concepts/serialization#json-mode) (a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) is raised). ```python from pydantic import BaseModel, ValidationError class Foo: pass class Bar(Foo): pass class Other: pass class SimpleModel(BaseModel): just_subclasses: type[Foo] SimpleModel(just_subclasses=Foo) SimpleModel(just_subclasses=Bar) try: SimpleModel(just_subclasses=Other) except ValidationError as e: print(e) """ 1 validation error for SimpleModel just_subclasses Input should be a subclass of Foo [type=is_subclass_of, input_value=, input_type=type] """ ``` ## Literals Typing construct: [`typing.Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) (see also: the [typing specification](https://typing.python.org/en/latest/spec/literal.html#literal)). Literals can be used to only allow specific literal values. Note that Pydantic applies [strict mode](/docs/validation/latest/concepts/strict_mode) behavior when validating literal values (see [this issue](https://github.com/pydantic/pydantic/issues/9991)). ### Example ```python from typing import Literal from pydantic import BaseModel, ValidationError class Pie(BaseModel): flavor: Literal['apple', 'pumpkin'] quantity: Literal[1, 2] = 1 Pie(flavor='apple') Pie(flavor='pumpkin') try: Pie(flavor='cherry') except ValidationError as e: print(str(e)) """ 1 validation error for Pie flavor Input should be 'apple' or 'pumpkin' [type=literal_error, input_value='cherry', input_type=str] """ try: Pie(flavor='apple', quantity='1') except ValidationError as e: print(str(e)) """ 1 validation error for Pie quantity Input should be 1 or 2 [type=literal_error, input_value='1', input_type=str] """ ``` ## Any Types: [`typing.Any`](https://docs.python.org/3/library/typing.html#typing.Any) or [`object`](https://docs.python.org/3/glossary.html#term-object). Allows any value, including `None`. ## Hashables Standard library type: [`collections.abc.Hashable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Hashable) (deprecated alias: [`typing.Hashable`](https://docs.python.org/3/library/typing.html#typing.Hashable)). ### Validation Any value that is hashable (using `isinstance(value, Hashable)`). ## Regex patterns Standard library type: [`re.Pattern`](https://docs.python.org/3/library/re.html#re.Pattern) (deprecated alias: [`typing.Pattern`](https://docs.python.org/3/library/typing.html#typing.Pattern)). ### Validation - For [`Pattern`](https://docs.python.org/3/library/re.html#re.Pattern) instances, check that the [`pattern`](https://docs.python.org/3/library/re.html#re.Pattern.pattern) attribute is of the right type ([`str`](https://docs.python.org/3/library/stdtypes.html#str) or [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) depending on the [`Pattern`](https://docs.python.org/3/library/re.html#re.Pattern) type parameter). - If the type parameter is [`str`](https://docs.python.org/3/library/stdtypes.html#str) or [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes), input values of type [`str`](https://docs.python.org/3/library/stdtypes.html#str) (or [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) respectively) are attempted to be compiled using [`re.compile()`](https://docs.python.org/3/library/re.html#re.compile). ### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), [`Pattern`](https://docs.python.org/3/library/re.html#re.Pattern) instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. ## Paths Standard library types: - [`pathlib.Path`](https://docs.python.org/3/library/pathlib.html#pathlib.Path). - [`pathlib.PurePath`](https://docs.python.org/3/library/pathlib.html#pathlib.PurePath). - [`pathlib.PosixPath`](https://docs.python.org/3/library/pathlib.html#pathlib.PosixPath). - [`pathlib.PurePosixPath`](https://docs.python.org/3/library/pathlib.html#pathlib.PurePosixPath). - [`pathlib.PureWindowsPath`](https://docs.python.org/3/library/pathlib.html#pathlib.PureWindowsPath). - [`os.PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) (must be parameterized with [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) or [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)). ### Validation - Path instances are validated as is. - Strings are accepted and passed to the type constructor. If [`os.PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) was used, bytes are accepted if it was parameterized with the [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) type. ### Strictness In [strict mode](/docs/validation/latest/concepts/strict_mode), only Path instances are accepted. In JSON mode, strict mode has no effect. ### Serialization In [Python mode](/docs/validation/latest/concepts/serialization#python-mode), Path instances are serialized as is. In [JSON mode](/docs/validation/latest/concepts/serialization#json-mode), they are serialized as strings. --- # [TypeAdapter](https://pydantic.dev/docs/validation/latest/api/pydantic/type_adapter/) # TypeAdapter ## TypeAdapter **Bases:** `Generic[T]` Usage Documentation [`TypeAdapter`](/docs/validation/latest/concepts/type_adapter) Type adapters provide a flexible way to perform validation and serialization based on a Python type. A `TypeAdapter` instance exposes some of the functionality from `BaseModel` instance methods for types that do not have such methods (such as dataclasses, primitive types, and more). **Note:** `TypeAdapter` instances are not types, and cannot be used as type annotations for fields. ### Constructor Parameters **`type`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The type associated with the `TypeAdapter`. **`config`** : [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Configuration for the `TypeAdapter`, should be a dictionary conforming to [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict). Note You cannot provide a configuration when instantiating a `TypeAdapter` if the type you're using has its own config that cannot be overridden (ex: `BaseModel`, `TypedDict`, and `dataclass`). A [`type-adapter-config-unused`](/docs/validation/latest/errors/usage_errors#type-adapter-config-unused) error will be raised in this case. **`_parent_depth`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `2` Depth at which to search for the [parent frame](https://docs.python.org/3/reference/datamodel.html#frame-objects). This frame is used when resolving forward annotations during schema building, by looking for the globals and locals of this frame. Defaults to 2, which will result in the frame where the `TypeAdapter` was instantiated. Note This parameter is named with an underscore to suggest its private nature and discourage use. It may be deprecated in a minor version, so we only recommend using it if you're comfortable with potential change in behavior/support. It's default value is 2 because internally, the `TypeAdapter` class makes another call to fetch the frame. **`module`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The module that passes to plugin if provided. ### Attributes #### core\_schema The core schema for the type. **Type:** `CoreSchema` #### validator The schema validator for the type. **Type:** `SchemaValidator` | `PluggableSchemaValidator` #### serializer The schema serializer for the type. **Type:** `SchemaSerializer` #### pydantic\_complete Whether the core schema for the type is successfully built. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) Compatibility with `mypy` Depending on the type used, `mypy` might raise an error when instantiating a `TypeAdapter`. As a workaround, you can explicitly annotate your variable: ```py from typing import Union from pydantic import TypeAdapter ta: TypeAdapter[Union[str, int]] = TypeAdapter(Union[str, int]) # type: ignore[arg-type] ``` Namespace management nuances and implementation details Here, we collect some notes on namespace management, and subtle differences from `BaseModel`: `BaseModel` uses its own `__module__` to find out where it was defined and then looks for symbols to resolve forward references in those globals. On the other hand, `TypeAdapter` can be initialized with arbitrary objects, which may not be types and thus do not have a `__module__` available. So instead we look at the globals in our parent stack frame. It is expected that the `ns_resolver` passed to this function will have the correct namespace for the type we're adapting. See the source code for `TypeAdapter.__init__` and `TypeAdapter.rebuild` for various ways to construct this namespace. This works for the case where this function is called in a module that has the target of forward references in its scope, but does not always work for more complex cases. For example, take the following: a.py ```python IntList = list[int] OuterDict = dict[str, 'IntList'] ``` b.py ```python from a import OuterDict from pydantic import TypeAdapter IntList = int # replaces the symbol the forward reference is looking for v = TypeAdapter(OuterDict) v({'x': 1}) # should fail but doesn't ``` If `OuterDict` were a `BaseModel`, this would work because it would resolve the forward reference within the `a.py` namespace. But `TypeAdapter(OuterDict)` can't determine what module `OuterDict` came from. In other words, the assumption that _all_ forward references exist in the module we are being called from is not technically always true. Although most of the time it is and it works fine for recursive models and such, `BaseModel`'s behavior isn't perfect either and _can_ break in similar ways, so there is no right or wrong between the two. But at the very least this behavior is _subtly_ different from `BaseModel`'s. ### Methods #### rebuild ```python def rebuild( force: bool = False, raise_errors: bool = True, _parent_namespace_depth: int = 2, _types_namespace: _namespace_utils.MappingNamespace | None = None, ) -> bool | None ``` Try to rebuild the pydantic-core schema for the adapter's type. This may be necessary when one of the annotations is a ForwardRef which could not be resolved during the initial attempt to build the schema, and automatic rebuilding fails. ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- Returns `None` if the schema is already "complete" and rebuilding was not required. [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) -- If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`. ##### Parameters **`force`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to force the rebuilding of the type adapter's schema, defaults to `False`. **`raise_errors`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to raise errors, defaults to `True`. **`_parent_namespace_depth`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `2` Depth at which to search for the [parent frame](https://docs.python.org/3/reference/datamodel.html#frame-objects). This frame is used when resolving forward annotations during schema rebuilding, by looking for the locals of this frame. Defaults to 2, which will result in the frame where the method was called. **`_types_namespace`** : `_namespace_utils.MappingNamespace` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` An explicit types namespace to use, instead of using the local namespace from the parent frame. Defaults to `None`. #### validate\_python ```python def validate_python( object: Any, strict: bool | None = None, extra: ExtraValues | None = None, from_attributes: bool | None = None, context: Any | None = None, experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> T ``` Validate a Python object against the model. Note When using `TypeAdapter` with a Pydantic `dataclass`, the use of the `from_attributes` argument is not supported. ##### Returns `T` -- The validated object. ##### Parameters **`object`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to validate against the model. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to strictly check types. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to extract data from object attributes. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the validator. **`experimental_allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` **Experimental** whether to enable [partial validation](/docs/validation/latest/concepts/experimental#partial-validation), e.g. to process streams. - False / 'off': Default behavior, no partial validation. - True / 'on': Enable partial validation. - 'trailing-strings': Enable partial validation and allow trailing strings in the input. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. #### validate\_json ```python def validate_json( data: str | bytes | bytearray, strict: bool | None = None, extra: ExtraValues | None = None, context: Any | None = None, experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> T ``` Usage Documentation [JSON Parsing](/docs/validation/latest/concepts/json#json-parsing) Validate a JSON string or bytes against the model. ##### Returns `T` -- The validated object. ##### Parameters **`data`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) | [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) The JSON data to validate against the model. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to strictly check types. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to use during validation. **`experimental_allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` **Experimental** whether to enable [partial validation](/docs/validation/latest/concepts/experimental#partial-validation), e.g. to process streams. - False / 'off': Default behavior, no partial validation. - True / 'on': Enable partial validation. - 'trailing-strings': Enable partial validation and allow trailing strings in the input. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. #### validate\_strings ```python def validate_strings( obj: Any, strict: bool | None = None, extra: ExtraValues | None = None, context: Any | None = None, experimental_allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> T ``` Validate object contains string data against the model. ##### Returns `T` -- The validated object. ##### Parameters **`obj`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The object contains string data to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to strictly check types. **`extra`** : `ExtraValues` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. See the [`extra` configuration value](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) for details. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to use during validation. **`experimental_allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` **Experimental** whether to enable [partial validation](/docs/validation/latest/concepts/experimental#partial-validation), e.g. to process streams. - False / 'off': Default behavior, no partial validation. - True / 'on': Enable partial validation. - 'trailing-strings': Enable partial validation and allow trailing strings in the input. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. #### get\_default\_value ```python def get_default_value( strict: bool | None = None, context: Any | None = None, ) -> Some[T] | None ``` Get the default value for the wrapped type. ##### Returns `Some`\[`T`\] | [`None`](https://docs.python.org/3/library/constants.html#None) -- The default value wrapped in a `Some` if there is one or None if not. ##### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to strictly check types. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the validator. #### dump\_python ```python def dump_python( instance: T, mode: Literal['json', 'python'] = 'python', include: IncEx | None = None, exclude: IncEx | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> Any ``` Dump an instance of the adapted type to a Python object. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The serialized object. ##### Parameters **`instance`** : `T` The Python object to serialize. **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['json', 'python'\] _Default:_ `'python'` The output format. **`include`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Fields to include in the output. **`exclude`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Fields to exclude from the output. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use alias names for field names. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude unset fields. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields with default values. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields with None values. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to output the serialized data in a way that is compatible with deserialization. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the serializer. #### dump\_json ```python def dump_json( instance: T, indent: int | None = None, ensure_ascii: bool = False, include: IncEx | None = None, exclude: IncEx | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> bytes ``` Usage Documentation [JSON Serialization](/docs/validation/latest/concepts/json#json-serialization) Serialize an instance of the adapted type to JSON. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The JSON representation of the given instance as bytes. ##### Parameters **`instance`** : `T` The instance to be serialized. **`indent`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Number of spaces for JSON indentation. **`ensure_ascii`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. If `False` (the default), these characters will be output as-is. **`include`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Fields to include. **`exclude`** : `IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Fields to exclude. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use alias names for field names. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude unset fields. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields with default values. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields with a value of `None`. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. While this can be useful for round-tripping, it is usually recommended to use the dedicated `round_trip` parameter instead. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize and deserialize the instance to ensure round-tripping. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered. If not provided, a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Additional context to pass to the serializer. #### json\_schema ```python def json_schema( by_alias: bool = True, ref_template: str = DEFAULT_REF_TEMPLATE, union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, mode: JsonSchemaMode = 'validation', ) -> dict[str, Any] ``` Generate a JSON schema for the adapted type. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- The JSON schema for the model as a dictionary. ##### Parameters **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use alias names for field names. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The format string used for generating $ref strings. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` To override the logic used to generate the JSON schema, as a subclass of `GenerateJsonSchema` with your desired modifications **`mode`** : `JsonSchemaMode` _Default:_ `'validation'` The mode in which to generate the schema. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` The generator class used for creating the schema. **`mode`** : `JsonSchemaMode` _Default:_ `'validation'` The mode to use for schema generation. #### json\_schemas `@staticmethod` ```python def json_schemas( inputs: Iterable[tuple[JsonSchemaKeyT, JsonSchemaMode, TypeAdapter[Any]]], by_alias: bool = True, title: str | None = None, description: str | None = None, ref_template: str = DEFAULT_REF_TEMPLATE, union_format: Literal['any_of', 'primitive_type_array'] = 'any_of', schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema, ) -> tuple[dict[tuple[JsonSchemaKeyT, JsonSchemaMode], JsonSchemaValue], JsonSchemaValue] ``` Generate a JSON schema including definitions from multiple type adapters. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`JsonSchemaKeyT`, `JsonSchemaMode`\], `JsonSchemaValue`\], `JsonSchemaValue`\] -- A tuple where: - The first element is a dictionary whose keys are tuples of JSON schema key type and JSON mode, and whose values are the JSON schema corresponding to that pair of inputs. (These schemas may have JsonRef references to definitions that are defined in the second returned element.) - The second element is a JSON schema containing all definitions referenced in the first returned element, along with the optional title and description keys. ##### Parameters **`inputs`** : [`Iterable`](https://docs.python.org/3/library/typing.html#typing.Iterable)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`JsonSchemaKeyT`, `JsonSchemaMode`, [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\]\] Inputs to schema generation. The first two items will form the keys of the (first) output mapping; the type adapters will provide the core schemas that get converted into definitions in the output JSON schema. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use alias names. **`title`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The title for the schema. **`description`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The description for the schema. **`ref_template`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `DEFAULT_REF_TEMPLATE` The format string used for generating $ref strings. **`union_format`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['any\_of', 'primitive\_type\_array'\] _Default:_ `'any_of'` The format to use when combining schemas from unions together. Can be one of: - `'any_of'`: Use the [`anyOf`](https://json-schema.org/understanding-json-schema/reference/combining#anyOf) keyword to combine schemas (the default). - `'primitive_type_array'`: Use the [`type`](https://json-schema.org/understanding-json-schema/reference/type) keyword as an array of strings, containing each type of the combination. If any of the schemas is not a primitive type (`string`, `boolean`, `null`, `integer` or `number`) or contains constraints/metadata, falls back to `any_of`. **`schema_generator`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`GenerateJsonSchema`\] _Default:_ `GenerateJsonSchema` The generator class used for creating the schema. --- # [Pydantic Types](https://pydantic.dev/docs/validation/latest/api/pydantic/types/) # Pydantic Types The types module contains custom types used by pydantic. ## Strict **Bases:** `PydanticMetadata`, `BaseMetadata` Usage Documentation [Strict Mode with `Annotated` `Strict`](/docs/validation/latest/concepts/strict_mode#strict-mode-with-annotated-strict) A field metadata class to indicate that a field should be validated in strict mode. Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. ### Attributes #### strict Whether to validate the field in strict mode. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ## AllowInfNan **Bases:** `PydanticMetadata` A field metadata class to indicate that a field should allow `-inf`, `inf`, and `nan`. Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. ### Attributes #### allow\_inf\_nan Whether to allow `-inf`, `inf`, and `nan`. Defaults to `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ## StringConstraints **Bases:** `GroupedMetadata` Usage Documentation [String types](/docs/validation/latest/api/pydantic/standard_library_types#strings) A field metadata class to apply constraints to `str` types. Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. ### Attributes #### strip\_whitespace Whether to remove leading and trailing whitespace. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### to\_upper Whether to convert the string to uppercase. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### to\_lower Whether to convert the string to lowercase. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### strict Whether to validate the string in strict mode. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### min\_length The minimum length of the string. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### max\_length The maximum length of the string. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) #### pattern A regex pattern that the string must match. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Pattern`](https://docs.python.org/3/library/typing.html#typing.Pattern)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### ascii\_only Whether the string should contain only ASCII characters. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) ## ImportString A type that can be used to import a Python object from a string. `ImportString` expects a string and loads the Python object importable at that dotted path. Attributes of modules may be separated from the module by `:` or `.`, e.g. if `'math:cos'` is provided, the resulting field value would be the function `cos`. If a `.` is used and both an attribute and submodule are present at the same path, the module will be preferred. On model instantiation, pointers will be evaluated and imported. There is some nuance to this behavior, demonstrated in the examples below. ```python import math from pydantic import BaseModel, Field, ImportString, ValidationError class ImportThings(BaseModel): obj: ImportString # A string value will cause an automatic import my_cos = ImportThings(obj='math.cos') # You can use the imported function as you would expect cos_of_0 = my_cos.obj(0) assert cos_of_0 == 1 # A string whose value cannot be imported will raise an error try: ImportThings(obj='foo.bar') except ValidationError as e: print(e) ''' 1 validation error for ImportThings obj Invalid python path: No module named 'foo' [type=import_error, input_value='foo.bar', input_type=str] ''' # Actual python objects can be assigned as well my_cos = ImportThings(obj=math.cos) my_cos_2 = ImportThings(obj='math.cos') my_cos_3 = ImportThings(obj='math:cos') assert my_cos == my_cos_2 == my_cos_3 # You can set default field value either as Python object: class ImportThingsDefaultPyObj(BaseModel): obj: ImportString = math.cos # or as a string value (but only if used with `validate_default=True`) class ImportThingsDefaultString(BaseModel): obj: ImportString = Field(default='math.cos', validate_default=True) my_cos_default1 = ImportThingsDefaultPyObj() my_cos_default2 = ImportThingsDefaultString() assert my_cos_default1.obj == my_cos_default2.obj == math.cos # note: this will not work! class ImportThingsMissingValidateDefault(BaseModel): obj: ImportString = 'math.cos' my_cos_default3 = ImportThingsMissingValidateDefault() assert my_cos_default3.obj == 'math.cos' # just string, not evaluated ``` Serializing an `ImportString` type to json is also possible. ```python from pydantic import BaseModel, ImportString class ImportThings(BaseModel): obj: ImportString # Create an instance m = ImportThings(obj='math.cos') print(m) #> obj= print(m.model_dump_json()) #> {"obj":"math.cos"} ``` ## UuidVersion A field metadata class to indicate a [UUID](https://docs.python.org/3/library/uuid.html) version. Use this class as an annotation via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), as seen below. ### Attributes #### uuid\_version The version of the UUID. Must be one of 1, 3, 4, 5, 6, 7 or 8. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\[1, 3, 4, 5, 6, 7, 8\] ## Json A special type wrapper which loads JSON before parsing. You can use the `Json` data type to make Pydantic first load a raw JSON string before validating the loaded data into the parametrized type: ```python from typing import Any from pydantic import BaseModel, Json, ValidationError class AnyJsonModel(BaseModel): json_obj: Json[Any] class ConstrainedJsonModel(BaseModel): json_obj: Json[list[int]] print(AnyJsonModel(json_obj='{"b": 1}')) #> json_obj={'b': 1} print(ConstrainedJsonModel(json_obj='[1, 2, 3]')) #> json_obj=[1, 2, 3] try: ConstrainedJsonModel(json_obj=12) except ValidationError as e: print(e) ''' 1 validation error for ConstrainedJsonModel json_obj JSON input should be string, bytes or bytearray [type=json_type, input_value=12, input_type=int] ''' try: ConstrainedJsonModel(json_obj='[a, b]') except ValidationError as e: print(e) ''' 1 validation error for ConstrainedJsonModel json_obj Invalid JSON: expected value at line 1 column 2 [type=json_invalid, input_value='[a, b]', input_type=str] ''' try: ConstrainedJsonModel(json_obj='["a", "b"]') except ValidationError as e: print(e) ''' 2 validation errors for ConstrainedJsonModel json_obj.0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] json_obj.1 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='b', input_type=str] ''' ``` When you dump the model using `model_dump` or `model_dump_json`, the dumped value will be the result of validation, not the original JSON string. However, you can use the argument `round_trip=True` to get the original JSON string back: ```python from pydantic import BaseModel, Json class ConstrainedJsonModel(BaseModel): json_obj: Json[list[int]] print(ConstrainedJsonModel(json_obj='[1, 2, 3]').model_dump_json()) #> {"json_obj":[1,2,3]} print( ConstrainedJsonModel(json_obj='[1, 2, 3]').model_dump_json(round_trip=True) ) #> {"json_obj":"[1,2,3]"} ``` ## Secret **Bases:** `_SecretBase[SecretType]` A generic base class used for defining a field with sensitive information that you do not want to be visible in logging or tracebacks. You may either directly parametrize `Secret` with a type, or subclass from `Secret` with a parametrized type. The benefit of subclassing is that you can define a custom `_display` method, which will be used for `repr()` and `str()` methods. The examples below demonstrate both ways of using `Secret` to create a new secret type. 1. Directly parametrizing `Secret` with a type: ```python from pydantic import BaseModel, Secret SecretBool = Secret[bool] class Model(BaseModel): secret_bool: SecretBool m = Model(secret_bool=True) print(m.model_dump()) #> {'secret_bool': Secret('**********')} print(m.model_dump_json()) #> {"secret_bool":"**********"} print(m.secret_bool.get_secret_value()) #> True ``` 2. Subclassing from parametrized `Secret`: ```python from datetime import date from pydantic import BaseModel, Secret class SecretDate(Secret[date]): def _display(self) -> str: return '****/**/**' class Model(BaseModel): secret_date: SecretDate m = Model(secret_date=date(2022, 1, 1)) print(m.model_dump()) #> {'secret_date': SecretDate('****/**/**')} print(m.model_dump_json()) #> {"secret_date":"****/**/**"} print(m.secret_date.get_secret_value()) #> 2022-01-01 ``` The value returned by the `_display` method will be used for `repr()` and `str()`. You can enforce constraints on the underlying type through annotations: For example: ```python from typing import Annotated from pydantic import BaseModel, Field, Secret, ValidationError SecretPosInt = Secret[Annotated[int, Field(gt=0, strict=True)]] class Model(BaseModel): sensitive_int: SecretPosInt m = Model(sensitive_int=42) print(m.model_dump()) #> {'sensitive_int': Secret('**********')} try: m = Model(sensitive_int=-42) # (1) except ValidationError as exc_info: print(exc_info.errors(include_url=False, include_input=False)) ''' [ { 'type': 'greater_than', 'loc': ('sensitive_int',), 'msg': 'Input should be greater than 0', 'ctx': {'gt': 0}, } ] ''' try: m = Model(sensitive_int='42') # (2) except ValidationError as exc_info: print(exc_info.errors(include_url=False, include_input=False)) ''' [ { 'type': 'int_type', 'loc': ('sensitive_int',), 'msg': 'Input should be a valid integer', } ] ''' ``` The input value is not greater than 0, so it raises a validation error. The input value is not an integer, so it raises a validation error because the `SecretPosInt` type has strict mode enabled. ## SecretStr **Bases:** `_SecretField[str]` A string used for storing sensitive information that you do not want to be visible in logging or tracebacks. When the secret value is nonempty, it is displayed as `'**********'` instead of the underlying value in calls to `repr()` and `str()`. If the value _is_ empty, it is displayed as `''`. ```python from pydantic import BaseModel, SecretStr class User(BaseModel): username: str password: SecretStr user = User(username='scolvin', password='password1') print(user) #> username='scolvin' password=SecretStr('**********') print(user.password.get_secret_value()) #> password1 print((SecretStr('password'), SecretStr(''))) #> (SecretStr('**********'), SecretStr('')) ``` As seen above, by default, [`SecretStr`](/docs/validation/latest/api/pydantic/types/#pydantic.types.SecretStr) (and [`SecretBytes`](/docs/validation/latest/api/pydantic/types/#pydantic.types.SecretBytes)) will be serialized as `**********` when serializing to json. You can use the [`field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.field_serializer) to dump the secret as plain-text when serializing to json. ```python from pydantic import BaseModel, SecretBytes, SecretStr, field_serializer class Model(BaseModel): password: SecretStr password_bytes: SecretBytes @field_serializer('password', 'password_bytes', when_used='json') def dump_secret(self, v): return v.get_secret_value() model = Model(password='IAmSensitive', password_bytes=b'IAmSensitiveBytes') print(model) #> password=SecretStr('**********') password_bytes=SecretBytes(b'**********') print(model.password) #> ********** print(model.model_dump()) ''' { 'password': SecretStr('**********'), 'password_bytes': SecretBytes(b'**********'), } ''' print(model.model_dump_json()) #> {"password":"IAmSensitive","password_bytes":"IAmSensitiveBytes"} ``` ## SecretBytes **Bases:** `_SecretField[bytes]` A bytes used for storing sensitive information that you do not want to be visible in logging or tracebacks. It displays `b'**********'` instead of the string value on `repr()` and `str()` calls. When the secret value is nonempty, it is displayed as `b'**********'` instead of the underlying value in calls to `repr()` and `str()`. If the value _is_ empty, it is displayed as `b''`. ```python from pydantic import BaseModel, SecretBytes class User(BaseModel): username: str password: SecretBytes user = User(username='scolvin', password=b'password1') #> username='scolvin' password=SecretBytes(b'**********') print(user.password.get_secret_value()) #> b'password1' print((SecretBytes(b'password'), SecretBytes(b''))) #> (SecretBytes(b'**********'), SecretBytes(b'')) ``` ## PaymentCardNumber **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) Based on: [https://en.wikipedia.org/wiki/Payment\_card\_number](https://en.wikipedia.org/wiki/Payment_card_number). ### Attributes #### masked Mask all but the last 4 digits of the card number. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### validate `@classmethod` ```python def validate(cls, input_value: str, _: core_schema.ValidationInfo) -> PaymentCardNumber ``` Validate the card number and return a `PaymentCardNumber` instance. ##### Returns [`PaymentCardNumber`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PaymentCardNumber) #### validate\_digits `@classmethod` ```python def validate_digits(cls, card_number: str) -> None ``` Validate that the card number is all digits. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) #### validate\_luhn\_check\_digit `@classmethod` ```python def validate_luhn_check_digit(cls, card_number: str) -> str ``` Based on: [https://en.wikipedia.org/wiki/Luhn\_algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm). ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### validate\_brand `@staticmethod` ```python def validate_brand(card_number: str) -> PaymentCardBrand ``` Validate length based on BIN for major brands: [https://en.wikipedia.org/wiki/Payment\_card\_number#Issuer\_identification\_number\_(IIN)](https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_\(IIN\)). ##### Returns `PaymentCardBrand` ## ByteSize **Bases:** [`int`](https://docs.python.org/3/library/functions.html#int) Converts a string representing a number of bytes with units (such as `'1KB'` or `'11.5MiB'`) into an integer. You can use the `ByteSize` data type to (case-insensitively) convert a string representation of a number of bytes into an integer, and also to print out human-readable strings representing a number of bytes. In conformance with [IEC 80000-13 Standard](https://en.wikipedia.org/wiki/ISO/IEC_80000) we interpret `'1KB'` to mean 1000 bytes, and `'1KiB'` to mean 1024 bytes. In general, including a middle `'i'` will cause the unit to be interpreted as a power of 2, rather than a power of 10 (so, for example, `'1 MB'` is treated as `1_000_000` bytes, whereas `'1 MiB'` is treated as `1_048_576` bytes). Note Note that `1b` will be parsed as "1 byte" and not "1 bit". ```python from pydantic import BaseModel, ByteSize class MyModel(BaseModel): size: ByteSize print(MyModel(size=52000).size) #> 52000 print(MyModel(size='3000 KiB').size) #> 3072000 m = MyModel(size='50 PB') print(m.size.human_readable()) #> 44.4PiB print(m.size.human_readable(decimal=True)) #> 50.0PB print(m.size.human_readable(separator=' ')) #> 44.4 PiB print(m.size.to('TiB')) #> 45474.73508864641 ``` ### Methods #### human\_readable ```python def human_readable(decimal: bool = False, separator: str = '') -> str ``` Converts a byte size to a human readable string. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- A human readable string representation of the byte size. ##### Parameters **`decimal`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If True, use decimal units (e.g. 1000 bytes per KB). If False, use binary units (e.g. 1024 bytes per KiB). **`separator`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `''` A string used to split the value and unit. Defaults to an empty string ("). #### to ```python def to(unit: str) -> float ``` Converts a byte size to another unit, including both byte and bit units. ##### Returns [`float`](https://docs.python.org/3/library/functions.html#float) -- The byte size in the new unit. ##### Parameters **`unit`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The unit to convert to. Must be one of the following: B, KB, MB, GB, TB, PB, EB, KiB, MiB, GiB, TiB, PiB, EiB (byte units) and bit, kbit, mbit, gbit, tbit, pbit, ebit, kibit, mibit, gibit, tibit, pibit, eibit (bit units). ## PastDate A date in the past. ## FutureDate A date in the future. ## AwareDatetime A datetime that requires timezone info. ## NaiveDatetime A datetime that doesn't require timezone info. ## PastDatetime A datetime that must be in the past. ## FutureDatetime A datetime that must be in the future. ## EncoderProtocol **Bases:** [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) Protocol for encoding and decoding data to and from bytes. ### Methods #### decode `@classmethod` ```python def decode(cls, data: bytes) -> bytes ``` Decode the data using the encoder. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The decoded data. ##### Parameters **`data`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to decode. #### encode `@classmethod` ```python def encode(cls, value: bytes) -> bytes ``` Encode the data using the encoder. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The encoded data. ##### Parameters **`value`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to encode. #### get\_json\_format `@classmethod` ```python def get_json_format(cls) -> str ``` Get the JSON format for the encoded data. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The JSON format for the encoded data. ## Base64Encoder **Bases:** [`EncoderProtocol`](/docs/validation/latest/api/pydantic/types/#pydantic.types.EncoderProtocol) Standard (non-URL-safe) Base64 encoder. ### Methods #### decode `@classmethod` ```python def decode(cls, data: bytes) -> bytes ``` Decode the data from base64 encoded bytes to original bytes data. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The decoded data. ##### Parameters **`data`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to decode. #### encode `@classmethod` ```python def encode(cls, value: bytes) -> bytes ``` Encode the data from bytes to a base64 encoded bytes. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The encoded data. ##### Parameters **`value`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to encode. #### get\_json\_format `@classmethod` ```python def get_json_format(cls) -> Literal['base64'] ``` Get the JSON format for the encoded data. ##### Returns [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['base64'\] -- The JSON format for the encoded data. ## Base64UrlEncoder **Bases:** [`EncoderProtocol`](/docs/validation/latest/api/pydantic/types/#pydantic.types.EncoderProtocol) URL-safe Base64 encoder. ### Methods #### decode `@classmethod` ```python def decode(cls, data: bytes) -> bytes ``` Decode the data from base64 encoded bytes to original bytes data. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The decoded data. ##### Parameters **`data`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to decode. #### encode `@classmethod` ```python def encode(cls, value: bytes) -> bytes ``` Encode the data from bytes to a base64 encoded bytes. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The encoded data. ##### Parameters **`value`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to encode. #### get\_json\_format `@classmethod` ```python def get_json_format(cls) -> Literal['base64url'] ``` Get the JSON format for the encoded data. ##### Returns [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['base64url'\] -- The JSON format for the encoded data. ## EncodedBytes A bytes type that is encoded and decoded using the specified encoder. `EncodedBytes` needs an encoder that implements `EncoderProtocol` to operate. ```python from typing import Annotated from pydantic import BaseModel, EncodedBytes, EncoderProtocol, ValidationError class MyEncoder(EncoderProtocol): @classmethod def decode(cls, data: bytes) -> bytes: if data == b'**undecodable**': raise ValueError('Cannot decode data') return data[13:] @classmethod def encode(cls, value: bytes) -> bytes: return b'**encoded**: ' + value @classmethod def get_json_format(cls) -> str: return 'my-encoder' MyEncodedBytes = Annotated[bytes, EncodedBytes(encoder=MyEncoder)] class Model(BaseModel): my_encoded_bytes: MyEncodedBytes # Initialize the model with encoded data m = Model(my_encoded_bytes=b'**encoded**: some bytes') # Access decoded value print(m.my_encoded_bytes) #> b'some bytes' # Serialize into the encoded form print(m.model_dump()) #> {'my_encoded_bytes': b'**encoded**: some bytes'} # Validate encoded data try: Model(my_encoded_bytes=b'**undecodable**') except ValidationError as e: print(e) ''' 1 validation error for Model my_encoded_bytes Value error, Cannot decode data [type=value_error, input_value=b'**undecodable**', input_type=bytes] ''' ``` ### Methods #### decode ```python def decode(data: bytes, _: core_schema.ValidationInfo) -> bytes ``` Decode the data using the specified encoder. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The decoded data. ##### Parameters **`data`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to decode. #### encode ```python def encode(value: bytes) -> bytes ``` Encode the data using the specified encoder. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- The encoded data. ##### Parameters **`value`** : [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) The data to encode. ## EncodedStr A str type that is encoded and decoded using the specified encoder. `EncodedStr` needs an encoder that implements `EncoderProtocol` to operate. ```python from typing import Annotated from pydantic import BaseModel, EncodedStr, EncoderProtocol, ValidationError class MyEncoder(EncoderProtocol): @classmethod def decode(cls, data: bytes) -> bytes: if data == b'**undecodable**': raise ValueError('Cannot decode data') return data[13:] @classmethod def encode(cls, value: bytes) -> bytes: return b'**encoded**: ' + value @classmethod def get_json_format(cls) -> str: return 'my-encoder' MyEncodedStr = Annotated[str, EncodedStr(encoder=MyEncoder)] class Model(BaseModel): my_encoded_str: MyEncodedStr # Initialize the model with encoded data m = Model(my_encoded_str='**encoded**: some str') # Access decoded value print(m.my_encoded_str) #> some str # Serialize into the encoded form print(m.model_dump()) #> {'my_encoded_str': '**encoded**: some str'} # Validate encoded data try: Model(my_encoded_str='**undecodable**') except ValidationError as e: print(e) ''' 1 validation error for Model my_encoded_str Value error, Cannot decode data [type=value_error, input_value='**undecodable**', input_type=str] ''' ``` ### Methods #### decode\_str ```python def decode_str(data: str, _: core_schema.ValidationInfo) -> str ``` Decode the data using the specified encoder. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The decoded data. ##### Parameters **`data`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The data to decode. #### encode\_str ```python def encode_str(value: str) -> str ``` Encode the data using the specified encoder. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The encoded data. ##### Parameters **`value`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The data to encode. ## GetPydanticSchema Usage Documentation [Using `GetPydanticSchema` to Reduce Boilerplate](/docs/validation/latest/concepts/types#using-getpydanticschema-to-reduce-boilerplate) A convenience class for creating an annotation that provides pydantic custom type hooks. This class is intended to eliminate the need to create a custom "marker" which defines the `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__` custom hook methods. For example, to have a field treated by type checkers as `int`, but by pydantic as `Any`, you can do: ```python from typing import Annotated, Any from pydantic import BaseModel, GetPydanticSchema HandleAsAny = GetPydanticSchema(lambda _s, h: h(Any)) class Model(BaseModel): x: Annotated[int, HandleAsAny] # pydantic sees `x: Any` print(repr(Model(x='abc').x)) #> 'abc' ``` ## Tag Provides a way to specify the expected tag to use for a case of a (callable) discriminated union. Also provides a way to label a union case in error messages. When using a callable `Discriminator`, attach a `Tag` to each case in the `Union` to specify the tag that should be used to identify that case. For example, in the below example, the `Tag` is used to specify that if `get_discriminator_value` returns `'apple'`, the input should be validated as an `ApplePie`, and if it returns `'pumpkin'`, the input should be validated as a `PumpkinPie`. The primary role of the `Tag` here is to map the return value from the callable `Discriminator` function to the appropriate member of the `Union` in question. ```python from typing import Annotated, Any, Literal, Union from pydantic import BaseModel, Discriminator, Tag class Pie(BaseModel): time_to_cook: int num_ingredients: int class ApplePie(Pie): fruit: Literal['apple'] = 'apple' class PumpkinPie(Pie): filling: Literal['pumpkin'] = 'pumpkin' def get_discriminator_value(v: Any) -> str: if isinstance(v, dict): return v.get('fruit', v.get('filling')) return getattr(v, 'fruit', getattr(v, 'filling', None)) class ThanksgivingDinner(BaseModel): dessert: Annotated[ Union[ Annotated[ApplePie, Tag('apple')], Annotated[PumpkinPie, Tag('pumpkin')], ], Discriminator(get_discriminator_value), ] apple_variation = ThanksgivingDinner.model_validate( {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} ) print(repr(apple_variation)) ''' ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) ''' pumpkin_variation = ThanksgivingDinner.model_validate( { 'dessert': { 'filling': 'pumpkin', 'time_to_cook': 40, 'num_ingredients': 6, } } ) print(repr(pumpkin_variation)) ''' ThanksgivingDinner(dessert=PumpkinPie(time_to_cook=40, num_ingredients=6, filling='pumpkin')) ''' ``` Note You must specify a `Tag` for every case in a `Tag` that is associated with a callable `Discriminator`. Failing to do so will result in a `PydanticUserError` with code [`callable-discriminator-no-tag`](/docs/validation/latest/errors/usage_errors#callable-discriminator-no-tag). See the [Discriminated Unions](/docs/validation/latest/concepts/unions#discriminated-unions) concepts docs for more details on how to use `Tag`s. ## Discriminator Usage Documentation [Discriminated Unions with `Callable` `Discriminator`](/docs/validation/latest/concepts/unions#discriminated-unions-with-callable-discriminator) Provides a way to use a custom callable as the way to extract the value of a union discriminator. This allows you to get validation behavior like you'd get from `Field(discriminator=)`, but without needing to have a single shared field across all the union choices. This also makes it possible to handle unions of models and primitive types with discriminated-union-style validation errors. Finally, this allows you to use a custom callable as the way to identify which member of a union a value belongs to, while still seeing all the performance benefits of a discriminated union. Consider this example, which is much more performant with the use of `Discriminator` and thus a `TaggedUnion` than it would be as a normal `Union`. ```python from typing import Annotated, Any, Literal, Union from pydantic import BaseModel, Discriminator, Tag class Pie(BaseModel): time_to_cook: int num_ingredients: int class ApplePie(Pie): fruit: Literal['apple'] = 'apple' class PumpkinPie(Pie): filling: Literal['pumpkin'] = 'pumpkin' def get_discriminator_value(v: Any) -> str: if isinstance(v, dict): return v.get('fruit', v.get('filling')) return getattr(v, 'fruit', getattr(v, 'filling', None)) class ThanksgivingDinner(BaseModel): dessert: Annotated[ Union[ Annotated[ApplePie, Tag('apple')], Annotated[PumpkinPie, Tag('pumpkin')], ], Discriminator(get_discriminator_value), ] apple_variation = ThanksgivingDinner.model_validate( {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} ) print(repr(apple_variation)) ''' ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) ''' pumpkin_variation = ThanksgivingDinner.model_validate( { 'dessert': { 'filling': 'pumpkin', 'time_to_cook': 40, 'num_ingredients': 6, } } ) print(repr(pumpkin_variation)) ''' ThanksgivingDinner(dessert=PumpkinPie(time_to_cook=40, num_ingredients=6, filling='pumpkin')) ''' ``` See the [Discriminated Unions](/docs/validation/latest/concepts/unions#discriminated-unions) concepts docs for more details on how to use `Discriminator`s. ### Attributes #### discriminator The callable or field name for discriminating the type in a tagged union. A `Callable` discriminator must extract the value of the discriminator from the input. A `str` discriminator must be the name of a field to discriminate against. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Hashable`](https://docs.python.org/3/library/typing.html#typing.Hashable)\] #### custom\_error\_type Type to use in [custom errors](/docs/validation/latest/errors/errors) replacing the standard discriminated union validation errors. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` #### custom\_error\_message Message to use in custom errors. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` #### custom\_error\_context Context to use in custom errors. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`float`](https://docs.python.org/3/library/functions.html#float)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` ## FailFast **Bases:** `PydanticMetadata`, `BaseMetadata` A `FailFast` annotation can be used to specify that validation should stop at the first error. This can be useful when you want to validate a large amount of data and you only need to know if it's valid or not. You might want to enable this setting if you want to validate your data faster (basically, if you use this, validation will be more performant with the caveat that you get less information). ```python from typing import Annotated from pydantic import BaseModel, FailFast, ValidationError class Model(BaseModel): x: Annotated[list[int], FailFast()] # This will raise a single error for the first invalid value and stop validation try: obj = Model(x=[1, 2, 'a', 4, 5, 'b', 7, 8, 9, 'c']) except ValidationError as e: print(e) ''' 1 validation error for Model x.2 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] ''' ``` ## conint ```python def conint( strict: bool | None = None, gt: int | None = None, ge: int | None = None, lt: int | None = None, le: int | None = None, multiple_of: int | None = None, ) -> type[int] ``` Discouraged This function is **discouraged** in favor of using [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) instead. This function will be **deprecated** in Pydantic 3.0. The reason is that `conint` returns a type, which doesn't play well with static analysis tools. - [:x: Don't do this](#tab-panel-704) - [:white\_check\_mark: Do this](#tab-panel-705) ```python from pydantic import BaseModel, conint class Foo(BaseModel): bar: conint(strict=True, gt=0) ``` ```python from typing import Annotated from pydantic import BaseModel, Field class Foo(BaseModel): bar: Annotated[int, Field(strict=True, gt=0)] ``` A wrapper around `int` that allows for additional constraints. ```python from pydantic import BaseModel, ValidationError, conint class ConstrainedExample(BaseModel): constrained_int: conint(gt=1) m = ConstrainedExample(constrained_int=2) print(repr(m)) #> ConstrainedExample(constrained_int=2) try: ConstrainedExample(constrained_int=0) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than', 'loc': ('constrained_int',), 'msg': 'Input should be greater than 1', 'input': 0, 'ctx': {'gt': 1}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] ''' ``` ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`int`](https://docs.python.org/3/library/functions.html#int)\] -- The wrapped integer type. ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the integer in strict mode. Defaults to `None`. **`gt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than this. **`ge`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this. **`lt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than this. **`le`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this. **`multiple_of`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this. ## confloat ```python def confloat( strict: bool | None = None, gt: float | None = None, ge: float | None = None, lt: float | None = None, le: float | None = None, multiple_of: float | None = None, allow_inf_nan: bool | None = None, ) -> type[float] ``` Discouraged This function is **discouraged** in favor of using [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) instead. This function will be **deprecated** in Pydantic 3.0. The reason is that `confloat` returns a type, which doesn't play well with static analysis tools. - [:x: Don't do this](#tab-panel-706) - [:white\_check\_mark: Do this](#tab-panel-707) ```python from pydantic import BaseModel, confloat class Foo(BaseModel): bar: confloat(strict=True, gt=0) ``` ```python from typing import Annotated from pydantic import BaseModel, Field class Foo(BaseModel): bar: Annotated[float, Field(strict=True, gt=0)] ``` A wrapper around `float` that allows for additional constraints. ```python from pydantic import BaseModel, ValidationError, confloat class ConstrainedExample(BaseModel): constrained_float: confloat(gt=1.0) m = ConstrainedExample(constrained_float=1.1) print(repr(m)) #> ConstrainedExample(constrained_float=1.1) try: ConstrainedExample(constrained_float=0.9) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than', 'loc': ('constrained_float',), 'msg': 'Input should be greater than 1', 'input': 0.9, 'ctx': {'gt': 1.0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] ''' ``` ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`float`](https://docs.python.org/3/library/functions.html#float)\] -- The wrapped float type. ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the float in strict mode. **`gt`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than this. **`ge`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this. **`lt`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than this. **`le`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this. **`multiple_of`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this. **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to allow `-inf`, `inf`, and `nan`. ## conbytes ```python def conbytes( min_length: int | None = None, max_length: int | None = None, strict: bool | None = None, ) -> type[bytes] ``` A wrapper around `bytes` that allows for additional constraints. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes)\] -- The wrapped bytes type. ### Parameters **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The minimum length of the bytes. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the bytes. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the bytes in strict mode. ## constr ```python def constr( strip_whitespace: bool | None = None, to_upper: bool | None = None, to_lower: bool | None = None, strict: bool | None = None, min_length: int | None = None, max_length: int | None = None, pattern: str | Pattern[str] | None = None, ascii_only: bool | None = None, ) -> type[str] ``` Discouraged This function is **discouraged** in favor of using [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with [`StringConstraints`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StringConstraints) instead. This function will be **deprecated** in Pydantic 3.0. The reason is that `constr` returns a type, which doesn't play well with static analysis tools. - [:x: Don't do this](#tab-panel-708) - [:white\_check\_mark: Do this](#tab-panel-709) ```python from pydantic import BaseModel, constr class Foo(BaseModel): bar: constr(strip_whitespace=True, to_upper=True, pattern=r'^[A-Z]+$') ``` ```python from typing import Annotated from pydantic import BaseModel, StringConstraints class Foo(BaseModel): bar: Annotated[ str, StringConstraints( strip_whitespace=True, to_upper=True, pattern=r'^[A-Z]+$' ), ] ``` A wrapper around `str` that allows for additional constraints. ```python from pydantic import BaseModel, constr class Foo(BaseModel): bar: constr(strip_whitespace=True, to_upper=True) foo = Foo(bar=' hello ') print(foo) #> bar='HELLO' ``` ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] -- The wrapped string type. ### Parameters **`strip_whitespace`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to remove leading and trailing whitespace. **`to_upper`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to turn all characters to uppercase. **`to_lower`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to turn all characters to lowercase. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the string in strict mode. **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The minimum length of the string. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the string. **`pattern`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Pattern`](https://docs.python.org/3/library/typing.html#typing.Pattern)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A regex pattern to validate the string against. **`ascii_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the string should contain only ASCII characters. ## conset ```python def conset( item_type: type[HashableItemType], min_length: int | None = None, max_length: int | None = None, ) -> type[set[HashableItemType]] ``` A wrapper around `typing.Set` that allows for additional constraints. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`set`](https://docs.python.org/3/reference/expressions.html#set)\[`HashableItemType`\]\] -- The wrapped set type. ### Parameters **`item_type`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`HashableItemType`\] The type of the items in the set. **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The minimum length of the set. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the set. ## confrozenset ```python def confrozenset( item_type: type[HashableItemType], min_length: int | None = None, max_length: int | None = None, ) -> type[frozenset[HashableItemType]] ``` A wrapper around `typing.FrozenSet` that allows for additional constraints. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`frozenset`](https://docs.python.org/3/library/stdtypes.html#frozenset)\[`HashableItemType`\]\] -- The wrapped frozenset type. ### Parameters **`item_type`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`HashableItemType`\] The type of the items in the frozenset. **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The minimum length of the frozenset. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the frozenset. ## conlist ```python def conlist( item_type: type[AnyItemType], min_length: int | None = None, max_length: int | None = None, unique_items: bool | None = None, ) -> type[list[AnyItemType]] ``` A wrapper around [`list`](https://docs.python.org/3/glossary.html#term-list) that adds validation. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[`AnyItemType`\]\] -- The wrapped list type. ### Parameters **`item_type`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`AnyItemType`\] The type of the items in the list. **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The minimum length of the list. Defaults to None. **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the list. Defaults to None. **`unique_items`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the items in the list must be unique. Defaults to None. Deprecated The `unique_items` parameter is deprecated, use `Set` instead. See [this issue](https://github.com/pydantic/pydantic-core/issues/296) for more details. ## condecimal ```python def condecimal( strict: bool | None = None, gt: int | Decimal | None = None, ge: int | Decimal | None = None, lt: int | Decimal | None = None, le: int | Decimal | None = None, multiple_of: int | Decimal | None = None, max_digits: int | None = None, decimal_places: int | None = None, allow_inf_nan: bool | None = None, ) -> type[Decimal] ``` Discouraged This function is **discouraged** in favor of using [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) with [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) instead. This function will be **deprecated** in Pydantic 3.0. The reason is that `condecimal` returns a type, which doesn't play well with static analysis tools. - [:x: Don't do this](#tab-panel-710) - [:white\_check\_mark: Do this](#tab-panel-711) ```python from pydantic import BaseModel, condecimal class Foo(BaseModel): bar: condecimal(strict=True, allow_inf_nan=True) ``` ```python from decimal import Decimal from typing import Annotated from pydantic import BaseModel, Field class Foo(BaseModel): bar: Annotated[Decimal, Field(strict=True, allow_inf_nan=True)] ``` A wrapper around Decimal that adds validation. ```python from decimal import Decimal from pydantic import BaseModel, ValidationError, condecimal class ConstrainedExample(BaseModel): constrained_decimal: condecimal(gt=Decimal('1.0')) m = ConstrainedExample(constrained_decimal=Decimal('1.1')) print(repr(m)) #> ConstrainedExample(constrained_decimal=Decimal('1.1')) try: ConstrainedExample(constrained_decimal=Decimal('0.9')) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than', 'loc': ('constrained_decimal',), 'msg': 'Input should be greater than 1.0', 'input': Decimal('0.9'), 'ctx': {'gt': Decimal('1.0')}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] ''' ``` ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[`Decimal`\] ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the value in strict mode. Defaults to `None`. **`gt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than this. Defaults to `None`. **`ge`** : [`int`](https://docs.python.org/3/library/functions.html#int) | `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this. Defaults to `None`. **`lt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than this. Defaults to `None`. **`le`** : [`int`](https://docs.python.org/3/library/functions.html#int) | `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this. Defaults to `None`. **`multiple_of`** : [`int`](https://docs.python.org/3/library/functions.html#int) | `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this. Defaults to `None`. **`max_digits`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum number of digits. Defaults to `None`. **`decimal_places`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The number of decimal places. Defaults to `None`. **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to allow infinity and NaN. Defaults to `None`. ## condate ```python def condate( strict: bool | None = None, gt: date | None = None, ge: date | None = None, lt: date | None = None, le: date | None = None, ) -> type[date] ``` A wrapper for date that adds constraints. ### Returns [`type`](https://docs.python.org/3/glossary.html#term-type)\[`date`\] -- A date type with the specified constraints. ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the date value in strict mode. Defaults to `None`. **`gt`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than this. Defaults to `None`. **`ge`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this. Defaults to `None`. **`lt`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than this. Defaults to `None`. **`le`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this. Defaults to `None`. ## StrictBool A boolean that must be either `True` or `False`. **Default:** `Annotated[bool, Strict()]` ## PositiveInt An integer that must be greater than zero. ```python from pydantic import BaseModel, PositiveInt, ValidationError class Model(BaseModel): positive_int: PositiveInt m = Model(positive_int=1) print(repr(m)) #> Model(positive_int=1) try: Model(positive_int=-1) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than', 'loc': ('positive_int',), 'msg': 'Input should be greater than 0', 'input': -1, 'ctx': {'gt': 0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] ''' ``` **Default:** `Annotated[int, annotated_types.Gt(0)]` ## NegativeInt An integer that must be less than zero. ```python from pydantic import BaseModel, NegativeInt, ValidationError class Model(BaseModel): negative_int: NegativeInt m = Model(negative_int=-1) print(repr(m)) #> Model(negative_int=-1) try: Model(negative_int=1) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'less_than', 'loc': ('negative_int',), 'msg': 'Input should be less than 0', 'input': 1, 'ctx': {'lt': 0}, 'url': 'https://errors.pydantic.dev/2/v/less_than', } ] ''' ``` **Default:** `Annotated[int, annotated_types.Lt(0)]` ## NonPositiveInt An integer that must be less than or equal to zero. ```python from pydantic import BaseModel, NonPositiveInt, ValidationError class Model(BaseModel): non_positive_int: NonPositiveInt m = Model(non_positive_int=0) print(repr(m)) #> Model(non_positive_int=0) try: Model(non_positive_int=1) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'less_than_equal', 'loc': ('non_positive_int',), 'msg': 'Input should be less than or equal to 0', 'input': 1, 'ctx': {'le': 0}, 'url': 'https://errors.pydantic.dev/2/v/less_than_equal', } ] ''' ``` **Default:** `Annotated[int, annotated_types.Le(0)]` ## NonNegativeInt An integer that must be greater than or equal to zero. ```python from pydantic import BaseModel, NonNegativeInt, ValidationError class Model(BaseModel): non_negative_int: NonNegativeInt m = Model(non_negative_int=0) print(repr(m)) #> Model(non_negative_int=0) try: Model(non_negative_int=-1) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than_equal', 'loc': ('non_negative_int',), 'msg': 'Input should be greater than or equal to 0', 'input': -1, 'ctx': {'ge': 0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than_equal', } ] ''' ``` **Default:** `Annotated[int, annotated_types.Ge(0)]` ## StrictInt An integer that must be validated in strict mode. ```python from pydantic import BaseModel, StrictInt, ValidationError class StrictIntModel(BaseModel): strict_int: StrictInt try: StrictIntModel(strict_int=3.14159) except ValidationError as e: print(e) ''' 1 validation error for StrictIntModel strict_int Input should be a valid integer [type=int_type, input_value=3.14159, input_type=float] ''' ``` **Default:** `Annotated[int, Strict()]` ## PositiveFloat A float that must be greater than zero. ```python from pydantic import BaseModel, PositiveFloat, ValidationError class Model(BaseModel): positive_float: PositiveFloat m = Model(positive_float=1.0) print(repr(m)) #> Model(positive_float=1.0) try: Model(positive_float=-1.0) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than', 'loc': ('positive_float',), 'msg': 'Input should be greater than 0', 'input': -1.0, 'ctx': {'gt': 0.0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] ''' ``` **Default:** `Annotated[float, annotated_types.Gt(0)]` ## NegativeFloat A float that must be less than zero. ```python from pydantic import BaseModel, NegativeFloat, ValidationError class Model(BaseModel): negative_float: NegativeFloat m = Model(negative_float=-1.0) print(repr(m)) #> Model(negative_float=-1.0) try: Model(negative_float=1.0) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'less_than', 'loc': ('negative_float',), 'msg': 'Input should be less than 0', 'input': 1.0, 'ctx': {'lt': 0.0}, 'url': 'https://errors.pydantic.dev/2/v/less_than', } ] ''' ``` **Default:** `Annotated[float, annotated_types.Lt(0)]` ## NonPositiveFloat A float that must be less than or equal to zero. ```python from pydantic import BaseModel, NonPositiveFloat, ValidationError class Model(BaseModel): non_positive_float: NonPositiveFloat m = Model(non_positive_float=0.0) print(repr(m)) #> Model(non_positive_float=0.0) try: Model(non_positive_float=1.0) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'less_than_equal', 'loc': ('non_positive_float',), 'msg': 'Input should be less than or equal to 0', 'input': 1.0, 'ctx': {'le': 0.0}, 'url': 'https://errors.pydantic.dev/2/v/less_than_equal', } ] ''' ``` **Default:** `Annotated[float, annotated_types.Le(0)]` ## NonNegativeFloat A float that must be greater than or equal to zero. ```python from pydantic import BaseModel, NonNegativeFloat, ValidationError class Model(BaseModel): non_negative_float: NonNegativeFloat m = Model(non_negative_float=0.0) print(repr(m)) #> Model(non_negative_float=0.0) try: Model(non_negative_float=-1.0) except ValidationError as e: print(e.errors()) ''' [ { 'type': 'greater_than_equal', 'loc': ('non_negative_float',), 'msg': 'Input should be greater than or equal to 0', 'input': -1.0, 'ctx': {'ge': 0.0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than_equal', } ] ''' ``` **Default:** `Annotated[float, annotated_types.Ge(0)]` ## StrictFloat A float that must be validated in strict mode. ```python from pydantic import BaseModel, StrictFloat, ValidationError class StrictFloatModel(BaseModel): strict_float: StrictFloat try: StrictFloatModel(strict_float='1.0') except ValidationError as e: print(e) ''' 1 validation error for StrictFloatModel strict_float Input should be a valid number [type=float_type, input_value='1.0', input_type=str] ''' ``` **Default:** `Annotated[float, Strict(True)]` ## FiniteFloat A float that must be finite (not `-inf`, `inf`, or `nan`). ```python from pydantic import BaseModel, FiniteFloat class Model(BaseModel): finite: FiniteFloat m = Model(finite=1.0) print(m) #> finite=1.0 ``` **Default:** `Annotated[float, AllowInfNan(False)]` ## StrictBytes A bytes that must be validated in strict mode. **Default:** `Annotated[bytes, Strict()]` ## StrictStr A string that must be validated in strict mode. **Default:** `Annotated[str, Strict()]` ## UUID1 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 1. ```python import uuid from pydantic import UUID1, BaseModel class Model(BaseModel): uuid1: UUID1 Model(uuid1=uuid.uuid1()) ``` **Default:** `Annotated[UUID, UuidVersion(1)]` ## UUID3 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 3. ```python import uuid from pydantic import UUID3, BaseModel class Model(BaseModel): uuid3: UUID3 Model(uuid3=uuid.uuid3(uuid.NAMESPACE_DNS, 'pydantic.org')) ``` **Default:** `Annotated[UUID, UuidVersion(3)]` ## UUID4 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 4. ```python import uuid from pydantic import UUID4, BaseModel class Model(BaseModel): uuid4: UUID4 Model(uuid4=uuid.uuid4()) ``` **Default:** `Annotated[UUID, UuidVersion(4)]` ## UUID5 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 5. ```python import uuid from pydantic import UUID5, BaseModel class Model(BaseModel): uuid5: UUID5 Model(uuid5=uuid.uuid5(uuid.NAMESPACE_DNS, 'pydantic.org')) ``` **Default:** `Annotated[UUID, UuidVersion(5)]` ## UUID6 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 6. ```python import uuid from pydantic import UUID6, BaseModel class Model(BaseModel): uuid6: UUID6 Model(uuid6=uuid.UUID('1efea953-c2d6-6790-aa0a-69db8c87df97')) ``` **Default:** `Annotated[UUID, UuidVersion(6)]` ## UUID7 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 7. ```python import uuid from pydantic import UUID7, BaseModel class Model(BaseModel): uuid7: UUID7 Model(uuid7=uuid.UUID('0194fdcb-1c47-7a09-b52c-561154de0b4a')) ``` **Default:** `Annotated[UUID, UuidVersion(7)]` ## UUID8 A [UUID](https://docs.python.org/3/library/uuid.html) that must be version 8. ```python import uuid from pydantic import UUID8, BaseModel class Model(BaseModel): uuid8: UUID8 Model(uuid8=uuid.UUID('81a0b92e-6078-8551-9c81-8ccb666bdab8')) ``` **Default:** `Annotated[UUID, UuidVersion(8)]` ## FilePath A path that must point to a file. ```python from pathlib import Path from pydantic import BaseModel, FilePath, ValidationError class Model(BaseModel): f: FilePath path = Path('text.txt') path.touch() m = Model(f='text.txt') print(m.model_dump()) #> {'f': PosixPath('text.txt')} path.unlink() path = Path('directory') path.mkdir(exist_ok=True) try: Model(f='directory') # directory except ValidationError as e: print(e) ''' 1 validation error for Model f Path does not point to a file [type=path_not_file, input_value='directory', input_type=str] ''' path.rmdir() try: Model(f='not-exists-file') except ValidationError as e: print(e) ''' 1 validation error for Model f Path does not point to a file [type=path_not_file, input_value='not-exists-file', input_type=str] ''' ``` **Default:** `Annotated[Path, PathType('file')]` ## DirectoryPath A path that must point to a directory. ```python from pathlib import Path from pydantic import BaseModel, DirectoryPath, ValidationError class Model(BaseModel): f: DirectoryPath path = Path('directory/') path.mkdir() m = Model(f='directory/') print(m.model_dump()) #> {'f': PosixPath('directory')} path.rmdir() path = Path('file.txt') path.touch() try: Model(f='file.txt') # file except ValidationError as e: print(e) ''' 1 validation error for Model f Path does not point to a directory [type=path_not_directory, input_value='file.txt', input_type=str] ''' path.unlink() try: Model(f='not-exists-directory') except ValidationError as e: print(e) ''' 1 validation error for Model f Path does not point to a directory [type=path_not_directory, input_value='not-exists-directory', input_type=str] ''' ``` **Default:** `Annotated[Path, PathType('dir')]` ## NewPath A path for a new file or directory that must not already exist. The parent directory must already exist. **Default:** `Annotated[Path, PathType('new')]` ## SocketPath A path to an existing socket file **Default:** `Annotated[Path, PathType('socket')]` ## Base64Bytes A bytes type that is encoded and decoded using the standard (non-URL-safe) base64 encoder. ↻ Changed in v2.10 `Base64Bytes` now uses [`base64.b64encode()`](https://docs.python.org/3/library/base64.html#base64.b64encode) and [`base64.b64decode()`](https://docs.python.org/3/library/base64.html#base64.b64decode) instead of [`base64.encodebytes()`](https://docs.python.org/3/library/base64.html#base64.encodebytes) and [`base64.decodebytes()`](https://docs.python.org/3/library/base64.html#base64.decodebytes). These methods are considered legacy implementation. If you'd still like to use these legacy encoders/decoders, you can achieve this by creating a custom annotated type, like follows: ```python import base64 from typing import Annotated, Literal from pydantic_core import PydanticCustomError from pydantic import EncodedBytes, EncoderProtocol class LegacyBase64Encoder(EncoderProtocol): @classmethod def decode(cls, data: bytes) -> bytes: try: return base64.decodebytes(data) except ValueError as e: raise PydanticCustomError( 'base64_decode', "Base64 decoding error: '{error}'", {'error': str(e)}, ) @classmethod def encode(cls, value: bytes) -> bytes: return base64.encodebytes(value) @classmethod def get_json_format(cls) -> Literal['base64']: return 'base64' LegacyBase64Bytes = Annotated[bytes, EncodedBytes(encoder=LegacyBase64Encoder)] ``` ```python from pydantic import Base64Bytes, BaseModel, ValidationError class Model(BaseModel): base64_bytes: Base64Bytes # Initialize the model with base64 data m = Model(base64_bytes=b'VGhpcyBpcyB0aGUgd2F5') # Access decoded value print(m.base64_bytes) #> b'This is the way' # Serialize into the base64 form print(m.model_dump()) #> {'base64_bytes': b'VGhpcyBpcyB0aGUgd2F5'} # Validate base64 data try: print(Model(base64_bytes=b'undecodable').base64_bytes) except ValidationError as e: print(e) ''' 1 validation error for Model base64_bytes Base64 decoding error: 'Incorrect padding' [type=base64_decode, input_value=b'undecodable', input_type=bytes] ''' ``` **Default:** `Annotated[bytes, EncodedBytes(encoder=Base64Encoder)]` ## Base64Str A string type that is encoded and decoded using the standard (non-URL-safe) base64 encoder. ↻ Changed in v2.10 `Base64Str` now uses [`base64.b64encode()`](https://docs.python.org/3/library/base64.html#base64.b64encode) and [`base64.b64decode()`](https://docs.python.org/3/library/base64.html#base64.b64decode) instead of [`base64.encodebytes()`](https://docs.python.org/3/library/base64.html#base64.encodebytes) and [`base64.decodebytes()`](https://docs.python.org/3/library/base64.html#base64.decodebytes). These methods are considered legacy implementation. See the documentation about the [`Base64Bytes`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Base64Bytes) type for more information on how to replicate the old behavior with the legacy encoders/decoders. ```python from pydantic import Base64Str, BaseModel, ValidationError class Model(BaseModel): base64_str: Base64Str # Initialize the model with base64 data m = Model(base64_str='VGhlc2UgYXJlbid0IHRoZSBkcm9pZHMgeW91J3JlIGxvb2tpbmcgZm9y') # Access decoded value print(m.base64_str) #> These aren't the droids you're looking for # Serialize into the base64 form print(m.model_dump()) #> {'base64_str': 'VGhlc2UgYXJlbid0IHRoZSBkcm9pZHMgeW91J3JlIGxvb2tpbmcgZm9y'} # Validate base64 data try: print(Model(base64_str='undecodable').base64_str) except ValidationError as e: print(e) ''' 1 validation error for Model base64_str Base64 decoding error: 'Incorrect padding' [type=base64_decode, input_value='undecodable', input_type=str] ''' ``` **Default:** `Annotated[str, EncodedStr(encoder=Base64Encoder)]` ## Base64UrlBytes A bytes type that is encoded and decoded using the URL-safe base64 encoder. ```python from pydantic import Base64UrlBytes, BaseModel class Model(BaseModel): base64url_bytes: Base64UrlBytes # Initialize the model with base64 data m = Model(base64url_bytes=b'SHc_dHc-TXc==') print(m) #> base64url_bytes=b'Hw?tw>Mw' ``` **Default:** `Annotated[bytes, EncodedBytes(encoder=Base64UrlEncoder)]` ## Base64UrlStr A str type that is encoded and decoded using the URL-safe base64 encoder. ```python from pydantic import Base64UrlStr, BaseModel class Model(BaseModel): base64url_str: Base64UrlStr # Initialize the model with base64 data m = Model(base64url_str='SHc_dHc-TXc==') print(m) #> base64url_str='Hw?tw>Mw' ``` **Default:** `Annotated[str, EncodedStr(encoder=Base64UrlEncoder)]` ## JsonValue A `JsonValue` is used to represent a value that can be serialized to JSON. It may be one of: - `list['JsonValue']` - `dict[str, 'JsonValue']` - `str` - `bool` - `int` - `float` - `None` The following example demonstrates how to use `JsonValue` to validate JSON data, and what kind of errors to expect when input data is not json serializable. ```python import json from pydantic import BaseModel, JsonValue, ValidationError class Model(BaseModel): j: JsonValue valid_json_data = {'j': {'a': {'b': {'c': 1, 'd': [2, None]}}}} invalid_json_data = {'j': {'a': {'b': ...}}} print(repr(Model.model_validate(valid_json_data))) #> Model(j={'a': {'b': {'c': 1, 'd': [2, None]}}}) print(repr(Model.model_validate_json(json.dumps(valid_json_data)))) #> Model(j={'a': {'b': {'c': 1, 'd': [2, None]}}}) try: Model.model_validate(invalid_json_data) except ValidationError as e: print(e) ''' 1 validation error for Model j.dict.a.dict.b input was not a valid JSON value [type=invalid-json-value, input_value=Ellipsis, input_type=ellipsis] ''' ``` **Type:** [`TypeAlias`](https://docs.python.org/3/library/typing.html#typing.TypeAlias) **Default:** `Union[list['JsonValue'], dict[str, 'JsonValue'], str, bool, int, float, None]` ## OnErrorOmit When used as an item in a list, the key type in a dict, optional values of a TypedDict, etc. this annotation omits the item from the iteration if there is any error validating it. That is, instead of a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) being propagated up and the entire iterable being discarded any invalid items are discarded and the valid ones are returned. **Default:** `Annotated[T, _OnErrorOmit]` --- # [Validate Call](https://pydantic.dev/docs/validation/latest/api/pydantic/validate_call/) # Validate Call Decorator for validating function calls. ## validate\_call ```python def validate_call( config: ConfigDict | None = None, validate_return: bool = False, ) -> Callable[[AnyCallableT], AnyCallableT] def validate_call(func: AnyCallableT) -> AnyCallableT ``` Usage Documentation [Validation Decorator](/docs/validation/latest/concepts/validation_decorator) Returns a decorated wrapper around the function that validates the arguments and, optionally, the return value. Usage may be either as a plain decorator `@validate_call` or with arguments `@validate_call(...)`. ### Returns `AnyCallableT` | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[`AnyCallableT`\], `AnyCallableT`\] -- The decorated function. ### Parameters **`func`** : `AnyCallableT` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The function to be decorated. **`config`** : [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The configuration dictionary. **`validate_return`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to validate the return value. --- # [Version Information](https://pydantic.dev/docs/validation/latest/api/pydantic/version/) # Version Information ## \_\_version\_\_ **Default:** `VERSION` ## version\_info ```python def version_info() -> str ``` Return complete version information for Pydantic and its dependencies. ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) --- # [pydantic_core](https://pydantic.dev/docs/validation/latest/api/pydantic-core/pydantic_core/) # pydantic\_core ## SchemaValidator `SchemaValidator` is the Python wrapper for `pydantic-core`'s Rust validation logic, internally it owns one `CombinedValidator` which may in turn own more `CombinedValidator`s which make up the full schema validator. ### Attributes #### title The title of the schema, as used in the heading of [`ValidationError.__str__()`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError). **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### validate\_python ```python def validate_python( input: Any, strict: bool | None = None, extra: ExtraBehavior | None = None, from_attributes: bool | None = None, context: Any | None = None, self_instance: Any | None = None, allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> Any ``` Validate a Python object against the schema and return the validated object. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The validated object. ##### Parameters **`input`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the object in strict mode. If `None`, the value of [`CoreConfig.strict`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`extra`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. If `None`, the value of [`CoreConfig.extra_fields_behavior`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate objects as inputs to models by extracting attributes. If `None`, the value of [`CoreConfig.from_attributes`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for validation, this is passed to functional validators as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context). **`self_instance`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` An instance of a model set attributes on from validation, this is used when running validation from the `__init__` method of a model. **`allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` Whether to allow partial validation; if `True` errors in the last element of sequences and mappings are ignored. `'trailing-strings'` means any final unfinished JSON string is included in the result. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If validation fails. - `Exception` -- Other error types maybe raised if internal errors occur. #### isinstance\_python ```python def isinstance_python( input: Any, strict: bool | None = None, extra: ExtraBehavior | None = None, from_attributes: bool | None = None, context: Any | None = None, self_instance: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None, ) -> bool ``` Similar to [`validate_python()`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaValidator.validate_python) but returns a boolean. Arguments match `validate_python()`. This method will not raise `ValidationError`s but will raise internal errors. ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- `True` if validation succeeds, `False` if validation fails. #### validate\_json ```python def validate_json( input: str | bytes | bytearray, strict: bool | None = None, extra: ExtraBehavior | None = None, context: Any | None = None, self_instance: Any | None = None, allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> Any ``` Validate JSON data directly against the schema and return the validated Python object. This method should be significantly faster than `validate_python(json.loads(json_data))` as it avoids the need to create intermediate Python objects It also handles constructing the correct Python type even in strict mode, where `validate_python(json.loads(json_data))` would fail validation. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The validated Python object. ##### Parameters **`input`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) | [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) The JSON data to validate. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the object in strict mode. If `None`, the value of [`CoreConfig.strict`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`extra`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. If `None`, the value of [`CoreConfig.extra_fields_behavior`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for validation, this is passed to functional validators as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context). **`self_instance`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` An instance of a model set attributes on from validation. **`allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` Whether to allow partial validation; if `True` incomplete JSON will be parsed successfully and errors in the last element of sequences and mappings are ignored. `'trailing-strings'` means any final unfinished JSON string is included in the result. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If validation fails or if the JSON data is invalid. - `Exception` -- Other error types maybe raised if internal errors occur. #### validate\_strings ```python def validate_strings( input: _StringInput, strict: bool | None = None, extra: ExtraBehavior | None = None, context: Any | None = None, allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, by_alias: bool | None = None, by_name: bool | None = None, ) -> Any ``` Validate a string against the schema and return the validated Python object. This is similar to `validate_json` but applies to scenarios where the input will be a string but not JSON data, e.g. URL fragments, query parameters, etc. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The validated Python object. ##### Parameters **`input`** : `_StringInput` The input as a string, or bytes/bytearray if `strict=False`. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the object in strict mode. If `None`, the value of [`CoreConfig.strict`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`extra`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. If `None`, the value of [`CoreConfig.extra_fields_behavior`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for validation, this is passed to functional validators as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context). **`allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` Whether to allow partial validation; if `True` errors in the last element of sequences and mappings are ignored. `'trailing-strings'` means any final unfinished JSON string is included in the result. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If validation fails or if the JSON data is invalid. - `Exception` -- Other error types maybe raised if internal errors occur. #### validate\_assignment ```python def validate_assignment( obj: Any, field_name: str, field_value: Any, strict: bool | None = None, extra: ExtraBehavior | None = None, from_attributes: bool | None = None, context: Any | None = None, by_alias: bool | None = None, by_name: bool | None = None, ) -> dict[str, Any] | tuple[dict[str, Any], dict[str, Any] | None, set[str]] ``` Validate an assignment to a field on a model. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None), [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\]\] -- Either the model dict or a tuple of `(model_data, model_extra, fields_set)` ##### Parameters **`obj`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The model instance being assigned to. **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name of the field to validate assignment for. **`field_value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The value to assign to the field. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the object in strict mode. If `None`, the value of [`CoreConfig.strict`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`extra`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore, allow, or forbid extra data during model validation. If `None`, the value of [`CoreConfig.extra_fields_behavior`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate objects as inputs to models by extracting attributes. If `None`, the value of [`CoreConfig.from_attributes`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for validation, this is passed to functional validators as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context). **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's alias when validating against the provided input data. **`by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the field's name when validating against the provided input data. ##### Raises - `ValidationError` -- If validation fails. - `Exception` -- Other error types maybe raised if internal errors occur. #### get\_default\_value ```python def get_default_value(strict: bool | None = None, context: Any = None) -> Some | None ``` Get the default value for the schema, including running default value validation. ##### Returns `Some` | [`None`](https://docs.python.org/3/library/constants.html#None) -- `None` if the schema has no default value, otherwise a [`Some`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.Some) containing the default. ##### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to validate the default value in strict mode. If `None`, the value of [`CoreConfig.strict`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.CoreConfig) is used. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `None` The context to use for validation, this is passed to functional validators as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context). ##### Raises - `ValidationError` -- If validation fails. - `Exception` -- Other error types maybe raised if internal errors occur. ## SchemaSerializer `SchemaSerializer` is the Python wrapper for `pydantic-core`'s Rust serialization logic, internally it owns one `CombinedSerializer` which may in turn own more `CombinedSerializer`s which make up the full schema serializer. ### Methods #### to\_python ```python def to_python( value: Any, mode: str | None = None, include: _IncEx | None = None, exclude: _IncEx | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> Any ``` Serialize/marshal a Python object to a Python object including transforming and filtering data. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The serialized Python object. ##### Parameters **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to serialize. **`mode`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The serialization mode to use, either `'python'` or `'json'`, defaults to `'python'`. In JSON mode, all values are converted to JSON compatible types, e.g. `None`, `int`, `float`, `str`, `list`, `dict`. **`include`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to include, if `None` all fields are included. **`exclude`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to exclude, if `None` no fields are excluded. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the alias names of fields. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are not set, e.g. are not included in `__pydantic_fields_set__`. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are equal to their default value. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to enable serialization and validation round-trip support. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle invalid fields. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered, if `None` a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for serialization, this is passed to functional serializers as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.context). ##### Raises - `PydanticSerializationError` -- If serialization fails and no `fallback` function is provided. #### to\_json ```python def to_json( value: Any, indent: int | None = None, ensure_ascii: bool = False, include: _IncEx | None = None, exclude: _IncEx | None = None, by_alias: bool | None = None, exclude_unset: bool = False, exclude_defaults: bool = False, exclude_none: bool = False, exclude_computed_fields: bool = False, round_trip: bool = False, warnings: bool | Literal['none', 'warn', 'error'] = True, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> bytes ``` Serialize a Python object to JSON including transforming and filtering data. ##### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- JSON bytes. ##### Parameters **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to serialize. **`indent`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` If `None`, the JSON will be compact, otherwise it will be pretty-printed with the indent provided. **`ensure_ascii`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. If `False` (the default), these characters will be output as-is. **`include`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to include, if `None` all fields are included. **`exclude`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to exclude, if `None` no fields are excluded. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the alias names of fields. **`exclude_unset`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are not set, e.g. are not included in `__pydantic_fields_set__`. **`exclude_defaults`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that are equal to their default value. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`exclude_computed_fields`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude computed fields. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to enable serialization and validation round-trip support. **`warnings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['none', 'warn', 'error'\] _Default:_ `True` How to handle invalid fields. False/"none" ignores them, True/"warn" logs errors, "error" raises a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError). **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered, if `None` a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for serialization, this is passed to functional serializers as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.context). ##### Raises - `PydanticSerializationError` -- If serialization fails and no `fallback` function is provided. ## ValidationError **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) `ValidationError` is the exception raised by `pydantic-core` when validation fails, it contains a list of errors which detail why validation failed. ### Attributes #### title The title of the error, as used in the heading of `str(validation_error)`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### from\_exception\_data `@classmethod` ```python def from_exception_data( cls, title: str, line_errors: list[InitErrorDetails], input_type: Literal['python', 'json'] = 'python', hide_input: bool = False, ) -> Self ``` Python constructor for a Validation Error. ##### Returns [`Self`](https://docs.python.org/3/library/typing.html#typing.Self) ##### Parameters **`title`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The title of the error, as used in the heading of `str(validation_error)` **`line_errors`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`InitErrorDetails`\] A list of [`InitErrorDetails`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.InitErrorDetails) which contain information about errors that occurred during validation. **`input_type`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['python', 'json'\] _Default:_ `'python'` Whether the error is for a Python object or JSON. **`hide_input`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to hide the input value in the error message. #### error\_count ```python def error_count() -> int ``` ##### Returns [`int`](https://docs.python.org/3/library/functions.html#int) -- The number of errors in the validation error. #### errors ```python def errors( include_url: bool = True, include_context: bool = True, include_input: bool = True, ) -> list[ErrorDetails] ``` Details about each error in the validation error. ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ErrorDetails`\] -- A list of [`ErrorDetails`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ErrorDetails) for each error in the validation error. ##### Parameters **`include_url`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include a URL to documentation on the error each error. **`include_context`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include the context of each error. **`include_input`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include the input value of each error. #### json ```python def json( indent: int | None = None, include_url: bool = True, include_context: bool = True, include_input: bool = True, ) -> str ``` Same as [`errors()`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError.errors) but returns a JSON string. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- a JSON string. ##### Parameters **`indent`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The number of spaces to indent the JSON by, or `None` for no indentation - compact JSON. **`include_url`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include a URL to documentation on the error each error. **`include_context`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include the context of each error. **`include_input`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to include the input value of each error. ## ErrorDetails **Bases:** `_TypedDict` ### Attributes #### type The type of error that occurred, this is an identifier designed for programmatic use that will change rarely or never. `type` is unique for each error message, and can hence be used as an identifier to build custom error messages. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### loc Tuple of strings and ints identifying where in the schema the error occurred. **Type:** [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str), ...\] #### msg A human readable error message. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### input The input data at this `loc` that caused the error. **Type:** `_Any` #### ctx Values which are required to render the error message, and could hence be useful in rendering custom error messages. Also useful for passing custom error data forward. **Type:** `_NotRequired`\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `_Any`\]\] #### url The documentation URL giving information about the error. No URL is available if a [`PydanticCustomError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticCustomError) is used. **Type:** `_NotRequired`\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] ## InitErrorDetails **Bases:** `_TypedDict` ### Attributes #### type The type of error that occurred, this should be a "slug" identifier that changes rarely or never. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | `PydanticCustomError` #### loc Tuple of strings and ints identifying where in the schema the error occurred. **Type:** `_NotRequired`\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str), ...\]\] #### input The input data at this `loc` that caused the error. **Type:** `_Any` #### ctx Values which are required to render the error message, and could hence be useful in rendering custom error messages. Also useful for passing custom error data forward. **Type:** `_NotRequired`\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `_Any`\]\] ## SchemaError **Bases:** [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception) Information about errors that occur while building a [`SchemaValidator`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaValidator) or [`SchemaSerializer`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaSerializer). ### Methods #### error\_count ```python def error_count() -> int ``` ##### Returns [`int`](https://docs.python.org/3/library/functions.html#int) -- The number of errors in the schema. #### errors ```python def errors() -> list[ErrorDetails] ``` ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ErrorDetails`\] -- A list of [`ErrorDetails`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ErrorDetails) for each error in the schema. ## PydanticCustomError **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) A custom exception providing flexible error handling for Pydantic validators. You can raise this error in custom validators when you'd like flexibility in regards to the error type, message, and context. ### Constructor Parameters **`error_type`** : [`LiteralString`](https://docs.python.org/3/library/typing.html#typing.LiteralString) The error type. **`message_template`** : [`LiteralString`](https://docs.python.org/3/library/typing.html#typing.LiteralString) The message template. **`context`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The data to inject into the message template. ### Attributes #### context Values which are required to render the error message, and could hence be useful in passing error data forward. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### type The error type associated with the error. For consistency with Pydantic, this is typically a snake\_case string. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### message\_template The message template associated with the error. This is a string that can be formatted with context variables in `{curly_braces}`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### message ```python def message() -> str ``` The formatted message associated with the error. This presents as the message template with context variables appropriately injected. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## PydanticKnownError **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) A helper class for raising exceptions that mimic Pydantic's built-in exceptions, with more flexibility in regards to context. Unlike [`PydanticCustomError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticCustomError), the `error_type` argument must be a known `ErrorType`. ### Constructor Parameters **`error_type`** : `ErrorType` The error type. **`context`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The data to inject into the message template. ### Attributes #### context Values which are required to render the error message, and could hence be useful in passing error data forward. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) #### type The type of the error. **Type:** `ErrorType` #### message\_template The message template associated with the provided error type. This is a string that can be formatted with context variables in `{curly_braces}`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### message ```python def message() -> str ``` The formatted message associated with the error. This presents as the message template with context variables appropriately injected. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## PydanticOmit **Bases:** [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception) An exception to signal that a field should be omitted from a generated result. This could span from omitting a field from a JSON Schema to omitting a field from a serialized result. Upcoming: more robust support for using PydanticOmit in custom serializers is still in development. Right now, this is primarily used in the JSON Schema generation process. For a more in depth example / explanation, see the [customizing JSON schema](/docs/validation/latest/concepts/json_schema#customizing-the-json-schema-generation-process) docs. ## PydanticUseDefault **Bases:** [`Exception`](https://docs.python.org/3/library/exceptions.html#Exception) An exception to signal that standard validation either failed or should be skipped, and the default value should be used instead. This warning can be raised in custom validation functions to redirect the flow of validation. For an additional example, see the [validating partial json data](/docs/validation/latest/concepts/json#partial-json-parsing) section of the Pydantic documentation. ## PydanticSerializationError **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) An error raised when an issue occurs during serialization. In custom serializers, this error can be used to indicate that serialization has failed. ### Constructor Parameters **`message`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The message associated with the error. ## PydanticSerializationUnexpectedValue **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) An error raised when an unexpected value is encountered during serialization. This error is often caught and coerced into a warning, as `pydantic-core` generally makes a best attempt at serializing values, in contrast with validation where errors are eagerly raised. This is often used internally in `pydantic-core` when unexpected types are encountered during serialization, but it can also be used by users in custom serializers, as seen above. ### Constructor Parameters **`message`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The message associated with the unexpected value. ## Url **Bases:** `SupportsAllComparisons` A URL type, internal logic uses the [url rust crate](https://docs.rs/url/latest/url/) originally developed by Mozilla. ## MultiHostUrl **Bases:** `SupportsAllComparisons` A URL type with support for multiple hosts, as used by some databases for DSNs, e.g. `https://foo.com,bar.com/path`. Internal URL logic uses the [url rust crate](https://docs.rs/url/latest/url/) originally developed by Mozilla. ## MultiHostHost **Bases:** `_TypedDict` A host part of a multi-host URL. ### Attributes #### username The username part of this host, or `None`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### password The password part of this host, or `None`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### host The host part of this host, or `None`. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### port The port part of this host, or `None`. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) ## ArgsKwargs A construct used to store arguments and keyword arguments for a function call. This data structure is generally used to store information for core schemas associated with functions (like in an arguments schema). This data structure is also currently used for some validation against dataclasses. ### Attributes #### args The arguments (inherently ordered) for a function call. **Type:** [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), ...\] #### kwargs The keyword arguments for a function call. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) ## Some **Bases:** `Generic[_T]` Similar to Rust's [`Option::Some`](https://doc.rust-lang.org/std/option/enum.Option.html) type, this identifies a value as being present, and provides a way to access it. Generally used in a union with `None` to different between "some value which could be None" and no value. ### Attributes #### value Returns the value wrapped by `Some`. **Type:** `_T` ## TzInfo **Bases:** [`tzinfo`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo) An `pydantic-core` implementation of the abstract [`datetime.tzinfo`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo) class. ### Methods #### tzname ```python def tzname(dt: datetime.datetime | None) -> str | None ``` Return the time zone name corresponding to the [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object _dt_, as a string. For more info, see [`tzinfo.tzname`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo.tzname). ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### utcoffset ```python def utcoffset(dt: datetime.datetime | None) -> datetime.timedelta | None ``` Return offset of local time from UTC, as a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) object that is positive east of UTC. If local time is west of UTC, this should be negative. More info can be found at [`tzinfo.utcoffset`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo.utcoffset). ##### Returns [`datetime.timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) | [`None`](https://docs.python.org/3/library/constants.html#None) #### dst ```python def dst(dt: datetime.datetime | None) -> datetime.timedelta | None ``` Return the daylight saving time (DST) adjustment, as a [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) object or `None` if DST information isn't known. More info can be found at[`tzinfo.dst`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo.dst). ##### Returns [`datetime.timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta) | [`None`](https://docs.python.org/3/library/constants.html#None) #### fromutc ```python def fromutc(dt: datetime.datetime) -> datetime.datetime ``` Adjust the date and time data associated datetime object _dt_, returning an equivalent datetime in self's local time. More info can be found at [`tzinfo.fromutc`](https://docs.python.org/3/library/datetime.html#datetime.tzinfo.fromutc). ##### Returns [`datetime.datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) ## ErrorTypeInfo **Bases:** `_TypedDict` Gives information about errors. ### Attributes #### type The type of error that occurred, this should be a "slug" identifier that changes rarely or never. **Type:** `ErrorType` #### message\_template\_python String template to render a human readable error message from using context, when the input is Python. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### example\_message\_python Example of a human readable error message, when the input is Python. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### message\_template\_json String template to render a human readable error message from using context, when the input is JSON data. **Type:** `_NotRequired`\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] #### example\_message\_json Example of a human readable error message, when the input is JSON data. **Type:** `_NotRequired`\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] #### example\_context Example of context values. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `_Any`\] | [`None`](https://docs.python.org/3/library/constants.html#None) ## to\_json ```python def to_json( value: Any, indent: int | None = None, ensure_ascii: bool = False, include: _IncEx | None = None, exclude: _IncEx | None = None, by_alias: bool = True, exclude_none: bool = False, round_trip: bool = False, timedelta_mode: Literal['iso8601', 'float'] = 'iso8601', temporal_mode: Literal['iso8601', 'seconds', 'milliseconds'] = 'iso8601', bytes_mode: Literal['utf8', 'base64', 'hex'] = 'utf8', inf_nan_mode: Literal['null', 'constants', 'strings'] = 'constants', serialize_unknown: bool = False, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> bytes ``` Serialize a Python object to JSON including transforming and filtering data. This is effectively a standalone version of [`SchemaSerializer.to_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaSerializer.to_json). ### Returns [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) -- JSON bytes. ### Parameters **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to serialize. **`indent`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` If `None`, the JSON will be compact, otherwise it will be pretty-printed with the indent provided. **`ensure_ascii`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. If `False` (the default), these characters will be output as-is. **`include`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to include, if `None` all fields are included. **`exclude`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to exclude, if `None` no fields are excluded. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use the alias names of fields. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to enable serialization and validation round-trip support. **`timedelta_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'float'\] _Default:_ `'iso8601'` How to serialize `timedelta` objects, either `'iso8601'` or `'float'`. **`temporal_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'seconds', 'milliseconds'\] _Default:_ `'iso8601'` How to serialize datetime-like objects (`datetime`, `date`, `time`), either `'iso8601'`, `'seconds'`, or `'milliseconds'`. `iso8601` returns an ISO 8601 string; `seconds` returns the Unix timestamp in seconds as a float; `milliseconds` returns the Unix timestamp in milliseconds as a float. **`bytes_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] _Default:_ `'utf8'` How to serialize `bytes` objects, either `'utf8'`, `'base64'`, or `'hex'`. **`inf_nan_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['null', 'constants', 'strings'\] _Default:_ `'constants'` How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'`, `'constants'`, or `'strings'`. **`serialize_unknown`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Attempt to serialize unknown types, `str(value)` will be used, if that fails `""` will be used. **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered, if `None` a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for serialization, this is passed to functional serializers as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.context). ### Raises - `PydanticSerializationError` -- If serialization fails and no `fallback` function is provided. ## from\_json ```python def from_json( data: str | bytes | bytearray, allow_inf_nan: bool = True, cache_strings: bool | Literal['all', 'keys', 'none'] = True, allow_partial: bool | Literal['off', 'on', 'trailing-strings'] = False, ) -> Any ``` Deserialize JSON data to a Python object. This is effectively a faster version of `json.loads()`, with some extra functionality. ### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The deserialized Python object. ### Parameters **`data`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) | [`bytearray`](https://docs.python.org/3/library/stdtypes.html#bytearray) The JSON data to deserialize. **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to allow `Infinity`, `-Infinity` and `NaN` values as `json.loads()` does by default. **`cache_strings`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['all', 'keys', 'none'\] _Default:_ `True` Whether to cache strings to avoid constructing new Python objects, this should have a significant impact on performance while increasing memory usage slightly, `all/True` means cache all strings, `keys` means cache only dict keys, `none/False` means no caching. **`allow_partial`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['off', 'on', 'trailing-strings'\] _Default:_ `False` Whether to allow partial deserialization, if `True` JSON data is returned if the end of the input is reached before the full object is deserialized, e.g. `["aa", "bb", "c` would return `['aa', 'bb']`. `'trailing-strings'` means any final unfinished JSON string is included in the result. ### Raises - `ValueError` -- If deserialization fails. ## to\_jsonable\_python ```python def to_jsonable_python( value: Any, include: _IncEx | None = None, exclude: _IncEx | None = None, by_alias: bool = True, exclude_none: bool = False, round_trip: bool = False, timedelta_mode: Literal['iso8601', 'float'] = 'iso8601', temporal_mode: Literal['iso8601', 'seconds', 'milliseconds'] = 'iso8601', bytes_mode: Literal['utf8', 'base64', 'hex'] = 'utf8', inf_nan_mode: Literal['null', 'constants', 'strings'] = 'constants', serialize_unknown: bool = False, fallback: Callable[[Any], Any] | None = None, serialize_as_any: bool = False, polymorphic_serialization: bool | None = None, context: Any | None = None, ) -> Any ``` Serialize/marshal a Python object to a JSON-serializable Python object including transforming and filtering data. This is effectively a standalone version of [`SchemaSerializer.to_python(mode='json')`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaSerializer.to_python). ### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The serialized Python object. ### Parameters **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The Python object to serialize. **`include`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to include, if `None` all fields are included. **`exclude`** : `_IncEx` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A set of fields to exclude, if `None` no fields are excluded. **`by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Whether to use the alias names of fields. **`exclude_none`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to exclude fields that have a value of `None`. **`round_trip`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to enable serialization and validation round-trip support. **`timedelta_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'float'\] _Default:_ `'iso8601'` How to serialize `timedelta` objects, either `'iso8601'` or `'float'`. **`temporal_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'seconds', 'milliseconds'\] _Default:_ `'iso8601'` How to serialize datetime-like objects (`datetime`, `date`, `time`), either `'iso8601'`, `'seconds'`, or `'milliseconds'`. `iso8601` returns an ISO 8601 string; `seconds` returns the Unix timestamp in seconds as a float; `milliseconds` returns the Unix timestamp in milliseconds as a float. **`bytes_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] _Default:_ `'utf8'` How to serialize `bytes` objects, either `'utf8'`, `'base64'`, or `'hex'`. **`inf_nan_mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['null', 'constants', 'strings'\] _Default:_ `'constants'` How to serialize `Infinity`, `-Infinity` and `NaN` values, either `'null'`, `'constants'`, or `'strings'`. **`serialize_unknown`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Attempt to serialize unknown types, `str(value)` will be used, if that fails `""` will be used. **`fallback`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to call when an unknown value is encountered, if `None` a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) error is raised. **`serialize_as_any`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Whether to serialize fields with duck-typing serialization behavior. **`polymorphic_serialization`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use model and dataclass polymorphic serialization for this call. **`context`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The context to use for serialization, this is passed to functional serializers as [`info.context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.context). ### Raises - `PydanticSerializationError` -- If serialization fails and no `fallback` function is provided. ## \_\_version\_\_ **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) --- # [pydantic_core.core_schema](https://pydantic.dev/docs/validation/latest/api/pydantic-core/pydantic_core_schema/) # pydantic\_core.core\_schema This module contains definitions to build schemas which `pydantic_core` can validate and serialize. ## CoreConfig **Bases:** [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) Base class for schema configuration options. ### Attributes #### title The name of the configuration. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### strict Whether the configuration should strictly adhere to specified rules. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### extra\_fields\_behavior The behavior for handling extra fields. **Type:** `ExtraBehavior` #### typed\_dict\_total Whether the TypedDict should be considered total. Default is `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### from\_attributes Whether to use attributes for models, dataclasses, and tagged union keys. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### loc\_by\_alias Whether to use the used alias (or first alias for "field required" errors) instead of `field_names` to construct error `loc`s. Default is `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### revalidate\_instances Whether instances of models and dataclasses should re-validate. Default is 'never'. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['always', 'never', 'subclass-instances'\] #### validate\_default Whether to validate default values during validation. Default is `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_max\_length The maximum length for string fields. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) #### str\_min\_length The minimum length for string fields. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) #### str\_strip\_whitespace Whether to strip whitespace from string fields. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_to\_lower Whether to convert string fields to lowercase. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### str\_to\_upper Whether to convert string fields to uppercase. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### allow\_inf\_nan Whether to allow infinity and NaN values for float fields. Default is `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### ser\_json\_timedelta The serialization option for `timedelta` values. Default is 'iso8601'. Note that if ser\_json\_temporal is set, then this param will be ignored. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'float'\] #### ser\_json\_temporal The serialization option for datetime like values. Default is 'iso8601'. The types this covers are datetime, date, time and timedelta. If this is set, it will take precedence over ser\_json\_timedelta **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['iso8601', 'seconds', 'milliseconds'\] #### ser\_json\_bytes The serialization option for `bytes` values. Default is 'utf8'. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] #### ser\_json\_inf\_nan The serialization option for infinity and NaN values in float fields. Default is 'null'. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['null', 'constants', 'strings'\] #### val\_json\_bytes The validation option for `bytes` values, complementing ser\_json\_bytes. Default is 'utf8'. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['utf8', 'base64', 'hex'\] #### hide\_input\_in\_errors Whether to hide input data from `ValidationError` representation. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### validation\_error\_cause Whether to add user-python excs to the **cause** of a ValidationError. Requires exceptiongroup backport pre Python 3.11. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### coerce\_numbers\_to\_str Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode). **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### regex\_engine The regex engine to use for regex pattern validation. Default is 'rust-regex'. See `StringSchema`. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['rust-regex', 'python-re'\] #### cache\_strings Whether to cache strings. Default is `True`, `True` or `'all'` is required to cache strings during general validation since validators don't know if they're in a key or a value. **Type:** [`Union`](https://docs.python.org/3/library/typing.html#typing.Union)\[[`bool`](https://docs.python.org/3/library/functions.html#bool), [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['all', 'keys', 'none'\]\] #### validate\_by\_alias Whether to use the field's alias when validating against the provided input data. Default is `True`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### validate\_by\_name Whether to use the field's name when validating against the provided input data. Default is `False`. Replacement for `populate_by_name`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### serialize\_by\_alias Whether to serialize by alias. Default is `False`, expected to change to `True` in V3. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### polymorphic\_serialization Whether to enable polymorphic serialization for models and dataclasses. Default is `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### url\_preserve\_empty\_path Whether to preserve empty URL paths when validating values for a URL type. Defaults to `False`. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ## SerializationInfo **Bases:** `Protocol[ContextT]` Extra data used during serialization. ### Attributes #### include The `include` argument set during serialization. **Type:** `IncExCall` #### exclude The `exclude` argument set during serialization. **Type:** `IncExCall` #### context The current serialization context. **Type:** `ContextT` #### mode The serialization mode set during serialization. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['python', 'json'\] | [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### by\_alias The `by_alias` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### exclude\_unset The `exclude_unset` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### exclude\_defaults The `exclude_defaults` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### exclude\_none The `exclude_none` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### exclude\_computed\_fields The `exclude_computed_fields` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### serialize\_as\_any The `serialize_as_any` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) #### polymorphic\_serialization The `polymorphic_serialization` argument set during serialization, if any. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) #### round\_trip The `round_trip` argument set during serialization. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) ## FieldSerializationInfo **Bases:** `SerializationInfo[ContextT]`, [`Protocol`](https://docs.python.org/3/library/typing.html#typing.Protocol) Extra data used during field serialization. ### Attributes #### field\_name The name of the current field being serialized. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## ValidationInfo **Bases:** `Protocol[ContextT]` Extra data used during validation. ### Attributes #### context The current validation context. **Type:** `ContextT` #### config The CoreConfig that applies to this validation. **Type:** `CoreConfig` | [`None`](https://docs.python.org/3/library/constants.html#None) #### mode The type of input data we are currently validating. **Type:** [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['python', 'json'\] #### data The data being validated for this model. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] #### field\_name The name of the current field being validated if this validator is attached to a model field. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) ## simple\_ser\_schema ```python def simple_ser_schema(type: ExpectedSerializationTypes) -> SimpleSerSchema ``` Returns a schema for serialization with a custom type. ### Returns `SimpleSerSchema` ### Parameters **`type`** : `ExpectedSerializationTypes` The type to use for serialization ## plain\_serializer\_function\_ser\_schema ```python def plain_serializer_function_ser_schema( function: SerializerFunction, is_field_serializer: bool | None = None, info_arg: bool | None = None, return_schema: CoreSchema | None = None, when_used: WhenUsed = 'always', ) -> PlainSerializerFunctionSerSchema ``` Returns a schema for serialization with a function, can be either a "general" or "field" function. ### Returns `PlainSerializerFunctionSerSchema` ### Parameters **`function`** : `SerializerFunction` The function to use for serialization **`is_field_serializer`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the serializer is for a field, e.g. takes `model` as the first argument, and `info` includes `field_name` **`info_arg`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the function takes an `info` argument **`return_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Schema to use for serializing return value **`when_used`** : `WhenUsed` _Default:_ `'always'` When the function should be called ## wrap\_serializer\_function\_ser\_schema ```python def wrap_serializer_function_ser_schema( function: WrapSerializerFunction, is_field_serializer: bool | None = None, info_arg: bool | None = None, schema: CoreSchema | None = None, return_schema: CoreSchema | None = None, when_used: WhenUsed = 'always', ) -> WrapSerializerFunctionSerSchema ``` Returns a schema for serialization with a wrap function, can be either a "general" or "field" function. ### Returns `WrapSerializerFunctionSerSchema` ### Parameters **`function`** : `WrapSerializerFunction` The function to use for serialization **`is_field_serializer`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the serializer is for a field, e.g. takes `model` as the first argument, and `info` includes `field_name` **`info_arg`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the function takes an `info` argument **`schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The schema to use for the inner serialization **`return_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Schema to use for serializing return value **`when_used`** : `WhenUsed` _Default:_ `'always'` When the function should be called ## format\_ser\_schema ```python def format_ser_schema( formatting_string: str, when_used: WhenUsed = 'json-unless-none', ) -> FormatSerSchema ``` Returns a schema for serialization using python's `format` method. ### Returns `FormatSerSchema` ### Parameters **`formatting_string`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) String defining the format to use **`when_used`** : `WhenUsed` _Default:_ `'json-unless-none'` Same meaning as for \[general\_function\_plain\_ser\_schema\], but with a different default ## to\_string\_ser\_schema ```python def to_string_ser_schema(when_used: WhenUsed = 'json-unless-none') -> ToStringSerSchema ``` Returns a schema for serialization using python's `str()` / `__str__` method. ### Returns `ToStringSerSchema` ### Parameters **`when_used`** : `WhenUsed` _Default:_ `'json-unless-none'` Same meaning as for \[general\_function\_plain\_ser\_schema\], but with a different default ## model\_ser\_schema ```python def model_ser_schema(cls: type[Any], schema: CoreSchema) -> ModelSerSchema ``` Returns a schema for serialization using a model. ### Returns `ModelSerSchema` ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The expected class type, used to generate warnings if the wrong type is passed **`schema`** : `CoreSchema` Internal schema to use to serialize the model dict ## invalid\_schema ```python def invalid_schema( ref: str | None = None, metadata: dict[str, Any] | None = None, ) -> InvalidSchema ``` Returns an invalid schema, used to indicate that a schema is invalid. ### Returns `InvalidSchema` ### Parameters **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core ## computed\_field ```python def computed_field( property_name: str, return_schema: CoreSchema, alias: str | None = None, serialization_exclude_if: Callable[[Any], bool] | None = None, metadata: dict[str, Any] | None = None, ) -> ComputedField ``` ComputedFields are properties of a model or dataclass that are included in serialization. ### Returns `ComputedField` ### Parameters **`property_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name of the property on the model or dataclass **`return_schema`** : `CoreSchema` The schema used for the type returned by the computed field **`alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name to use in the serialized output **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core ## any\_schema ```python def any_schema( ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> AnySchema ``` Returns a schema that matches any value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.any_schema() v = SchemaValidator(schema) assert v.validate_python(1) == 1 ``` ### Returns `AnySchema` ### Parameters **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## none\_schema ```python def none_schema( ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> NoneSchema ``` Returns a schema that matches a None value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.none_schema() v = SchemaValidator(schema) assert v.validate_python(None) is None ``` ### Returns `NoneSchema` ### Parameters **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## bool\_schema ```python def bool_schema( strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> BoolSchema ``` Returns a schema that matches a bool value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.bool_schema() v = SchemaValidator(schema) assert v.validate_python('True') is True ``` ### Returns `BoolSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a bool or a value that can be converted to a bool **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## int\_schema ```python def int_schema( multiple_of: int | None = None, le: int | None = None, ge: int | None = None, lt: int | None = None, gt: int | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> IntSchema ``` Returns a schema that matches a int value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.int_schema(multiple_of=2, le=6, ge=2) v = SchemaValidator(schema) assert v.validate_python('4') == 4 ``` ### Returns `IntSchema` ### Parameters **`multiple_of`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this number **`le`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this number **`ge`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this number **`lt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this number **`gt`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this number **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a int or a value that can be converted to a int **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## float\_schema ```python def float_schema( allow_inf_nan: bool | None = None, multiple_of: float | None = None, le: float | None = None, ge: float | None = None, lt: float | None = None, gt: float | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> FloatSchema ``` Returns a schema that matches a float value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.float_schema(le=0.8, ge=0.2) v = SchemaValidator(schema) assert v.validate_python('0.5') == 0.5 ``` ### Returns `FloatSchema` ### Parameters **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to allow inf and nan values **`multiple_of`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this number **`le`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this number **`ge`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this number **`lt`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this number **`gt`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this number **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a float or a value that can be converted to a float **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## decimal\_schema ```python def decimal_schema( allow_inf_nan: bool | None = None, multiple_of: Decimal | None = None, le: Decimal | None = None, ge: Decimal | None = None, lt: Decimal | None = None, gt: Decimal | None = None, max_digits: int | None = None, decimal_places: int | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> DecimalSchema ``` Returns a schema that matches a decimal value, e.g.: ```py from decimal import Decimal from pydantic_core import SchemaValidator, core_schema schema = core_schema.decimal_schema(le=0.8, ge=0.2) v = SchemaValidator(schema) assert v.validate_python('0.5') == Decimal('0.5') ``` ### Returns `DecimalSchema` ### Parameters **`allow_inf_nan`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to allow inf and nan values **`multiple_of`** : `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a multiple of this number **`le`** : `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this number **`ge`** : `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this number **`lt`** : `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this number **`gt`** : `Decimal` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this number **`max_digits`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum number of decimal digits allowed **`decimal_places`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum number of decimal places allowed **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a float or a value that can be converted to a float **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## complex\_schema ```python def complex_schema( strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ComplexSchema ``` Returns a schema that matches a complex value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.complex_schema() v = SchemaValidator(schema) assert v.validate_python('1+2j') == complex(1, 2) assert v.validate_python(complex(1, 2)) == complex(1, 2) ``` ### Returns `ComplexSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a complex object instance or a value that can be converted to a complex object **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## str\_schema ```python def str_schema( pattern: str | Pattern[str] | None = None, max_length: int | None = None, min_length: int | None = None, strip_whitespace: bool | None = None, to_lower: bool | None = None, to_upper: bool | None = None, regex_engine: Literal['rust-regex', 'python-re'] | None = None, strict: bool | None = None, coerce_numbers_to_str: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> StringSchema ``` Returns a schema that matches a string value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.str_schema(max_length=10, min_length=2) v = SchemaValidator(schema) assert v.validate_python('hello') == 'hello' ``` ### Returns `StringSchema` ### Parameters **`pattern`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`Pattern`](https://docs.python.org/3/library/typing.html#typing.Pattern)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A regex pattern that the value must match **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be at most this length **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be at least this length **`strip_whitespace`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to strip whitespace from the value **`to_lower`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to convert the value to lowercase **`to_upper`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to convert the value to uppercase **`regex_engine`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['rust-regex', 'python-re'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The regex engine to use for pattern validation. Default is 'rust-regex'. - `rust-regex` uses the [`regex`](https://docs.rs/regex) Rust crate, which is non-backtracking and therefore more DDoS resistant, but does not support all regex features. - `python-re` use the [`re`](https://docs.python.org/3/library/re.html) module, which supports all regex features, but may be slower. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a string or a value that can be converted to a string **`coerce_numbers_to_str`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to enable coercion of any `Number` type to `str` (not applicable in `strict` mode). **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## bytes\_schema ```python def bytes_schema( max_length: int | None = None, min_length: int | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> BytesSchema ``` Returns a schema that matches a bytes value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.bytes_schema(max_length=10, min_length=2) v = SchemaValidator(schema) assert v.validate_python(b'hello') == b'hello' ``` ### Returns `BytesSchema` ### Parameters **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be at most this length **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be at least this length **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a bytes or a value that can be converted to a bytes **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## date\_schema ```python def date_schema( strict: bool | None = None, le: date | None = None, ge: date | None = None, lt: date | None = None, gt: date | None = None, now_op: Literal['past', 'future'] | None = None, now_utc_offset: int | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> DateSchema ``` Returns a schema that matches a date value, e.g.: ```py from datetime import date from pydantic_core import SchemaValidator, core_schema schema = core_schema.date_schema(le=date(2020, 1, 1), ge=date(2019, 1, 1)) v = SchemaValidator(schema) assert v.validate_python(date(2019, 6, 1)) == date(2019, 6, 1) ``` ### Returns `DateSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a date or a value that can be converted to a date **`le`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this date **`ge`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this date **`lt`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this date **`gt`** : `date` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this date **`now_op`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['past', 'future'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be in the past or future relative to the current date **`now_utc_offset`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be in the past or future relative to the current date with this utc offset **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## time\_schema ```python def time_schema( strict: bool | None = None, le: time | None = None, ge: time | None = None, lt: time | None = None, gt: time | None = None, tz_constraint: Literal['aware', 'naive'] | int | None = None, microseconds_precision: Literal['truncate', 'error'] = 'truncate', ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> TimeSchema ``` Returns a schema that matches a time value, e.g.: ```py from datetime import time from pydantic_core import SchemaValidator, core_schema schema = core_schema.time_schema(le=time(12, 0, 0), ge=time(6, 0, 0)) v = SchemaValidator(schema) assert v.validate_python(time(9, 0, 0)) == time(9, 0, 0) ``` ### Returns `TimeSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a time or a value that can be converted to a time **`le`** : [`time`](https://docs.python.org/3/library/time.html#module-time) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this time **`ge`** : [`time`](https://docs.python.org/3/library/time.html#module-time) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this time **`lt`** : [`time`](https://docs.python.org/3/library/time.html#module-time) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this time **`gt`** : [`time`](https://docs.python.org/3/library/time.html#module-time) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this time **`tz_constraint`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['aware', 'naive'\] | [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be timezone aware or naive, or an int to indicate required tz offset **`microseconds_precision`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['truncate', 'error'\] _Default:_ `'truncate'` The behavior when seconds have more than 6 digits or microseconds is too large **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## datetime\_schema ```python def datetime_schema( strict: bool | None = None, le: datetime | None = None, ge: datetime | None = None, lt: datetime | None = None, gt: datetime | None = None, now_op: Literal['past', 'future'] | None = None, tz_constraint: Literal['aware', 'naive'] | int | None = None, now_utc_offset: int | None = None, microseconds_precision: Literal['truncate', 'error'] = 'truncate', ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> DatetimeSchema ``` Returns a schema that matches a datetime value, e.g.: ```py from datetime import datetime from pydantic_core import SchemaValidator, core_schema schema = core_schema.datetime_schema() v = SchemaValidator(schema) now = datetime.now() assert v.validate_python(str(now)) == now ``` ### Returns `DatetimeSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a datetime or a value that can be converted to a datetime **`le`** : [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this datetime **`ge`** : [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this datetime **`lt`** : [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this datetime **`gt`** : [`datetime`](https://docs.python.org/3/library/datetime.html#module-datetime) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this datetime **`now_op`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['past', 'future'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be in the past or future relative to the current datetime **`tz_constraint`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['aware', 'naive'\] | [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be timezone aware or naive, or an int to indicate required tz offset TODO: use of a tzinfo where offset changes based on the datetime is not yet supported **`now_utc_offset`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be in the past or future relative to the current datetime with this utc offset **`microseconds_precision`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['truncate', 'error'\] _Default:_ `'truncate'` The behavior when seconds have more than 6 digits or microseconds is too large **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## timedelta\_schema ```python def timedelta_schema( strict: bool | None = None, le: timedelta | None = None, ge: timedelta | None = None, lt: timedelta | None = None, gt: timedelta | None = None, microseconds_precision: Literal['truncate', 'error'] = 'truncate', ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> TimedeltaSchema ``` Returns a schema that matches a timedelta value, e.g.: ```py from datetime import timedelta from pydantic_core import SchemaValidator, core_schema schema = core_schema.timedelta_schema(le=timedelta(days=1), ge=timedelta(days=0)) v = SchemaValidator(schema) assert v.validate_python(timedelta(hours=12)) == timedelta(hours=12) ``` ### Returns `TimedeltaSchema` ### Parameters **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the value should be a timedelta or a value that can be converted to a timedelta **`le`** : `timedelta` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be less than or equal to this timedelta **`ge`** : `timedelta` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be greater than or equal to this timedelta **`lt`** : `timedelta` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly less than this timedelta **`gt`** : `timedelta` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be strictly greater than this timedelta **`microseconds_precision`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['truncate', 'error'\] _Default:_ `'truncate'` The behavior when seconds have more than 6 digits or microseconds is too large **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## literal\_schema ```python def literal_schema( expected: list[Any], ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> LiteralSchema ``` Returns a schema that matches a literal value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.literal_schema(['hello', 'world']) v = SchemaValidator(schema) assert v.validate_python('hello') == 'hello' ``` ### Returns `LiteralSchema` ### Parameters **`expected`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The value must be one of these values **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## enum\_schema ```python def enum_schema( cls: Any, members: list[Any], sub_type: Literal['str', 'int', 'float'] | None = None, missing: Callable[[Any], Any] | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> EnumSchema ``` Returns a schema that matches an enum value, e.g.: ```py from enum import Enum from pydantic_core import SchemaValidator, core_schema class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 schema = core_schema.enum_schema(Color, list(Color.__members__.values())) v = SchemaValidator(schema) assert v.validate_python(2) is Color.GREEN ``` ### Returns `EnumSchema` ### Parameters **`cls`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The enum class **`members`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The members of the enum, generally `list(MyEnum.__members__.values())` **`sub_type`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['str', 'int', 'float'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The type of the enum, either 'str' or 'int' or None for plain enums **`missing`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A function to use when the value is not found in the enum, from `_missing_` **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use strict mode, defaults to False **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## missing\_sentinel\_schema ```python def missing_sentinel_schema( metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> MissingSentinelSchema ``` Returns a schema for the `MISSING` sentinel. ### Returns `MissingSentinelSchema` ## is\_instance\_schema ```python def is_instance_schema( cls: Any, cls_repr: str | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> IsInstanceSchema ``` Returns a schema that checks if a value is an instance of a class, equivalent to python's `isinstance` method, e.g.: ```py from pydantic_core import SchemaValidator, core_schema class A: pass schema = core_schema.is_instance_schema(cls=A) v = SchemaValidator(schema) v.validate_python(A()) ``` ### Returns `IsInstanceSchema` ### Parameters **`cls`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The value must be an instance of this class **`cls_repr`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` If provided this string is used in the validator name instead of `repr(cls)` **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## is\_subclass\_schema ```python def is_subclass_schema( cls: type[Any], cls_repr: str | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> IsInstanceSchema ``` Returns a schema that checks if a value is a subtype of a class, equivalent to python's `issubclass` method, e.g.: ```py from pydantic_core import SchemaValidator, core_schema class A: pass class B(A): pass schema = core_schema.is_subclass_schema(cls=A) v = SchemaValidator(schema) v.validate_python(B) ``` ### Returns `IsInstanceSchema` ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The value must be a subclass of this class **`cls_repr`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` If provided this string is used in the validator name instead of `repr(cls)` **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## callable\_schema ```python def callable_schema( ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> CallableSchema ``` Returns a schema that checks if a value is callable, equivalent to python's `callable` method, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.callable_schema() v = SchemaValidator(schema) v.validate_python(min) ``` ### Returns `CallableSchema` ### Parameters **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## list\_schema ```python def list_schema( items_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, fail_fast: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: IncExSeqOrElseSerSchema | None = None, ) -> ListSchema ``` Returns a schema that matches a list value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.list_schema(core_schema.int_schema(), min_length=0, max_length=10) v = SchemaValidator(schema) assert v.validate_python(['4']) == [4] ``` ### Returns `ListSchema` ### Parameters **`items_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a list of items that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a list with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a list with at most this many items **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Stop validation on the first error **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a list with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `IncExSeqOrElseSerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## tuple\_positional\_schema ```python def tuple_positional_schema( items_schema: list[CoreSchema], extras_schema: CoreSchema | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: IncExSeqOrElseSerSchema | None = None, ) -> TupleSchema ``` Returns a schema that matches a tuple of schemas, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.tuple_positional_schema( [core_schema.int_schema(), core_schema.str_schema()] ) v = SchemaValidator(schema) assert v.validate_python((1, 'hello')) == (1, 'hello') ``` ### Returns `TupleSchema` ### Parameters **`items_schema`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`CoreSchema`\] The value must be a tuple with items that match these schemas **`extras_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with items that match this schema This was inspired by JSON schema's `prefixItems` and `items` fields. In python's `typing.Tuple`, you can't specify a type for "extra" items -- they must all be the same type if the length is variable. So this field won't be set from a `typing.Tuple` annotation on a pydantic model. **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `IncExSeqOrElseSerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## tuple\_variable\_schema ```python def tuple_variable_schema( items_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: IncExSeqOrElseSerSchema | None = None, ) -> TupleSchema ``` Returns a schema that matches a tuple of a given schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.tuple_variable_schema( items_schema=core_schema.int_schema(), min_length=0, max_length=10 ) v = SchemaValidator(schema) assert v.validate_python(('1', 2, 3)) == (1, 2, 3) ``` ### Returns `TupleSchema` ### Parameters **`items_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with items that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with at most this many items **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `IncExSeqOrElseSerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## tuple\_schema ```python def tuple_schema( items_schema: list[CoreSchema], variadic_item_index: int | None = None, min_length: int | None = None, max_length: int | None = None, fail_fast: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: IncExSeqOrElseSerSchema | None = None, ) -> TupleSchema ``` Returns a schema that matches a tuple of schemas, with an optional variadic item, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.tuple_schema( [core_schema.int_schema(), core_schema.str_schema(), core_schema.float_schema()], variadic_item_index=1, ) v = SchemaValidator(schema) assert v.validate_python((1, 'hello', 'world', 1.5)) == (1, 'hello', 'world', 1.5) ``` ### Returns `TupleSchema` ### Parameters **`items_schema`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`CoreSchema`\] The value must be a tuple with items that match these schemas **`variadic_item_index`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The index of the schema in `items_schema` to be treated as variadic (following PEP 646) **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with at most this many items **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Stop validation on the first error **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a tuple with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `IncExSeqOrElseSerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## set\_schema ```python def set_schema( items_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, fail_fast: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> SetSchema ``` Returns a schema that matches a set of a given schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.set_schema( items_schema=core_schema.int_schema(), min_length=0, max_length=10 ) v = SchemaValidator(schema) assert v.validate_python({1, '2', 3}) == {1, 2, 3} ``` ### Returns `SetSchema` ### Parameters **`items_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a set with items that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a set with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a set with at most this many items **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Stop validation on the first error **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a set with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## frozenset\_schema ```python def frozenset_schema( items_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, fail_fast: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> FrozenSetSchema ``` Returns a schema that matches a frozenset of a given schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.frozenset_schema( items_schema=core_schema.int_schema(), min_length=0, max_length=10 ) v = SchemaValidator(schema) assert v.validate_python(frozenset(range(3))) == frozenset({0, 1, 2}) ``` ### Returns `FrozenSetSchema` ### Parameters **`items_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a frozenset with items that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a frozenset with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a frozenset with at most this many items **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Stop validation on the first error **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a frozenset with exactly this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## generator\_schema ```python def generator_schema( items_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: IncExSeqOrElseSerSchema | None = None, ) -> GeneratorSchema ``` Returns a schema that matches a generator value, e.g.: ```py from typing import Iterator from pydantic_core import SchemaValidator, core_schema def gen() -> Iterator[int]: yield 1 schema = core_schema.generator_schema(items_schema=core_schema.int_schema()) v = SchemaValidator(schema) v.validate_python(gen()) ``` Unlike other types, validated generators do not raise ValidationErrors eagerly, but instead will raise a ValidationError when a violating value is actually read from the generator. This is to ensure that "validated" generators retain the benefit of lazy evaluation. ### Returns `GeneratorSchema` ### Parameters **`items_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a generator with items that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a generator that yields at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a generator that yields at most this many items **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `IncExSeqOrElseSerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## dict\_schema ```python def dict_schema( keys_schema: CoreSchema | None = None, values_schema: CoreSchema | None = None, min_length: int | None = None, max_length: int | None = None, fail_fast: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> DictSchema ``` Returns a schema that matches a dict value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.dict_schema( keys_schema=core_schema.str_schema(), values_schema=core_schema.int_schema() ) v = SchemaValidator(schema) assert v.validate_python({'a': '1', 'b': 2}) == {'a': 1, 'b': 2} ``` ### Returns `DictSchema` ### Parameters **`keys_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a dict with keys that match this schema **`values_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a dict with values that match this schema **`min_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a dict with at least this many items **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The value must be a dict with at most this many items **`fail_fast`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Stop validation on the first error **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the keys and values should be validated with strict mode **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## no\_info\_before\_validator\_function ```python def no_info_before_validator_function( function: NoInfoValidatorFunction, schema: CoreSchema, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> BeforeValidatorFunctionSchema ``` Returns a schema that calls a validator function before validating, no `info` argument is provided, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: bytes) -> str: return v.decode() + 'world' func_schema = core_schema.no_info_before_validator_function( function=fn, schema=core_schema.str_schema() ) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) v = SchemaValidator(schema) assert v.validate_python({'a': b'hello '}) == {'a': 'hello world'} ``` ### Returns `BeforeValidatorFunctionSchema` ### Parameters **`function`** : `NoInfoValidatorFunction` The validator function to call **`schema`** : `CoreSchema` The schema to validate the output of the validator function **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## with\_info\_before\_validator\_function ```python def with_info_before_validator_function( function: WithInfoValidatorFunction, schema: CoreSchema, field_name: str | None = None, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> BeforeValidatorFunctionSchema ``` Returns a schema that calls a validator function before validation, the function is called with an `info` argument, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: bytes, info: core_schema.ValidationInfo) -> str: assert info.data is not None assert info.field_name is not None return v.decode() + 'world' func_schema = core_schema.with_info_before_validator_function( function=fn, schema=core_schema.str_schema() ) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) v = SchemaValidator(schema) assert v.validate_python({'a': b'hello '}) == {'a': 'hello world'} ``` ### Returns `BeforeValidatorFunctionSchema` ### Parameters **`function`** : `WithInfoValidatorFunction` The validator function to call **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the field this validator is applied to, if any (deprecated) **`schema`** : `CoreSchema` The schema to validate the output of the validator function **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## no\_info\_after\_validator\_function ```python def no_info_after_validator_function( function: NoInfoValidatorFunction, schema: CoreSchema, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> AfterValidatorFunctionSchema ``` Returns a schema that calls a validator function after validating, no `info` argument is provided, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str) -> str: return v + 'world' func_schema = core_schema.no_info_after_validator_function(fn, core_schema.str_schema()) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) v = SchemaValidator(schema) assert v.validate_python({'a': b'hello '}) == {'a': 'hello world'} ``` ### Returns `AfterValidatorFunctionSchema` ### Parameters **`function`** : `NoInfoValidatorFunction` The validator function to call after the schema is validated **`schema`** : `CoreSchema` The schema to validate before the validator function **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## with\_info\_after\_validator\_function ```python def with_info_after_validator_function( function: WithInfoValidatorFunction, schema: CoreSchema, field_name: str | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> AfterValidatorFunctionSchema ``` Returns a schema that calls a validator function after validation, the function is called with an `info` argument, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str, info: core_schema.ValidationInfo) -> str: assert info.data is not None assert info.field_name is not None return v + 'world' func_schema = core_schema.with_info_after_validator_function( function=fn, schema=core_schema.str_schema() ) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) v = SchemaValidator(schema) assert v.validate_python({'a': b'hello '}) == {'a': 'hello world'} ``` ### Returns `AfterValidatorFunctionSchema` ### Parameters **`function`** : `WithInfoValidatorFunction` The validator function to call after the schema is validated **`schema`** : `CoreSchema` The schema to validate before the validator function **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the field this validator is applied to, if any (deprecated) **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## no\_info\_wrap\_validator\_function ```python def no_info_wrap_validator_function( function: NoInfoWrapValidatorFunction, schema: CoreSchema, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> WrapValidatorFunctionSchema ``` Returns a schema which calls a function with a `validator` callable argument which can optionally be used to call inner validation with the function logic, this is much like the "onion" implementation of middleware in many popular web frameworks, no `info` argument is passed, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn( v: str, validator: core_schema.ValidatorFunctionWrapHandler, ) -> str: return validator(input_value=v) + 'world' schema = core_schema.no_info_wrap_validator_function( function=fn, schema=core_schema.str_schema() ) v = SchemaValidator(schema) assert v.validate_python('hello ') == 'hello world' ``` ### Returns `WrapValidatorFunctionSchema` ### Parameters **`function`** : `NoInfoWrapValidatorFunction` The validator function to call **`schema`** : `CoreSchema` The schema to validate the output of the validator function **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## with\_info\_wrap\_validator\_function ```python def with_info_wrap_validator_function( function: WithInfoWrapValidatorFunction, schema: CoreSchema, field_name: str | None = None, json_schema_input_schema: CoreSchema | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> WrapValidatorFunctionSchema ``` Returns a schema which calls a function with a `validator` callable argument which can optionally be used to call inner validation with the function logic, this is much like the "onion" implementation of middleware in many popular web frameworks, an `info` argument is also passed, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn( v: str, validator: core_schema.ValidatorFunctionWrapHandler, info: core_schema.ValidationInfo, ) -> str: return validator(input_value=v) + 'world' schema = core_schema.with_info_wrap_validator_function( function=fn, schema=core_schema.str_schema() ) v = SchemaValidator(schema) assert v.validate_python('hello ') == 'hello world' ``` ### Returns `WrapValidatorFunctionSchema` ### Parameters **`function`** : `WithInfoWrapValidatorFunction` The validator function to call **`schema`** : `CoreSchema` The schema to validate the output of the validator function **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the field this validator is applied to, if any (deprecated) **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## no\_info\_plain\_validator\_function ```python def no_info_plain_validator_function( function: NoInfoValidatorFunction, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> PlainValidatorFunctionSchema ``` Returns a schema that uses the provided function for validation, no `info` argument is passed, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str) -> str: assert 'hello' in v return v + 'world' schema = core_schema.no_info_plain_validator_function(function=fn) v = SchemaValidator(schema) assert v.validate_python('hello ') == 'hello world' ``` ### Returns `PlainValidatorFunctionSchema` ### Parameters **`function`** : `NoInfoValidatorFunction` The validator function to call **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## with\_info\_plain\_validator\_function ```python def with_info_plain_validator_function( function: WithInfoValidatorFunction, field_name: str | None = None, ref: str | None = None, json_schema_input_schema: CoreSchema | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> PlainValidatorFunctionSchema ``` Returns a schema that uses the provided function for validation, an `info` argument is passed, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str, info: core_schema.ValidationInfo) -> str: assert 'hello' in v return v + 'world' schema = core_schema.with_info_plain_validator_function(function=fn) v = SchemaValidator(schema) assert v.validate_python('hello ') == 'hello world' ``` ### Returns `PlainValidatorFunctionSchema` ### Parameters **`function`** : `WithInfoValidatorFunction` The validator function to call **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the field this validator is applied to, if any (deprecated) **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`json_schema_input_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The core schema to be used to generate the corresponding JSON Schema input type **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## with\_default\_schema ```python def with_default_schema( schema: CoreSchema, default: Any = PydanticUndefined, default_factory: Union[Callable[[], Any], Callable[[dict[str, Any]], Any], None] = None, default_factory_takes_data: bool | None = None, on_error: Literal['raise', 'omit', 'default'] | None = None, validate_default: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> WithDefaultSchema ``` Returns a schema that adds a default value to the given schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.with_default_schema(core_schema.str_schema(), default='hello') wrapper_schema = core_schema.typed_dict_schema( {'a': core_schema.typed_dict_field(schema)} ) v = SchemaValidator(wrapper_schema) assert v.validate_python({}) == v.validate_python({'a': 'hello'}) ``` ### Returns `WithDefaultSchema` ### Parameters **`schema`** : `CoreSchema` The schema to add a default value to **`default`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `PydanticUndefined` The default value to use **`default_factory`** : [`Union`](https://docs.python.org/3/library/typing.html#typing.Union)\[[`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`None`](https://docs.python.org/3/library/constants.html#None)\] _Default:_ `None` A callable that returns the default value to use **`default_factory_takes_data`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the default factory takes a validated data argument **`on_error`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['raise', 'omit', 'default'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` What to do if the schema validation fails. One of 'raise', 'omit', 'default' **`validate_default`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the default value should be validated **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the underlying schema should be validated with strict mode **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## nullable\_schema ```python def nullable_schema( schema: CoreSchema, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> NullableSchema ``` Returns a schema that matches a nullable value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.nullable_schema(core_schema.str_schema()) v = SchemaValidator(schema) assert v.validate_python(None) is None ``` ### Returns `NullableSchema` ### Parameters **`schema`** : `CoreSchema` The schema to wrap **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the underlying schema should be validated with strict mode **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## union\_schema ```python def union_schema( choices: list[CoreSchema | tuple[CoreSchema, str]], auto_collapse: bool | None = None, custom_error_type: str | None = None, custom_error_message: str | None = None, custom_error_context: dict[str, str | int] | None = None, mode: Literal['smart', 'left_to_right'] | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> UnionSchema ``` Returns a schema that matches a union value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.union_schema([core_schema.str_schema(), core_schema.int_schema()]) v = SchemaValidator(schema) assert v.validate_python('hello') == 'hello' assert v.validate_python(1) == 1 ``` ### Returns `UnionSchema` ### Parameters **`choices`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`CoreSchema` | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`CoreSchema`, [`str`](https://docs.python.org/3/library/stdtypes.html#str)\]\] The schemas to match. If a tuple, the second item is used as the label for the case. **`auto_collapse`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` whether to automatically collapse unions with one element to the inner validator, default true **`custom_error_type`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error type to use if the validation fails **`custom_error_message`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error message to use if the validation fails **`custom_error_context`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error context to use if the validation fails **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['smart', 'left\_to\_right'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` How to select which choice to return - `smart` (default) will try to return the choice which is the closest match to the input value - `left_to_right` will return the first choice in `choices` which succeeds validation **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## tagged\_union\_schema ```python def tagged_union_schema( choices: dict[Any, CoreSchema], discriminator: str | list[str | int] | list[list[str | int]] | Callable[[Any], Any], custom_error_type: str | None = None, custom_error_message: str | None = None, custom_error_context: dict[str, int | str | float] | None = None, strict: bool | None = None, from_attributes: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> TaggedUnionSchema ``` Returns a schema that matches a tagged union value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema apple_schema = core_schema.typed_dict_schema( { 'foo': core_schema.typed_dict_field(core_schema.str_schema()), 'bar': core_schema.typed_dict_field(core_schema.int_schema()), } ) banana_schema = core_schema.typed_dict_schema( { 'foo': core_schema.typed_dict_field(core_schema.str_schema()), 'spam': core_schema.typed_dict_field( core_schema.list_schema(items_schema=core_schema.int_schema()) ), } ) schema = core_schema.tagged_union_schema( choices={ 'apple': apple_schema, 'banana': banana_schema, }, discriminator='foo', ) v = SchemaValidator(schema) assert v.validate_python({'foo': 'apple', 'bar': '123'}) == {'foo': 'apple', 'bar': 123} assert v.validate_python({'foo': 'banana', 'spam': [1, 2, 3]}) == { 'foo': 'banana', 'spam': [1, 2, 3], } ``` ### Returns `TaggedUnionSchema` ### Parameters **`choices`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), `CoreSchema`\] The schemas to match When retrieving a schema from `choices` using the discriminator value, if the value is a str, it should be fed back into the `choices` map until a schema is obtained (This approach is to prevent multiple ownership of a single schema in Rust) **`discriminator`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The discriminator to use to determine the schema to use - If `discriminator` is a str, it is the name of the attribute to use as the discriminator - If `discriminator` is a list of int/str, it should be used as a "path" to access the discriminator - If `discriminator` is a list of lists, each inner list is a path, and the first path that exists is used - If `discriminator` is a callable, it should return the discriminator when called on the value to validate; the callable can return `None` to indicate that there is no matching discriminator present on the input **`custom_error_type`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error type to use if the validation fails **`custom_error_message`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error message to use if the validation fails **`custom_error_context`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`float`](https://docs.python.org/3/library/functions.html#float)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error context to use if the validation fails **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the underlying schemas should be validated with strict mode **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use the attributes of the object to retrieve the discriminator value **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## chain\_schema ```python def chain_schema( steps: list[CoreSchema], ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ChainSchema ``` Returns a schema that chains the provided validation schemas, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str, info: core_schema.ValidationInfo) -> str: assert 'hello' in v return v + ' world' fn_schema = core_schema.with_info_plain_validator_function(function=fn) schema = core_schema.chain_schema( [fn_schema, fn_schema, fn_schema, core_schema.str_schema()] ) v = SchemaValidator(schema) assert v.validate_python('hello') == 'hello world world world' ``` ### Returns `ChainSchema` ### Parameters **`steps`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`CoreSchema`\] The schemas to chain **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## lax\_or\_strict\_schema ```python def lax_or_strict_schema( lax_schema: CoreSchema, strict_schema: CoreSchema, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> LaxOrStrictSchema ``` Returns a schema that uses the lax or strict schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema def fn(v: str, info: core_schema.ValidationInfo) -> str: assert 'hello' in v return v + ' world' lax_schema = core_schema.int_schema(strict=False) strict_schema = core_schema.int_schema(strict=True) schema = core_schema.lax_or_strict_schema( lax_schema=lax_schema, strict_schema=strict_schema, strict=True ) v = SchemaValidator(schema) assert v.validate_python(123) == 123 schema = core_schema.lax_or_strict_schema( lax_schema=lax_schema, strict_schema=strict_schema, strict=False ) v = SchemaValidator(schema) assert v.validate_python('123') == 123 ``` ### Returns `LaxOrStrictSchema` ### Parameters **`lax_schema`** : `CoreSchema` The lax schema to use **`strict_schema`** : `CoreSchema` The strict schema to use **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the strict schema should be used **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## json\_or\_python\_schema ```python def json_or_python_schema( json_schema: CoreSchema, python_schema: CoreSchema, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> JsonOrPythonSchema ``` Returns a schema that uses the Json or Python schema depending on the input: ```py from pydantic_core import SchemaValidator, ValidationError, core_schema v = SchemaValidator( core_schema.json_or_python_schema( json_schema=core_schema.int_schema(), python_schema=core_schema.int_schema(strict=True), ) ) assert v.validate_json('"123"') == 123 try: v.validate_python('123') except ValidationError: pass else: raise AssertionError('Validation should have failed') ``` ### Returns `JsonOrPythonSchema` ### Parameters **`json_schema`** : `CoreSchema` The schema to use for Json inputs **`python_schema`** : `CoreSchema` The schema to use for Python inputs **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## typed\_dict\_field ```python def typed_dict_field( schema: CoreSchema, required: bool | None = None, validation_alias: str | list[str | int] | list[list[str | int]] | None = None, serialization_alias: str | None = None, serialization_exclude: bool | None = None, metadata: dict[str, Any] | None = None, serialization_exclude_if: Callable[[Any], bool] | None = None, ) -> TypedDictField ``` Returns a schema that matches a typed dict field, e.g.: ```py from pydantic_core import core_schema field = core_schema.typed_dict_field(schema=core_schema.int_schema(), required=True) ``` ### Returns `TypedDictField` ### Parameters **`schema`** : `CoreSchema` The schema to use for the field **`required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field is required, otherwise uses the value from `total` on the typed dict **`validation_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias(es) to use to find the field in the validation data **`serialization_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias to use as a key when serializing **`serialization_exclude`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to exclude the field when serializing **`serialization_exclude_if`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable that determines whether to exclude the field when serializing based on its value. **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core ## typed\_dict\_schema ```python def typed_dict_schema( fields: dict[str, TypedDictField], cls: type[Any] | None = None, cls_name: str | None = None, computed_fields: list[ComputedField] | None = None, strict: bool | None = None, extras_schema: CoreSchema | None = None, extra_behavior: ExtraBehavior | None = None, total: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, config: CoreConfig | None = None, ) -> TypedDictSchema ``` Returns a schema that matches a typed dict, e.g.: ```py from typing_extensions import TypedDict from pydantic_core import SchemaValidator, core_schema class MyTypedDict(TypedDict): a: str wrapper_schema = core_schema.typed_dict_schema( {'a': core_schema.typed_dict_field(core_schema.str_schema())}, cls=MyTypedDict ) v = SchemaValidator(wrapper_schema) assert v.validate_python({'a': 'hello'}) == {'a': 'hello'} ``` ### Returns `TypedDictSchema` ### Parameters **`fields`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `TypedDictField`\] The fields to use for the typed dict **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The class to use for the typed dict **`cls_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name to use in error locations. Falls back to `cls.__name__`, or the validator name if no class is provided. **`computed_fields`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ComputedField`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Computed fields to use when serializing the model, only applies when directly inside a model **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the typed dict is strict **`extras_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The extra validator to use for the typed dict **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`extra_behavior`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The extra behavior to use for the typed dict **`total`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the typed dict is total, otherwise uses `typed_dict_total` from config **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## model\_field ```python def model_field( schema: CoreSchema, validation_alias: str | list[str | int] | list[list[str | int]] | None = None, serialization_alias: str | None = None, serialization_exclude: bool | None = None, serialization_exclude_if: Callable[[Any], bool] | None = None, frozen: bool | None = None, metadata: dict[str, Any] | None = None, ) -> ModelField ``` Returns a schema for a model field, e.g.: ```py from pydantic_core import core_schema field = core_schema.model_field(schema=core_schema.int_schema()) ``` ### Returns `ModelField` ### Parameters **`schema`** : `CoreSchema` The schema to use for the field **`validation_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias(es) to use to find the field in the validation data **`serialization_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias to use as a key when serializing **`serialization_exclude`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to exclude the field when serializing **`serialization_exclude_if`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A Callable that determines whether to exclude a field during serialization based on its value. **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field is frozen **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core ## model\_fields\_schema ```python def model_fields_schema( fields: dict[str, ModelField], model_name: str | None = None, computed_fields: list[ComputedField] | None = None, strict: bool | None = None, extras_schema: CoreSchema | None = None, extras_keys_schema: CoreSchema | None = None, extra_behavior: ExtraBehavior | None = None, from_attributes: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ModelFieldsSchema ``` Returns a schema that matches the fields of a Pydantic model, e.g.: ```py from pydantic_core import SchemaValidator, core_schema wrapper_schema = core_schema.model_fields_schema( {'a': core_schema.model_field(core_schema.str_schema())} ) v = SchemaValidator(wrapper_schema) print(v.validate_python({'a': 'hello'})) #> ({'a': 'hello'}, None, {'a'}) ``` ### Returns `ModelFieldsSchema` ### Parameters **`fields`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), `ModelField`\] The fields of the model **`model_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name of the model, used for error messages, defaults to "Model" **`computed_fields`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ComputedField`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Computed fields to use when serializing the model, only applies when directly inside a model **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model is strict **`extras_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The schema to use when validating extra input data **`extras_keys_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The schema to use when validating the keys of extra input data **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`extra_behavior`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The extra behavior to use for the model fields **`from_attributes`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model fields should be populated from attributes **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## model\_schema ```python def model_schema( cls: type[Any], schema: CoreSchema, generic_origin: type[Any] | None = None, custom_init: bool | None = None, root_model: bool | None = None, post_init: str | None = None, revalidate_instances: Literal['always', 'never', 'subclass-instances'] | None = None, strict: bool | None = None, frozen: bool | None = None, extra_behavior: ExtraBehavior | None = None, config: CoreConfig | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ModelSchema ``` A model schema generally contains a typed-dict schema. It will run the typed dict validator, then create a new class and set the dict and fields set returned from the typed dict validator to `__dict__` and `__pydantic_fields_set__` respectively. Example: ```py from pydantic_core import CoreConfig, SchemaValidator, core_schema class MyModel: __slots__ = ( '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__', ) schema = core_schema.model_schema( cls=MyModel, config=CoreConfig(str_max_length=5), schema=core_schema.model_fields_schema( fields={'a': core_schema.model_field(core_schema.str_schema())}, ), ) v = SchemaValidator(schema) assert v.isinstance_python({'a': 'hello'}) is True assert v.isinstance_python({'a': 'too long'}) is False ``` ### Returns `ModelSchema` ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The class to use for the model **`schema`** : `CoreSchema` The schema to use for the model **`generic_origin`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The origin type used for this model, if it's a parametrized generic. Ex, if this model schema represents `SomeModel[int]`, generic\_origin is `SomeModel` **`custom_init`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model has a custom init method **`root_model`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model is a `RootModel` **`post_init`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The call after init to use for the model **`revalidate_instances`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['always', 'never', 'subclass-instances'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` whether instances of models and dataclasses (including subclass instances) should re-validate defaults to config.revalidate\_instances, else 'never' **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model is strict **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the model is frozen **`extra_behavior`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The extra behavior to use for the model, used in serialization **`config`** : `CoreConfig` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The config to use for the model **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## dataclass\_field ```python def dataclass_field( name: str, schema: CoreSchema, kw_only: bool | None = None, init: bool | None = None, init_only: bool | None = None, validation_alias: str | list[str | int] | list[list[str | int]] | None = None, serialization_alias: str | None = None, serialization_exclude: bool | None = None, metadata: dict[str, Any] | None = None, serialization_exclude_if: Callable[[Any], bool] | None = None, frozen: bool | None = None, ) -> DataclassField ``` Returns a schema for a dataclass field, e.g.: ```py from pydantic_core import SchemaValidator, core_schema field = core_schema.dataclass_field( name='a', schema=core_schema.str_schema(), kw_only=False ) schema = core_schema.dataclass_args_schema('Foobar', [field]) v = SchemaValidator(schema) assert v.validate_python({'a': 'hello'}) == ({'a': 'hello'}, None) ``` ### Returns `DataclassField` ### Parameters **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name to use for the argument parameter **`schema`** : `CoreSchema` The schema to use for the argument parameter **`kw_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field can be set with a positional argument as well as a keyword argument **`init`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field should be validated during initialization **`init_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field should be omitted from `__dict__` and passed to `__post_init__` **`validation_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias(es) to use to find the field in the validation data **`serialization_alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias to use as a key when serializing **`serialization_exclude`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to exclude the field when serializing **`serialization_exclude_if`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\], [`bool`](https://docs.python.org/3/library/functions.html#bool)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A callable that determines whether to exclude the field when serializing based on its value. **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the field is frozen ## dataclass\_args\_schema ```python def dataclass_args_schema( dataclass_name: str, fields: list[DataclassField], computed_fields: list[ComputedField] | None = None, collect_init_only: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, extra_behavior: ExtraBehavior | None = None, ) -> DataclassArgsSchema ``` Returns a schema for validating dataclass arguments, e.g.: ```py from pydantic_core import SchemaValidator, core_schema field_a = core_schema.dataclass_field( name='a', schema=core_schema.str_schema(), kw_only=False ) field_b = core_schema.dataclass_field( name='b', schema=core_schema.bool_schema(), kw_only=False ) schema = core_schema.dataclass_args_schema('Foobar', [field_a, field_b]) v = SchemaValidator(schema) assert v.validate_python({'a': 'hello', 'b': True}) == ({'a': 'hello', 'b': True}, None) ``` ### Returns `DataclassArgsSchema` ### Parameters **`dataclass_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name of the dataclass being validated **`fields`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`DataclassField`\] The fields to use for the dataclass **`computed_fields`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ComputedField`\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Computed fields to use when serializing the dataclass **`collect_init_only`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to collect init only fields into a dict to pass to `__post_init__` **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema **`extra_behavior`** : `ExtraBehavior` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` How to handle extra fields ## dataclass\_schema ```python def dataclass_schema( cls: type[Any], schema: CoreSchema, fields: list[str], generic_origin: type[Any] | None = None, cls_name: str | None = None, post_init: bool | None = None, revalidate_instances: Literal['always', 'never', 'subclass-instances'] | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, frozen: bool | None = None, slots: bool | None = None, config: CoreConfig | None = None, ) -> DataclassSchema ``` Returns a schema for a dataclass. As with `ModelSchema`, this schema can only be used as a field within another schema, not as the root type. ### Returns `DataclassSchema` ### Parameters **`cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The dataclass type, used to perform subclass checks **`schema`** : `CoreSchema` The schema to use for the dataclass fields **`fields`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] Fields of the dataclass, this is used in serialization and in validation during re-validation and while validating assignment **`generic_origin`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The origin type used for this dataclass, if it's a parametrized generic. Ex, if this model schema represents `SomeDataclass[int]`, generic\_origin is `SomeDataclass` **`cls_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The name to use in error locs, etc; this is useful for generics (default: `cls.__name__`) **`post_init`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to call `__post_init__` after validation **`revalidate_instances`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['always', 'never', 'subclass-instances'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` whether instances of models and dataclasses (including subclass instances) should re-validate defaults to config.revalidate\_instances, else 'never' **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to require an exact instance of `cls` **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema **`frozen`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the dataclass is frozen **`slots`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether `slots=True` on the dataclass, means each field is assigned independently, rather than simply setting `__dict__`, default false ## arguments\_parameter ```python def arguments_parameter( name: str, schema: CoreSchema, mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only'] | None = None, alias: str | list[str | int] | list[list[str | int]] | None = None, ) -> ArgumentsParameter ``` Returns a schema that matches an argument parameter, e.g.: ```py from pydantic_core import SchemaValidator, core_schema param = core_schema.arguments_parameter( name='a', schema=core_schema.str_schema(), mode='positional_only' ) schema = core_schema.arguments_schema([param]) v = SchemaValidator(schema) assert v.validate_python(('hello',)) == (('hello',), {}) ``` ### Returns `ArgumentsParameter` ### Parameters **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name to use for the argument parameter **`schema`** : `CoreSchema` The schema to use for the argument parameter **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['positional\_only', 'positional\_or\_keyword', 'keyword\_only'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The mode to use for the argument parameter **`alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias to use for the argument parameter ## arguments\_schema ```python def arguments_schema( arguments: list[ArgumentsParameter], validate_by_name: bool | None = None, validate_by_alias: bool | None = None, var_args_schema: CoreSchema | None = None, var_kwargs_mode: VarKwargsMode | None = None, var_kwargs_schema: CoreSchema | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ArgumentsSchema ``` Returns a schema that matches an arguments schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema param_a = core_schema.arguments_parameter( name='a', schema=core_schema.str_schema(), mode='positional_only' ) param_b = core_schema.arguments_parameter( name='b', schema=core_schema.bool_schema(), mode='positional_only' ) schema = core_schema.arguments_schema([param_a, param_b]) v = SchemaValidator(schema) assert v.validate_python(('hello', True)) == (('hello', True), {}) ``` ### Returns `ArgumentsSchema` ### Parameters **`arguments`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ArgumentsParameter`\] The arguments to use for the arguments schema **`validate_by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to populate by the parameter names, defaults to `False`. **`validate_by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to populate by the parameter aliases, defaults to `True`. **`var_args_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The variable args schema to use for the arguments schema **`var_kwargs_mode`** : `VarKwargsMode` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The validation mode to use for variadic keyword arguments. If `'uniform'`, every value of the keyword arguments will be validated against the `var_kwargs_schema` schema. If `'unpacked-typed-dict'`, the `var_kwargs_schema` argument must be a [`typed_dict_schema`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.typed_dict_schema) **`var_kwargs_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The variable kwargs schema to use for the arguments schema **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## arguments\_v3\_parameter ```python def arguments_v3_parameter( name: str, schema: CoreSchema, mode: Literal['positional_only', 'positional_or_keyword', 'keyword_only', 'var_args', 'var_kwargs_uniform', 'var_kwargs_unpacked_typed_dict'] | None = None, alias: str | list[str | int] | list[list[str | int]] | None = None, ) -> ArgumentsV3Parameter ``` Returns a schema that matches an argument parameter, e.g.: ```py from pydantic_core import SchemaValidator, core_schema param = core_schema.arguments_v3_parameter( name='a', schema=core_schema.str_schema(), mode='positional_only' ) schema = core_schema.arguments_v3_schema([param]) v = SchemaValidator(schema) assert v.validate_python({'a': 'hello'}) == (('hello',), {}) ``` ### Returns `ArgumentsV3Parameter` ### Parameters **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The name to use for the argument parameter **`schema`** : `CoreSchema` The schema to use for the argument parameter **`mode`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['positional\_only', 'positional\_or\_keyword', 'keyword\_only', 'var\_args', 'var\_kwargs\_uniform', 'var\_kwargs\_unpacked\_typed\_dict'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The mode to use for the argument parameter **`alias`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\] | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`int`](https://docs.python.org/3/library/functions.html#int)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The alias to use for the argument parameter ## arguments\_v3\_schema ```python def arguments_v3_schema( arguments: list[ArgumentsV3Parameter], validate_by_name: bool | None = None, validate_by_alias: bool | None = None, extra_behavior: Literal['forbid', 'ignore'] | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> ArgumentsV3Schema ``` Returns a schema that matches an arguments schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema param_a = core_schema.arguments_v3_parameter( name='a', schema=core_schema.str_schema(), mode='positional_only' ) param_b = core_schema.arguments_v3_parameter( name='kwargs', schema=core_schema.bool_schema(), mode='var_kwargs_uniform' ) schema = core_schema.arguments_v3_schema([param_a, param_b]) v = SchemaValidator(schema) assert v.validate_python({'a': 'hi', 'kwargs': {'b': True}}) == (('hi',), {'b': True}) ``` This schema is currently not used by other Pydantic components. In V3, it will most likely become the default arguments schema for the `'call'` schema. ### Returns `ArgumentsV3Schema` ### Parameters **`arguments`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`ArgumentsV3Parameter`\] The arguments to use for the arguments schema. **`validate_by_name`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to populate by the parameter names, defaults to `False`. **`validate_by_alias`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to populate by the parameter aliases, defaults to `True`. **`extra_behavior`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['forbid', 'ignore'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The extra behavior to use. **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places. **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core. **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema. ## call\_schema ```python def call_schema( arguments: CoreSchema, function: Callable[..., Any], function_name: str | None = None, return_schema: CoreSchema | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> CallSchema ``` Returns a schema that matches an arguments schema, then calls a function, e.g.: ```py from pydantic_core import SchemaValidator, core_schema param_a = core_schema.arguments_parameter( name='a', schema=core_schema.str_schema(), mode='positional_only' ) param_b = core_schema.arguments_parameter( name='b', schema=core_schema.bool_schema(), mode='positional_only' ) args_schema = core_schema.arguments_schema([param_a, param_b]) schema = core_schema.call_schema( arguments=args_schema, function=lambda a, b: a + str(not b), return_schema=core_schema.str_schema(), ) v = SchemaValidator(schema) assert v.validate_python((('hello', True))) == 'helloFalse' ``` ### Returns `CallSchema` ### Parameters **`arguments`** : `CoreSchema` The arguments to use for the arguments schema **`function`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] The function to use for the call schema **`function_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The function name to use for the call schema, if not provided `function.__name__` is used **`return_schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The return schema to use for the call schema **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## custom\_error\_schema ```python def custom_error_schema( schema: CoreSchema, custom_error_type: str, custom_error_message: str | None = None, custom_error_context: dict[str, Any] | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> CustomErrorSchema ``` Returns a schema that matches a custom error value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.custom_error_schema( schema=core_schema.int_schema(), custom_error_type='MyError', custom_error_message='Error msg', ) v = SchemaValidator(schema) v.validate_python(1) ``` ### Returns `CustomErrorSchema` ### Parameters **`schema`** : `CoreSchema` The schema to use for the custom error schema **`custom_error_type`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The custom error type to use for the custom error schema **`custom_error_message`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error message to use for the custom error schema **`custom_error_context`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The custom error context to use for the custom error schema **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## json\_schema ```python def json_schema( schema: CoreSchema | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> JsonSchema ``` Returns a schema that matches a JSON value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema dict_schema = core_schema.model_fields_schema( { 'field_a': core_schema.model_field(core_schema.str_schema()), 'field_b': core_schema.model_field(core_schema.bool_schema()), }, ) class MyModel: __slots__ = ( '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__', ) field_a: str field_b: bool json_schema = core_schema.json_schema(schema=dict_schema) schema = core_schema.model_schema(cls=MyModel, schema=json_schema) v = SchemaValidator(schema) m = v.validate_python('{"field_a": "hello", "field_b": true}') assert isinstance(m, MyModel) ``` ### Returns `JsonSchema` ### Parameters **`schema`** : `CoreSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The schema to use for the JSON schema **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## url\_schema ```python def url_schema( max_length: int | None = None, allowed_schemes: list[str] | None = None, host_required: bool | None = None, default_host: str | None = None, default_port: int | None = None, default_path: str | None = None, preserve_empty_path: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> UrlSchema ``` Returns a schema that matches a URL value, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.url_schema() v = SchemaValidator(schema) print(v.validate_python('https://example.com')) #> https://example.com/ ``` ### Returns `UrlSchema` ### Parameters **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the URL **`allowed_schemes`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The allowed URL schemes **`host_required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the URL must have a host **`default_host`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default host to use if the URL does not have a host **`default_port`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default port to use if the URL does not have a port **`default_path`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default path to use if the URL does not have a path **`preserve_empty_path`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to preserve an empty path or convert it to '/', default False **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use strict URL parsing **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## multi\_host\_url\_schema ```python def multi_host_url_schema( max_length: int | None = None, allowed_schemes: list[str] | None = None, host_required: bool | None = None, default_host: str | None = None, default_port: int | None = None, default_path: str | None = None, preserve_empty_path: bool | None = None, strict: bool | None = None, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> MultiHostUrlSchema ``` Returns a schema that matches a URL value with possibly multiple hosts, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.multi_host_url_schema() v = SchemaValidator(schema) print(v.validate_python('redis://localhost,0.0.0.0,127.0.0.1')) #> redis://localhost,0.0.0.0,127.0.0.1 ``` ### Returns `MultiHostUrlSchema` ### Parameters **`max_length`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The maximum length of the URL **`allowed_schemes`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The allowed URL schemes **`host_required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether the URL must have a host **`default_host`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default host to use if the URL does not have a host **`default_port`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default port to use if the URL does not have a port **`default_path`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The default path to use if the URL does not have a path **`preserve_empty_path`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to preserve an empty path or convert it to '/', default False **`strict`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to use strict URL parsing **`ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` optional unique identifier of the schema, used to reference the schema in other places **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## definitions\_schema ```python def definitions_schema( schema: CoreSchema, definitions: list[CoreSchema], ) -> DefinitionsSchema ``` Build a schema that contains both an inner schema and a list of definitions which can be used within the inner schema. ```py from pydantic_core import SchemaValidator, core_schema schema = core_schema.definitions_schema( core_schema.list_schema(core_schema.definition_reference_schema('foobar')), [core_schema.int_schema(ref='foobar')], ) v = SchemaValidator(schema) assert v.validate_python([1, 2, '3']) == [1, 2, 3] ``` ### Returns `DefinitionsSchema` ### Parameters **`schema`** : `CoreSchema` The inner schema **`definitions`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[`CoreSchema`\] List of definitions which can be referenced within inner schema ## definition\_reference\_schema ```python def definition_reference_schema( schema_ref: str, ref: str | None = None, metadata: dict[str, Any] | None = None, serialization: SerSchema | None = None, ) -> DefinitionReferenceSchema ``` Returns a schema that points to a schema stored in "definitions", this is useful for nested recursive models and also when you want to define validators separately from the main schema, e.g.: ```py from pydantic_core import SchemaValidator, core_schema schema_definition = core_schema.definition_reference_schema('list-schema') schema = core_schema.definitions_schema( schema=schema_definition, definitions=[ core_schema.list_schema(items_schema=schema_definition, ref='list-schema'), ], ) v = SchemaValidator(schema) assert v.validate_python([()]) == [[]] ``` ### Returns `DefinitionReferenceSchema` ### Parameters **`schema_ref`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The schema ref to use for the definition reference schema **`metadata`** : [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Any other information you want to include with the schema, not used by pydantic-core **`serialization`** : `SerSchema` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Custom serialization schema ## iter\_union\_choices ```python def iter_union_choices(union_schema: UnionSchema) -> Generator[CoreSchema] ``` Iterate over the choices of a `'union'` schema. ### Returns [`Generator`](https://docs.python.org/3/library/typing.html#typing.Generator)\[`CoreSchema`\] ## WhenUsed Values have the following meanings: - `'always'` means always use - `'unless-none'` means use unless the value is `None` - `'json'` means use when serializing to JSON - `'json-unless-none'` means use when serializing to JSON and the value is not `None` **Default:** `Literal['always', 'unless-none', 'json', 'json-unless-none']` --- # [Color](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_color/) # Color Color definitions are used as per the CSS3 [CSS Color Module Level 3](http://www.w3.org/TR/css3-color/#svg-color) specification. A few colors have multiple names referring to the same colors, e.g. `grey` and `gray` or `aqua` and `cyan`. In these cases the _last_ color when sorted alphabetically takes precedence. eg. `Color((0, 255, 255)).as_named() == 'cyan'` because "cyan" comes after "aqua". ## RGBA Internal use only as a representation of a color. ## Color **Bases:** `Representation` Represents a color. ### Methods #### original ```python def original() -> ColorType ``` Original value passed to `Color`. ##### Returns `ColorType` #### as\_named ```python def as_named(fallback: bool = False) -> str ``` Returns the name of the color if it can be found in `COLORS_BY_VALUE` dictionary, otherwise returns the hexadecimal representation of the color or raises `ValueError`. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The name of the color, or the hexadecimal representation of the color. ##### Parameters **`fallback`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` If True, falls back to returning the hexadecimal representation of the color instead of raising a ValueError when no named color is found. ##### Raises - `ValueError` -- When no named color is found and fallback is `False`. #### as\_hex ```python def as_hex(format: Literal['short', 'long'] = 'short') -> str ``` Returns the hexadecimal representation of the color. Hex string representing the color can be 3, 4, 6, or 8 characters depending on whether the string a "short" representation of the color is possible and whether there's an alpha channel. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The hexadecimal representation of the color. #### as\_rgb ```python def as_rgb() -> str ``` Color as an `rgb(, , )` or `rgba(, , , )` string. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### as\_rgb\_tuple ```python def as_rgb_tuple(alpha: bool | None = None) -> ColorTuple ``` Returns the color as an RGB or RGBA tuple. ##### Returns `ColorTuple` -- A tuple that contains the values of the red, green, and blue channels in the range 0 to 255. If alpha is included, it is in the range 0 to 1. ##### Parameters **`alpha`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to include the alpha channel. There are three options for this input: - `None` (default): Include alpha only if it's set. (e.g. not `None`) - `True`: Always include alpha. - `False`: Always omit alpha. #### as\_hsl ```python def as_hsl() -> str ``` Color as an `hsl(, , )` or `hsl(, , , )` string. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### as\_hsl\_tuple ```python def as_hsl_tuple(alpha: bool | None = None) -> HslColorTuple ``` Returns the color as an HSL or HSLA tuple. ##### Returns `HslColorTuple` -- The color as a tuple of hue, saturation, lightness, and alpha (if included). All elements are in the range 0 to 1. ##### Parameters **`alpha`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to include the alpha channel. - `None` (default): Include the alpha channel only if it's set (e.g. not `None`). - `True`: Always include alpha. - `False`: Always omit alpha. ## parse\_tuple ```python def parse_tuple(value: tuple[Any, ...]) -> RGBA ``` Parse a tuple or list to get RGBA values. ### Returns `RGBA` -- An `RGBA` tuple parsed from the input tuple. ### Parameters **`value`** : [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), ...\] A tuple or list. ### Raises - `PydanticCustomError` -- If tuple is not valid. ## parse\_str ```python def parse_str(value: str) -> RGBA ``` Parse a string representing a color to an RGBA tuple. Possible formats for the input string include: - named color, see `COLORS_BY_NAME` - hex short eg. `fff` (prefix can be `#`, `0x` or nothing) - hex long eg. `ffffff` (prefix can be `#`, `0x` or nothing) - `rgb(, , )` - `rgba(, , , )` - `transparent` ### Returns `RGBA` -- An `RGBA` tuple parsed from the input string. ### Parameters **`value`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) A string representing a color. ### Raises - `ValueError` -- If the input string cannot be parsed to an RGBA tuple. ## ints\_to\_rgba ```python def ints_to_rgba( r: int | str, g: int | str, b: int | str, alpha: float | None = None, ) -> RGBA ``` Converts integer or string values for RGB color and an optional alpha value to an `RGBA` object. ### Returns `RGBA` -- An instance of the `RGBA` class with the corresponding color and alpha values. ### Parameters **`r`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) An integer or string representing the red color value. **`g`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) An integer or string representing the green color value. **`b`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) An integer or string representing the blue color value. **`alpha`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A float representing the alpha value. Defaults to None. ## parse\_color\_value ```python def parse_color_value(value: int | str, max_val: int = 255) -> float ``` Parse the color value provided and return a number between 0 and 1. ### Returns [`float`](https://docs.python.org/3/library/functions.html#float) -- A number between 0 and 1. ### Parameters **`value`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) An integer or string color value. **`max_val`** : [`int`](https://docs.python.org/3/library/functions.html#int) _Default:_ `255` Maximum range value. Defaults to 255. ### Raises - `PydanticCustomError` -- If the value is not a valid color. ## parse\_float\_alpha ```python def parse_float_alpha(value: None | str | float | int) -> float | None ``` Parse an alpha value checking it's a valid float in the range 0 to 1. ### Returns [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) -- The parsed value as a float, or `None` if the value was None or equal 1. ### Parameters **`value`** : [`None`](https://docs.python.org/3/library/constants.html#None) | [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`float`](https://docs.python.org/3/library/functions.html#float) | [`int`](https://docs.python.org/3/library/functions.html#int) The input value to parse. ### Raises - `PydanticCustomError` -- If the input value cannot be successfully parsed as a float in the expected range. ## parse\_hsl ```python def parse_hsl( h: str, h_units: str, sat: str, light: str, alpha: float | None = None, ) -> RGBA ``` Parse raw hue, saturation, lightness, and alpha values and convert to RGBA. ### Returns `RGBA` -- An instance of `RGBA`. ### Parameters **`h`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The hue value. **`h_units`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The unit for hue value. **`sat`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The saturation value. **`light`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The lightness value. **`alpha`** : [`float`](https://docs.python.org/3/library/functions.html#float) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Alpha value. ## float\_to\_255 ```python def float_to_255(c: float) -> int ``` Converts a float value between 0 and 1 (inclusive) to an integer between 0 and 255 (inclusive). ### Returns [`int`](https://docs.python.org/3/library/functions.html#int) -- The integer equivalent of the given float value rounded to the nearest whole number. ### Parameters **`c`** : [`float`](https://docs.python.org/3/library/functions.html#float) The float value to be converted. Must be between 0 and 1 (inclusive). --- # [Coordinate](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_coordinate/) # Coordinate The `pydantic_extra_types.coordinate` module provides the [`Latitude`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_coordinate/#pydantic_extra_types.coordinate.Latitude), [`Longitude`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_coordinate/#pydantic_extra_types.coordinate.Longitude), and [`Coordinate`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_coordinate/#pydantic_extra_types.coordinate.Coordinate) data types. ## Latitude **Bases:** [`float`](https://docs.python.org/3/library/functions.html#float) Latitude value should be between -90 and 90, inclusive. Supports both float and Decimal types. ```py from decimal import Decimal from pydantic import BaseModel from pydantic_extra_types.coordinate import Latitude class Location(BaseModel): latitude: Latitude # Using float location1 = Location(latitude=41.40338) # Using Decimal location2 = Location(latitude=Decimal('41.40338')) ``` ## Longitude **Bases:** [`float`](https://docs.python.org/3/library/functions.html#float) Longitude value should be between -180 and 180, inclusive. Supports both float and Decimal types. ```py from decimal import Decimal from pydantic import BaseModel from pydantic_extra_types.coordinate import Longitude class Location(BaseModel): longitude: Longitude # Using float location1 = Location(longitude=2.17403) # Using Decimal location2 = Location(longitude=Decimal('2.17403')) ``` ## Coordinate **Bases:** `Representation` Coordinate parses Latitude and Longitude. You can use the `Coordinate` data type for storing coordinates. Coordinates can be defined using one of the following formats: 1. Tuple: `(Latitude, Longitude)`. For example: `(41.40338, 2.17403)` or `(Decimal('41.40338'), Decimal('2.17403'))`. 2. `Coordinate` instance: `Coordinate(latitude=Latitude, longitude=Longitude)`. ```py from decimal import Decimal from pydantic import BaseModel from pydantic_extra_types.coordinate import Coordinate class Location(BaseModel): coordinate: Coordinate # Using float values location1 = Location(coordinate=(41.40338, 2.17403)) # > coordinate=Coordinate(latitude=41.40338, longitude=2.17403) # Using Decimal values location2 = Location(coordinate=(Decimal('41.40338'), Decimal('2.17403'))) # > coordinate=Coordinate(latitude=41.40338, longitude=2.17403) ``` --- # [Country](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_country/) # Country Country definitions that are based on the [ISO 3166](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). ## CountryAlpha2 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) CountryAlpha2 parses country codes in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. ```py from pydantic import BaseModel from pydantic_extra_types.country import CountryAlpha2 class Product(BaseModel): made_in: CountryAlpha2 product = Product(made_in='ES') print(product) # > made_in='ES' ``` ### Attributes #### alpha3 The country code in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### numeric\_code The country code in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### short\_name The country short name. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## CountryAlpha3 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) CountryAlpha3 parses country codes in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) format. ```py from pydantic import BaseModel from pydantic_extra_types.country import CountryAlpha3 class Product(BaseModel): made_in: CountryAlpha3 product = Product(made_in='USA') print(product) # > made_in='USA' ``` ### Attributes #### alpha2 The country code in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### numeric\_code The country code in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### short\_name The country short name. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## CountryNumericCode **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) CountryNumericCode parses country codes in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format. ```py from pydantic import BaseModel from pydantic_extra_types.country import CountryNumericCode class Product(BaseModel): made_in: CountryNumericCode product = Product(made_in='840') print(product) # > made_in='840' ``` ### Attributes #### alpha2 The country code in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### alpha3 The country code in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### short\_name The country short name. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## CountryShortName **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) CountryShortName parses country codes in the short name format. ```py from pydantic import BaseModel from pydantic_extra_types.country import CountryShortName class Product(BaseModel): made_in: CountryShortName product = Product(made_in='United States') print(product) # > made_in='United States' ``` ### Attributes #### alpha2 The country code in the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### alpha3 The country code in the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### numeric\_code The country code in the [ISO 3166-1 numeric](https://en.wikipedia.org/wiki/ISO_3166-1_numeric) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) --- # [Currency](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_currency_code/) # Currency Currency definitions that are based on the [ISO4217](https://en.wikipedia.org/wiki/ISO_4217). ## ISO4217 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ISO4217 parses Currency in the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) format. ```py from pydantic import BaseModel from pydantic_extra_types.currency_code import ISO4217 class Currency(BaseModel): alpha_3: ISO4217 currency = Currency(alpha_3='AED') print(currency) # > alpha_3='AED' ``` ## Currency **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) Currency parses currency subset of the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) format. It excludes bonds testing codes and precious metals. ```py from pydantic import BaseModel from pydantic_extra_types.currency_code import Currency class currency(BaseModel): alpha_3: Currency cur = currency(alpha_3='AED') print(cur) # > alpha_3='AED' ``` --- # [ISBN](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_isbn/) # ISBN The `pydantic_extra_types.isbn` module provides functionality to receive and validate ISBN. ISBN (International Standard Book Number) is a numeric commercial book identifier which is intended to be unique. This module provides an ISBN type for Pydantic models. ## ISBN **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) Represents a ISBN and provides methods for conversion, validation, and serialization. ```py from pydantic import BaseModel from pydantic_extra_types.isbn import ISBN class Book(BaseModel): isbn: ISBN book = Book(isbn='8537809667') print(book) # > isbn='9788537809662' ``` ### Methods #### validate\_isbn\_format `@staticmethod` ```python def validate_isbn_format(value: str) -> None ``` Validate a ISBN format from the provided str value. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) ##### Parameters **`value`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The str value representing the ISBN in 10 or 13 digits. ##### Raises - `PydanticCustomError` -- If the ISBN is not valid. #### convert\_isbn10\_to\_isbn13 `@staticmethod` ```python def convert_isbn10_to_isbn13(value: str) -> str ``` Convert an ISBN-10 to ISBN-13. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The converted ISBN or the original value if no conversion is necessary. ##### Parameters **`value`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The ISBN-10 value to be converted. ## isbn10\_digit\_calc ```python def isbn10_digit_calc(isbn: str) -> str ``` Calculate the ISBN-10 check digit from the provided str value. More information on the validation algorithm on [Wikipedia](https://en.wikipedia.org/wiki/ISBN#Check_digits) ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The calculated last digit of the ISBN-10 value. ### Parameters **`isbn`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The str value representing the ISBN in 10 digits. ## isbn13\_digit\_calc ```python def isbn13_digit_calc(isbn: str) -> str ``` Calc a ISBN-13 last digit from the provided str value. More information on the validation algorithm on [Wikipedia](https://en.wikipedia.org/wiki/ISBN#Check_digits) ### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The calculated last digit of the ISBN-13 value. ### Parameters **`isbn`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The str value representing the ISBN in 13 digits. --- # [Language](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_language_code/) # Language Language definitions that are based on the [ISO 639-3](https://en.wikipedia.org/wiki/ISO_639-3) & [ISO 639-5](https://en.wikipedia.org/wiki/ISO_639-5). ## LanguageInfo LanguageInfo is a dataclass that contains the language information. ### Constructor Parameters **`alpha2`** : [`Union`](https://docs.python.org/3/library/typing.html#typing.Union)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`None`](https://docs.python.org/3/library/constants.html#None)\] The language code in the [ISO 639-1 alpha-2](https://en.wikipedia.org/wiki/ISO_639-1) format. **`alpha3`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The language code in the [ISO 639-3 alpha-3](https://en.wikipedia.org/wiki/ISO_639-3) format. **`name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The language name. ## LanguageAlpha2 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) LanguageAlpha2 parses languages codes in the [ISO 639-1 alpha-2](https://en.wikipedia.org/wiki/ISO_639-1) format. ```py from pydantic import BaseModel from pydantic_extra_types.language_code import LanguageAlpha2 class Movie(BaseModel): audio_lang: LanguageAlpha2 subtitles_lang: LanguageAlpha2 movie = Movie(audio_lang='de', subtitles_lang='fr') print(movie) # > audio_lang='de' subtitles_lang='fr' ``` ### Attributes #### alpha3 The language code in the [ISO 639-3 alpha-3](https://en.wikipedia.org/wiki/ISO_639-3) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) #### name The language name. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## LanguageName **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) LanguageName parses languages names listed in the [ISO 639-3 standard](https://en.wikipedia.org/wiki/ISO_639-3) format. ```py from pydantic import BaseModel from pydantic_extra_types.language_code import LanguageName class Movie(BaseModel): audio_lang: LanguageName subtitles_lang: LanguageName movie = Movie(audio_lang='Dutch', subtitles_lang='Mandarin Chinese') print(movie) # > audio_lang='Dutch' subtitles_lang='Mandarin Chinese' ``` ### Attributes #### alpha2 The language code in the [ISO 639-1 alpha-2](https://en.wikipedia.org/wiki/ISO_639-1) format. Does not exist for all languages. **Type:** [`Union`](https://docs.python.org/3/library/typing.html#typing.Union)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`None`](https://docs.python.org/3/library/constants.html#None)\] #### alpha3 The language code in the [ISO 639-3 alpha-3](https://en.wikipedia.org/wiki/ISO_639-3) format. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ## ISO639\_3 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ISO639\_3 parses Language in the [ISO 639-3 alpha-3](https://en.wikipedia.org/wiki/ISO_639-3_alpha-3) format. ```py from pydantic import BaseModel from pydantic_extra_types.language_code import ISO639_3 class Language(BaseModel): alpha_3: ISO639_3 lang = Language(alpha_3='ssr') print(lang) # > alpha_3='ssr' ``` ## ISO639\_5 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ISO639\_5 parses Language in the [ISO 639-5 alpha-3](https://en.wikipedia.org/wiki/ISO_639-5_alpha-3) format. ```py from pydantic import BaseModel from pydantic_extra_types.language_code import ISO639_5 class Language(BaseModel): alpha_3: ISO639_5 lang = Language(alpha_3='gem') print(lang) # > alpha_3='gem' ``` --- # [Mac Address](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_mac_address/) # Mac Address The MAC address module provides functionality to parse and validate MAC addresses in different formats, such as IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet format. ## MacAddress **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) Represents a MAC address and provides methods for conversion, validation, and serialization. ```py from pydantic import BaseModel from pydantic_extra_types.mac_address import MacAddress class Network(BaseModel): mac_address: MacAddress network = Network(mac_address='00:00:5e:00:53:01') print(network) # > mac_address='00:00:5e:00:53:01' ``` ### Methods #### validate\_mac\_address `@staticmethod` ```python def validate_mac_address(value: bytes) -> str ``` Validate a MAC Address from the provided byte value. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) --- # [Payment](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_payment/) # Payment The `pydantic_extra_types.payment` module provides the [`PaymentCardNumber`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_payment/#pydantic_extra_types.payment.PaymentCardNumber) data type. ## PaymentCardBrand **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str), `Enum` Payment card brands supported by the [`PaymentCardNumber`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_payment/#pydantic_extra_types.payment.PaymentCardNumber). ## PaymentCardNumber **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) A [payment card number](https://en.wikipedia.org/wiki/Payment_card_number). ### Attributes #### strip\_whitespace Whether to strip whitespace from the input value. **Type:** [`bool`](https://docs.python.org/3/library/functions.html#bool) **Default:** `True` #### min\_length The minimum length of the card number. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) **Default:** `12` #### max\_length The maximum length of the card number. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) **Default:** `19` #### bin The first 6 digits of the card number. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) **Default:** `card_number[:6]` #### last4 The last 4 digits of the card number. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) **Default:** `card_number[(-4):]` #### brand The brand of the card. **Type:** `PaymentCardBrand` **Default:** `self.validate_brand(card_number)` #### masked The masked card number. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ### Methods #### validate `@classmethod` ```python def validate( cls, __input_value: str, _: core_schema.ValidationInfo, ) -> PaymentCardNumber ``` Validate the `PaymentCardNumber` instance. ##### Returns [`PaymentCardNumber`](/docs/validation/latest/api/pydantic/types/#pydantic.types.PaymentCardNumber) -- The validated `PaymentCardNumber` instance. ##### Parameters **`__input_value`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The input value to validate. **`_`** : `core_schema.ValidationInfo` The validation info. #### validate\_digits `@classmethod` ```python def validate_digits(cls, card_number: str) -> None ``` Validate that the card number is all digits. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) ##### Parameters **`card_number`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The card number to validate. ##### Raises - `PydanticCustomError` -- If the card number is not all digits. #### validate\_luhn\_check\_digit `@classmethod` ```python def validate_luhn_check_digit(cls, card_number: str) -> str ``` Validate the payment card number. Based on the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm). ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The validated card number. ##### Parameters **`card_number`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The card number to validate. ##### Raises - `PydanticCustomError` -- If the card number is not valid. #### validate\_brand `@staticmethod` ```python def validate_brand(card_number: str) -> PaymentCardBrand ``` Validate length based on [BIN](https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_\(IIN\)) for major brands. ##### Returns `PaymentCardBrand` -- The validated card brand. ##### Parameters **`card_number`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The card number to validate. ##### Raises - `PydanticCustomError` -- If the card number is not valid. --- # [Pendulum](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_pendulum_dt/) # Pendulum Native Pendulum DateTime object implementation. This is a copy of the Pendulum DateTime object, but with a Pydantic CoreSchema implementation. This allows Pydantic to validate the DateTime object. ## DateTime **Bases:** `_DateTime` A `pendulum.DateTime` object. At runtime, this type decomposes into pendulum.DateTime automatically. This type exists because Pydantic throws a fit on unknown types. ```python from pydantic import BaseModel from pydantic_extra_types.pendulum_dt import DateTime class test_model(BaseModel): dt: DateTime print(test_model(dt='2021-01-01T00:00:00+00:00')) # > test_model(dt=DateTime(2021, 1, 1, 0, 0, 0, tzinfo=FixedTimezone(0, name="+00:00"))) ``` ## Time **Bases:** `_Time` A `pendulum.Time` object. At runtime, this type decomposes into pendulum.Time automatically. This type exists because Pydantic throws a fit on unknown types. ```python from pydantic import BaseModel from pydantic_extra_types.pendulum_dt import Time class test_model(BaseModel): dt: Time print(test_model(dt='00:00:00')) # > test_model(dt=Time(0, 0, 0)) ``` ## Date **Bases:** `_Date` A `pendulum.Date` object. At runtime, this type decomposes into pendulum.Date automatically. This type exists because Pydantic throws a fit on unknown types. ```python from pydantic import BaseModel from pydantic_extra_types.pendulum_dt import Date class test_model(BaseModel): dt: Date print(test_model(dt='2021-01-01')) # > test_model(dt=Date(2021, 1, 1)) ``` ## Duration **Bases:** `_Duration` A `pendulum.Duration` object. At runtime, this type decomposes into pendulum.Duration automatically. This type exists because Pydantic throws a fit on unknown types. ```python from pydantic import BaseModel from pydantic_extra_types.pendulum_dt import Duration class test_model(BaseModel): delta_t: Duration print(test_model(delta_t='P1DT25H')) # > test_model(delta_t=Duration(days=2, hours=1)) ``` ### Methods #### to\_iso8601\_string ```python def to_iso8601_string() -> str ``` Convert a Duration object to an ISO 8601 string. In addition to the standard ISO 8601 format, this method also supports the representation of fractions of a second and negative durations. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The ISO 8601 string representation of the duration. --- # [Phone Numbers](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_phone_numbers/) # Phone Numbers The `pydantic_extra_types.phone_numbers` module provides the [`PhoneNumber`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_phone_numbers/#pydantic_extra_types.phone_numbers.PhoneNumber) data type. This class depends on the [phonenumbers](https://pypi.org/project/phonenumbers/) package, which is a Python port of Google's [libphonenumber](https://github.com/google/libphonenumber/). ## PhoneNumber **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) A wrapper around the `phonenumbers.PhoneNumber` object. It provides class-level configuration points you can change by subclassing: ## Examples ### Normal usage: ```python from pydantic import BaseModel from pydantic_extra_types.phone_numbers import PhoneNumber class Contact(BaseModel): name: str phone: PhoneNumber c = Contact(name='Alice', phone='+1 650-253-0000') print(c.phone) # > tel:+1-650-253-0000 (formatted using RFC3966 by default) ``` ### Changing defaults by subclassing: ```python from pydantic_extra_types.phone_numbers import PhoneNumber class USPhone(PhoneNumber): default_region_code = 'US' supported_regions = ['US'] phone_format = 'NATIONAL' # Now parsing will accept national numbers for the US p = USPhone('650-253-0000') print(p) # > 650-253-0000 ``` ### Changing defaults by using the provided validator annotation: ```python from typing import Annotated, Union import phonenumbers from pydantic import BaseModel from pydantic_extra_types.phone_numbers import PhoneNumberValidator E164NumberType = Annotated[Union[str, phonenumbers.PhoneNumber], PhoneNumberValidator(number_format='E164')] class Model(BaseModel): phone: E164NumberType m = Model(phone='+1 650-253-0000') print(m.phone) # > +16502530000 ``` ### Attributes #### default\_region\_code The default region code to use when parsing phone numbers without an international prefix. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` #### supported\_regions The supported regions. If empty, all regions are supported. **Type:** [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] **Default:** `[]` #### phone\_format The format of the phone number. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) **Default:** `'RFC3966'` ## PhoneNumberValidator An annotation to validate `phonenumbers.PhoneNumber` objects. ### Attributes #### default\_region The default region code to use when parsing phone numbers without an international prefix. If `None` (the default), the region must be supplied in the phone number as an international prefix. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` #### number\_format The format of the phone number to return. See `phonenumbers.PhoneNumberFormat` for valid values. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) **Default:** `'RFC3966'` #### supported\_regions The supported regions. If empty (the default), all regions are supported. **Type:** [`Sequence`](https://docs.python.org/3/library/typing.html#typing.Sequence)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`None`](https://docs.python.org/3/library/constants.html#None) **Default:** `None` --- # [Routing Numbers](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_routing_numbers/) # Routing Numbers The `pydantic_extra_types.routing_number` module provides the [`ABARoutingNumber`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_routing_numbers/#pydantic_extra_types.routing_number.ABARoutingNumber) data type. ## ABARoutingNumber **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) The `ABARoutingNumber` data type is a string of 9 digits representing an ABA routing transit number. The algorithm used to validate the routing number is described in the [ABA routing transit number](https://en.wikipedia.org/wiki/ABA_routing_transit_number#Check_digit) Wikipedia article. ```py from pydantic import BaseModel from pydantic_extra_types.routing_number import ABARoutingNumber class BankAccount(BaseModel): routing_number: ABARoutingNumber account = BankAccount(routing_number='122105155') print(account) # > routing_number='122105155' ``` --- # [Script Code](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_script_code/) # Script Code script definitions that are based on the [ISO 15924](https://en.wikipedia.org/wiki/ISO_15924) ## ISO\_15924 **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) ISO\_15924 parses script in the [ISO 15924](https://en.wikipedia.org/wiki/ISO_15924) format. ```py from pydantic import BaseModel from pydantic_extra_types.script_code import ISO_15924 class Script(BaseModel): alpha_4: ISO_15924 script = Script(alpha_4='Java') print(lang) # > script='Java' ``` --- # [Semantic Version](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_semantic_version/) # Semantic Version SemanticVersion definition that is based on the Semantiv Versioning Specification [semver](https://semver.org/). ## SemanticVersion **Bases:** `Version` Semantic version based on the official [semver thread](https://python-semver.readthedocs.io/en/latest/advanced/combine-pydantic-and-semver.html). --- # [Timezone Name](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_timezone_name/) # Timezone Name Time zone name validation and serialization module. ## TimeZoneName **Bases:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) TimeZoneName is a custom string subclass for validating and serializing timezone names. The TimeZoneName class uses the IANA Time Zone Database for validation. It supports both strict and non-strict modes for timezone name validation. ## Examples: Some examples of using the TimeZoneName class: ### Normal usage: ```python from pydantic_extra_types.timezone_name import TimeZoneName from pydantic import BaseModel class Location(BaseModel): city: str timezone: TimeZoneName loc = Location(city="New York", timezone="America/New_York") print(loc.timezone) >> America/New_York ``` ### Non-strict mode: ```python from pydantic_extra_types.timezone_name import TimeZoneName, timezone_name_settings @timezone_name_settings(strict=False) class TZNonStrict(TimeZoneName): pass tz = TZNonStrict("america/new_york") print(tz) >> america/new_york ``` ## get\_timezones ```python def get_timezones() -> set[str] ``` Determine the timezone provider and return available timezones. ### Returns [`set`](https://docs.python.org/3/reference/expressions.html#set)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] --- # [ULID](https://pydantic.dev/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_ulid/) # ULID The `pydantic_extra_types.ULID` module provides the \[`ULID`\] data type. This class depends on the \[python-ulid\] package, which is a validate by the [ULID-spec](https://github.com/ulid/spec#implementations-in-other-languages). ## ULID **Bases:** `Representation` A wrapper around [python-ulid](https://pypi.org/project/python-ulid/) package, which is a validate by the [ULID-spec](https://github.com/ulid/spec#implementations-in-other-languages). --- # [Pydantic Settings](https://pydantic.dev/docs/validation/latest/api/pydantic_settings/) # Pydantic Settings ## SettingsError **Bases:** [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) Base exception for settings-related errors. ## PyprojectTomlConfigSettingsSource **Bases:** `TomlConfigSettingsSource` A source class that loads variables from a `pyproject.toml` file. ## JsonConfigSettingsSource **Bases:** `InitSettingsSource`, `ConfigFileSourceMixin` A source class that loads variables from a JSON file ## NoDecode Annotation to prevent decoding of a field value. ## SecretsSettingsSource **Bases:** `PydanticBaseEnvSettingsSource` Source class for loading settings values from secret files. ### Methods #### find\_case\_path `@classmethod` ```python def find_case_path( cls, dir_path: Path, file_name: str, case_sensitive: bool, ) -> Path | None ``` Find a file within path's directory matching filename, optionally ignoring case. ##### Returns `Path` | [`None`](https://docs.python.org/3/library/constants.html#None) -- Whether file path or `None` if file does not exist in directory. ##### Parameters **`dir_path`** : `Path` Directory path. **`file_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) File name. **`case_sensitive`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) Whether to search for file name case sensitively. #### get\_field\_value ```python def get_field_value(field: FieldInfo, field_name: str) -> tuple[Any, str, bool] ``` Gets the value for field from secret file and a flag to determine whether value is complex. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`bool`](https://docs.python.org/3/library/functions.html#bool)\] -- A tuple that contains the value (`None` if the file does not exist), key, and a flag to determine whether value is complex. ##### Parameters **`field`** : `FieldInfo` The field. **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. ## ForceDecode Annotation to force decoding of a field value. ## DotEnvSettingsSource **Bases:** `EnvSettingsSource` Source class for loading settings values from env files. ## YamlConfigSettingsSource **Bases:** `InitSettingsSource`, `ConfigFileSourceMixin` A source class that loads variables from a yaml file ## EnvSettingsSource **Bases:** `PydanticBaseEnvSettingsSource` Source class for loading settings values from environment variables. ### Methods #### get\_field\_value ```python def get_field_value(field: FieldInfo, field_name: str) -> tuple[Any, str, bool] ``` Gets the value for field from environment variables and a flag to determine whether value is complex. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`bool`](https://docs.python.org/3/library/functions.html#bool)\] -- A tuple that contains the value (`None` if not found), key, and a flag to determine whether value is complex. ##### Parameters **`field`** : `FieldInfo` The field. **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. #### prepare\_field\_value ```python def prepare_field_value( field_name: str, field: FieldInfo, value: Any, value_is_complex: bool, ) -> Any ``` Prepare value for the field. - Extract value for nested field. - Deserialize value to python object for complex field. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- A tuple contains prepared value for the field. ##### Parameters **`field`** : `FieldInfo` The field. **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. ##### Raises - `ValuesError` -- When There is an error in deserializing value for complex field. #### next\_field ```python def next_field( field: FieldInfo | Any | None, key: str, case_sensitive: bool | None = None, ) -> FieldInfo | None ``` Find the field in a sub model by key(env name) By having the following models: ```py class SubSubModel(BaseSettings): dvals: Dict class SubModel(BaseSettings): vals: list[str] sub_sub_model: SubSubModel class Cfg(BaseSettings): sub_model: SubModel ``` ##### Returns `FieldInfo` | [`None`](https://docs.python.org/3/library/constants.html#None) -- Field if it finds the next field otherwise `None`. ##### Parameters **`field`** : `FieldInfo` | [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) | [`None`](https://docs.python.org/3/library/constants.html#None) The field. **`key`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The key (env name). **`case_sensitive`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to search for key case sensitively. #### explode\_env\_vars ```python def explode_env_vars( field_name: str, field: FieldInfo, env_vars: Mapping[str, str | None], ) -> dict[str, Any] ``` Process env\_vars and extract the values of keys containing env\_nested\_delimiter into nested dictionaries. This is applied to a single field, hence filtering by env\_var prefix. ##### Returns [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] -- A dictionary contains extracted values from nested env values. ##### Parameters **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. **`field`** : `FieldInfo` The field. **`env_vars`** : [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None)\] Environment variables. ## TomlConfigSettingsSource **Bases:** `InitSettingsSource`, `ConfigFileSourceMixin` A source class that loads variables from a TOML file ## SettingsConfigDict **Bases:** [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) ### Attributes #### yaml\_config\_section Specifies the section in a YAML file from which to load the settings. Supports dot-notation for nested paths (e.g., 'config.app.settings'). If provided, the settings will be loaded from the specified section. This is useful when the YAML file contains multiple configuration sections and you only want to load a specific subset into your settings model. **Type:** [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) #### pyproject\_toml\_depth Number of levels **up** from the current working directory to attempt to find a pyproject.toml file. This is only used when a pyproject.toml file is not found in the current working directory. **Type:** [`int`](https://docs.python.org/3/library/functions.html#int) #### pyproject\_toml\_table\_header Header of the TOML table within a pyproject.toml file to use when filling variables. This is supplied as a `tuple[str, ...]` instead of a `str` to accommodate for headers containing a `.`. For example, `toml_table_header = ("tool", "my.tool", "foo")` can be used to fill variable values from a table with header `[tool."my.tool".foo]`. To use the root table, exclude this config setting or provide an empty tuple. **Type:** [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), ...\] ## PydanticBaseSettingsSource **Bases:** `ABC` Abstract base class for settings sources, every settings source classes should inherit from it. ### Attributes #### current\_state The current state of the settings, populated by the previous settings sources. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] #### settings\_sources\_data The state of all previous settings sources. **Type:** [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\] ### Methods #### get\_field\_value `@abstractmethod` ```python def get_field_value(field: FieldInfo, field_name: str) -> tuple[Any, str, bool] ``` Gets the value, the key for model creation, and a flag to determine whether value is complex. This is an abstract method that should be overridden in every settings source classes. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any), [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`bool`](https://docs.python.org/3/library/functions.html#bool)\] -- A tuple that contains the value, key and a flag to determine whether value is complex. ##### Parameters **`field`** : `FieldInfo` The field. **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. #### field\_is\_complex ```python def field_is_complex(field: FieldInfo) -> bool ``` Checks whether a field is complex, in which case it will attempt to be parsed as JSON. ##### Returns [`bool`](https://docs.python.org/3/library/functions.html#bool) -- Whether the field is complex. ##### Parameters **`field`** : `FieldInfo` The field. #### prepare\_field\_value ```python def prepare_field_value( field_name: str, field: FieldInfo, value: Any, value_is_complex: bool, ) -> Any ``` Prepares the value of a field. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The prepared value. ##### Parameters **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. **`field`** : `FieldInfo` The field. **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The value of the field that has to be prepared. **`value_is_complex`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) A flag to determine whether value is complex. #### decode\_complex\_value ```python def decode_complex_value(field_name: str, field: FieldInfo, value: Any) -> Any ``` Decode the value for a complex field ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- The decoded value for further preparation ##### Parameters **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The field name. **`field`** : `FieldInfo` The field. **`value`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) The value of the field that has to be prepared. ## BaseSettings **Bases:** [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) Base class for settings, allowing values to be overridden by environment variables. This is useful in production for secrets you do not wish to save in code, it plays nicely with docker(-compose), Heroku and any 12 factor app design. All the below attributes can be set via `model_config`. ### Constructor Parameters **`_case_sensitive`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether environment and CLI variable names should be read with case-sensitivity. Defaults to `None`. **`_nested_model_default_partial_update`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to allow partial updates on nested model default object fields. Defaults to `False`. **`_env_prefix`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Prefix for all environment variables. Defaults to `None`. **`_env_prefix_target`** : `EnvPrefixTarget` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Targets to which `_env_prefix` is applied. Default: `variable`. **`_env_file`** : `DotenvType` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `ENV_FILE_SENTINEL` The env file(s) to load settings values from. Defaults to `Path('')`, which means that the value from `model_config['env_file']` should be used. You can also pass `None` to indicate that environment variables should not be loaded from an env file. **`_env_file_encoding`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The env file encoding, e.g. `'latin-1'`. Defaults to `None`. **`_env_ignore_empty`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Ignore environment variables where the value is an empty string. Default to `False`. **`_env_nested_delimiter`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The nested env values delimiter. Defaults to `None`. **`_env_nested_max_split`** : [`int`](https://docs.python.org/3/library/functions.html#int) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The nested env values maximum nesting. Defaults to `None`, which means no limit. **`_env_parse_none_str`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The env string value that should be parsed (e.g. "null", "void", "None", etc.) into `None` type(None). Defaults to `None` type(None), which means no parsing should occur. **`_env_parse_enums`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Parse enum field names to values. Defaults to `None.`, which means no parsing should occur. **`_cli_prog_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The CLI program name to display in help text. Defaults to `None` if \_cli\_parse\_args is `None`. Otherwise, defaults to sys.argv\[0\]. **`_cli_parse_args`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), ...\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The list of CLI arguments to parse. Defaults to None. If set to `True`, defaults to sys.argv\[1:\]. **`_cli_settings_source`** : `CliSettingsSource`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Override the default CLI settings source with a user defined instance. Defaults to None. **`_cli_parse_none_str`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The CLI string value that should be parsed (e.g. "null", "void", "None", etc.) into `None` type(None). Defaults to \_env\_parse\_none\_str value if set. Otherwise, defaults to "null" if \_cli\_avoid\_json is `False`, and "None" if \_cli\_avoid\_json is `True`. **`_cli_hide_none_type`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Hide `None` values in CLI help text. Defaults to `False`. **`_cli_avoid_json`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Avoid complex JSON objects in CLI help text. Defaults to `False`. **`_cli_enforce_required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Enforce required fields at the CLI. Defaults to `False`. **`_cli_use_class_docs_for_groups`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Use class docstrings in CLI group help text instead of field descriptions. Defaults to `False`. **`_cli_exit_on_error`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines whether or not the internal parser exits with error info when an error occurs. Defaults to `True`. **`_cli_prefix`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The root parser command line arguments prefix. Defaults to "". **`_cli_flag_prefix_char`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The flag prefix character to use for CLI optional arguments. Defaults to '-'. **`_cli_implicit_flags`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['dual', 'toggle'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Controls how `bool` fields are exposed as CLI flags. - False (default): no implicit flags are generated; booleans must be set explicitly (e.g. --flag=true). - True / 'dual': optional boolean fields generate both positive and negative forms (--flag and --no-flag). - 'toggle': required boolean fields remain in 'dual' mode, while optional boolean fields generate a single flag aligned with the default value (if default=False, expose --flag; if default=True, expose --no-flag). **`_cli_ignore_unknown_args`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore unknown CLI args and parse only known ones. Defaults to `False`. **`_cli_kebab_case`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['all', 'no\_enums'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` CLI args use kebab case. Defaults to `False`. **`_cli_shortcuts`** : [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Mapping of target field name to alias names. Defaults to `None`. **`_secrets_dir`** : `PathType` | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The secret files directory or a sequence of directories. Defaults to `None`. **`_build_sources`** : [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`PydanticBaseSettingsSource`, ...\], [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Pre-initialized sources and init kwargs to use for building instantiation values. Defaults to `None`. ### Methods #### settings\_customise\_sources `@classmethod` ```python def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...] ``` Define the sources and their order for loading the settings values. ##### Returns [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[`PydanticBaseSettingsSource`, ...\] -- A tuple containing the sources and their order for loading the settings values. ##### Parameters **`settings_cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`BaseSettings`\] The Settings class. **`init_settings`** : `PydanticBaseSettingsSource` The `InitSettingsSource` instance. **`env_settings`** : `PydanticBaseSettingsSource` The `EnvSettingsSource` instance. **`dotenv_settings`** : `PydanticBaseSettingsSource` The `DotEnvSettingsSource` instance. **`file_secret_settings`** : `PydanticBaseSettingsSource` The `SecretsSettingsSource` instance. ## GoogleSecretManagerSettingsSource **Bases:** `EnvSettingsSource` ### Methods #### get\_field\_value ```python def get_field_value(field: FieldInfo, field_name: str) -> tuple[Any, str, bool] ``` Override get\_field\_value to get the secret value from GCP Secret Manager. Look for a SecretVersion metadata field to specify a particular SecretVersion. ##### Returns [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) -- A tuple of (value, key, value\_is\_complex), where `key` is the identifier used [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- to populate the model (either the field name or an alias, depending on [`bool`](https://docs.python.org/3/library/functions.html#bool) -- configuration). ##### Parameters **`field`** : `FieldInfo` The field to get the value for **`field_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) The declared name of the field ## CliSettingsSource **Bases:** `EnvSettingsSource`, `Generic[T]` Source class for loading settings values from CLI. ### Constructor Parameters **`cli_prog_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The CLI program name to display in help text. Defaults to `None` if cli\_parse\_args is `None`. Otherwise, defaults to sys.argv\[0\]. **`cli_parse_args`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | [`tuple`](https://docs.python.org/3/library/stdtypes.html#tuple)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), ...\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The list of CLI arguments to parse. Defaults to None. If set to `True`, defaults to sys.argv\[1:\]. **`cli_parse_none_str`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The CLI string value that should be parsed (e.g. "null", "void", "None", etc.) into `None` type(None). Defaults to "null" if cli\_avoid\_json is `False`, and "None" if cli\_avoid\_json is `True`. **`cli_hide_none_type`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Hide `None` values in CLI help text. Defaults to `False`. **`cli_avoid_json`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Avoid complex JSON objects in CLI help text. Defaults to `False`. **`cli_enforce_required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Enforce required fields at the CLI. Defaults to `False`. **`cli_use_class_docs_for_groups`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Use class docstrings in CLI group help text instead of field descriptions. Defaults to `False`. **`cli_exit_on_error`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines whether or not the internal parser exits with error info when an error occurs. Defaults to `True`. **`cli_prefix`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Prefix for command line arguments added under the root parser. Defaults to "". **`cli_flag_prefix_char`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The flag prefix character to use for CLI optional arguments. Defaults to '-'. **`cli_implicit_flags`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['dual', 'toggle'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Controls how `bool` fields are exposed as CLI flags. - False (default): no implicit flags are generated; booleans must be set explicitly (e.g. --flag=true). - True / 'dual': optional boolean fields generate both positive and negative forms (--flag and --no-flag). - 'toggle': required boolean fields remain in 'dual' mode, while optional boolean fields generate a single flag aligned with the default value (if default=False, expose --flag; if default=True, expose --no-flag). **`cli_ignore_unknown_args`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Whether to ignore unknown CLI args and parse only known ones. Defaults to `False`. **`cli_kebab_case`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['all', 'no\_enums'\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` CLI args use kebab case. Defaults to `False`. **`cli_shortcuts`** : [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`str`](https://docs.python.org/3/library/stdtypes.html#str) | [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\]\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Mapping of target field name to alias names. Defaults to `None`. **`case_sensitive`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `True` Whether CLI "--arg" names should be read with case-sensitivity. Defaults to `True`. Note: Case-insensitive matching is only supported on the internal root parser and does not apply to CLI subcommands. **`root_parser`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `None` The root parser object. **`parse_args_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The root parser parse args method. Defaults to `argparse.ArgumentParser.parse_args`. **`add_argument_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `ArgumentParser.add_argument` The root parser add argument method. Defaults to `argparse.ArgumentParser.add_argument`. **`add_argument_group_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `ArgumentParser.add_argument_group` The root parser add argument group method. Defaults to `argparse.ArgumentParser.add_argument_group`. **`add_parser_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `_SubParsersAction.add_parser` The root parser add new parser (sub-command) method. Defaults to `argparse._SubParsersAction.add_parser`. **`add_subparsers_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `ArgumentParser.add_subparsers` The root parser add subparsers (sub-commands) method. Defaults to `argparse.ArgumentParser.add_subparsers`. **`format_help_method`** : [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable)\[..., [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `ArgumentParser.format_help` The root parser format help method. Defaults to `argparse.ArgumentParser.format_help`. **`formatter_class`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `RawDescriptionHelpFormatter` A class for customizing the root parser help text. Defaults to `argparse.RawDescriptionHelpFormatter`. ### Attributes #### root\_parser The connected root parser instance. **Type:** `T` ## InitSettingsSource **Bases:** `PydanticBaseSettingsSource` Source class for loading values provided during settings class initialization. ## CliApp A utility class for running Pydantic `BaseSettings`, `BaseModel`, or `pydantic.dataclasses.dataclass` as CLI applications. ### Methods #### run `@staticmethod` ```python def run( model_cls: type[T], cli_args: list[str] | Namespace | SimpleNamespace | dict[str, Any] | None = None, cli_settings_source: CliSettingsSource[Any] | None = None, cli_exit_on_error: bool | None = None, cli_cmd_method_name: str = 'cli_cmd', model_init_data: Any = {}, ) -> T ``` Runs a Pydantic `BaseSettings`, `BaseModel`, or `pydantic.dataclasses.dataclass` as a CLI application. Running a model as a CLI application requires the `cli_cmd` method to be defined in the model class. ##### Returns `T` -- The ran instance of model. ##### Parameters **`model_cls`** : [`type`](https://docs.python.org/3/glossary.html#term-type)\[`T`\] The model class to run as a CLI application. **`cli_args`** : [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] | `Namespace` | `SimpleNamespace` | [`dict`](https://docs.python.org/3/reference/expressions.html#dict)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str), [`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` The list of CLI arguments to parse. If `cli_settings_source` is specified, this may also be a namespace or dictionary of pre-parsed CLI arguments. Defaults to `sys.argv[1:]`. **`cli_settings_source`** : `CliSettingsSource`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Override the default CLI settings source with a user defined instance. Defaults to `None`. **`cli_exit_on_error`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines whether this function exits on error. If model is subclass of `BaseSettings`, defaults to BaseSettings `cli_exit_on_error` value. Otherwise, defaults to `True`. **`cli_cmd_method_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `'cli_cmd'` The CLI command method name to run. Defaults to "cli\_cmd". **`model_init_data`** : [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) _Default:_ `{}` The model init data. ##### Raises - `SettingsError` -- If model\_cls is not subclass of `BaseModel` or `pydantic.dataclasses.dataclass`. - `SettingsError` -- If model\_cls does not have a `cli_cmd` entrypoint defined. #### run\_subcommand `@staticmethod` ```python def run_subcommand( model: PydanticModel, cli_exit_on_error: bool | None = None, cli_cmd_method_name: str = 'cli_cmd', ) -> PydanticModel ``` Runs the model subcommand. Running a model subcommand requires the `cli_cmd` method to be defined in the nested model subcommand class. ##### Returns `PydanticModel` -- The ran subcommand model. ##### Parameters **`model`** : `PydanticModel` The model to run the subcommand from. **`cli_exit_on_error`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines whether this function exits with error if no subcommand is found. Defaults to model\_config `cli_exit_on_error` value if set. Otherwise, defaults to `True`. **`cli_cmd_method_name`** : [`str`](https://docs.python.org/3/library/stdtypes.html#str) _Default:_ `'cli_cmd'` The CLI command method name to run. Defaults to "cli\_cmd". ##### Raises - `SystemExit` -- When no subcommand is found and cli\_exit\_on\_error=`True` (the default). - `SettingsError` -- When no subcommand is found and cli\_exit\_on\_error=`False`. #### serialize `@staticmethod` ```python def serialize( model: PydanticModel, list_style: Literal['json', 'argparse', 'lazy'] = 'json', dict_style: Literal['json', 'env'] = 'json', positionals_first: bool = False, ) -> list[str] ``` Serializes the CLI arguments for a Pydantic data model. ##### Returns [`list`](https://docs.python.org/3/glossary.html#term-list)\[[`str`](https://docs.python.org/3/library/stdtypes.html#str)\] -- The serialized CLI arguments for the data model. ##### Parameters **`model`** : `PydanticModel` The data model to serialize. **`list_style`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['json', 'argparse', 'lazy'\] _Default:_ `'json'` Controls how list-valued fields are serialized on the command line. - 'json' (default): Lists are encoded as a single JSON array. Example: `--tags '["a","b","c"]'` - 'argparse': Each list element becomes its own repeated flag, following typical `argparse` conventions. Example: `--tags a --tags b --tags c` - 'lazy': Lists are emitted as a single comma-separated string without JSON quoting or escaping. Example: `--tags a,b,c` **`dict_style`** : [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal)\['json', 'env'\] _Default:_ `'json'` Controls how dictionary-valued fields are serialized. - 'json' (default): The entire dictionary is emitted as a single JSON object. Example: `--config '{"host": "localhost", "port": 5432}'` - 'env': The dictionary is flattened into multiple CLI flags using environment-variable-style assignement. Example: `--config host=localhost --config port=5432` **`positionals_first`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Controls whether positional arguments should be serialized first compared to optional arguments. Defaults to `False`. #### format\_help `@staticmethod` ```python def format_help( model: PydanticModel | type[T], cli_settings_source: CliSettingsSource[Any] | None = None, strip_ansi_color: bool = False, ) -> str ``` Return a string containing a help message for a Pydantic model. ##### Returns [`str`](https://docs.python.org/3/library/stdtypes.html#str) -- The help message string for the model. ##### Parameters **`model`** : `PydanticModel` | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`T`\] The model or model class. **`cli_settings_source`** : `CliSettingsSource`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Override the default CLI settings source with a user defined instance. Defaults to `None`. **`strip_ansi_color`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Strips ANSI color codes from the help message when set to `True`. #### print\_help `@staticmethod` ```python def print_help( model: PydanticModel | type[T], cli_settings_source: CliSettingsSource[Any] | None = None, file: TextIO | None = None, strip_ansi_color: bool = False, ) -> None ``` Print a help message for a Pydantic model. ##### Returns [`None`](https://docs.python.org/3/library/constants.html#None) ##### Parameters **`model`** : `PydanticModel` | [`type`](https://docs.python.org/3/glossary.html#term-type)\[`T`\] The model or model class. **`cli_settings_source`** : `CliSettingsSource`\[[`Any`](https://docs.python.org/3/library/typing.html#typing.Any)\] | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Override the default CLI settings source with a user defined instance. Defaults to `None`. **`file`** : [`TextIO`](https://docs.python.org/3/library/typing.html#typing.TextIO) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` A text stream to which the help message is written. If `None`, the output is sent to sys.stdout. **`strip_ansi_color`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `False` Strips ANSI color codes from the help message when set to `True`. ## get\_subcommand ```python def get_subcommand( model: PydanticModel, is_required: bool = True, cli_exit_on_error: bool | None = None, _suppress_errors: list[SettingsError | SystemExit] | None = None, ) -> PydanticModel | None ``` Get the subcommand from a model. ### Returns `PydanticModel` | [`None`](https://docs.python.org/3/library/constants.html#None) -- The subcommand model if found, otherwise `None`. ### Parameters **`model`** : `PydanticModel` The model to get the subcommand from. **`is_required`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) _Default:_ `True` Determines whether a model must have subcommand set and raises error if not found. Defaults to `True`. **`cli_exit_on_error`** : [`bool`](https://docs.python.org/3/library/functions.html#bool) | [`None`](https://docs.python.org/3/library/constants.html#None) _Default:_ `None` Determines whether this function exits with error if no subcommand is found. Defaults to model\_config `cli_exit_on_error` value if set. Otherwise, defaults to `True`. ### Raises - `SystemExit` -- When no subcommand is found and is\_required=`True` and cli\_exit\_on\_error=`True` (the default). - `SettingsError` -- When no subcommand is found and is\_required=`True` and cli\_exit\_on\_error=`False`. --- # [Alias](https://pydantic.dev/docs/validation/latest/concepts/alias/) # Alias An alias is an alternative name for a field, used when serializing and deserializing data. You can specify an alias in the following ways: - `alias` on the [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) - must be a `str` - `validation_alias` on the [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) - can be an instance of `str`, [`AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath), or [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) - `serialization_alias` on the [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) - must be a `str` - `alias_generator` on the [`Config`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.alias_generator) - can be a callable or an instance of [`AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator) For examples of how to use `alias`, `validation_alias`, and `serialization_alias`, see [Field aliases](/docs/validation/latest/concepts/fields#field-aliases). ## `AliasPath` and `AliasChoices` API Documentation [`pydantic.aliases.AliasPath`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasPath) [`pydantic.aliases.AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) Pydantic provides two special types for convenience when using `validation_alias`: `AliasPath` and `AliasChoices`. The `AliasPath` is used to specify a path to a field using aliases. For example: ```python from pydantic import BaseModel, Field, AliasPath class User(BaseModel): first_name: str = Field(validation_alias=AliasPath('names', 0)) last_name: str = Field(validation_alias=AliasPath('names', 1)) address: str = Field(validation_alias=AliasPath('contact', 'address')) user = User.model_validate({ # (1) 'names': ['John', 'Doe'], 'contact': {'address': '221B Baker Street'} }) print(user) #> first_name='John' last_name='Doe' address='221B Baker Street' ``` We are using [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate) to validate a dictionary using the field aliases. Refer to documentation about [validating data](/docs/validation/latest/concepts/models#validating-data) for more details. In the `'first_name'` field, we are using the alias `'names'` and the index `0` to specify the path to the first name. In the `'last_name'` field, we are using the alias `'names'` and the index `1` to specify the path to the last name. `AliasChoices` is used to specify a list of choices of aliases. Choices that appear first in the list will have higher priority during validation. For example: ```python from pydantic import BaseModel, Field, AliasChoices class User(BaseModel): first_name: str = Field(validation_alias=AliasChoices('first_name', 'fname')) last_name: str = Field(validation_alias=AliasChoices('last_name', 'lname')) user = User.model_validate({'fname': 'John', 'lname': 'Doe'}) # (1) print(user) #> first_name='John' last_name='Doe' user = User.model_validate({'first_name': 'John', 'lname': 'Doe'}) # (2) print(user) #> first_name='John' last_name='Doe' user = User.model_validate({'first_name': 'John', 'fname': 'J', 'lname': 'Doe'}) # (3) print(user) #> first_name='John' last_name='Doe' ``` We are using the second alias choice for both fields. We are using the first alias choice for the field `'first_name'` and the second alias choice for the field `'last_name'`. Both `'first_name'` and `'fname'` are provided, `'first_name'` is used because it has higher priority. You can also use `AliasChoices` with `AliasPath`: ```python from pydantic import BaseModel, Field, AliasPath, AliasChoices class User(BaseModel): first_name: str = Field(validation_alias=AliasChoices('first_name', AliasPath('names', 0))) last_name: str = Field(validation_alias=AliasChoices('last_name', AliasPath('names', 1))) user = User.model_validate({'first_name': 'John', 'last_name': 'Doe'}) print(user) #> first_name='John' last_name='Doe' user = User.model_validate({'names': ['John', 'Doe']}) print(user) #> first_name='John' last_name='Doe' user = User.model_validate({'names': ['John'], 'last_name': 'Doe'}) print(user) #> first_name='John' last_name='Doe' ``` ## Using alias generators You can use the `alias_generator` parameter of [`Config`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.alias_generator) to specify a callable (or group of callables, via `AliasGenerator`) that will generate aliases for all fields in a model. This is useful if you want to use a consistent naming convention for all fields in a model, but do not want to specify the alias for each field individually. Note Pydantic offers three built-in alias generators that you can use out of the box: [`to_pascal`](/docs/validation/latest/api/pydantic/config/#pydantic.alias_generators.to_pascal) [`to_camel`](/docs/validation/latest/api/pydantic/config/#pydantic.alias_generators.to_camel) [`to_snake`](/docs/validation/latest/api/pydantic/config/#pydantic.alias_generators.to_snake) ### Using a callable Here's a basic example using a callable: ```python from pydantic import BaseModel, ConfigDict class Tree(BaseModel): model_config = ConfigDict( alias_generator=lambda field_name: field_name.upper() ) age: int height: float kind: str t = Tree.model_validate({'AGE': 12, 'HEIGHT': 1.2, 'KIND': 'oak'}) print(t.model_dump(by_alias=True)) #> {'AGE': 12, 'HEIGHT': 1.2, 'KIND': 'oak'} ``` ### Using an `AliasGenerator` API Documentation [`pydantic.aliases.AliasGenerator`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasGenerator) `AliasGenerator` is a class that allows you to specify multiple alias generators for a model. You can use an `AliasGenerator` to specify different alias generators for validation and serialization. This is particularly useful if you need to use different naming conventions for loading and saving data, but you don't want to specify the validation and serialization aliases for each field individually. For example: ```python from pydantic import AliasGenerator, BaseModel, ConfigDict class Tree(BaseModel): model_config = ConfigDict( alias_generator=AliasGenerator( validation_alias=lambda field_name: field_name.upper(), serialization_alias=lambda field_name: field_name.title(), ) ) age: int height: float kind: str t = Tree.model_validate({'AGE': 12, 'HEIGHT': 1.2, 'KIND': 'oak'}) print(t.model_dump(by_alias=True)) #> {'Age': 12, 'Height': 1.2, 'Kind': 'oak'} ``` ## Alias Precedence If you specify an `alias` on the [`Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field), it will take precedence over the generated alias by default: ```python from pydantic import BaseModel, ConfigDict, Field def to_camel(string: str) -> str: return ''.join(word.capitalize() for word in string.split('_')) class Voice(BaseModel): model_config = ConfigDict(alias_generator=to_camel) name: str language_code: str = Field(alias='lang') voice = Voice(Name='Filiz', lang='tr-TR') print(voice.language_code) #> tr-TR print(voice.model_dump(by_alias=True)) #> {'Name': 'Filiz', 'lang': 'tr-TR'} ``` ### Alias Priority You may set `alias_priority` on a field to change this behavior: - `alias_priority=2` the alias will _not_ be overridden by the alias generator. - `alias_priority=1` the alias _will_ be overridden by the alias generator. - `alias_priority` not set: - alias is set: the alias will _not_ be overridden by the alias generator. - alias is not set: the alias _will_ be overridden by the alias generator. The same precedence applies to `validation_alias` and `serialization_alias`. See more about the different field aliases under [field aliases](/docs/validation/latest/concepts/fields#field-aliases). ## Alias Configuration You can use [`ConfigDict`](/docs/validation/latest/concepts/config) settings or runtime validation/serialization settings to control whether or not aliases are used. ### `ConfigDict` Settings You can use [configuration settings](/docs/validation/latest/concepts/config) to control, at the model level, whether or not aliases are used for validation and serialization. If you would like to control this behavior for nested models/surpassing the config-model boundary, use [runtime settings](#runtime-settings). #### Validation When validating data, you can enable population of attributes by attribute name, alias, or both. **By default**, Pydantic uses aliases for validation. Further configuration is available via: - [`ConfigDict.validate_by_alias`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_alias): `True` by default - [`ConfigDict.validate_by_name`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_name): `False` by default - [validate\_by\_alias](#tab-panel-570) - [validate\_by\_name](#tab-panel-571) - [validate\_by\_alias and validate\_by\_name](#tab-panel-572) ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') model_config = ConfigDict(validate_by_alias=True, validate_by_name=False) print(repr(Model(my_alias='foo'))) # (1) #> Model(my_field='foo') ``` The alias `my_alias` is used for validation. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') model_config = ConfigDict(validate_by_alias=False, validate_by_name=True) print(repr(Model(my_field='foo'))) # (1) #> Model(my_field='foo') ``` the attribute identifier `my_field` is used for validation. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') model_config = ConfigDict(validate_by_alias=True, validate_by_name=True) print(repr(Model(my_alias='foo'))) # (1) #> Model(my_field='foo') print(repr(Model(my_field='foo'))) # (2) #> Model(my_field='foo') ``` The alias `my_alias` is used for validation. the attribute identifier `my_field` is used for validation. Caution You cannot set both `validate_by_alias` and `validate_by_name` to `False`. A [user error](/docs/validation/latest/errors/usage_errors#validate-by-alias-and-name-false) is raised in this case. #### Serialization When serializing data, you can enable serialization by alias, which is disabled by default. See the [`ConfigDict.serialize_by_alias`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.serialize_by_alias) API documentation for more details. ```python from pydantic import BaseModel, ConfigDict, Field class Model(BaseModel): my_field: str = Field(serialization_alias='my_alias') model_config = ConfigDict(serialize_by_alias=True) m = Model(my_field='foo') print(m.model_dump()) # (1) #> {'my_alias': 'foo'} ``` The alias `my_alias` is used for serialization. Note The fact that serialization by alias is disabled by default is notably inconsistent with the default for validation (where aliases are used by default). We anticipate changing this default in V3. ### Runtime Settings You can use runtime alias flags to control alias use for validation and serialization on a per-call basis. If you would like to control this behavior on a model level, use [`ConfigDict` settings](#configdict-settings). #### Validation When validating data, you can enable population of attributes by attribute name, alias, or both. The `by_alias` and `by_name` flags are available on the [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate), [`model_validate_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json), and [`model_validate_strings()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_strings) methods, as well as the [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) validation methods. By default: - `by_alias` is `True` - `by_name` is `False` - [by\_alias](#tab-panel-573) - [by\_name](#tab-panel-574) - [validate\_by\_alias and validate\_by\_name](#tab-panel-575) ```python from pydantic import BaseModel, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') m = Model.model_validate( {'my_alias': 'foo'}, # (1) by_alias=True, by_name=False, ) print(repr(m)) #> Model(my_field='foo') ``` The alias `my_alias` is used for validation. ```python from pydantic import BaseModel, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') m = Model.model_validate( {'my_field': 'foo'}, by_alias=False, by_name=True # (1) ) print(repr(m)) #> Model(my_field='foo') ``` The attribute name `my_field` is used for validation. ```python from pydantic import BaseModel, Field class Model(BaseModel): my_field: str = Field(validation_alias='my_alias') m = Model.model_validate( {'my_alias': 'foo'}, by_alias=True, by_name=True # (1) ) print(repr(m)) #> Model(my_field='foo') m = Model.model_validate( {'my_field': 'foo'}, by_alias=True, by_name=True # (2) ) print(repr(m)) #> Model(my_field='foo') ``` The alias `my_alias` is used for validation. The attribute name `my_field` is used for validation. Caution You cannot set both `by_alias` and `by_name` to `False`. A [user error](/docs/validation/latest/errors/usage_errors#validate-by-alias-and-name-false) is raised in this case. #### Serialization When serializing data, you can enable serialization by alias via the `by_alias` flag which is available on the [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) and [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) methods, as well as the [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) ones. By default, `by_alias` is `False`. ```py from pydantic import BaseModel, Field class Model(BaseModel): my_field: str = Field(serialization_alias='my_alias') m = Model(my_field='foo') print(m.model_dump(by_alias=True)) # (1) #> {'my_alias': 'foo'} ``` The alias `my_alias` is used for serialization. Note The fact that serialization by alias is disabled by default is notably inconsistent with the default for validation (where aliases are used by default). We anticipate changing this default in V3. --- # [Configuration](https://pydantic.dev/docs/validation/latest/concepts/config/) # Configuration The behaviour of Pydantic can be controlled via a variety of configuration values, documented on the [`ConfigDict`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) class. This page describes how configuration can be specified for Pydantic's supported types. ## Configuration on Pydantic models On Pydantic models, configuration can be specified in two ways: - Using the [`model_config`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_config) class attribute: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): model_config = ConfigDict(str_max_length=5) # (1) v: str try: m = Model(v='abcdef') except ValidationError as e: print(e) """ 1 validation error for Model v String should have at most 5 characters [type=string_too_long, input_value='abcdef', input_type=str] """ ``` A plain dictionary (i.e. `{'str_max_length': 5}`) can also be used. Note In Pydantic V1, the `Config` class was used. This is still supported, but **deprecated**. - Using class arguments: ```python from pydantic import BaseModel class Model(BaseModel, frozen=True): a: str ``` Unlike the [`model_config`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_config) class attribute, static type checkers will recognize class arguments. For `frozen`, any instance mutation will be flagged as an type checking error. ## Configuration on Pydantic dataclasses [Pydantic dataclasses](/docs/validation/latest/concepts/dataclasses) also support configuration (read more in the [dedicated section](/docs/validation/latest/concepts/dataclasses#dataclass-config)). ```python from pydantic import ConfigDict, ValidationError from pydantic.dataclasses import dataclass @dataclass(config=ConfigDict(str_max_length=10, validate_assignment=True)) class User: name: str user = User(name='John Doe') try: user.name = 'x' * 20 except ValidationError as e: print(e) """ 1 validation error for User name String should have at most 10 characters [type=string_too_long, input_value='xxxxxxxxxxxxxxxxxxxx', input_type=str] """ ``` ## Configuration on `TypeAdapter` [Type adapters](/docs/validation/latest/concepts/type_adapter) (using the [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) class) support configuration, by providing the `config` argument. ```python from pydantic import ConfigDict, TypeAdapter ta = TypeAdapter(list[str], config=ConfigDict(coerce_numbers_to_str=True)) print(ta.validate_python([1, 2])) #> ['1', '2'] ``` Configuration can't be provided if the type adapter directly wraps a type that support it, and a [usage error](/docs/validation/latest/errors/usage_errors) is raised in this case. The [configuration propagation](#configuration-propagation) rules also apply. ## Configuration on other supported types If you are using [standard library dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses) or [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) classes, the configuration can be set in two ways: - Using the `__pydantic_config__` class attribute: ```python from dataclasses import dataclass from pydantic import ConfigDict @dataclass class User: __pydantic_config__ = ConfigDict(strict=True) id: int name: str = 'John Doe' ``` - Using the [`@with_config`](/docs/validation/latest/api/pydantic/config/#pydantic.config.with_config) decorator (this avoids static type checking errors with [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict)): ```python from typing_extensions import TypedDict from pydantic import ConfigDict, with_config @with_config(ConfigDict(str_to_lower=True)) class Model(TypedDict): x: str ``` ## Configuration on the `@validate_call` decorator The [`@validate_call`](/docs/validation/latest/concepts/validation_decorator) also supports setting custom configuration. See the [dedicated section](/docs/validation/latest/concepts/validation_decorator#custom-configuration) for more details. ## Change behaviour globally If you wish to change the behaviour of Pydantic globally, you can create your own custom parent class with a custom configuration, as the configuration is inherited: ```python from pydantic import BaseModel, ConfigDict class Parent(BaseModel): model_config = ConfigDict(extra='allow') class Model(Parent): x: str m = Model(x='foo', y='bar') print(m.model_dump()) #> {'x': 'foo', 'y': 'bar'} ``` If you provide configuration to the subclasses, it will be _merged_ with the parent configuration: ```python from pydantic import BaseModel, ConfigDict class Parent(BaseModel): model_config = ConfigDict(extra='allow', str_to_lower=False) class Model(Parent): model_config = ConfigDict(str_to_lower=True) x: str m = Model(x='FOO', y='bar') print(m.model_dump()) #> {'x': 'foo', 'y': 'bar'} print(Model.model_config) #> {'extra': 'allow', 'str_to_lower': True} ``` Caution If your model inherits from multiple bases, Pydantic currently _doesn't_ follow the [MRO](https://docs.python.org/3/glossary.html#term-method-resolution-order). For more details, see [this issue](https://github.com/pydantic/pydantic/issues/9992). ## Configuration propagation When using types that support configuration as field annotations, configuration may not be propagated: - For Pydantic models and dataclasses, configuration will _not_ be propagated, each model has its own "configuration boundary": ```python from pydantic import BaseModel, ConfigDict class User(BaseModel): name: str class Parent(BaseModel): user: User model_config = ConfigDict(str_to_lower=True) print(Parent(user={'name': 'JOHN'})) #> user=User(name='JOHN') ``` - For stdlib types (dataclasses and typed dictionaries), configuration will be propagated, unless the type has its own configuration set: ```python from dataclasses import dataclass from pydantic import BaseModel, ConfigDict, with_config @dataclass class UserWithoutConfig: name: str @dataclass @with_config(str_to_lower=False) class UserWithConfig: name: str class Parent(BaseModel): user_1: UserWithoutConfig user_2: UserWithConfig model_config = ConfigDict(str_to_lower=True) print(Parent(user_1={'name': 'JOHN'}, user_2={'name': 'JOHN'})) #> user_1=UserWithoutConfig(name='john') user_2=UserWithConfig(name='JOHN') ``` --- # [Conversion Table](https://pydantic.dev/docs/validation/latest/concepts/conversion_table/) # Conversion Table The following table provides details on how Pydantic converts data during validation in both strict and lax modes. The "Strict" column contains checkmarks for type conversions that are allowed when validating in [Strict Mode](/docs/validation/latest/concepts/strict_mode). - [All](#tab-panel-592) - [JSON](#tab-panel-593) - [JSON - Strict](#tab-panel-594) - [Python](#tab-panel-595) - [Python - Strict](#tab-panel-596) Field Type Input Strict Input Source Conditions `bool` `bool` ✓ Python & JSON `bool` `float` Python & JSON Allowed values: `0.0, 1.0`. `bool` `int` Python & JSON Allowed values: `0, 1`. `bool` `str` Python & JSON Allowed values: `'f'`, `'n'`, `'no'`, `'off'`, `'false'`, `'False'`, `'t'`, `'y'`, `'on'`, `'yes'`, `'true'`, `'True'`. `bool` `Decimal` Python Allowed values: `Decimal(0), Decimal(1)`. `bytes` `bytearray` Python `bytes` `bytes` ✓ Python `bytes` `str` ✓ JSON `bytes` `str` Python `callable` `-` JSON Never valid. `callable` `Any` ✓ Python `callable()` check must return `True`. `date` `bytes` Python Format: `YYYY-MM-DD` (UTF-8). `date` `date` ✓ Python `date` `datetime` Python Must be exact date, eg. no `H`, `M`, `S`, `f`. `date` `float` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `int` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `str` Python & JSON Format: `YYYY-MM-DD`. `date` `Decimal` Python Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `datetime` `bytes` Python Format: `YYYY-MM-DDTHH:MM:SS.f` or `YYYY-MM-DD`. See [speedate](https://docs.rs/speedate/latest/speedate/), (UTF-8). `datetime` `date` Python `datetime` `datetime` ✓ Python `datetime` `float` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `int` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `str` Python & JSON Format: `YYYY-MM-DDTHH:MM:SS.f` or `YYYY-MM-DD`. See [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `Decimal` Python Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `deque` `deque` ✓ Python `deque` `frozenset` Python `deque` `list` Python `deque` `set` Python `deque` `tuple` Python `deque` `Array` ✓ JSON `dict` `dict` ✓ Python `dict` `Mapping` Python Must implement the mapping interface and have an `items()` method. `dict` `Object` ✓ JSON `float` `bool` Python & JSON `float` `bytes` Python Must match `[0-9]+(\.[0-9]+)?`. `float` `float` ✓ Python & JSON `bool` is explicitly forbidden. `float` `int` ✓ Python & JSON `float` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `float` `Decimal` Python `frozenset` `deque` Python `frozenset` `dict_keys` Python `frozenset` `dict_values` Python `frozenset` `frozenset` ✓ Python `frozenset` `list` Python `frozenset` `set` Python `frozenset` `tuple` Python `frozenset` `Array` ✓ JSON `int` `bool` Python & JSON `int` `bytes` Python Must be numeric only, e.g. `[0-9]+`. `int` `float` Python & JSON Must be exact int, e.g. `val % 1 == 0`, raises error for `nan`, `inf`. `int` `int` ✓ Python & JSON `bool` is explicitly forbidden. `int` `int` Python & JSON `int` `str` Python & JSON Must be numeric only, e.g. `[0-9]+`. `int` `Decimal` Python Must be exact int, e.g. `val % 1 == 0`. `list` `deque` Python `list` `dict_keys` Python `list` `dict_values` Python `list` `frozenset` Python `list` `list` ✓ Python `list` `set` Python `list` `tuple` Python `list` `Array` ✓ JSON `namedtuple` `dict` ✓ Python `namedtuple` `list` ✓ Python `namedtuple` `namedtuple` ✓ Python `namedtuple` `tuple` ✓ Python `namedtuple` `Array` ✓ JSON `namedtuple` `NamedTuple` ✓ Python `set` `deque` Python `set` `dict_keys` Python `set` `dict_values` Python `set` `frozenset` Python `set` `list` Python `set` `set` ✓ Python `set` `tuple` Python `set` `Array` ✓ JSON `str` `bytearray` Python Assumes UTF-8, error on unicode decoding error. `str` `bytes` Python Assumes UTF-8, error on unicode decoding error. `str` `str` ✓ Python & JSON `time` `bytes` Python Format: `HH:MM:SS.FFFFFF`. See [speedate](https://docs.rs/speedate/latest/speedate/). `time` `float` Python & JSON Interpreted as seconds, range `0 - 86399.9*`. `time` `int` Python & JSON Interpreted as seconds, range `0 - 86399`. `time` `str` Python & JSON Format: `HH:MM:SS.FFFFFF`. See [speedate](https://docs.rs/speedate/latest/speedate/). `time` `time` ✓ Python `time` `Decimal` Python Interpreted as seconds, range `0 - 86399.9*`. `timedelta` `bytes` Python Format: `ISO8601`. See [speedate](https://docs.rs/speedate/latest/speedate/), (UTF-8). `timedelta` `float` Python & JSON Interpreted as seconds. `timedelta` `int` Python & JSON Interpreted as seconds. `timedelta` `str` Python & JSON Format: `ISO8601`. See [speedate](https://docs.rs/speedate/latest/speedate/). `timedelta` `timedelta` ✓ Python `timedelta` `Decimal` Python Interpreted as seconds. `tuple` `deque` Python `tuple` `dict_keys` Python `tuple` `dict_values` Python `tuple` `frozenset` Python `tuple` `list` Python `tuple` `set` Python `tuple` `tuple` ✓ Python `tuple` `Array` ✓ JSON `type` `type` ✓ Python `Any` `Any` ✓ Python & JSON `ByteSize` `float` ✓ Python & JSON `ByteSize` `int` ✓ Python & JSON `ByteSize` `str` ✓ Python & JSON `ByteSize` `Decimal` ✓ Python `Decimal` `float` ✓ JSON `Decimal` `float` Python & JSON `Decimal` `int` ✓ JSON `Decimal` `int` Python & JSON `Decimal` `str` ✓ JSON `Decimal` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `Decimal` `Decimal` ✓ Python `Enum` `Any` ✓ JSON Input value must be convertible to enum values. `Enum` `Any` Python Input value must be convertible to enum values. `Enum` `Enum` ✓ Python `IPv4Address` `bytes` Python `IPv4Address` `int` Python integer representing the IP address, must be less than `2**32` `IPv4Address` `str` ✓ JSON `IPv4Address` `str` Python & JSON `IPv4Address` `IPv4Address` ✓ Python `IPv4Address` `IPv4Interface` ✓ Python `IPv4Interface` `bytes` Python `IPv4Interface` `int` Python integer representing the IP address, must be less than `2**32` `IPv4Interface` `str` ✓ JSON `IPv4Interface` `str` Python & JSON `IPv4Interface` `tuple` Python `IPv4Interface` `IPv4Address` Python `IPv4Interface` `IPv4Interface` ✓ Python `IPv4Network` `bytes` Python `IPv4Network` `int` Python integer representing the IP network, must be less than `2**32` `IPv4Network` `str` ✓ JSON `IPv4Network` `str` Python & JSON `IPv4Network` `IPv4Address` Python `IPv4Network` `IPv4Interface` Python `IPv4Network` `IPv4Network` ✓ Python `IPv6Address` `bytes` Python `IPv6Address` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Address` `str` ✓ JSON `IPv6Address` `str` Python & JSON `IPv6Address` `IPv6Address` ✓ Python `IPv6Address` `IPv6Interface` ✓ Python `IPv6Interface` `bytes` Python `IPv6Interface` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Interface` `str` ✓ JSON `IPv6Interface` `str` Python & JSON `IPv6Interface` `tuple` Python `IPv6Interface` `IPv6Address` Python `IPv6Interface` `IPv6Interface` ✓ Python `IPv6Network` `bytes` Python `IPv6Network` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Network` `str` ✓ JSON `IPv6Network` `str` Python & JSON `IPv6Network` `IPv6Address` Python `IPv6Network` `IPv6Interface` Python `IPv6Network` `IPv6Network` ✓ Python `InstanceOf` `-` JSON Never valid. `InstanceOf` `Any` ✓ Python `isinstance()` check must return `True`. `IntEnum` `Any` ✓ JSON Input value must be convertible to enum values. `IntEnum` `Any` Python Input value must be convertible to enum values. `IntEnum` `IntEnum` ✓ Python `Iterable` `deque` ✓ Python `Iterable` `frozenset` ✓ Python `Iterable` `list` ✓ Python `Iterable` `set` ✓ Python `Iterable` `tuple` ✓ Python `Iterable` `Array` ✓ JSON `NamedTuple` `dict` ✓ Python `NamedTuple` `list` ✓ Python `NamedTuple` `namedtuple` ✓ Python `NamedTuple` `tuple` ✓ Python `NamedTuple` `Array` ✓ JSON `NamedTuple` `NamedTuple` ✓ Python `None` `None` ✓ Python & JSON `Path` `str` ✓ JSON `Path` `str` Python `Path` `Path` ✓ Python `Pattern` `bytes` ✓ Python Input must be a valid pattern. `Pattern` `str` ✓ Python & JSON Input must be a valid pattern. `Sequence` `deque` Python `Sequence` `list` ✓ Python `Sequence` `tuple` Python `Sequence` `Array` ✓ JSON `TypedDict` `dict` ✓ Python `TypedDict` `Any` ✓ Python `TypedDict` `Mapping` Python Must implement the mapping interface and have an `items()` method. `TypedDict` `Object` ✓ JSON `UUID` `str` ✓ JSON `UUID` `str` Python `UUID` `UUID` ✓ Python Field Type Input Strict Input Source Conditions `bool` `bool` ✓ Python & JSON `bool` `float` Python & JSON Allowed values: `0.0, 1.0`. `bool` `int` Python & JSON Allowed values: `0, 1`. `bool` `str` Python & JSON Allowed values: `'f'`, `'n'`, `'no'`, `'off'`, `'false'`, `'False'`, `'t'`, `'y'`, `'on'`, `'yes'`, `'true'`, `'True'`. `bytes` `str` ✓ JSON `callable` `-` JSON Never valid. `date` `float` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `int` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `str` Python & JSON Format: `YYYY-MM-DD`. `datetime` `float` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `int` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `str` Python & JSON Format: `YYYY-MM-DDTHH:MM:SS.f` or `YYYY-MM-DD`. See [speedate](https://docs.rs/speedate/latest/speedate/). `deque` `Array` ✓ JSON `dict` `Object` ✓ JSON `float` `bool` Python & JSON `float` `float` ✓ Python & JSON `bool` is explicitly forbidden. `float` `int` ✓ Python & JSON `float` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `frozenset` `Array` ✓ JSON `int` `bool` Python & JSON `int` `float` Python & JSON Must be exact int, e.g. `val % 1 == 0`, raises error for `nan`, `inf`. `int` `int` ✓ Python & JSON `bool` is explicitly forbidden. `int` `int` Python & JSON `int` `str` Python & JSON Must be numeric only, e.g. `[0-9]+`. `list` `Array` ✓ JSON `namedtuple` `Array` ✓ JSON `set` `Array` ✓ JSON `str` `str` ✓ Python & JSON `time` `float` Python & JSON Interpreted as seconds, range `0 - 86399.9*`. `time` `int` Python & JSON Interpreted as seconds, range `0 - 86399`. `time` `str` Python & JSON Format: `HH:MM:SS.FFFFFF`. See [speedate](https://docs.rs/speedate/latest/speedate/). `timedelta` `float` Python & JSON Interpreted as seconds. `timedelta` `int` Python & JSON Interpreted as seconds. `timedelta` `str` Python & JSON Format: `ISO8601`. See [speedate](https://docs.rs/speedate/latest/speedate/). `tuple` `Array` ✓ JSON `Any` `Any` ✓ Python & JSON `ByteSize` `float` ✓ Python & JSON `ByteSize` `int` ✓ Python & JSON `ByteSize` `str` ✓ Python & JSON `Decimal` `float` ✓ JSON `Decimal` `float` Python & JSON `Decimal` `int` ✓ JSON `Decimal` `int` Python & JSON `Decimal` `str` ✓ JSON `Decimal` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `Enum` `Any` ✓ JSON Input value must be convertible to enum values. `IPv4Address` `str` ✓ JSON `IPv4Address` `str` Python & JSON `IPv4Interface` `str` ✓ JSON `IPv4Interface` `str` Python & JSON `IPv4Network` `str` ✓ JSON `IPv4Network` `str` Python & JSON `IPv6Address` `str` ✓ JSON `IPv6Address` `str` Python & JSON `IPv6Interface` `str` ✓ JSON `IPv6Interface` `str` Python & JSON `IPv6Network` `str` ✓ JSON `IPv6Network` `str` Python & JSON `InstanceOf` `-` JSON Never valid. `IntEnum` `Any` ✓ JSON Input value must be convertible to enum values. `Iterable` `Array` ✓ JSON `NamedTuple` `Array` ✓ JSON `None` `None` ✓ Python & JSON `Path` `str` ✓ JSON `Pattern` `str` ✓ Python & JSON Input must be a valid pattern. `Sequence` `Array` ✓ JSON `TypedDict` `Object` ✓ JSON `UUID` `str` ✓ JSON Field Type Input Strict Input Source Conditions `bool` `bool` ✓ Python & JSON `bytes` `str` ✓ JSON `deque` `Array` ✓ JSON `dict` `Object` ✓ JSON `float` `float` ✓ Python & JSON `bool` is explicitly forbidden. `float` `int` ✓ Python & JSON `frozenset` `Array` ✓ JSON `int` `int` ✓ Python & JSON `bool` is explicitly forbidden. `list` `Array` ✓ JSON `namedtuple` `Array` ✓ JSON `set` `Array` ✓ JSON `str` `str` ✓ Python & JSON `tuple` `Array` ✓ JSON `Any` `Any` ✓ Python & JSON `ByteSize` `float` ✓ Python & JSON `ByteSize` `int` ✓ Python & JSON `ByteSize` `str` ✓ Python & JSON `Decimal` `float` ✓ JSON `Decimal` `int` ✓ JSON `Decimal` `str` ✓ JSON `Enum` `Any` ✓ JSON Input value must be convertible to enum values. `IPv4Address` `str` ✓ JSON `IPv4Interface` `str` ✓ JSON `IPv4Network` `str` ✓ JSON `IPv6Address` `str` ✓ JSON `IPv6Interface` `str` ✓ JSON `IPv6Network` `str` ✓ JSON `IntEnum` `Any` ✓ JSON Input value must be convertible to enum values. `Iterable` `Array` ✓ JSON `NamedTuple` `Array` ✓ JSON `None` `None` ✓ Python & JSON `Path` `str` ✓ JSON `Pattern` `str` ✓ Python & JSON Input must be a valid pattern. `Sequence` `Array` ✓ JSON `TypedDict` `Object` ✓ JSON `UUID` `str` ✓ JSON Field Type Input Strict Input Source Conditions `bool` `bool` ✓ Python & JSON `bool` `float` Python & JSON Allowed values: `0.0, 1.0`. `bool` `int` Python & JSON Allowed values: `0, 1`. `bool` `str` Python & JSON Allowed values: `'f'`, `'n'`, `'no'`, `'off'`, `'false'`, `'False'`, `'t'`, `'y'`, `'on'`, `'yes'`, `'true'`, `'True'`. `bool` `Decimal` Python Allowed values: `Decimal(0), Decimal(1)`. `bytes` `bytearray` Python `bytes` `bytes` ✓ Python `bytes` `str` Python `callable` `Any` ✓ Python `callable()` check must return `True`. `date` `bytes` Python Format: `YYYY-MM-DD` (UTF-8). `date` `date` ✓ Python `date` `datetime` Python Must be exact date, eg. no `H`, `M`, `S`, `f`. `date` `float` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `int` Python & JSON Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `date` `str` Python & JSON Format: `YYYY-MM-DD`. `date` `Decimal` Python Interpreted as seconds or ms from epoch. See [speedate](https://docs.rs/speedate/latest/speedate/). Must be exact date. `datetime` `bytes` Python Format: `YYYY-MM-DDTHH:MM:SS.f` or `YYYY-MM-DD`. See [speedate](https://docs.rs/speedate/latest/speedate/), (UTF-8). `datetime` `date` Python `datetime` `datetime` ✓ Python `datetime` `float` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `int` Python & JSON Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `str` Python & JSON Format: `YYYY-MM-DDTHH:MM:SS.f` or `YYYY-MM-DD`. See [speedate](https://docs.rs/speedate/latest/speedate/). `datetime` `Decimal` Python Interpreted as seconds or ms from epoch, see [speedate](https://docs.rs/speedate/latest/speedate/). `deque` `deque` ✓ Python `deque` `frozenset` Python `deque` `list` Python `deque` `set` Python `deque` `tuple` Python `dict` `dict` ✓ Python `dict` `Mapping` Python Must implement the mapping interface and have an `items()` method. `float` `bool` Python & JSON `float` `bytes` Python Must match `[0-9]+(\.[0-9]+)?`. `float` `float` ✓ Python & JSON `bool` is explicitly forbidden. `float` `int` ✓ Python & JSON `float` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `float` `Decimal` Python `frozenset` `deque` Python `frozenset` `dict_keys` Python `frozenset` `dict_values` Python `frozenset` `frozenset` ✓ Python `frozenset` `list` Python `frozenset` `set` Python `frozenset` `tuple` Python `int` `bool` Python & JSON `int` `bytes` Python Must be numeric only, e.g. `[0-9]+`. `int` `float` Python & JSON Must be exact int, e.g. `val % 1 == 0`, raises error for `nan`, `inf`. `int` `int` ✓ Python & JSON `bool` is explicitly forbidden. `int` `int` Python & JSON `int` `str` Python & JSON Must be numeric only, e.g. `[0-9]+`. `int` `Decimal` Python Must be exact int, e.g. `val % 1 == 0`. `list` `deque` Python `list` `dict_keys` Python `list` `dict_values` Python `list` `frozenset` Python `list` `list` ✓ Python `list` `set` Python `list` `tuple` Python `namedtuple` `dict` ✓ Python `namedtuple` `list` ✓ Python `namedtuple` `namedtuple` ✓ Python `namedtuple` `tuple` ✓ Python `namedtuple` `NamedTuple` ✓ Python `set` `deque` Python `set` `dict_keys` Python `set` `dict_values` Python `set` `frozenset` Python `set` `list` Python `set` `set` ✓ Python `set` `tuple` Python `str` `bytearray` Python Assumes UTF-8, error on unicode decoding error. `str` `bytes` Python Assumes UTF-8, error on unicode decoding error. `str` `str` ✓ Python & JSON `time` `bytes` Python Format: `HH:MM:SS.FFFFFF`. See [speedate](https://docs.rs/speedate/latest/speedate/). `time` `float` Python & JSON Interpreted as seconds, range `0 - 86399.9*`. `time` `int` Python & JSON Interpreted as seconds, range `0 - 86399`. `time` `str` Python & JSON Format: `HH:MM:SS.FFFFFF`. See [speedate](https://docs.rs/speedate/latest/speedate/). `time` `time` ✓ Python `time` `Decimal` Python Interpreted as seconds, range `0 - 86399.9*`. `timedelta` `bytes` Python Format: `ISO8601`. See [speedate](https://docs.rs/speedate/latest/speedate/), (UTF-8). `timedelta` `float` Python & JSON Interpreted as seconds. `timedelta` `int` Python & JSON Interpreted as seconds. `timedelta` `str` Python & JSON Format: `ISO8601`. See [speedate](https://docs.rs/speedate/latest/speedate/). `timedelta` `timedelta` ✓ Python `timedelta` `Decimal` Python Interpreted as seconds. `tuple` `deque` Python `tuple` `dict_keys` Python `tuple` `dict_values` Python `tuple` `frozenset` Python `tuple` `list` Python `tuple` `set` Python `tuple` `tuple` ✓ Python `type` `type` ✓ Python `Any` `Any` ✓ Python & JSON `ByteSize` `float` ✓ Python & JSON `ByteSize` `int` ✓ Python & JSON `ByteSize` `str` ✓ Python & JSON `ByteSize` `Decimal` ✓ Python `Decimal` `float` Python & JSON `Decimal` `int` Python & JSON `Decimal` `str` Python & JSON Must match `[0-9]+(\.[0-9]+)?`. `Decimal` `Decimal` ✓ Python `Enum` `Any` Python Input value must be convertible to enum values. `Enum` `Enum` ✓ Python `IPv4Address` `bytes` Python `IPv4Address` `int` Python integer representing the IP address, must be less than `2**32` `IPv4Address` `str` Python & JSON `IPv4Address` `IPv4Address` ✓ Python `IPv4Address` `IPv4Interface` ✓ Python `IPv4Interface` `bytes` Python `IPv4Interface` `int` Python integer representing the IP address, must be less than `2**32` `IPv4Interface` `str` Python & JSON `IPv4Interface` `tuple` Python `IPv4Interface` `IPv4Address` Python `IPv4Interface` `IPv4Interface` ✓ Python `IPv4Network` `bytes` Python `IPv4Network` `int` Python integer representing the IP network, must be less than `2**32` `IPv4Network` `str` Python & JSON `IPv4Network` `IPv4Address` Python `IPv4Network` `IPv4Interface` Python `IPv4Network` `IPv4Network` ✓ Python `IPv6Address` `bytes` Python `IPv6Address` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Address` `str` Python & JSON `IPv6Address` `IPv6Address` ✓ Python `IPv6Address` `IPv6Interface` ✓ Python `IPv6Interface` `bytes` Python `IPv6Interface` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Interface` `str` Python & JSON `IPv6Interface` `tuple` Python `IPv6Interface` `IPv6Address` Python `IPv6Interface` `IPv6Interface` ✓ Python `IPv6Network` `bytes` Python `IPv6Network` `int` Python integer representing the IP address, must be less than `2**128` `IPv6Network` `str` Python & JSON `IPv6Network` `IPv6Address` Python `IPv6Network` `IPv6Interface` Python `IPv6Network` `IPv6Network` ✓ Python `InstanceOf` `Any` ✓ Python `isinstance()` check must return `True`. `IntEnum` `Any` Python Input value must be convertible to enum values. `IntEnum` `IntEnum` ✓ Python `Iterable` `deque` ✓ Python `Iterable` `frozenset` ✓ Python `Iterable` `list` ✓ Python `Iterable` `set` ✓ Python `Iterable` `tuple` ✓ Python `NamedTuple` `dict` ✓ Python `NamedTuple` `list` ✓ Python `NamedTuple` `namedtuple` ✓ Python `NamedTuple` `tuple` ✓ Python `NamedTuple` `NamedTuple` ✓ Python `None` `None` ✓ Python & JSON `Path` `str` Python `Path` `Path` ✓ Python `Pattern` `bytes` ✓ Python Input must be a valid pattern. `Pattern` `str` ✓ Python & JSON Input must be a valid pattern. `Sequence` `deque` Python `Sequence` `list` ✓ Python `Sequence` `tuple` Python `TypedDict` `dict` ✓ Python `TypedDict` `Any` ✓ Python `TypedDict` `Mapping` Python Must implement the mapping interface and have an `items()` method. `UUID` `str` Python `UUID` `UUID` ✓ Python Field Type Input Strict Input Source Conditions `bool` `bool` ✓ Python & JSON `bytes` `bytes` ✓ Python `callable` `Any` ✓ Python `callable()` check must return `True`. `date` `date` ✓ Python `datetime` `datetime` ✓ Python `deque` `deque` ✓ Python `dict` `dict` ✓ Python `float` `float` ✓ Python & JSON `bool` is explicitly forbidden. `float` `int` ✓ Python & JSON `frozenset` `frozenset` ✓ Python `int` `int` ✓ Python & JSON `bool` is explicitly forbidden. `list` `list` ✓ Python `namedtuple` `dict` ✓ Python `namedtuple` `list` ✓ Python `namedtuple` `namedtuple` ✓ Python `namedtuple` `tuple` ✓ Python `namedtuple` `NamedTuple` ✓ Python `set` `set` ✓ Python `str` `str` ✓ Python & JSON `time` `time` ✓ Python `timedelta` `timedelta` ✓ Python `tuple` `tuple` ✓ Python `type` `type` ✓ Python `Any` `Any` ✓ Python & JSON `ByteSize` `float` ✓ Python & JSON `ByteSize` `int` ✓ Python & JSON `ByteSize` `str` ✓ Python & JSON `ByteSize` `Decimal` ✓ Python `Decimal` `Decimal` ✓ Python `Enum` `Enum` ✓ Python `IPv4Address` `IPv4Address` ✓ Python `IPv4Address` `IPv4Interface` ✓ Python `IPv4Interface` `IPv4Interface` ✓ Python `IPv4Network` `IPv4Network` ✓ Python `IPv6Address` `IPv6Address` ✓ Python `IPv6Address` `IPv6Interface` ✓ Python `IPv6Interface` `IPv6Interface` ✓ Python `IPv6Network` `IPv6Network` ✓ Python `InstanceOf` `Any` ✓ Python `isinstance()` check must return `True`. `IntEnum` `IntEnum` ✓ Python `Iterable` `deque` ✓ Python `Iterable` `frozenset` ✓ Python `Iterable` `list` ✓ Python `Iterable` `set` ✓ Python `Iterable` `tuple` ✓ Python `NamedTuple` `dict` ✓ Python `NamedTuple` `list` ✓ Python `NamedTuple` `namedtuple` ✓ Python `NamedTuple` `tuple` ✓ Python `NamedTuple` `NamedTuple` ✓ Python `None` `None` ✓ Python & JSON `Path` `Path` ✓ Python `Pattern` `bytes` ✓ Python Input must be a valid pattern. `Pattern` `str` ✓ Python & JSON Input must be a valid pattern. `Sequence` `list` ✓ Python `TypedDict` `dict` ✓ Python `TypedDict` `Any` ✓ Python `UUID` `UUID` ✓ Python --- # [Dataclasses](https://pydantic.dev/docs/validation/latest/concepts/dataclasses/) # Dataclasses API Documentation [`@pydantic.dataclasses.dataclass`](/docs/validation/latest/api/pydantic/dataclasses/#pydantic.dataclasses.dataclass) If you don't want to use Pydantic's [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) you can instead get the same data validation on standard [dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses). ```python from datetime import datetime from typing import Optional from pydantic.dataclasses import dataclass @dataclass class User: id: int name: str = 'John Doe' signup_ts: Optional[datetime] = None user = User(id='42', signup_ts='2032-06-21T12:00') print(user) """ User(id=42, name='John Doe', signup_ts=datetime.datetime(2032, 6, 21, 12, 0)) """ ``` Note Keep in mind that Pydantic dataclasses are **not** a replacement for [Pydantic models](/docs/validation/latest/concepts/models). They provide a similar functionality to stdlib dataclasses with the addition of Pydantic validation. There are cases where using Pydantic models is the better choice. For more information and discussion see [pydantic/pydantic#710](https://github.com/pydantic/pydantic/issues/710). Similarities between Pydantic dataclasses and models include support for: - [Configuration](#dataclass-config) support (note that dataclasses doesn't support the `model_config` attribute as with Pydantic models) - [Nested](/docs/validation/latest/concepts/models#nested-models) classes - Arguments used to instantiate the dataclass are also [copied](/docs/validation/latest/concepts/models#attribute-copies). Some differences between Pydantic dataclasses and models include: - The [various methods](/docs/validation/latest/concepts/models#model-methods-and-properties) to validate, dump and generate a JSON Schema aren't available. Instead, you can wrap the dataclass with a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) and make use of its methods: ```python from pydantic import TypeAdapter from pydantic.dataclasses import dataclass @dataclass class Foo: f: int foo = Foo(f=1) TypeAdapter(Foo).dump_python(foo) #> {'f': 1} TypeAdapter(Foo).validate_python({'f': 1}) #> Foo(f=1) ``` - Validators (see the [dedicated section](#validators-and-initialization-hooks)). - The [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) configuration behavior: - Extra data is not included in [serialization](/docs/validation/latest/concepts/serialization#serializing-data). - There is no way to customize validation of extra values [using the `__pydantic_extra__` attribute](/docs/validation/latest/concepts/models#extra-data). - Generic dataclasses are supported, but as with other standard library generic types, using a parameterized dataclass won't work as expected: - [Python 3.9 and above](#tab-panel-590) - [Python 3.12 and above (new syntax)](#tab-panel-591) ```python from typing import Generic, TypeVar from pydantic.dataclasses import dataclass T = TypeVar('T') @dataclass class Foo(Generic[T]): f: T Foo[int](f='not_an_int') # (1) #> Foo(f='not_an_int') ``` Unlike [generic Pydantic models](/docs/validation/latest/concepts/models#generic-models), `Foo[int]` is a [generic alias](https://docs.python.org/3/library/stdtypes.html#types-genericalias) and not a proper type object. As such, Pydantic currently treats `Foo[int]` the same as `Foo[Any]`, without performing validation for `f`. ```python from pydantic.dataclasses import dataclass @dataclass class Foo[T]: f: T Foo[int](f='not_an_int') # (1) #> Foo(f='not_an_int') ``` Unlike [generic Pydantic models](/docs/validation/latest/concepts/models#generic-models), `Foo[int]` is a [generic alias](https://docs.python.org/3/library/stdtypes.html#types-genericalias) and not a proper type object. As such, Pydantic currently performs no validation. Instead, you can wrap the `Foo[int]` parameterized class with a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter). You can use both the Pydantic's [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) and the stdlib's [`field()`](https://docs.python.org/3/library/dataclasses.html#dataclasses.field) functions: ```python import dataclasses from typing import Optional from pydantic import Field from pydantic.dataclasses import dataclass @dataclass class User: id: int name: str = 'John Doe' friends: list[int] = dataclasses.field(default_factory=lambda: [0]) age: Optional[int] = dataclasses.field( default=None, metadata={'title': 'The age of the user', 'description': 'do not lie!'}, ) height: Optional[int] = Field( default=None, title='The height in cm', ge=50, le=300 ) user = User(id='42', height='250') print(user) #> User(id=42, name='John Doe', friends=[0], age=None, height=250) ``` The Pydantic [`@dataclass`](/docs/validation/latest/api/pydantic/dataclasses/#pydantic.dataclasses.dataclass) decorator accepts the same arguments as the standard decorator, with the addition of a `config` parameter. ## Dataclass config If you want to modify the configuration like you would with a [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel), you have two options: - Use the `config` parameter of the decorator. - Define the configuration with the `__pydantic_config__` attribute. ```python from pydantic import ConfigDict from pydantic.dataclasses import dataclass # Option 1 -- using the decorator argument: @dataclass(config=ConfigDict(validate_assignment=True)) # (1) class MyDataclass1: a: int # Option 2 -- using an attribute: @dataclass class MyDataclass2: a: int __pydantic_config__ = ConfigDict(validate_assignment=True) ``` You can read more about `validate_assignment` in the [API reference](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_assignment). ## Rebuilding dataclass schema The [`rebuild_dataclass()`](/docs/validation/latest/api/pydantic/dataclasses/#pydantic.dataclasses.rebuild_dataclass) function can be used to rebuild the core schema of the dataclass. See the [rebuilding model schema](/docs/validation/latest/concepts/models#rebuilding-model-schema) section for more details. ## Stdlib dataclasses and Pydantic dataclasses ### Inherit from stdlib dataclasses Stdlib dataclasses (nested or not) can also be inherited and Pydantic will automatically validate all the inherited fields. ```python import dataclasses import pydantic @dataclasses.dataclass class Z: z: int @dataclasses.dataclass class Y(Z): y: int = 0 @pydantic.dataclasses.dataclass class X(Y): x: int = 0 foo = X(x=b'1', y='2', z='3') print(foo) #> X(z=3, y=2, x=1) try: X(z='pika') except pydantic.ValidationError as e: print(e) """ 1 validation error for X z Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='pika', input_type=str] """ ``` The decorator can also be applied directly on a stdlib dataclass, in which case a new subclass will be created: ```python import dataclasses import pydantic @dataclasses.dataclass class A: a: int PydanticA = pydantic.dataclasses.dataclass(A) print(PydanticA(a='1')) #> A(a=1) ``` ### Usage of stdlib dataclasses with `BaseModel` When a standard library dataclass is used within a Pydantic model, a Pydantic dataclass or a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter), validation will be applied (and the [configuration](#dataclass-config) stays the same). This means that using a stdlib or a Pydantic dataclass as a field annotation is functionally equivalent. ```python import dataclasses from typing import Optional from pydantic import BaseModel, ConfigDict, ValidationError @dataclasses.dataclass(frozen=True) class User: name: str class Foo(BaseModel): # Required so that pydantic revalidates the model attributes: model_config = ConfigDict(revalidate_instances='always') user: Optional[User] = None # nothing is validated as expected: user = User(name=['not', 'a', 'string']) print(user) #> User(name=['not', 'a', 'string']) try: Foo(user=user) except ValidationError as e: print(e) """ 1 validation error for Foo user.name Input should be a valid string [type=string_type, input_value=['not', 'a', 'string'], input_type=list] """ foo = Foo(user=User(name='pika')) try: foo.user.name = 'bulbi' except dataclasses.FrozenInstanceError as e: print(e) #> cannot assign to field 'name' ``` ### Using custom types As said above, validation is applied on standard library dataclasses. If you make use of custom types, you will get an error when trying to refer to the dataclass. To circumvent the issue, you can set the [`arbitrary_types_allowed`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.arbitrary_types_allowed) configuration value on the dataclass: ```python import dataclasses from pydantic import BaseModel, ConfigDict from pydantic.errors import PydanticSchemaGenerationError class ArbitraryType: def __init__(self, value): self.value = value def __repr__(self): return f'ArbitraryType(value={self.value!r})' @dataclasses.dataclass class DC: a: ArbitraryType b: str # valid as it is a stdlib dataclass without validation: my_dc = DC(a=ArbitraryType(value=3), b='qwe') try: class Model(BaseModel): dc: DC other: str # invalid as dc is now validated with pydantic, and ArbitraryType is not a known type Model(dc=my_dc, other='other') except PydanticSchemaGenerationError as e: print(e.message) """ Unable to generate pydantic-core schema for . Set `arbitrary_types_allowed=True` in the model_config to ignore this error or implement `__get_pydantic_core_schema__` on your type to fully support it. If you got this error by calling handler() within `__get_pydantic_core_schema__` then you likely need to call `handler.generate_schema()` since we do not call `__get_pydantic_core_schema__` on `` otherwise to avoid infinite recursion. """ # valid as we set arbitrary_types_allowed=True, and that config pushes down to the nested vanilla dataclass class Model(BaseModel): model_config = ConfigDict(arbitrary_types_allowed=True) dc: DC other: str m = Model(dc=my_dc, other='other') print(repr(m)) #> Model(dc=DC(a=ArbitraryType(value=3), b='qwe'), other='other') ``` ### Checking if a dataclass is a Pydantic dataclass Pydantic dataclasses are still considered dataclasses, so using [`dataclasses.is_dataclass()`](https://docs.python.org/3/library/dataclasses.html#dataclasses.is_dataclass) will return `True`. To check if a type is specifically a Pydantic dataclass you can use the [`is_pydantic_dataclass()`](/docs/validation/latest/api/pydantic/dataclasses/#pydantic.dataclasses.is_pydantic_dataclass) function. ```python import dataclasses import pydantic @dataclasses.dataclass class StdLibDataclass: id: int PydanticDataclass = pydantic.dataclasses.dataclass(StdLibDataclass) print(dataclasses.is_dataclass(StdLibDataclass)) #> True print(pydantic.dataclasses.is_pydantic_dataclass(StdLibDataclass)) #> False print(dataclasses.is_dataclass(PydanticDataclass)) #> True print(pydantic.dataclasses.is_pydantic_dataclass(PydanticDataclass)) #> True ``` ## Validators and initialization hooks Validators also work with Pydantic dataclasses: ```python from pydantic import field_validator from pydantic.dataclasses import dataclass @dataclass class DemoDataclass: product_id: str # should be a five-digit string, may have leading zeros @field_validator('product_id', mode='before') @classmethod def convert_int_serial(cls, v): if isinstance(v, int): v = str(v).zfill(5) return v print(DemoDataclass(product_id='01234')) #> DemoDataclass(product_id='01234') print(DemoDataclass(product_id=2468)) #> DemoDataclass(product_id='02468') ``` The dataclass [`__post_init__()`](https://docs.python.org/3/library/dataclasses.html#dataclasses.__post_init__) method is also supported, and will be called between the calls to _before_ and _after_ model validators. Example ```python from pydantic_core import ArgsKwargs from typing_extensions import Self from pydantic import model_validator from pydantic.dataclasses import dataclass @dataclass class Birth: year: int month: int day: int @dataclass class User: birth: Birth @model_validator(mode='before') @classmethod def before(cls, values: ArgsKwargs) -> ArgsKwargs: print(f'First: {values}') # (1) """ First: ArgsKwargs((), {'birth': {'year': 1995, 'month': 3, 'day': 2}}) """ return values @model_validator(mode='after') def after(self) -> Self: print(f'Third: {self}') #> Third: User(birth=Birth(year=1995, month=3, day=2)) return self def __post_init__(self): print(f'Second: {self.birth}') #> Second: Birth(year=1995, month=3, day=2) user = User(**{'birth': {'year': 1995, 'month': 3, 'day': 2}}) ``` Unlike Pydantic models, the `values` parameter is of type [`ArgsKwargs`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ArgsKwargs) --- # [Experimental](https://pydantic.dev/docs/validation/latest/concepts/experimental/) # Experimental In this section you will find documentation for new, experimental features in Pydantic. These features are subject to change or removal, and we are looking for feedback and suggestions before making them a permanent part of Pydantic. See our [Version Policy](/docs/validation/latest/get-started/version-policy#experimental-features) for more information on experimental features. ## Feedback We welcome feedback on experimental features! Please open an issue on the [Pydantic GitHub repository](https://github.com/pydantic/pydantic/issues/new/choose) to share your thoughts, requests, or suggestions. We also encourage you to read through existing feedback and add your thoughts to existing issues. ## Pipeline API Pydantic v2.8.0 introduced an experimental "pipeline" API that allows composing of parsing (validation), constraints and transformations in a more type-safe manner than existing APIs. This API is subject to change or removal, we are looking for feedback and suggestions before making it a permanent part of Pydantic. API Documentation [`pydantic.experimental.pipeline`](/docs/validation/latest/api/pydantic/experimental/#pydantic.experimental.pipeline) Generally, the pipeline API is used to define a sequence of steps to apply to incoming data during validation. The pipeline API is designed to be more type-safe and composable than the existing Pydantic API. Each step in the pipeline can be: - A validation step that runs pydantic validation on the provided type - A transformation step that modifies the data - A constraint step that checks the data against a condition - A predicate step that checks the data against a condition and raises an error if it returns `False` Note that the following example attempts to be exhaustive at the cost of complexity: if you find yourself writing this many transformations in type annotations you may want to consider having a `UserIn` and `UserOut` model (example below) or similar where you make the transformations via idiomatic plain Python code. These APIs are meant for situations where the code savings are significant and the added complexity is relatively small. ```python from __future__ import annotations from datetime import datetime from typing import Annotated from pydantic import BaseModel from pydantic.experimental.pipeline import validate_as class User(BaseModel): name: Annotated[str, validate_as(str).str_lower()] # (1) age: Annotated[int, validate_as(int).gt(0)] # (2) username: Annotated[str, validate_as(str).str_pattern(r'[a-z]+')] # (3) password: Annotated[ str, validate_as(str) .transform(str.lower) .predicate(lambda x: x != 'password'), # (4) ] favorite_number: Annotated[ # (5) int, (validate_as(int) | validate_as(str).str_strip().validate_as(int)).gt( 0 ), ] friends: Annotated[list[User], validate_as(...).len(0, 100)] # (6) bio: Annotated[ datetime, validate_as(int) .transform(lambda x: x / 1_000_000) .validate_as(...), # (8) ] ``` Lowercase a string. Constrain an integer to be greater than zero. Constrain a string to match a regex pattern. You can also use the lower level transform, constrain and predicate methods. Use the `|` or `&` operators to combine steps (like a logical OR or AND). Calling `validate_as(...)` with `Ellipsis`, `...` as the first positional argument implies `validate_as()`. Use `validate_as(Any)` to accept any type. You can call `validate_as()` before or after other steps to do pre or post processing. ### Mapping from `BeforeValidator`, `AfterValidator` and `WrapValidator` The `validate_as` method is a more type-safe way to define `BeforeValidator`, `AfterValidator` and `WrapValidator`: ```python from typing import Annotated from pydantic.experimental.pipeline import transform, validate_as # BeforeValidator Annotated[int, validate_as(str).str_strip().validate_as(...)] # (1) # AfterValidator Annotated[int, transform(lambda x: x * 2)] # (2) # WrapValidator Annotated[ int, validate_as(str) .str_strip() .validate_as(...) .transform(lambda x: x * 2), # (3) ] ``` Strip whitespace from a string before parsing it as an integer. Multiply an integer by 2 after parsing it. Strip whitespace from a string, validate it as an integer, then multiply it by 2. ### Alternative patterns There are many alternative patterns to use depending on the scenario. Just as an example, consider the `UserIn` and `UserOut` pattern mentioned above: ```python from __future__ import annotations from pydantic import BaseModel class UserIn(BaseModel): favorite_number: int | str class UserOut(BaseModel): favorite_number: int def my_api(user: UserIn) -> UserOut: favorite_number = user.favorite_number if isinstance(favorite_number, str): favorite_number = int(user.favorite_number.strip()) return UserOut(favorite_number=favorite_number) assert my_api(UserIn(favorite_number=' 1 ')).favorite_number == 1 ``` This example uses plain idiomatic Python code that may be easier to understand, type-check, etc. than the examples above. The approach you choose should really depend on your use case. You will have to compare verbosity, performance, ease of returning meaningful errors to your users, etc. to choose the right pattern. Just be mindful of abusing advanced patterns like the pipeline API just because you can. ## Partial Validation ✦ New in v2.10 Partial validation allows you to validate an incomplete JSON string, or a Python object representing incomplete input data. Partial validation is particularly helpful when processing the output of an LLM, where the model streams structured responses, and you may wish to begin validating the stream while you're still receiving data (e.g. to show partial data to users). Caution Partial validation is an experimental feature and may change in future versions of Pydantic. The current implementation should be considered a proof of concept at this time and has a number of [limitations](#limitations-of-partial-validation). Partial validation can be enabled when using the three validation methods on `TypeAdapter`: [`TypeAdapter.validate_json()`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_json), [`TypeAdapter.validate_python()`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_python), and [`TypeAdapter.validate_strings()`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_strings). This allows you to parse and validation incomplete JSON, but also to validate Python objects created by parsing incomplete data of any format. The `experimental_allow_partial` flag can be passed to these methods to enable partial validation. It can take the following values (and is `False`, by default): - `False` or `'off'` - disable partial validation - `True` or `'on'` - enable partial validation, but don't support trailing strings - `'trailing-strings'` - enable partial validation and support trailing strings `'trailing-strings'` mode `'trailing-strings'` mode allows for trailing incomplete strings at the end of partial JSON to be included in the output. For example, if you're validating against the following model: ```python from typing import TypedDict class Model(TypedDict): a: str b: str ``` Then the following JSON input would be considered valid, despite the incomplete string at the end: ```json '{"a": "hello", "b": "wor' ``` And would be validated as: ```python {'a': 'hello', 'b': 'wor'} ``` `experiment_allow_partial` in action: ```python from typing import Annotated from annotated_types import MinLen from typing_extensions import NotRequired, TypedDict from pydantic import TypeAdapter class Foobar(TypedDict): # (1) a: int b: NotRequired[float] c: NotRequired[Annotated[str, MinLen(5)]] ta = TypeAdapter(list[Foobar]) v = ta.validate_json('[{"a": 1, "b"', experimental_allow_partial=True) # (2) print(v) #> [{'a': 1}] v = ta.validate_json( '[{"a": 1, "b": 1.0, "c": "abcd', experimental_allow_partial=True # (3) ) print(v) #> [{'a': 1, 'b': 1.0}] v = ta.validate_json( '[{"b": 1.0, "c": "abcde"', experimental_allow_partial=True # (4) ) print(v) #> [] v = ta.validate_json( '[{"a": 1, "b": 1.0, "c": "abcde"},{"a": ', experimental_allow_partial=True ) print(v) #> [{'a': 1, 'b': 1.0, 'c': 'abcde'}] v = ta.validate_python([{'a': 1}], experimental_allow_partial=True) # (5) print(v) #> [{'a': 1}] v = ta.validate_python( [{'a': 1, 'b': 1.0, 'c': 'abcd'}], experimental_allow_partial=True # (6) ) print(v) #> [{'a': 1, 'b': 1.0}] v = ta.validate_json( '[{"a": 1, "b": 1.0, "c": "abcdefg', experimental_allow_partial='trailing-strings', # (7) ) print(v) #> [{'a': 1, 'b': 1.0, 'c': 'abcdefg'}] ``` The TypedDict `Foobar` has three field, but only `a` is required, that means that a valid instance of `Foobar` can be created even if the `b` and `c` fields are missing. Parsing JSON, the input is valid JSON up to the point where the string is truncated. In this case truncation of the input means the value of `c` (`abcd`) is invalid as input to `c` field, hence it's omitted. The `a` field is required, so validation on the only item in the list fails and is dropped. Partial validation also works with Python objects, it should have the same semantics as with JSON except of course you can't have a genuinely "incomplete" Python object. The same as above but with a Python object, `c` is dropped as it's not required and failed validation. The `trailing-strings` mode allows for incomplete strings at the end of partial JSON to be included in the output, in this case the input is valid JSON up to the point where the string is truncated, so the last string is included. ### How Partial Validation Works Partial validation follows the zen of Pydantic -- it makes no guarantees about what the input data might have been, but it does guarantee to return a valid instance of the type you required, or raise a validation error. To do this, the `experimental_allow_partial` flag enables two pieces of behavior: #### 1\. Partial JSON parsing The [jiter](https://github.com/pydantic/jiter) JSON parser used by Pydantic already supports parsing partial JSON, `experimental_allow_partial` is simply passed to jiter via the `allow_partial` argument. Note If you just want pure JSON parsing with support for partial JSON, you can use the [`jiter`](https://pypi.org/project/jiter/) Python library directly, or pass the `allow_partial` argument when calling [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json). #### 2\. Ignore errors in the last element of the input Only having access to part of the input data means errors can commonly occur in the last element of the input data. For example: - if a string has a constraint `MinLen(5)`, when you only see part of the input, validation might fail because part of the string is missing (e.g. `{"name": "Sam` instead of `{"name": "Samuel"}`) - if an `int` field has a constraint `Ge(10)`, when you only see part of the input, validation might fail because the number is too small (e.g. `1` instead of `10`) - if a `TypedDict` field has 3 required fields, but the partial input only has two of the fields, validation would fail because some field are missing - etc. etc. -- there are lost more cases like this The point is that if you only see part of some valid input data, validation errors can often occur in the last element of a sequence or last value of mapping. To avoid these errors breaking partial validation, Pydantic will ignore ALL errors in the last element of the input data. Errors in last element ignored ```python from typing import Annotated from annotated_types import MinLen from pydantic import BaseModel, TypeAdapter class MyModel(BaseModel): a: int b: Annotated[str, MinLen(5)] ta = TypeAdapter(list[MyModel]) v = ta.validate_json( '[{"a": 1, "b": "12345"}, {"a": 1,', experimental_allow_partial=True, ) print(v) #> [MyModel(a=1, b='12345')] ``` ### Limitations of Partial Validation #### TypeAdapter only You can only pass `experiment_allow_partial` to [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) methods, it's not yet supported via other Pydantic entry points like [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). #### Types supported Right now only a subset of collection validators know how to handle partial validation: - `list` - `set` - `frozenset` - `dict` (as in `dict[X, Y]`) - `TypedDict` -- only non-required fields may be missing, e.g. via [`NotRequired`](https://docs.python.org/3/library/typing.html#typing.NotRequired) or [`total=False`](https://docs.python.org/3/library/typing.html#typing.TypedDict.__total__)) While you can use `experimental_allow_partial` while validating against types that include other collection validators, those types will be validated "all or nothing", and partial validation will not work on more nested types. E.g. in the [above](#2-ignore-errors-in-last) example partial validation works although the second item in the list is dropped completely since `BaseModel` doesn't (yet) support partial validation. But partial validation won't work at all in the follow example because `BaseModel` doesn't support partial validation so it doesn't forward the `allow_partial` instruction down to the list validator in `b`: ```python from typing import Annotated from annotated_types import MinLen from pydantic import BaseModel, TypeAdapter, ValidationError class MyModel(BaseModel): a: int = 1 b: list[Annotated[str, MinLen(5)]] = [] # (1) ta = TypeAdapter(MyModel) try: v = ta.validate_json( '{"a": 1, "b": ["12345", "12', experimental_allow_partial=True ) except ValidationError as e: print(e) """ 1 validation error for MyModel b.1 String should have at least 5 characters [type=string_too_short, input_value='12', input_type=str] """ ``` The list validator for `b` doesn't get the `allow_partial` instruction passed down to it by the model validator so it doesn't know to ignore errors in the last element of the input. #### Some invalid but complete JSON will be accepted The way [jiter](https://github.com/pydantic/jiter) (the JSON parser used by Pydantic) works means it's currently not possible to differentiate between complete JSON like `{"a": 1, "b": "12"}` and incomplete JSON like `{"a": 1, "b": "12`. This means that some invalid JSON will be accepted by Pydantic when using `experimental_allow_partial`, e.g.: ```python from typing import Annotated from annotated_types import MinLen from typing_extensions import TypedDict from pydantic import TypeAdapter class Foobar(TypedDict, total=False): a: int b: Annotated[str, MinLen(5)] ta = TypeAdapter(Foobar) v = ta.validate_json( '{"a": 1, "b": "12', experimental_allow_partial=True # (1) ) print(v) #> {'a': 1} v = ta.validate_json( '{"a": 1, "b": "12"}', experimental_allow_partial=True # (2) ) print(v) #> {'a': 1} ``` This will pass validation as expected although the last field will be omitted as it failed validation. This will also pass validation since the binary representation of the JSON data passed to pydantic-core is indistinguishable from the previous case. #### Any error in the last field of the input will be ignored As described [above](#2-ignore-errors-in-last), many errors can result from truncating the input. Rather than trying to specifically ignore errors that could result from truncation, Pydantic ignores all errors in the last element of the input in partial validation mode. This means clearly invalid data will pass validation if the error is in the last field of the input: ```python from typing import Annotated from annotated_types import Ge from pydantic import TypeAdapter ta = TypeAdapter(list[Annotated[int, Ge(10)]]) v = ta.validate_python([20, 30, 4], experimental_allow_partial=True) # (1) print(v) #> [20, 30] ta = TypeAdapter(list[int]) v = ta.validate_python([1, 2, 'wrong'], experimental_allow_partial=True) # (2) print(v) #> [1, 2] ``` As you would expect, this will pass validation since Pydantic correctly ignores the error in the (truncated) last item. This will also pass validation since the error in the last item is ignored. ## Validation of a callable's arguments Pydantic provides the [`@validate_call`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) decorator to perform validation on the provided arguments (and additionally return type) of a callable. However, it only allows arguments to be provided by actually calling the decorated callable. In some situations, you may want to just _validate_ the arguments, such as when loading from other data sources such as JSON data. For this reason, the experimental [`generate_arguments_schema()`](/docs/validation/latest/api/pydantic/experimental/#pydantic.experimental.arguments_schema.generate_arguments_schema) function can be used to construct a core schema, which can later be used with a [`SchemaValidator`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaValidator). ```python from pydantic_core import SchemaValidator from pydantic.experimental.arguments_schema import generate_arguments_schema def func(p: bool, *args: str, **kwargs: int) -> None: ... arguments_schema = generate_arguments_schema(func=func) val = SchemaValidator(arguments_schema, config={'coerce_numbers_to_str': True}) args, kwargs = val.validate_json( '{"p": true, "args": ["arg1", 1], "kwargs": {"extra": 1}}' ) print(args, kwargs) # (1) #> (True, 'arg1', '1') {'extra': 1} ``` If you want the validated arguments as a dictionary, you can use the [`Signature.bind()`](https://docs.python.org/3/library/inspect.html#inspect.Signature.bind) method: ```python from inspect import signature signature(func).bind(*args, **kwargs).arguments #> {'p': True, 'args': ('arg1', '1'), 'kwargs': {'extra': 1}} ``` Note Unlike [`@validate_call`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call), this core schema will only validate the provided arguments; the underlying callable will _not_ be called. Additionally, you can ignore specific parameters by providing a callback, which is called for every parameter: ```python from typing import Any from pydantic_core import SchemaValidator from pydantic.experimental.arguments_schema import generate_arguments_schema def func(p: bool, *args: str, **kwargs: int) -> None: ... def skip_first_parameter(index: int, name: str, annotation: Any) -> Any: if index == 0: return 'skip' arguments_schema = generate_arguments_schema( func=func, parameters_callback=skip_first_parameter, ) val = SchemaValidator(arguments_schema) args, kwargs = val.validate_json('{"args": ["arg1"], "kwargs": {"extra": 1}}') print(args, kwargs) #> ('arg1',) {'extra': 1} ``` ## `MISSING` sentinel The `MISSING` sentinel is a singleton indicating a field value was not provided during validation. This singleton can be used as a default value, as an alternative to `None` when it has an explicit meaning. During serialization, any field with `MISSING` as a value is excluded from the output. ```python from typing import Union from pydantic import BaseModel from pydantic.experimental.missing_sentinel import MISSING class Configuration(BaseModel): timeout: Union[int, None, MISSING] = MISSING # configuration defaults, stored somewhere else: defaults = {'timeout': 200} conf = Configuration() # `timeout` is excluded from the serialization output: conf.model_dump() # {} # The `MISSING` value doesn't appear in the JSON Schema: Configuration.model_json_schema()['properties']['timeout'] #> {'anyOf': [{'type': 'integer'}, {'type': 'null'}], 'title': 'Timeout'}} # `is` can be used to discriminate between the sentinel and other values: timeout = conf.timeout if conf.timeout is not MISSING else defaults['timeout'] ``` This feature is marked as experimental because it relies on the draft [PEP 661](https://peps.python.org/pep-0661/), introducing sentinels in the standard library. As such, the following limitations currently apply: - Static type checking of sentinels is only supported with Pyright [1.1.402](https://github.com/microsoft/pyright/releases/tag/1.1.402) or greater, and the `enableExperimentalFeatures` type evaluation setting should be enabled. - Pickling of models containing `MISSING` as a value is not supported. Note When [applying constraints](/docs/validation/latest/concepts/fields#field-constraints) to a union containing the `MISSING` sentinel, such constraints are automatically applied to the remaining type(s) of the union. --- # [Fields](https://pydantic.dev/docs/validation/latest/concepts/fields/) # Fields API Documentation [`pydantic.fields.Field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) In this section, we will go through the available mechanisms to customize Pydantic model fields: [default values](#default-values), [JSON Schema metadata](#customizing-json-schema), [constraints](#field-constraints), etc. To do so, the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function is used a lot, and behaves the same way as the standard library [`field()`](https://docs.python.org/3/library/dataclasses.html#dataclasses.field) function for dataclasses - by assigning to the annotated attribute: ```python from pydantic import BaseModel, Field class Model(BaseModel): name: str = Field(frozen=True) ``` Note Even though `name` is assigned a value, it is still required and has no default value. If you want to emphasize on the fact that a value must be provided, you can use the [ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis): ```python class Model(BaseModel): name: str = Field(..., frozen=True) ``` However, its usage is discouraged as it doesn't play well with static type checkers. ## The annotated pattern To apply constraints or attach [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) functions to a model field, Pydantic also supports the [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) typing construct to attach metadata to an annotation: ```python from typing import Annotated from pydantic import BaseModel, Field, WithJsonSchema class Model(BaseModel): name: Annotated[str, Field(strict=True), WithJsonSchema({'extra': 'data'})] ``` As far as static type checkers are concerned, `name` is still typed as `str`, but Pydantic leverages the available metadata to add validation logic, type constraints, etc. Using this pattern has some advantages: - Using the `f: = Field(...)` form can be confusing and might trick users into thinking `f` has a default value, while in reality it is still required. - You can provide an arbitrary amount of metadata elements for a field. As shown in the example above, the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function only supports a limited set of constraints/metadata, and you may have to use different Pydantic utilities such as [`WithJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.WithJsonSchema) in some cases. - Types can be made reusable (see the documentation on [custom types](/docs/validation/latest/concepts/types#using-the-annotated-pattern) using this pattern). However, note that certain arguments to the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function (namely, `default`, `default_factory`, and `alias`) are taken into account by static type checkers to synthesize a correct `__init__()` method. The annotated pattern is _not_ understood by them, so you should use the normal assignment form instead. Tip The annotated pattern can also be used to add metadata to specific parts of the type. For instance, [validation constraints](#field-constraints) can be added this way: ```python from typing import Annotated from pydantic import BaseModel, Field class Model(BaseModel): int_list: list[Annotated[int, Field(gt=0)]] # Valid: [1, 3] # Invalid: [-1, 2] ``` Be careful not mixing _field_ and _type_ metadata: ```python class Model(BaseModel): field_bad: Annotated[int, Field(deprecated=True)] | None = None # (1) field_ok: Annotated[int | None, Field(deprecated=True)] = None # (2) ``` The [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function is applied to `int` type, hence the `deprecated` flag won't have any effect. While this may be confusing given that the name of the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function would imply it should apply to the field, the API was designed when this function was the only way to provide metadata. You can alternatively make use of the [`annotated_types`](https://github.com/annotated-types/annotated-types) library which is now supported by Pydantic. The [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function is applied to the "top-level" union type, hence the `deprecated` flag will be applied to the field. ## Inspecting model fields The fields of a model can be inspected using the [`model_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields) class attribute (or the `__pydantic_fields__` attribute for [Pydantic dataclasses](/docs/validation/latest/concepts/dataclasses)). It is a mapping of field names to their definition (represented as [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instances). ```python from typing import Annotated from pydantic import BaseModel, Field, WithJsonSchema class Model(BaseModel): a: Annotated[ int, Field(gt=1), WithJsonSchema({'extra': 'data'}), Field(alias='b') ] = 1 field_info = Model.model_fields['a'] print(field_info.annotation) #> print(field_info.alias) #> b print(field_info.metadata) #> [Gt(gt=1), WithJsonSchema(json_schema={'extra': 'data'}, mode=None)] ``` ⚠ Deprecated in v2.11, removed in v3 [`model_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields) can only be accessed from the class object, not the instance. ## Default values Default values for fields can be provided using the normal assignment syntax or by providing a value to the `default` argument: ```python from pydantic import BaseModel, Field class User(BaseModel): # Both fields aren't required: name: str = 'John Doe' age: int = Field(default=20) ``` ↻ Changed in v2 [In Pydantic V1](/docs/validation/latest/get-started/migration#required-optional-and-nullable-fields), a type annotated as [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) or wrapped by [`Optional`](https://docs.python.org/3/library/typing.html#typing.Optional) would be given an implicit default of `None` even if no default was explicitly specified. This is no longer the case in Pydantic V2. You can also pass a callable to the `default_factory` argument that will be called to generate a default value: ```python from uuid import uuid4 from pydantic import BaseModel, Field class User(BaseModel): id: str = Field(default_factory=lambda: uuid4().hex) ``` The default factory can also take a single required argument, in which case the already validated data will be passed as a dictionary. ```python from pydantic import BaseModel, EmailStr, Field class User(BaseModel): email: EmailStr username: str = Field(default_factory=lambda data: data['email']) user = User(email='user@example.com') print(user.username) #> user@example.com ``` The `data` argument will _only_ contain the already validated data, based on the [order of model fields](/docs/validation/latest/concepts/models#field-ordering) (the above example would fail if `username` were to be defined before `email`). ✦ New in v2.10 Default factories can take already validated data as an argument. ✦ New in v2.13 Default factories for [private attributes](/docs/validation/latest/concepts/models#private-model-attributes) can take the validated data as an argument. ## Validate default values By default, Pydantic will _not_ validate default values. The `validate_default` field parameter (or the [`validate_default`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_default) configuration value) can be used to enable this behavior: ```python from pydantic import BaseModel, Field, ValidationError class User(BaseModel): age: int = Field(default='twelve', validate_default=True) try: user = User() except ValidationError as e: print(e) """ 1 validation error for User age Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='twelve', input_type=str] """ ``` ### Mutable default values A common source of bugs in Python is to use a mutable object as a default value for a function or method argument, as the same instance ends up being reused in each call. The [`dataclasses`](https://docs.python.org/3/library/dataclasses.html#module-dataclasses) module actually raises an error in this case, indicating that you should use a [default factory](https://docs.python.org/3/library/dataclasses.html#default-factory-functions) instead. While the same thing can be done in Pydantic, it is not required. In the event that the default value is not hashable, Pydantic will create a deep copy of the default value when creating each instance of the model: ```python from pydantic import BaseModel class Model(BaseModel): item_counts: list[dict[str, int]] = [{}] m1 = Model() m1.item_counts[0]['a'] = 1 print(m1.item_counts) #> [{'a': 1}] m2 = Model() print(m2.item_counts) #> [{}] ``` ## Field aliases Tip Read more about aliases in the [dedicated section](/docs/validation/latest/concepts/alias). For validation and serialization, you can define an alias for a field. There are three ways to define an alias: - `Field(alias='foo')` - `Field(validation_alias='foo')` - `Field(serialization_alias='foo')` The `alias` parameter is used for both validation _and_ serialization. If you want to use _different_ aliases for validation and serialization respectively, you can use the `validation_alias` and `serialization_alias` parameters, which will apply only in their respective use cases. Here is an example of using the `alias` parameter: ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(alias='username') user = User(username='johndoe') # (1) print(user) #> name='johndoe' print(user.model_dump(by_alias=True)) # (2) #> {'username': 'johndoe'} ``` The alias `'username'` is used for instance creation and validation. We are using [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) to convert the model into a serializable format. Note that the `by_alias` keyword argument defaults to `False`, and must be specified explicitly to dump models using the field (serialization) aliases. You can also use [`ConfigDict.serialize_by_alias`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.serialize_by_alias) to configure this behavior at the model level. When `by_alias=True`, the alias `'username'` used during serialization. If you want to use an alias _only_ for validation, you can use the `validation_alias` parameter: ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(validation_alias='username') user = User(username='johndoe') # (1) print(user) #> name='johndoe' print(user.model_dump(by_alias=True)) # (2) #> {'name': 'johndoe'} ``` The validation alias `'username'` is used during validation. The field name `'name'` is used during serialization. If you only want to define an alias for _serialization_, you can use the `serialization_alias` parameter: ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(serialization_alias='username') user = User(name='johndoe') # (1) print(user) #> name='johndoe' print(user.model_dump(by_alias=True)) # (2) #> {'username': 'johndoe'} ``` The field name `'name'` is used for validation. The serialization alias `'username'` is used for serialization. Alias precedence and priority In case you use `alias` together with `validation_alias` or `serialization_alias` at the same time, the `validation_alias` will have priority over `alias` for validation, and `serialization_alias` will have priority over `alias` for serialization. If you provide a value for the [`alias_generator`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.alias_generator) model setting, you can control the order of precedence for field alias and generated aliases via the `alias_priority` field parameter. You can read more about alias precedence [here](/docs/validation/latest/concepts/alias#alias-precedence). Static type checking/IDE support If you provide a value for the `alias` field parameter, static type checkers will use this alias instead of the actual field name to synthesize the `__init__` method: ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(alias='username') user = User(username='johndoe') # (1) ``` Accepted by type checkers. This means that when using the [`validate_by_name`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.validate_by_name) model setting (which allows both the field name and alias to be used during model validation), type checkers will error when the actual field name is used: ```python from pydantic import BaseModel, ConfigDict, Field class User(BaseModel): model_config = ConfigDict(validate_by_name=True) name: str = Field(alias='username') user = User(name='johndoe') # (1) ``` _Not_ accepted by type checkers. If you still want type checkers to use the field name and not the alias, the [annotated pattern](#the-annotated-pattern) can be used (which is only understood by Pydantic): ```python from typing import Annotated from pydantic import BaseModel, ConfigDict, Field class User(BaseModel): model_config = ConfigDict(validate_by_name=True, validate_by_alias=True) name: Annotated[str, Field(alias='username')] user = User(name='johndoe') # (1) user = User(username='johndoe') # (2) ``` Accepted by type checkers. _Not_ accepted by type checkers. ### Validation Alias Even though Pydantic treats `alias` and `validation_alias` the same when creating model instances, type checkers only understand the `alias` field parameter. As a workaround, you can instead specify both an `alias` and `serialization_alias` (identical to the field name), as the `serialization_alias` will override the `alias` during serialization: ```python from pydantic import BaseModel, Field class MyModel(BaseModel): my_field: int = Field(validation_alias='myValidationAlias') ``` with: ```python from pydantic import BaseModel, Field class MyModel(BaseModel): my_field: int = Field( alias='myValidationAlias', serialization_alias='my_field', ) m = MyModel(myValidationAlias=1) print(m.model_dump(by_alias=True)) #> {'my_field': 1} ``` ## Field constraints The [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function can also be used to add constraints to specific types: ```python from decimal import Decimal from pydantic import BaseModel, Field class Model(BaseModel): positive: int = Field(gt=0) short_str: str = Field(max_length=3) precise_decimal: Decimal = Field(max_digits=5, decimal_places=2) ``` The available constraints for each type (and the way they affect the JSON Schema) are described in the [standard library types](/docs/validation/latest/api/pydantic/standard_library_types) documentation. Note When adding constraints to a union type, if a member of the union is `None` or the [`MISSING` sentinel](/docs/validation/latest/concepts/experimental#missing-sentinel), the constraints will be automatically applied to the remaining type(s) of the union: ```python from typing import Annotated, Union from pydantic import BaseModel, Field class Model(BaseModel): positive: Union[int, None] = Field(gt=0) # Also works with the annotated pattern: negative: Annotated[Union[int, None], Field(lt=0)] ``` ## Strict fields The `strict` parameter of the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function specifies whether the field should be validated in [strict mode](/docs/validation/latest/concepts/strict_mode). ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(strict=True) age: int = Field(strict=False) # (1) user = User(name='John', age='42') # (2) print(user) #> name='John' age=42 ``` This is the default value. The `age` field is validated in lax mode. Therefore, it can be assigned a string. The [standard library types](/docs/validation/latest/api/pydantic/standard_library_types) documentation describes the strict behavior for each type. ## Dataclass fields Some parameters of the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function can be used on [dataclasses](/docs/validation/latest/concepts/dataclasses): - `init`: Whether the field should be included in the synthesized `__init__()` method of the dataclass. - `init_var`: Whether the field should be [init-only](https://docs.python.org/3/library/dataclasses.html#dataclasses-init-only-variables) in the dataclass. - `kw_only`: Whether the field should be a keyword-only argument in the constructor of the dataclass. Here is an example: ```python from pydantic import BaseModel, Field from pydantic.dataclasses import dataclass @dataclass class Foo: bar: str baz: str = Field(init_var=True) qux: str = Field(kw_only=True) class Model(BaseModel): foo: Foo model = Model(foo=Foo('bar', baz='baz', qux='qux')) print(model.model_dump()) # (1) #> {'foo': {'bar': 'bar', 'qux': 'qux'}} ``` The `baz` field is not included in the serialized output, since it is an init-only field. ## Field Representation The parameter `repr` can be used to control whether the field should be included in the string representation of the model. ```python from pydantic import BaseModel, Field class User(BaseModel): name: str = Field(repr=True) # (1) age: int = Field(repr=False) user = User(name='John', age=42) print(user) #> name='John' ``` This is the default value. ## Discriminator The parameter `discriminator` can be used to control the field that will be used to discriminate between different models in a union. It takes either the name of a field or a `Discriminator` instance. The `Discriminator` approach can be useful when the discriminator fields aren't the same for all the models in the `Union`. The following example shows how to use `discriminator` with a field name: ```python from typing import Literal, Union from pydantic import BaseModel, Field class Cat(BaseModel): pet_type: Literal['cat'] age: int class Dog(BaseModel): pet_type: Literal['dog'] age: int class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') print(Model.model_validate({'pet': {'pet_type': 'cat', 'age': 12}})) # (1) #> pet=Cat(pet_type='cat', age=12) ``` See more about `model_validate()` in the [Validating data](/docs/validation/latest/concepts/models#validating-data) documentation. The following example shows how to use the `discriminator` keyword argument with a `Discriminator` instance: ```python from typing import Annotated, Literal, Union from pydantic import BaseModel, Discriminator, Field, Tag class Cat(BaseModel): pet_type: Literal['cat'] age: int class Dog(BaseModel): pet_kind: Literal['dog'] age: int def pet_discriminator(v): if isinstance(v, dict): return v.get('pet_type', v.get('pet_kind')) return getattr(v, 'pet_type', getattr(v, 'pet_kind', None)) class Model(BaseModel): pet: Union[Annotated[Cat, Tag('cat')], Annotated[Dog, Tag('dog')]] = Field( discriminator=Discriminator(pet_discriminator) ) print(repr(Model.model_validate({'pet': {'pet_type': 'cat', 'age': 12}}))) #> Model(pet=Cat(pet_type='cat', age=12)) print(repr(Model.model_validate({'pet': {'pet_kind': 'dog', 'age': 12}}))) #> Model(pet=Dog(pet_kind='dog', age=12)) ``` You can also take advantage of `Annotated` to define your discriminated unions. See the [Discriminated Unions](/docs/validation/latest/concepts/unions#discriminated-unions) documentation for more details. ## Immutability The parameter `frozen` is used to emulate the frozen dataclass behaviour. It is used to prevent the field from being assigned a new value after the model is created (immutability). See the [frozen dataclass documentation](https://docs.python.org/3/library/dataclasses.html#frozen-instances) for more details. ```python from pydantic import BaseModel, Field, ValidationError class User(BaseModel): name: str = Field(frozen=True) age: int user = User(name='John', age=42) try: user.name = 'Jane' # (1) except ValidationError as e: print(e) """ 1 validation error for User name Field is frozen [type=frozen_field, input_value='Jane', input_type=str] """ ``` Since `name` field is frozen, the assignment is not allowed. ## Excluding fields The `exclude` and `exclude_if` parameters can be used to control which fields should be excluded from the model when exporting the model. See the following example: ```python from pydantic import BaseModel, Field class User(BaseModel): name: str age: int = Field(exclude=True) user = User(name='John', age=42) print(user.model_dump()) # (1) #> {'name': 'John'} ``` The `age` field is not included in the [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) output, since it is excluded. See the dedicated [serialization section](/docs/validation/latest/concepts/serialization#field-inclusion-and-exclusion) for more details. ✦ New in v2.12 The `exclude_if` parameter. ## Deprecated fields ✦ New in v2.7.0 The `deprecated` parameter can be used to mark a field as being deprecated. Doing so will result in: - a runtime deprecation warning emitted when accessing the field. - The [deprecated](https://json-schema.org/draft/2020-12/json-schema-validation#section-9.3) keyword being set in the generated JSON schema. This parameter accepts different types, described below. ### `deprecated` as a string The value will be used as the deprecation message. ```python from typing import Annotated from pydantic import BaseModel, Field class Model(BaseModel): deprecated_field: Annotated[int, Field(deprecated='This is deprecated')] print(Model.model_json_schema()['properties']['deprecated_field']) #> {'deprecated': True, 'title': 'Deprecated Field', 'type': 'integer'} ``` ### `deprecated` via the `@warnings.deprecated` decorator The [`@warnings.deprecated`](https://docs.python.org/3/library/warnings.html#warnings.deprecated) decorator (or the [`typing_extensions` backport](https://typing-extensions.readthedocs.io/en/latest/index.html#typing_extensions.deprecated) on Python 3.12 and lower) can be used as an instance. - [Python 3.9 and above](#tab-panel-558) - [Python 3.13 and above](#tab-panel-559) ```python from typing import Annotated from typing_extensions import deprecated from pydantic import BaseModel, Field class Model(BaseModel): deprecated_field: Annotated[int, deprecated('This is deprecated')] # Or explicitly using `Field`: alt_form: Annotated[int, Field(deprecated=deprecated('This is deprecated'))] ``` ```python from typing import Annotated from warnings import deprecated from pydantic import BaseModel, Field class Model(BaseModel): deprecated_field: Annotated[int, deprecated('This is deprecated')] # Or explicitly using `Field`: alt_form: Annotated[int, Field(deprecated=deprecated('This is deprecated'))] ``` Support for `category` and `stacklevel` The current implementation of this feature does not take into account the `category` and `stacklevel` arguments to the `deprecated` decorator. This might land in a future version of Pydantic. ### `deprecated` as a boolean ```python from typing import Annotated from pydantic import BaseModel, Field class Model(BaseModel): deprecated_field: Annotated[int, Field(deprecated=True)] print(Model.model_json_schema()['properties']['deprecated_field']) #> {'deprecated': True, 'title': 'Deprecated Field', 'type': 'integer'} ``` Accessing a deprecated field in validators When accessing a deprecated field inside a validator, the deprecation warning will be emitted. You can use [`catch_warnings`](https://docs.python.org/3/library/warnings.html#warnings.catch_warnings) to explicitly ignore it: ```python import warnings from typing_extensions import Self from pydantic import BaseModel, Field, model_validator class Model(BaseModel): deprecated_field: int = Field(deprecated='This is deprecated') @model_validator(mode='after') def validate_model(self) -> Self: with warnings.catch_warnings(): warnings.simplefilter('ignore', DeprecationWarning) self.deprecated_field = self.deprecated_field * 2 ``` ## Customizing JSON Schema Some field parameters are used exclusively to customize the generated JSON schema. The parameters in question are: - `title` - `description` - `examples` - `json_schema_extra` Read more about JSON schema customization / modification with fields in the [Customizing JSON Schema](/docs/validation/latest/concepts/json_schema#field-level-customization) section of the JSON schema docs. ## The `computed_field` decorator API Documentation [`@computed_field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.computed_field) ✦ New in v2.13 Computed fields can be conditionally excluded from the serialization output by using the `exclude_if` parameter of the decorator. The [`@computed_field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.computed_field) decorator can be used to include [properties](https://docs.python.org/3/library/functions.html#property) (or [cached properties](https://docs.python.org/3/library/functools.html#functools.cached_property)) when serializing a model or dataclass. The property will also be included in the JSON Schema (in serialization mode). Note Properties can be useful for fields that are computed from other fields, or for fields that are expensive to be computed (and thus, are cached if using [`@cached_property`](https://docs.python.org/3/library/functools.html#functools.cached_property)). However, note that Pydantic will _not_ perform any additional logic on the wrapped property (validation, cache invalidation, etc.). Here's an example of the JSON schema (in serialization mode) generated for a model with a computed field: ```python from pydantic import BaseModel, computed_field class Box(BaseModel): width: float height: float depth: float @computed_field @property # (1) def volume(self) -> float: return self.width * self.height * self.depth print(Box.model_json_schema(mode='serialization')) """ { 'properties': { 'width': {'title': 'Width', 'type': 'number'}, 'height': {'title': 'Height', 'type': 'number'}, 'depth': {'title': 'Depth', 'type': 'number'}, 'volume': {'readOnly': True, 'title': 'Volume', 'type': 'number'}, }, 'required': ['width', 'height', 'depth', 'volume'], 'title': 'Box', 'type': 'object', } """ ``` If not specified, [`@computed_field`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.computed_field) will implicitly convert the method to a [`@property`](https://docs.python.org/3/library/functions.html#property). However, it is preferable to explicitly use the [`@property`](https://docs.python.org/3/library/functions.html#property) decorator for type checking purposes. Here's an example using the [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) method with a computed field: ```python from pydantic import BaseModel, computed_field class Box(BaseModel): width: float height: float depth: float @computed_field @property def volume(self) -> float: return self.width * self.height * self.depth b = Box(width=1, height=2, depth=3) print(b.model_dump()) #> {'width': 1.0, 'height': 2.0, 'depth': 3.0, 'volume': 6.0} ``` As with regular fields, computed fields can be marked as being deprecated: ```python from typing_extensions import deprecated from pydantic import BaseModel, computed_field class Box(BaseModel): width: float height: float depth: float @computed_field @property @deprecated("'volume' is deprecated") def volume(self) -> float: return self.width * self.height * self.depth ``` --- # [Forward Annotations](https://pydantic.dev/docs/validation/latest/concepts/forward_annotations/) # Forward Annotations Forward annotations (wrapped in quotes) or using the `from __future__ import annotations` [future statement](https://docs.python.org/3/reference/simple_stmts.html#future) (as introduced in [PEP563](https://www.python.org/dev/peps/pep-0563/)) are supported: ```python from __future__ import annotations from pydantic import BaseModel MyInt = int class Model(BaseModel): a: MyInt # Without the future import, equivalent to: # a: 'MyInt' print(Model(a='1')) #> a=1 ``` As shown in the following sections, forward annotations are useful when you want to reference a type that is not yet defined in your code. The internal logic to resolve forward annotations is described in detail in [this section](/docs/validation/latest/internals/resolving_annotations). ## Self-referencing (or "Recursive") Models Models with self-referencing fields are also supported. These annotations will be resolved during model creation. Within the model, you can either add the `from __future__ import annotations` import or wrap the annotation in a string: ```python from typing import Optional from pydantic import BaseModel class Foo(BaseModel): a: int = 123 sibling: 'Optional[Foo]' = None print(Foo()) #> a=123 sibling=None print(Foo(sibling={'a': '321'})) #> a=123 sibling=Foo(a=321, sibling=None) ``` ### Cyclic references When working with self-referencing recursive models, it is possible that you might encounter cyclic references in validation inputs. For example, this can happen when validating ORM instances with back-references from attributes. Rather than raising a [`RecursionError`](https://docs.python.org/3/library/exceptions.html#RecursionError) while attempting to validate data with cyclic references, Pydantic is able to detect the cyclic reference and raise an appropriate [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError): ```python from typing import Optional from pydantic import BaseModel, ValidationError class ModelA(BaseModel): b: 'Optional[ModelB]' = None class ModelB(BaseModel): a: Optional[ModelA] = None cyclic_data = {} cyclic_data['a'] = {'b': cyclic_data} print(cyclic_data) #> {'a': {'b': {...}}} try: ModelB.model_validate(cyclic_data) except ValidationError as exc: print(exc) """ 1 validation error for ModelB a.b Recursion error - cyclic reference detected [type=recursion_loop, input_value={'a': {'b': {...}}}, input_type=dict] """ ``` Because this error is raised without actually exceeding the maximum recursion depth, you can catch and handle the raised [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) without needing to worry about the limited remaining recursion depth: ```python from __future__ import annotations from collections.abc import Generator from contextlib import contextmanager from dataclasses import field from pydantic import BaseModel, ValidationError, field_validator def is_recursion_validation_error(exc: ValidationError) -> bool: errors = exc.errors() return len(errors) == 1 and errors[0]['type'] == 'recursion_loop' @contextmanager def suppress_recursion_validation_error() -> Generator[None]: try: yield except ValidationError as exc: if not is_recursion_validation_error(exc): raise exc class Node(BaseModel): id: int children: list[Node] = field(default_factory=list) @field_validator('children', mode='wrap') @classmethod def drop_cyclic_references(cls, children, h): try: return h(children) except ValidationError as exc: if not ( is_recursion_validation_error(exc) and isinstance(children, list) ): raise exc value_without_cyclic_refs = [] for child in children: with suppress_recursion_validation_error(): value_without_cyclic_refs.extend(h([child])) return h(value_without_cyclic_refs) # Create data with cyclic references representing the graph 1 -> 2 -> 3 -> 1 node_data = {'id': 1, 'children': [{'id': 2, 'children': [{'id': 3}]}]} node_data['children'][0]['children'][0]['children'] = [node_data] print(Node.model_validate(node_data)) #> id=1 children=[Node(id=2, children=[Node(id=3, children=[])])] ``` Similarly, if Pydantic encounters a recursive reference during _serialization_, rather than waiting for the maximum recursion depth to be exceeded, a [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError) is raised immediately: ```python from pydantic import TypeAdapter # Create data with cyclic references representing the graph 1 -> 2 -> 3 -> 1 node_data = {'id': 1, 'children': [{'id': 2, 'children': [{'id': 3}]}]} node_data['children'][0]['children'][0]['children'] = [node_data] try: # Try serializing the circular reference as JSON TypeAdapter(dict).dump_json(node_data) except ValueError as exc: print(exc) """ Error serializing to JSON: ValueError: Circular reference detected (id repeated) """ ``` This can also be handled if desired: ```python from dataclasses import field from typing import Any from pydantic import ( SerializerFunctionWrapHandler, TypeAdapter, field_serializer, ) from pydantic.dataclasses import dataclass @dataclass class NodeReference: id: int @dataclass class Node(NodeReference): children: list['Node'] = field(default_factory=list) @field_serializer('children', mode='wrap') def serialize( self, children: list['Node'], handler: SerializerFunctionWrapHandler ) -> Any: """ Serialize a list of nodes, handling circular references by excluding the children. """ try: return handler(children) except ValueError as exc: if not str(exc).startswith('Circular reference'): raise exc result = [] for node in children: try: serialized = handler([node]) except ValueError as exc: if not str(exc).startswith('Circular reference'): raise exc result.append({'id': node.id}) else: result.append(serialized) return result # Create a cyclic graph: nodes = [Node(id=1), Node(id=2), Node(id=3)] nodes[0].children.append(nodes[1]) nodes[1].children.append(nodes[2]) nodes[2].children.append(nodes[0]) print(nodes[0]) #> Node(id=1, children=[Node(id=2, children=[Node(id=3, children=[...])])]) # Serialize the cyclic graph: print(TypeAdapter(Node).dump_python(nodes[0])) """ { 'id': 1, 'children': [{'id': 2, 'children': [{'id': 3, 'children': [{'id': 1}]}]}], } """ ``` --- # [JSON](https://pydantic.dev/docs/validation/latest/concepts/json/) # JSON ## Json Parsing API Documentation [`pydantic.main.BaseModel.model_validate_json`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json) [`pydantic.type_adapter.TypeAdapter.validate_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_json) [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json) Pydantic provides builtin JSON parsing, which helps achieve: - Significant performance improvements without the cost of using a 3rd party library - Support for custom errors - Support for `strict` specifications Here's an example of Pydantic's builtin JSON parsing via the [`model_validate_json`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json) method, showcasing the support for `strict` specifications while parsing JSON data that doesn't match the model's type annotations: ```python from datetime import date from pydantic import BaseModel, ConfigDict, ValidationError class Event(BaseModel): model_config = ConfigDict(strict=True) when: date where: tuple[int, int] json_data = '{"when": "1987-01-28", "where": [51, -1]}' print(Event.model_validate_json(json_data)) # (1) #> when=datetime.date(1987, 1, 28) where=(51, -1) try: Event.model_validate({'when': '1987-01-28', 'where': [51, -1]}) # (2) except ValidationError as e: print(e) """ 2 validation errors for Event when Input should be a valid date [type=date_type, input_value='1987-01-28', input_type=str] where Input should be a valid tuple [type=tuple_type, input_value=[51, -1], input_type=list] """ ``` JSON has no `date` or tuple types, but Pydantic knows that so allows strings and arrays as inputs respectively when parsing JSON directly. If you pass the same values to the [`model_validate`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate) method, Pydantic will raise a validation error because the `strict` configuration is enabled. In v2.5.0 and above, Pydantic uses [`jiter`](https://docs.rs/jiter/latest/jiter/), a fast and iterable JSON parser, to parse JSON data. Using `jiter` compared to `serde` results in modest performance improvements that will get even better in the future. The `jiter` JSON parser is almost entirely compatible with the `serde` JSON parser, with one noticeable enhancement being that `jiter` supports deserialization of `inf` and `NaN` values. In the future, `jiter` is intended to enable support validation errors to include the location in the original JSON input which contained the invalid value. ### Partial JSON Parsing **Starting in v2.7.0**, Pydantic's [JSON parser](https://docs.rs/jiter/latest/jiter/) offers support for partial JSON parsing, which is exposed via [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json). Here's an example of this feature in action: ```python from pydantic_core import from_json partial_json_data = '["aa", "bb", "c' # (1) try: result = from_json(partial_json_data, allow_partial=False) except ValueError as e: print(e) # (2) #> EOF while parsing a string at line 1 column 15 result = from_json(partial_json_data, allow_partial=True) print(result) # (3) #> ['aa', 'bb'] ``` The JSON list is incomplete - it's missing a closing `"]` When `allow_partial` is set to `False` (the default), a parsing error occurs. When `allow_partial` is set to `True`, part of the input is deserialized successfully. This also works for deserializing partial dictionaries. For example: ```python from pydantic_core import from_json partial_dog_json = '{"breed": "lab", "name": "fluffy", "friends": ["buddy", "spot", "rufus"], "age' dog_dict = from_json(partial_dog_json, allow_partial=True) print(dog_dict) #> {'breed': 'lab', 'name': 'fluffy', 'friends': ['buddy', 'spot', 'rufus']} ``` Validating LLM Output This feature is particularly beneficial for validating LLM outputs. We've written some blog posts about this topic, which you can find on [our website](https://pydantic.dev/articles). In future versions of Pydantic, we expect to expand support for this feature through either Pydantic's other JSON validation functions ([`pydantic.main.BaseModel.model_validate_json`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json) and [`pydantic.type_adapter.TypeAdapter.validate_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_json)) or model configuration. Stay tuned 🚀! For now, you can use [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json) in combination with [`pydantic.main.BaseModel.model_validate`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate) to achieve the same result. Here's an example: ```python from pydantic_core import from_json from pydantic import BaseModel class Dog(BaseModel): breed: str name: str friends: list partial_dog_json = '{"breed": "lab", "name": "fluffy", "friends": ["buddy", "spot", "rufus"], "age' dog = Dog.model_validate(from_json(partial_dog_json, allow_partial=True)) print(repr(dog)) #> Dog(breed='lab', name='fluffy', friends=['buddy', 'spot', 'rufus']) ``` Tip For partial JSON parsing to work reliably, all fields on the model should have default values. Check out the following example for a more in-depth look at how to use default values with partial JSON parsing: Using default values with partial JSON parsing ```python from typing import Annotated, Any, Optional import pydantic_core from pydantic import BaseModel, ValidationError, WrapValidator def default_on_error(v, handler) -> Any: """ Raise a PydanticUseDefault exception if the value is missing. This is useful for avoiding errors from partial JSON preventing successful validation. """ try: return handler(v) except ValidationError as exc: # there might be other types of errors resulting from partial JSON parsing # that you allow here, feel free to customize as needed if all(e['type'] == 'missing' for e in exc.errors()): raise pydantic_core.PydanticUseDefault() else: raise class NestedModel(BaseModel): x: int y: str class MyModel(BaseModel): foo: Optional[str] = None bar: Annotated[ Optional[tuple[str, int]], WrapValidator(default_on_error) ] = None nested: Annotated[ Optional[NestedModel], WrapValidator(default_on_error) ] = None m = MyModel.model_validate( pydantic_core.from_json('{"foo": "x", "bar": ["world",', allow_partial=True) ) print(repr(m)) #> MyModel(foo='x', bar=None, nested=None) m = MyModel.model_validate( pydantic_core.from_json( '{"foo": "x", "bar": ["world", 1], "nested": {"x":', allow_partial=True ) ) print(repr(m)) #> MyModel(foo='x', bar=('world', 1), nested=None) ``` ### Caching Strings **Starting in v2.7.0**, Pydantic's [JSON parser](https://docs.rs/jiter/latest/jiter/) offers support for configuring how Python strings are cached during JSON parsing and validation (when Python strings are constructed from Rust strings during Python validation, e.g. after `strip_whitespace=True`). The `cache_strings` setting is exposed via both [model config](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) and [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json). The `cache_strings` setting can take any of the following values: - `True` or `'all'` (the default): cache all strings - `'keys'`: cache only dictionary keys, this **only** applies when used with [`pydantic_core.from_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.from_json) or when parsing JSON using [`Json`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Json) - `False` or `'none'`: no caching Using the string caching feature results in performance improvements, but increases memory usage slightly. String Caching Details 1. Strings are cached using a fully associative cache with a size of [16,384](https://github.com/pydantic/jiter/blob/5bbdcfd22882b7b286416b22f74abd549c7b2fd7/src/py_string_cache.rs#L113). 2. Only strings where `len(string) < 64` are cached. 3. There is some overhead to looking up the cache, which is normally worth it to avoid constructing strings. However, if you know there will be very few repeated strings in your data, you might get a performance boost by disabling this setting with `cache_strings=False`. ## JSON Serialization API Documentation [`pydantic.main.BaseModel.model_dump_json`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) [`pydantic.type_adapter.TypeAdapter.dump_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_json) [`pydantic_core.to_json`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.to_json) For more information on JSON serialization, see the [serialization concepts](/docs/validation/latest/concepts/serialization) page. --- # [JSON Schema](https://pydantic.dev/docs/validation/latest/concepts/json_schema/) # JSON Schema API Documentation [`pydantic.json_schema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema) Pydantic allows automatic creation and customization of JSON schemas from models. The generated JSON schemas are compliant with the following specifications: - [JSON Schema Draft 2020-12](https://json-schema.org/draft/2020-12/release-notes.html) - [OpenAPI Specification v3.1.0](https://github.com/OAI/OpenAPI-Specification). ## Generating JSON Schema Use the following functions to generate JSON schema: - [`BaseModel.model_json_schema`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) returns a jsonable dict of a model's schema. - [`TypeAdapter.json_schema`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.json_schema) returns a jsonable dict of an adapted type's schema. Note These methods are not to be confused with [`BaseModel.model_dump_json`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) and [`TypeAdapter.dump_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_json), which serialize instances of the model or adapted type, respectively. These methods return JSON strings. In comparison, [`BaseModel.model_json_schema`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) and [`TypeAdapter.json_schema`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.json_schema) return a jsonable dict representing the JSON schema of the model or adapted type, respectively. on the Regarding the "jsonable" nature of the [`model_json_schema`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) results, calling `json.dumps(m.model_json_schema())`on some `BaseModel` `m` returns a valid JSON string. Similarly, for [`TypeAdapter.json_schema`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.json_schema), calling `json.dumps(TypeAdapter().json_schema())` returns a valid JSON string. Tip Pydantic offers support for both of: 1. [Customizing JSON Schema](#customizing-json-schema) 2. [Customizing the JSON Schema Generation Process](#customizing-the-json-schema-generation-process) The first approach generally has a more narrow scope, allowing for customization of the JSON schema for more specific cases and types. The second approach generally has a more broad scope, allowing for customization of the JSON schema generation process overall. The same effects can be achieved with either approach, but depending on your use case, one approach might offer a more simple solution than the other. Here's an example of generating JSON schema from a `BaseModel`: ```python import json from enum import Enum from typing import Annotated, Union from pydantic import BaseModel, Field from pydantic.config import ConfigDict class FooBar(BaseModel): count: int size: Union[float, None] = None class Gender(str, Enum): male = 'male' female = 'female' other = 'other' not_given = 'not_given' class MainModel(BaseModel): """ This is the description of the main model """ model_config = ConfigDict(title='Main') foo_bar: FooBar gender: Annotated[Union[Gender, None], Field(alias='Gender')] = None snap: int = Field( default=42, title='The Snap', description='this is the value of snap', gt=30, lt=50, ) main_model_schema = MainModel.model_json_schema() # (1) print(json.dumps(main_model_schema, indent=2)) # (2) """ { "$defs": { "FooBar": { "properties": { "count": { "title": "Count", "type": "integer" }, "size": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "default": null, "title": "Size" } }, "required": [ "count" ], "title": "FooBar", "type": "object" }, "Gender": { "enum": [ "male", "female", "other", "not_given" ], "title": "Gender", "type": "string" } }, "description": "This is the description of the main model", "properties": { "foo_bar": { "$ref": "#/$defs/FooBar" }, "Gender": { "anyOf": [ { "$ref": "#/$defs/Gender" }, { "type": "null" } ], "default": null }, "snap": { "default": 42, "description": "this is the value of snap", "exclusiveMaximum": 50, "exclusiveMinimum": 30, "title": "The Snap", "type": "integer" } }, "required": [ "foo_bar" ], "title": "Main", "type": "object" } """ ``` This produces a "jsonable" dict of `MainModel`'s schema. Calling `json.dumps` on the schema dict produces a JSON string. The [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) class lets you create an object with methods for validating, serializing, and producing JSON schemas for arbitrary types. This serves as a complete replacement for `schema_of` in Pydantic V1 (which is now deprecated). Here's an example of generating JSON schema from a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter): ```python from pydantic import TypeAdapter adapter = TypeAdapter(list[int]) print(adapter.json_schema()) #> {'items': {'type': 'integer'}, 'type': 'array'} ``` You can also generate JSON schemas for combinations of [`BaseModel`s](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) and [`TypeAdapter`s](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter), as shown in this example: ```python import json from typing import Union from pydantic import BaseModel, TypeAdapter class Cat(BaseModel): name: str color: str class Dog(BaseModel): name: str breed: str ta = TypeAdapter(Union[Cat, Dog]) ta_schema = ta.json_schema() print(json.dumps(ta_schema, indent=2)) ``` **JSON output:** ```json { "$defs": { "Cat": { "properties": { "name": { "title": "Name", "type": "string" }, "color": { "title": "Color", "type": "string" } }, "required": [ "name", "color" ], "title": "Cat", "type": "object" }, "Dog": { "properties": { "name": { "title": "Name", "type": "string" }, "breed": { "title": "Breed", "type": "string" } }, "required": [ "name", "breed" ], "title": "Dog", "type": "object" } }, "anyOf": [ { "$ref": "#/$defs/Cat" }, { "$ref": "#/$defs/Dog" } ] } ``` ### Configuring the `JsonSchemaMode` Specify the mode of JSON schema generation via the `mode` parameter in the [`model_json_schema`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) and [`TypeAdapter.json_schema`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.json_schema) methods. By default, the mode is set to `'validation'`, which produces a JSON schema corresponding to the model's validation schema. The [`JsonSchemaMode`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.JsonSchemaMode) is a type alias that represents the available options for the `mode` parameter: - `'validation'` - `'serialization'` Here's an example of how to specify the `mode` parameter, and how it affects the generated JSON schema: ```python from decimal import Decimal from pydantic import BaseModel class Model(BaseModel): a: Decimal = Decimal('12.34') print(Model.model_json_schema(mode='validation')) """ { 'properties': { 'a': { 'anyOf': [ {'type': 'number'}, { 'pattern': '^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$', 'type': 'string', }, ], 'default': '12.34', 'title': 'A', } }, 'title': 'Model', 'type': 'object', } """ print(Model.model_json_schema(mode='serialization')) """ { 'properties': { 'a': { 'default': '12.34', 'pattern': '^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$', 'title': 'A', 'type': 'string', } }, 'title': 'Model', 'type': 'object', } """ ``` ## Customizing JSON Schema The generated JSON schema can be customized at both the [field level](#field-level-customization) and [model level](#model-level-customization). At both the field and model levels, you can use the [`json_schema_extra` option](#using-json_schema_extra) to add extra information to the JSON schema. For custom types, Pydantic offers other tools for customizing JSON schema generation: 1. [`WithJsonSchema` annotation](#withjsonschema-annotation) 2. [`SkipJsonSchema` annotation](#skipjsonschema-annotation) 3. [Implementing `__get_pydantic_core_schema__`](#implementing_get_pydantic_core_schema) 4. [Implementing `__get_pydantic_json_schema__`](#implementing_get_pydantic_json_schema) ### Field-Level Customization [Fields](/docs/validation/latest/concepts/fields) can have their JSON Schema customized. This is usually done using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. Some field parameters are used exclusively to customize the generated JSON Schema: - `title`: The title of the field. - `description`: The description of the field. - `examples`: The examples of the field. - `json_schema_extra`: Extra JSON Schema properties to be added to the field (see the [dedicated documentation](#using-json_schema_extra)). - `field_title_generator`: A function that programmatically sets the field's title, based on its name and info. Here's an example: ```python import json from typing import Annotated from pydantic import BaseModel, EmailStr, Field, SecretStr class User(BaseModel): age: int = Field(description='Age of the user') email: Annotated[EmailStr, Field(examples=['marcelo@mail.com'])] # (1) name: str = Field(title='Username') password: SecretStr = Field( json_schema_extra={ 'title': 'Password', 'description': 'Password of the user', 'examples': ['123456'], } ) print(json.dumps(User.model_json_schema(), indent=2)) """ { "properties": { "age": { "description": "Age of the user", "title": "Age", "type": "integer" }, "email": { "examples": [ "marcelo@mail.com" ], "format": "email", "title": "Email", "type": "string" }, "name": { "title": "Username", "type": "string" }, "password": { "description": "Password of the user", "examples": [ "123456" ], "format": "password", "title": "Password", "type": "string", "writeOnly": true } }, "required": [ "age", "email", "name", "password" ], "title": "User", "type": "object" } """ ``` The [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) can also be used. ### Programmatic field title generation The `field_title_generator` parameter can be used to programmatically generate the title for a field based on its name and info. See the following example: ```python import json from pydantic import BaseModel, Field from pydantic.fields import FieldInfo def make_title(field_name: str, field_info: FieldInfo) -> str: return field_name.upper() class Person(BaseModel): name: str = Field(field_title_generator=make_title) age: int = Field(field_title_generator=make_title) print(json.dumps(Person.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "properties": { "name": { "title": "NAME", "type": "string" }, "age": { "title": "AGE", "type": "integer" } }, "required": [ "name", "age" ], "title": "Person", "type": "object" } ``` ### Model-Level Customization You can also use [model config](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) to customize JSON schema generation on a model. Specifically, the following config options are relevant: - [`title`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.title) - [`json_schema_extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.json_schema_extra) - [`json_schema_mode_override`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.json_schema_mode_override) - [`field_title_generator`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.field_title_generator) - [`model_title_generator`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.model_title_generator) ### Using `json_schema_extra` The `json_schema_extra` option can be used to add extra information to the JSON schema, either at the [Field level](#field-level-customization) or at the [Model level](#model-level-customization). You can pass a `dict` or a `Callable` to `json_schema_extra`. #### Using `json_schema_extra` with a `dict` You can pass a `dict` to `json_schema_extra` to add extra information to the JSON schema: ```python import json from pydantic import BaseModel, ConfigDict class Model(BaseModel): a: str model_config = ConfigDict(json_schema_extra={'examples': [{'a': 'Foo'}]}) print(json.dumps(Model.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "examples": [ { "a": "Foo" } ], "properties": { "a": { "title": "A", "type": "string" } }, "required": [ "a" ], "title": "Model", "type": "object" } ``` #### Using `json_schema_extra` with a `Callable` You can pass a `Callable` to `json_schema_extra` to modify the JSON schema with a function: ```python import json from pydantic import BaseModel, Field def pop_default(s): s.pop('default') class Model(BaseModel): a: int = Field(default=1, json_schema_extra=pop_default) print(json.dumps(Model.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "properties": { "a": { "title": "A", "type": "integer" } }, "title": "Model", "type": "object" } ``` #### Merging `json_schema_extra` Starting in v2.9, Pydantic merges `json_schema_extra` dictionaries from annotated types. This pattern offers a more additive approach to merging rather than the previous override behavior. This can be quite helpful for cases of reusing json schema extra information across multiple types. We viewed this change largely as a bug fix, as it resolves unintentional differences in the `json_schema_extra` merging behavior between `BaseModel` and `TypeAdapter` instances - see [this issue](https://github.com/pydantic/pydantic/issues/9210) for more details. ```python import json from typing import Annotated from typing_extensions import TypeAlias from pydantic import Field, TypeAdapter ExternalType: TypeAlias = Annotated[ int, Field(json_schema_extra={'key1': 'value1'}) ] ta = TypeAdapter( Annotated[ExternalType, Field(json_schema_extra={'key2': 'value2'})] ) print(json.dumps(ta.json_schema(), indent=2)) ``` **JSON output:** ```json { "key1": "value1", "key2": "value2", "type": "integer" } ``` Note We no longer (and never fully did) support composing a mix of `dict` and `callable` type `json_schema_extra` specifications. If this is a requirement for your use case, please [open a pydantic issue](https://github.com/pydantic/pydantic/issues/new/choose) and explain your situation - we'd be happy to reconsider this decision when presented with a compelling case. ### `WithJsonSchema` annotation Tip Using [`WithJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.WithJsonSchema) is preferred over [implementing `__get_pydantic_json_schema__()`](#implementing_get_pydantic_json_schema) for custom types, as it's more simple and less error-prone. An annotation used to override the JSON Schema for a type. This is useful when you want to set a JSON Schema for a type that don't produce any JSON Schemas by default (e.g. [`Callable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable)). Note that this overrides the whole generated JSON Schema for the type (in the following example, the `'type'` also needs to be provided). ```python import json from typing import Annotated from pydantic import BaseModel, WithJsonSchema MyInt = Annotated[ int, WithJsonSchema({'type': 'integer', 'examples': [1, 0, -1]}), ] class Model(BaseModel): a: MyInt print(json.dumps(Model.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "properties": { "a": { "examples": [ 1, 0, -1 ], "title": "A", "type": "integer" } }, "required": [ "a" ], "title": "Model", "type": "object" } ``` See the [API documentation](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.WithJsonSchema) for more details. Note You might be tempted to use the [`WithJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.WithJsonSchema) annotation to fine-tune the JSON Schema of fields having [validators](/docs/validation/latest/concepts/validators) attached. Instead, it is recommended to use [the `json_schema_input_type` argument](/docs/validation/latest/concepts/validators#json-schema-and-field-validators). ### `SkipJsonSchema` annotation API Documentation [`pydantic.json_schema.SkipJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.SkipJsonSchema) The [`SkipJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.SkipJsonSchema) annotation can be used to skip an included field (or part of a field's specifications) from the generated JSON schema. See the API docs for more details. ### Implementing `__get_pydantic_core_schema__` Custom types (used as `field_name: TheType` or `field_name: Annotated[TheType, ...]`) as well as `Annotated` metadata (used as `field_name: Annotated[int, SomeMetadata]`) can modify or override the generated schema by implementing `__get_pydantic_core_schema__`. This method receives two positional arguments: 1. The type annotation that corresponds to this type (so in the case of `TheType[T](https://docs.python.org/3/library/functions.html#int)` it would be `TheType[int]`). 2. A handler/callback to call the next implementer of `__get_pydantic_core_schema__`. The handler system works just like [_wrap_ field validators](/docs/validation/latest/concepts/validators#field-wrap-validator). In this case the input is the type and the output is a `core_schema`. Here is an example of a custom type that _overrides_ the generated `core_schema`: ```python from dataclasses import dataclass from typing import Any from pydantic_core import core_schema from pydantic import BaseModel, GetCoreSchemaHandler @dataclass class CompressedString: dictionary: dict[int, str] text: list[int] def build(self) -> str: return ' '.join([self.dictionary[key] for key in self.text]) @classmethod def __get_pydantic_core_schema__( cls, source: type[Any], handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: assert source is CompressedString return core_schema.no_info_after_validator_function( cls._validate, core_schema.str_schema(), serialization=core_schema.plain_serializer_function_ser_schema( cls._serialize, info_arg=False, return_schema=core_schema.str_schema(), ), ) @staticmethod def _validate(value: str) -> 'CompressedString': inverse_dictionary: dict[str, int] = {} text: list[int] = [] for word in value.split(' '): if word not in inverse_dictionary: inverse_dictionary[word] = len(inverse_dictionary) text.append(inverse_dictionary[word]) return CompressedString( {v: k for k, v in inverse_dictionary.items()}, text ) @staticmethod def _serialize(value: 'CompressedString') -> str: return value.build() class MyModel(BaseModel): value: CompressedString print(MyModel.model_json_schema()) """ { 'properties': {'value': {'title': 'Value', 'type': 'string'}}, 'required': ['value'], 'title': 'MyModel', 'type': 'object', } """ print(MyModel(value='fox fox fox dog fox')) """ value = CompressedString(dictionary={0: 'fox', 1: 'dog'}, text=[0, 0, 0, 1, 0]) """ print(MyModel(value='fox fox fox dog fox').model_dump(mode='json')) #> {'value': 'fox fox fox dog fox'} ``` Since Pydantic would not know how to generate a schema for `CompressedString`, if you call `handler(source)` in its `__get_pydantic_core_schema__` method you would get a `pydantic.errors.PydanticSchemaGenerationError` error. This will be the case for most custom types, so you almost never want to call into `handler` for custom types. The process for `Annotated` metadata is much the same except that you can generally call into `handler` to have Pydantic handle generating the schema. ```python from collections.abc import Sequence from dataclasses import dataclass from typing import Annotated, Any from pydantic_core import core_schema from pydantic import BaseModel, GetCoreSchemaHandler, ValidationError @dataclass class RestrictCharacters: alphabet: Sequence[str] def __get_pydantic_core_schema__( self, source: type[Any], handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: if not self.alphabet: raise ValueError('Alphabet may not be empty') schema = handler( source ) # get the CoreSchema from the type / inner constraints if schema['type'] != 'str': raise TypeError('RestrictCharacters can only be applied to strings') return core_schema.no_info_after_validator_function( self.validate, schema, ) def validate(self, value: str) -> str: if any(c not in self.alphabet for c in value): raise ValueError( f'{value!r} is not restricted to {self.alphabet!r}' ) return value class MyModel(BaseModel): value: Annotated[str, RestrictCharacters('ABC')] print(MyModel.model_json_schema()) """ { 'properties': {'value': {'title': 'Value', 'type': 'string'}}, 'required': ['value'], 'title': 'MyModel', 'type': 'object', } """ print(MyModel(value='CBA')) #> value='CBA' try: MyModel(value='XYZ') except ValidationError as e: print(e) """ 1 validation error for MyModel value Value error, 'XYZ' is not restricted to 'ABC' [type=value_error, input_value='XYZ', input_type=str] """ ``` So far we have been wrapping the schema, but if you just want to _modify_ it or _ignore_ it you can as well. To modify the schema, first call the handler, then mutate the result: ```python from typing import Annotated, Any from pydantic_core import ValidationError, core_schema from pydantic import BaseModel, GetCoreSchemaHandler class SmallString: def __get_pydantic_core_schema__( self, source: type[Any], handler: GetCoreSchemaHandler, ) -> core_schema.CoreSchema: schema = handler(source) assert schema['type'] == 'str' schema['max_length'] = 10 # modify in place return schema class MyModel(BaseModel): value: Annotated[str, SmallString()] try: MyModel(value='too long!!!!!') except ValidationError as e: print(e) """ 1 validation error for MyModel value String should have at most 10 characters [type=string_too_long, input_value='too long!!!!!', input_type=str] """ ``` Tip Note that you _must_ return a schema, even if you are just mutating it in place. To override the schema completely, do not call the handler and return your own `CoreSchema`: ```python from typing import Annotated, Any from pydantic_core import ValidationError, core_schema from pydantic import BaseModel, GetCoreSchemaHandler class AllowAnySubclass: def __get_pydantic_core_schema__( self, source: type[Any], handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: # we can't call handler since it will fail for arbitrary types def validate(value: Any) -> Any: if not isinstance(value, source): raise ValueError( f'Expected an instance of {source}, got an instance of {type(value)}' ) return value return core_schema.no_info_plain_validator_function(validate) class Foo: pass class Model(BaseModel): f: Annotated[Foo, AllowAnySubclass()] print(Model(f=Foo())) #> f=<__main__.Foo object at 0x0123456789ab> class NotFoo: pass try: Model(f=NotFoo()) except ValidationError as e: print(e) """ 1 validation error for Model f Value error, Expected an instance of , got an instance of [type=value_error, input_value=<__main__.NotFoo object at 0x0123456789ab>, input_type=NotFoo] """ ``` ### Implementing `__get_pydantic_json_schema__` You can also implement `__get_pydantic_json_schema__` to modify or override the generated json schema. Modifying this method only affects the JSON schema - it doesn't affect the core schema, which is used for validation and serialization. Here's an example of modifying the generated JSON schema: ```python import json from typing import Any from pydantic_core import core_schema as cs from pydantic import GetCoreSchemaHandler, GetJsonSchemaHandler, TypeAdapter from pydantic.json_schema import JsonSchemaValue class Person: name: str age: int def __init__(self, name: str, age: int): self.name = name self.age = age @classmethod def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> cs.CoreSchema: return cs.typed_dict_schema( { 'name': cs.typed_dict_field(cs.str_schema()), 'age': cs.typed_dict_field(cs.int_schema()), }, ) @classmethod def __get_pydantic_json_schema__( cls, core_schema: cs.CoreSchema, handler: GetJsonSchemaHandler ) -> JsonSchemaValue: json_schema = handler(core_schema) json_schema = handler.resolve_ref_schema(json_schema) json_schema['examples'] = [ { 'name': 'John Doe', 'age': 25, } ] json_schema['title'] = 'Person' return json_schema print(json.dumps(TypeAdapter(Person).json_schema(), indent=2)) """ { "examples": [ { "age": 25, "name": "John Doe" } ], "properties": { "name": { "title": "Name", "type": "string" }, "age": { "title": "Age", "type": "integer" } }, "required": [ "name", "age" ], "title": "Person", "type": "object" } """ ``` ### Using `field_title_generator` The `field_title_generator` parameter can be used to programmatically generate the title for a field based on its name and info. This is similar to the field level `field_title_generator`, but the `ConfigDict` option will be applied to all fields of the class. See the following example: ```python import json from pydantic import BaseModel, ConfigDict class Person(BaseModel): model_config = ConfigDict( field_title_generator=lambda field_name, field_info: field_name.upper() ) name: str age: int print(json.dumps(Person.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "properties": { "name": { "title": "NAME", "type": "string" }, "age": { "title": "AGE", "type": "integer" } }, "required": [ "name", "age" ], "title": "Person", "type": "object" } ``` ### Using `model_title_generator` The `model_title_generator` config option is similar to the `field_title_generator` option, but it applies to the title of the model itself, and accepts the model class as input. See the following example: ```python import json from pydantic import BaseModel, ConfigDict def make_title(model: type) -> str: return f'Title-{model.__name__}' class Person(BaseModel): model_config = ConfigDict(model_title_generator=make_title) name: str age: int print(json.dumps(Person.model_json_schema(), indent=2)) ``` **JSON output:** ```json { "properties": { "name": { "title": "Name", "type": "string" }, "age": { "title": "Age", "type": "integer" } }, "required": [ "name", "age" ], "title": "Title-Person", "type": "object" } ``` ## JSON schema types Types, custom field types, and constraints (like `max_length`) are mapped to the corresponding spec formats in the following priority order (when there is an equivalent available): 1. [JSON Schema Core](https://json-schema.org/draft/2020-12/json-schema-core) 2. [JSON Schema Validation](https://json-schema.org/draft/2020-12/json-schema-validation) 3. [OpenAPI Data Types](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#data-types) 4. The standard `format` JSON field is used to define Pydantic extensions for more complex `string` sub-types. The field schema mapping from Python or Pydantic to JSON schema is done as follows: Python type JSON Schema Type Additional JSON Schema Defined in Notes `None` `null` JSON Schema Core Same for `type(None)` or `Literal[None]` `bool` `boolean` JSON Schema Core `str` `string` JSON Schema Core `float` `number` JSON Schema Core `int` `integer` JSON Schema Validation `dict` `object` JSON Schema Core `list` `array` `{"items": {}}` JSON Schema Core `tuple-positional` `array` `{"items": {}}` JSON Schema Core `tuple-variable` `array` `{"items": {}}` JSON Schema Core `set` `array` `{"uniqueItems": true, "items": {}}` JSON Schema Validation `frozenset` `array` `{"uniqueItems": true, "items": {}}` JSON Schema Validation `List[str]` `array` `{"items": {"type": "string"}}` JSON Schema Validation And equivalently for any other sub type, e.g. `List[int]`. `Tuple[str, ...]` `array` `{"items": {"type": "string"}}` JSON Schema Validation And equivalently for any other sub type, e.g. `Tuple[int, ...]`. `Tuple[str, int]` `array` `{"minItems": 2, "maxItems": 2, "items": [{"type": "string"}, {"type": "integer"}]}` JSON Schema Validation And equivalently for any other set of subtypes. Note: If using schemas for OpenAPI, you shouldn't use this declaration, as it would not be valid in OpenAPI (although it is valid in JSON Schema). `Dict[str, int]` `object` `{"additionalProperties": {"type": "integer"}}` JSON Schema Validation And equivalently for any other subfields for dicts. Have in mind that although you can use other types as keys for dicts with Pydantic, only strings are valid keys for JSON, and so, only str is valid as JSON Schema key types. `Union[str, int]` `anyOf` `{"anyOf": [{"type": "string"}, {"type": "integer"}]}` JSON Schema Validation And equivalently for any other subfields for unions. `Enum` `enum` `{"enum": [...]}` JSON Schema Validation All the literal values in the enum are included in the definition. `SecretStr` `string` `{"writeOnly": true}` JSON Schema Validation `SecretBytes` `string` `{"writeOnly": true}` JSON Schema Validation `EmailStr` `string` `{"format": "email"}` JSON Schema Validation `NameEmail` `string` `{"format": "name-email"}` Pydantic standard "format" extension `AnyUrl` `string` `{"format": "uri"}` JSON Schema Validation `Pattern` `string` `{"format": "regex"}` JSON Schema Validation `bytes` `string` `{"format": "binary"}` OpenAPI `Decimal` `number` JSON Schema Core `UUID1` `string` `{"format": "uuid1"}` Pydantic standard "format" extension `UUID3` `string` `{"format": "uuid3"}` Pydantic standard "format" extension `UUID4` `string` `{"format": "uuid4"}` Pydantic standard "format" extension `UUID5` `string` `{"format": "uuid5"}` Pydantic standard "format" extension `UUID` `string` `{"format": "uuid"}` Pydantic standard "format" extension Suggested in OpenAPI. `FilePath` `string` `{"format": "file-path"}` Pydantic standard "format" extension `DirectoryPath` `string` `{"format": "directory-path"}` Pydantic standard "format" extension `Path` `string` `{"format": "path"}` Pydantic standard "format" extension `datetime` `string` `{"format": "date-time"}` JSON Schema Validation `date` `string` `{"format": "date"}` JSON Schema Validation `time` `string` `{"format": "time"}` JSON Schema Validation `timedelta` `number` `{"format": "time-delta"}` Difference in seconds (a `float`), with Pydantic standard "format" extension Suggested in JSON Schema repository's issues by maintainer. `Json` `string` `{"format": "json-string"}` Pydantic standard "format" extension `IPv4Address` `string` `{"format": "ipv4"}` JSON Schema Validation `IPv6Address` `string` `{"format": "ipv6"}` JSON Schema Validation `IPvAnyAddress` `string` `{"format": "ipvanyaddress"}` Pydantic standard "format" extension IPv4 or IPv6 address as used in `ipaddress` module `IPv4Interface` `string` `{"format": "ipv4interface"}` Pydantic standard "format" extension IPv4 interface as used in `ipaddress` module `IPv6Interface` `string` `{"format": "ipv6interface"}` Pydantic standard "format" extension IPv6 interface as used in `ipaddress` module `IPvAnyInterface` `string` `{"format": "ipvanyinterface"}` Pydantic standard "format" extension IPv4 or IPv6 interface as used in `ipaddress` module `IPv4Network` `string` `{"format": "ipv4network"}` Pydantic standard "format" extension IPv4 network as used in `ipaddress` module `IPv6Network` `string` `{"format": "ipv6network"}` Pydantic standard "format" extension IPv6 network as used in `ipaddress` module `IPvAnyNetwork` `string` `{"format": "ipvanynetwork"}` Pydantic standard "format" extension IPv4 or IPv6 network as used in `ipaddress` module `StrictBool` `boolean` JSON Schema Core `StrictStr` `string` JSON Schema Core `ConstrainedStr` `string` JSON Schema Core If the type has values declared for the constraints, they are included as validations. See the mapping for `constr` below. \`constr(pattern='^text `string` `\{"pattern": "^text$", "minLength": 2, "maxLength": 10\}` JSON Schema Validation Any argument not passed to the function (not defined) will not be included in the schema. `ConstrainedInt` `integer` JSON Schema Core If the type has values declared for the constraints, they are included as validations. See the mapping for `conint` below. `conint(gt=1, ge=2, lt=6, le=5, multiple_of=2)` `integer` `{"maximum": 5, "exclusiveMaximum": 6, "minimum": 2, "exclusiveMinimum": 1, "multipleOf": 2}` Any argument not passed to the function (not defined) will not be included in the schema. `PositiveInt` `integer` `{"exclusiveMinimum": 0}` JSON Schema Validation `NegativeInt` `integer` `{"exclusiveMaximum": 0}` JSON Schema Validation `NonNegativeInt` `integer` `{"minimum": 0}` JSON Schema Validation `NonPositiveInt` `integer` `{"maximum": 0}` JSON Schema Validation `ConstrainedFloat` `number` JSON Schema Core If the type has values declared for the constraints, they are included as validations. See the mapping for `confloat` below. `confloat(gt=1, ge=2, lt=6, le=5, multiple_of=2)` `number` `{"maximum": 5, "exclusiveMaximum": 6, "minimum": 2, "exclusiveMinimum": 1, "multipleOf": 2}` JSON Schema Validation Any argument not passed to the function (not defined) will not be included in the schema. `PositiveFloat` `number` `{"exclusiveMinimum": 0}` JSON Schema Validation `NegativeFloat` `number` `{"exclusiveMaximum": 0}` JSON Schema Validation `NonNegativeFloat` `number` `{"minimum": 0}` JSON Schema Validation `NonPositiveFloat` `number` `{"maximum": 0}` JSON Schema Validation `ConstrainedDecimal` `number` JSON Schema Core If the type has values declared for the constraints, they are included as validations. See the mapping for `condecimal` below. `condecimal(gt=1, ge=2, lt=6, le=5, multiple_of=2)` `number` `{"maximum": 5, "exclusiveMaximum": 6, "minimum": 2, "exclusiveMinimum": 1, "multipleOf": 2}` JSON Schema Validation Any argument not passed to the function (not defined) will not be included in the schema. `BaseModel` `object` JSON Schema Core All the properties defined will be defined with standard JSON Schema, including submodels. `Color` `string` `{"format": "color"}` Pydantic standard "format" extension ## Top-level schema generation You can also generate a top-level JSON schema that only includes a list of models and related sub-models in its `$defs`: ```python import json from pydantic import BaseModel from pydantic.json_schema import models_json_schema class Foo(BaseModel): a: str = None class Model(BaseModel): b: Foo class Bar(BaseModel): c: int _, top_level_schema = models_json_schema( [(Model, 'validation'), (Bar, 'validation')], title='My Schema' ) print(json.dumps(top_level_schema, indent=2)) ``` **JSON output:** ```json { "$defs": { "Bar": { "properties": { "c": { "title": "C", "type": "integer" } }, "required": [ "c" ], "title": "Bar", "type": "object" }, "Foo": { "properties": { "a": { "default": null, "title": "A", "type": "string" } }, "title": "Foo", "type": "object" }, "Model": { "properties": { "b": { "$ref": "#/$defs/Foo" } }, "required": [ "b" ], "title": "Model", "type": "object" } }, "title": "My Schema" } ``` ## Customizing the JSON Schema Generation Process API Documentation [`pydantic.json_schema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema) If you need custom schema generation, you can use a `schema_generator`, modifying the [`GenerateJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema) class as necessary for your application. The various methods that can be used to produce JSON schema accept a keyword argument `schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema`, and you can pass your custom subclass to these methods in order to use your own approach to generating JSON schema. `GenerateJsonSchema` implements the translation of a type's `pydantic-core` schema into a JSON schema. By design, this class breaks the JSON schema generation process into smaller methods that can be easily overridden in subclasses to modify the "global" approach to generating JSON schema. ```python from pydantic import BaseModel from pydantic.json_schema import GenerateJsonSchema class MyGenerateJsonSchema(GenerateJsonSchema): def generate(self, schema, mode='validation'): json_schema = super().generate(schema, mode=mode) json_schema['title'] = 'Customize title' json_schema['$schema'] = self.schema_dialect return json_schema class MyModel(BaseModel): x: int print(MyModel.model_json_schema(schema_generator=MyGenerateJsonSchema)) """ { 'properties': {'x': {'title': 'X', 'type': 'integer'}}, 'required': ['x'], 'title': 'Customize title', 'type': 'object', '$schema': 'https://json-schema.org/draft/2020-12/schema', } """ ``` Below is an approach you can use to exclude any fields from the schema that don't have valid json schemas: ```python from typing import Callable from pydantic_core import PydanticOmit, core_schema from pydantic import BaseModel from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue class MyGenerateJsonSchema(GenerateJsonSchema): def handle_invalid_for_json_schema( self, schema: core_schema.CoreSchema, error_info: str ) -> JsonSchemaValue: raise PydanticOmit def example_callable(): return 1 class Example(BaseModel): name: str = 'example' function: Callable = example_callable instance_example = Example() validation_schema = instance_example.model_json_schema( schema_generator=MyGenerateJsonSchema, mode='validation' ) print(validation_schema) """ { 'properties': { 'name': {'default': 'example', 'title': 'Name', 'type': 'string'} }, 'title': 'Example', 'type': 'object', } """ ``` ### JSON schema sorting By default, Pydantic recursively sorts JSON schemas by alphabetically sorting keys. Notably, Pydantic skips sorting the values of the `properties` key, to preserve the order of the fields as they were defined in the model. If you would like to customize this behavior, you can override the `sort` method in your custom `GenerateJsonSchema` subclass. The below example uses a no-op `sort` method to disable sorting entirely, which is reflected in the preserved order of the model fields and `json_schema_extra` keys: ```python import json from typing import Optional from pydantic import BaseModel, Field from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue class MyGenerateJsonSchema(GenerateJsonSchema): def sort( self, value: JsonSchemaValue, parent_key: Optional[str] = None ) -> JsonSchemaValue: """No-op, we don't want to sort schema values at all.""" return value class Bar(BaseModel): c: str b: str a: str = Field(json_schema_extra={'c': 'hi', 'b': 'hello', 'a': 'world'}) json_schema = Bar.model_json_schema(schema_generator=MyGenerateJsonSchema) print(json.dumps(json_schema, indent=2)) ``` **JSON output:** ```json { "type": "object", "properties": { "c": { "type": "string", "title": "C" }, "b": { "type": "string", "title": "B" }, "a": { "type": "string", "c": "hi", "b": "hello", "a": "world", "title": "A" } }, "required": [ "c", "b", "a" ], "title": "Bar" } ``` ## Customizing the `$ref`s in JSON Schema The format of `$ref`s can be altered by calling [`model_json_schema()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) or [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) with the `ref_template` keyword argument. The definitions are always stored under the key `$defs`, but a specified prefix can be used for the references. This is useful if you need to extend or modify the JSON schema default definitions location. For example, with OpenAPI: ```python import json from pydantic import BaseModel from pydantic.type_adapter import TypeAdapter class Foo(BaseModel): a: int class Model(BaseModel): a: Foo adapter = TypeAdapter(Model) print( json.dumps( adapter.json_schema(ref_template='#/components/schemas/{model}'), indent=2, ) ) ``` **JSON output:** ```json { "$defs": { "Foo": { "properties": { "a": { "title": "A", "type": "integer" } }, "required": [ "a" ], "title": "Foo", "type": "object" } }, "properties": { "a": { "$ref": "#/components/schemas/Foo" } }, "required": [ "a" ], "title": "Model", "type": "object" } ``` ## Miscellaneous Notes on JSON Schema Generation - The JSON schema for `Optional` fields indicates that the value `null` is allowed. - The `Decimal` type is exposed in JSON schema (and serialized) as a string. - Since the `namedtuple` type doesn't exist in JSON, a model's JSON schema does not preserve `namedtuple`s as `namedtuple`s. - Sub-models used are added to the `$defs` JSON attribute and referenced, as per the spec. - Sub-models with modifications (via the `Field` class) like a custom title, description, or default value, are recursively included instead of referenced. - The `description` for models is taken from either the docstring of the class or the argument `description` to the `Field` class. - The schema is generated by default using aliases as keys, but it can be generated using model property names instead by calling [`model_json_schema()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema) or [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) with the `by_alias=False` keyword argument. --- # [Models](https://pydantic.dev/docs/validation/latest/concepts/models/) # Models API Documentation [`pydantic.main.BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) One of the primary ways of defining schema in Pydantic is via models. Models are simply classes which inherit from [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) and define fields as annotated attributes. You can think of models as similar to structs in languages like C, or as the requirements of a single endpoint in an API. Models share many similarities with Python's [dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses), but have been designed with some subtle-yet-important differences that streamline certain workflows related to validation, serialization, and JSON schema generation. You can find more discussion of this in the [Dataclasses](/docs/validation/latest/concepts/dataclasses) section of the docs. Untrusted data can be passed to a model and, after parsing and validation, Pydantic guarantees that the fields of the resultant model instance will conform to the field types defined on the model. Validation -- a _deliberate_ misnomer ### TL;DR We use the term "validation" to refer to the process of instantiating a model (or other type) that adheres to specified types and constraints. This task, which Pydantic is well known for, is most widely recognized as "validation" in colloquial terms, even though in other contexts the term "validation" may be more restrictive. * * * ### The long version The potential confusion around the term "validation" arises from the fact that, strictly speaking, Pydantic's primary focus doesn't align precisely with the dictionary definition of "validation": > ### validation > > _noun_ the action of checking or proving the validity or accuracy of something. In Pydantic, the term "validation" refers to the process of instantiating a model (or other type) that adheres to specified types and constraints. Pydantic guarantees the types and constraints of the output, not the input data. This distinction becomes apparent when considering that Pydantic's `ValidationError` is raised when data cannot be successfully parsed into a model instance. While this distinction may initially seem subtle, it holds practical significance. In some cases, "validation" goes beyond just model creation, and can include the copying and coercion of data. This can involve copying arguments passed to the constructor in order to perform coercion to a new type without mutating the original input data. For a more in-depth understanding of the implications for your usage, refer to the [Data Conversion](#data-conversion) and [Attribute Copies](#attribute-copies) sections below. In essence, Pydantic's primary goal is to assure that the resulting structure post-processing (termed "validation") precisely conforms to the applied type hints. Given the widespread adoption of "validation" as the colloquial term for this process, we will consistently use it in our documentation. While the terms "parse" and "validation" were previously used interchangeably, moving forward, we aim to exclusively employ "validate", with "parse" reserved specifically for discussions related to [JSON parsing](/docs/validation/latest/concepts/json). ## Basic model usage Note Pydantic relies heavily on the existing Python typing constructs to define models. If you are not familiar with those, the following resources can be useful: - The [Type System Guides](https://typing.readthedocs.io/en/latest/guides/index.html) - The [mypy documentation](https://mypy.readthedocs.io/en/latest/) ```python from pydantic import BaseModel, ConfigDict class User(BaseModel): id: int name: str = 'Jane Doe' model_config = ConfigDict(str_max_length=10) # (1) ``` Pydantic models support a variety of [configuration values](/docs/validation/latest/concepts/config) (see [here](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) for the available configuration values). In this example, `User` is a model with two fields: - `id`, which is an integer (defined using the [`int`](https://docs.python.org/3/library/functions.html#int) type) and is required - `name`, which is a string (defined using the [`str`](https://docs.python.org/3/library/stdtypes.html#str) type) and is not required (it has a default value). The documentation on [types](/docs/validation/latest/concepts/types) expands on the supported types. Fields can be customized in a number of ways using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function. See the [documentation on fields](/docs/validation/latest/concepts/fields) for more information. The model can then be instantiated: ```python user = User(id='123') ``` `user` is an instance of `User`. Initialization of the object will perform all parsing and validation. If no [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) exception is raised, you know the resulting model instance is valid. Fields of a model can be accessed as normal attributes of the `user` object: ```python assert user.name == 'Jane Doe' # (1) assert user.id == 123 # (2) assert isinstance(user.id, int) ``` `name` wasn't set when `user` was initialized, so the default value was used. The [`model_fields_set`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields_set) attribute can be inspected to check the field names explicitly set during instantiation. Note that the string `'123'` was coerced to an integer and its value is `123`. More details on Pydantic's coercion logic can be found in the [data conversion](#data-conversion) section. The model instance can be serialized using the [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) method: ```python assert user.model_dump() == {'id': 123, 'name': 'Jane Doe'} ``` Calling [dict](https://docs.python.org/3/reference/expressions.html#dict) on the instance will also provide a dictionary, but nested fields will not be recursively converted into dictionaries. [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) also provides numerous arguments to customize the serialization result. By default, models are mutable and field values can be changed through attribute assignment: ```python user.id = 321 assert user.id == 321 ``` Caution When defining your models, watch out for naming collisions between your field name and its type annotation. For example, the following will not behave as expected and would yield a validation error: ```python from typing import Optional from pydantic import BaseModel class Boo(BaseModel): int: Optional[int] = None m = Boo(int=123) # Will fail to validate. ``` Because of how Python evaluates [annotated assignment statements](https://docs.python.org/3/reference/simple_stmts.html#annassign), the statement is equivalent to `int: None = None`, thus leading to a validation error. ### Model methods and properties The example above only shows the tip of the iceberg of what models can do. Model classes possess the following methods and attributes: - [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate): Validates the given object against the Pydantic model. See [Validating data](#validating-data). - [`model_validate_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json): Validates the given JSON data against the Pydantic model. See [Validating data](#validating-data). - [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct): Creates models without running validation. See [Creating models without validation](#creating-models-without-validation). - [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump): Returns a dictionary of the model's fields and values. See [Serialization](/docs/validation/latest/concepts/serialization#python-mode). - [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json): Returns a JSON string representation of [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump). See [Serialization](/docs/validation/latest/concepts/serialization#json-mode). - [`model_copy()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_copy): Returns a copy (by default, shallow copy) of the model. See [Model copy](#model-copy). - [`model_json_schema()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_json_schema): Returns a jsonable dictionary representing the model's JSON Schema. See [JSON Schema](/docs/validation/latest/concepts/json_schema). - [`model_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields): A mapping between field names and their definitions ([`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instances). - [`model_computed_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_computed_fields): A mapping between computed field names and their definitions ([`ComputedFieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.ComputedFieldInfo) instances). - [`model_parametrized_name()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_parametrized_name): Computes the class name for parametrizations of generic classes. - [`model_post_init()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_post_init): Performs additional actions after the model is instantiated and all field validators are applied. - [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild): Rebuilds the model schema, which also supports building recursive generic models. See [Rebuilding model schema](#rebuilding-model-schema). Model instances possess the following attributes: - [`model_extra`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_extra): The extra fields set during validation. - [`model_fields_set`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields_set): The set of fields which were explicitly provided when the model was initialized. Note See the API documentation of [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) for the class definition including a full list of methods and attributes. Tip See [Changes to `pydantic.BaseModel`](/docs/validation/latest/get-started/migration#changes-to-pydanticbasemodel) in the [Migration Guide](/docs/validation/latest/get-started/migration) for details on changes from Pydantic V1. ## Data conversion Pydantic may cast input data to force it to conform to model field types, and in some cases this may result in a loss of information. For example: ```python from pydantic import BaseModel class Model(BaseModel): a: int b: float c: str print(Model(a=3.000, b='2.72', c=b'binary data').model_dump()) #> {'a': 3, 'b': 2.72, 'c': 'binary data'} ``` This is a deliberate decision of Pydantic, and is frequently the most useful approach. See [this issue](https://github.com/pydantic/pydantic/issues/578) for a longer discussion on the subject. Nevertheless, Pydantic provides a [strict mode](/docs/validation/latest/concepts/strict_mode), where no data conversion is performed. Values must be of the same type as the declared field type. This is also the case for collections. In most cases, you shouldn't make use of abstract container classes and just use a concrete type, such as [`list`](https://docs.python.org/3/glossary.html#term-list): ```python from pydantic import BaseModel class Model(BaseModel): items: list[int] # (1) print(Model(items=(1, 2, 3))) #> items=[1, 2, 3] ``` In this case, you might be tempted to use the abstract [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) type to allow both lists and tuples. But Pydantic takes care of converting the tuple input to a list, so in most cases this isn't necessary. Besides, using these abstract types can also lead to [poor validation performance](/docs/validation/latest/concepts/performance#sequence-vs-list-or-tuple-with-mapping-vs-dict), and in general using concrete container types will avoid unnecessary checks. ## Extra data By default, Pydantic models **won't error when you provide extra data**, and these values will simply be ignored: ```python from pydantic import BaseModel class Model(BaseModel): x: int m = Model(x=1, y='a') assert m.model_dump() == {'x': 1} ``` The [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) configuration value can be used to control this behavior: ```python from pydantic import BaseModel, ConfigDict class Model(BaseModel): x: int model_config = ConfigDict(extra='allow') m = Model(x=1, y='a') # (1) assert m.model_dump() == {'x': 1, 'y': 'a'} assert m.__pydantic_extra__ == {'y': 'a'} ``` If [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) was set to `'forbid'`, this would fail. The configuration can take three values: - `'ignore'`: Providing extra data is ignored (the default). - `'forbid'`: Providing extra data is not permitted. - `'allow'`: Providing extra data is allowed and stored in the `__pydantic_extra__` dictionary attribute. The `__pydantic_extra__` can explicitly be annotated to provide validation for extra fields. The validation methods (e.g. [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate)) have an optional `extra` argument that will override the `extra` configuration value of the model for that validation call. For more details, refer to the [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) API documentation. Pydantic dataclasses also support extra data (see the [dataclass configuration](/docs/validation/latest/concepts/dataclasses#dataclass-config) section). ## Nested models More complex hierarchical data structures can be defined using models themselves as types in annotations. ```python from typing import Optional from pydantic import BaseModel class Foo(BaseModel): count: int size: Optional[float] = None class Bar(BaseModel): apple: str = 'x' banana: str = 'y' class Spam(BaseModel): foo: Foo bars: list[Bar] m = Spam(foo={'count': 4}, bars=[{'apple': 'x1'}, {'apple': 'x2'}]) print(m) """ foo=Foo(count=4, size=None) bars=[Bar(apple='x1', banana='y'), Bar(apple='x2', banana='y')] """ print(m.model_dump()) """ { 'foo': {'count': 4, 'size': None}, 'bars': [{'apple': 'x1', 'banana': 'y'}, {'apple': 'x2', 'banana': 'y'}], } """ ``` Self-referencing models are supported. For more details, see the documentation related to [forward annotations](/docs/validation/latest/concepts/forward_annotations#self-referencing-or-recursive-models). ## Rebuilding model schema When you define a model class in your code, Pydantic will analyze the body of the class to collect a variety of information required to perform validation and serialization, gathered in a core schema. Notably, the model's type annotations are evaluated to understand the valid types for each field (more information can be found in the [Architecture](/docs/validation/latest/internals/architecture) documentation). However, it might be the case that annotations refer to symbols not defined when the model class is being created. To circumvent this issue, the [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) method can be used: ```python from pydantic import BaseModel, PydanticUserError class Foo(BaseModel): x: 'Bar' # (1) try: Foo.model_json_schema() except PydanticUserError as e: print(e) """ `Foo` is not fully defined; you should define `Bar`, then call `Foo.model_rebuild()`. For further information visit https://errors.pydantic.dev/2/u/class-not-fully-defined """ class Bar(BaseModel): pass Foo.model_rebuild() print(Foo.model_json_schema()) """ { '$defs': {'Bar': {'properties': {}, 'title': 'Bar', 'type': 'object'}}, 'properties': {'x': {'$ref': '#/$defs/Bar'}}, 'required': ['x'], 'title': 'Foo', 'type': 'object', } """ ``` `Bar` is not yet defined when the `Foo` class is being created. For this reason, a [forward annotation](/docs/validation/latest/concepts/forward_annotations) is being used. Pydantic tries to determine when this is necessary automatically and error if it wasn't done, but you may want to call [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) proactively when dealing with recursive models or generics. In V2, [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) replaced `update_forward_refs()` from V1. There are some slight differences with the new behavior. The biggest change is that when calling [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) on the outermost model, it builds a core schema used for validation of the whole model (nested models and all), so all types at all levels need to be ready before [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) is called. ## Validating data Pydantic can validate data in three different modes: _Python_, _JSON_ and _strings_. The _Python_ mode gets used when using: - The `__init__()` model constructor. Field values must be provided using keyword arguments. - [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate): data can be provided either as a dictionary, or as a model instance (by default, instances are assumed to be valid; see the [`revalidate_instances`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.revalidate_instances) setting). [Arbitrary objects](#arbitrary-class-instances) can also be provided if explicitly enabled. The _JSON_ and _strings_ modes can be used with dedicated methods: - [`model_validate_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_json): data is validated as a JSON string or `bytes` object. If your incoming data is a JSON payload, this is generally considered faster (instead of manually parsing the data as a dictionary). Learn more about JSON parsing in the [JSON](/docs/validation/latest/concepts/json) documentation. - [`model_validate_strings()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_strings): data is validated as a dictionary (can be nested) with string keys and values and validates the data in JSON mode so that said strings can be coerced into the correct types. Compared to using the model constructor, it is possible to control several validation parameters when using the `model_validate_*()` methods ([strictness](/docs/validation/latest/concepts/strict_mode), [extra data](#extra-data), [validation context](/docs/validation/latest/concepts/validators#validation-context), etc.). Note Depending on the types and model configuration involved, the _Python_ and _JSON_ modes may have different validation behavior (e.g. with [strictness](/docs/validation/latest/concepts/strict_mode)). If you have data coming from a non-JSON source, but want the same validation behavior and errors you'd get from the _JSON_ mode, our recommendation for now is to either dump your data to JSON (e.g. using [`json.dumps()`](https://docs.python.org/3/library/json.html#json.dumps)), or use [`model_validate_strings()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate_strings) if the data takes the form of a (potentially nested) dictionary with string keys and values. Progress for this feature can be tracked in [this issue](https://github.com/pydantic/pydantic/issues/11154). ```python from datetime import datetime from typing import Optional from pydantic import BaseModel, ValidationError class User(BaseModel): id: int name: str = 'John Doe' signup_ts: Optional[datetime] = None m = User.model_validate({'id': 123, 'name': 'James'}) print(m) #> id=123 name='James' signup_ts=None try: m = User.model_validate_json('{"id": 123, "name": 123}') except ValidationError as e: print(e) """ 1 validation error for User name Input should be a valid string [type=string_type, input_value=123, input_type=int] """ m = User.model_validate_strings({'id': '123', 'name': 'James'}) print(m) #> id=123 name='James' signup_ts=None m = User.model_validate_strings( {'id': '123', 'name': 'James', 'signup_ts': '2024-04-01T12:00:00'} ) print(m) #> id=123 name='James' signup_ts=datetime.datetime(2024, 4, 1, 12, 0) try: m = User.model_validate_strings( {'id': '123', 'name': 'James', 'signup_ts': '2024-04-01'}, strict=True ) except ValidationError as e: print(e) """ 1 validation error for User signup_ts Input should be a valid datetime, invalid datetime separator, expected `T`, `t`, `_` or space [type=datetime_parsing, input_value='2024-04-01', input_type=str] """ ``` ### Creating models without validation Pydantic also provides the [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) method, which allows models to be created **without validation**. This can be useful in at least a few cases: - when working with complex data that is already known to be valid (for performance reasons) - when one or more of the validator functions are non-idempotent - when one or more of the validator functions have side effects that you don't want to be triggered. Caution [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) does not do any validation, meaning it can create models which are invalid. **You should only ever use the [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) method with data which has already been validated, or that you definitely trust.** Note In Pydantic V2, the performance gap between validation (either with direct instantiation or the `model_validate*` methods) and [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) has been narrowed considerably. For simple models, going with validation may even be faster. If you are using [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) for performance reasons, you may want to profile your use case before assuming it is actually faster. Note that for [root models](#rootmodel-and-custom-root-types), the root value can be passed to [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) positionally, instead of using a keyword argument. Here are some additional notes on the behavior of [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct): - When we say "no validation is performed" -- this includes converting dictionaries to model instances. So if you have a field referring to a model type, you will need to convert the inner dictionary to a model yourself. - If you do not pass keyword arguments for fields with defaults, the default values will still be used. - For models with private attributes, the `__pydantic_private__` dictionary will be populated the same as it would be when creating the model with validation. - No `__init__` method from the model or any of its parent classes will be called, even when a custom `__init__` method is defined. On [extra data](#extra-data) behavior with [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) - For models with [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) set to `'allow'`, data not corresponding to fields will be correctly stored in the `__pydantic_extra__` dictionary and saved to the model's `__dict__` attribute. - For models with [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) set to `'ignore'`, data not corresponding to fields will be ignored -- that is, not stored in `__pydantic_extra__` or `__dict__` on the instance. - Unlike when instantiating the model with validation, a call to [`model_construct()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_construct) with [`extra`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.extra) set to `'forbid'` doesn't raise an error in the presence of data not corresponding to fields. Rather, said input data is simply ignored. ### Defining a custom `__init__()` Pydantic provides a default `__init__()` implementation for Pydantic models, that is called _only_ when using the model constructor (and not with the `model_validate_*()` methods). This implementation delegates validation to `pydantic-core`. However, it is possible to define a custom `__init__()` on your models. In this case, it will be called unconditionally from all the [validation methods](#validating-data), without performing validation (and so you should call `super().__init__(**kwargs)` in your implementation). Defining a custom `__init__()` is not recommended, as all the validation parameters ([strictness](/docs/validation/latest/concepts/strict_mode), [extra data behavior](#extra-data), [validation context](/docs/validation/latest/concepts/validators#validation-context)) will be lost. If you need to perform actions after the model was initialized, you can make use of _after_ [field](/docs/validation/latest/concepts/validators#field-after-validator) or [model](/docs/validation/latest/concepts/validators#model-after-validator) validators, or define a [`model_post_init()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_post_init) implementation: ```python import logging from typing import Any from pydantic import BaseModel class MyModel(BaseModel): id: int def model_post_init(self, context: Any) -> None: logging.info("Model initialized with id %d", self.id) ``` ## Error handling Pydantic will raise a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) exception whenever it finds an error in the data it's validating. A single exception will be raised regardless of the number of errors found, and that validation error will contain information about all of the errors and how they happened. See [Error Handling](/docs/validation/latest/errors/errors) for details on standard and custom errors. As a demonstration: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): list_of_ints: list[int] a_float: float data = { 'list_of_ints': ['1', 2, 'bad'], 'a_float': 'not a float', } try: Model(**data) except ValidationError as e: print(e) """ 2 validation errors for Model list_of_ints.2 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='bad', input_type=str] a_float Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='not a float', input_type=str] """ ``` ## Arbitrary class instances (Formerly known as "ORM Mode"/`from_orm()`). When using the [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate) method, Pydantic can also validate arbitrary objects, by getting attributes on the object corresponding the field names. One common application of this functionality is integration with object-relational mappings (ORMs). This feature need to be manually enabled, either by setting the [`from_attributes`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.from_attributes) configuration value, or by using the `from_attributes` parameter on [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate). The example here uses [SQLAlchemy](https://www.sqlalchemy.org/), but the same approach should work for any ORM. ```python from typing import Annotated from sqlalchemy import ARRAY, String from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from pydantic import BaseModel, ConfigDict, StringConstraints class Base(DeclarativeBase): pass class CompanyOrm(Base): __tablename__ = 'companies' id: Mapped[int] = mapped_column(primary_key=True, nullable=False) public_key: Mapped[str] = mapped_column( String(20), index=True, nullable=False, unique=True ) domains: Mapped[list[str]] = mapped_column(ARRAY(String(255))) class CompanyModel(BaseModel): model_config = ConfigDict(from_attributes=True) id: int public_key: Annotated[str, StringConstraints(max_length=20)] domains: list[Annotated[str, StringConstraints(max_length=255)]] co_orm = CompanyOrm( id=123, public_key='foobar', domains=['example.com', 'foobar.com'], ) print(co_orm) #> <__main__.CompanyOrm object at 0x0123456789ab> co_model = CompanyModel.model_validate(co_orm) print(co_model) #> id=123 public_key='foobar' domains=['example.com', 'foobar.com'] ``` ### Nested attributes When using attributes to validate models, model instances will be created from both top-level attributes and deeper-nested attributes as appropriate. Here is an example demonstrating the principle: ```python from pydantic import BaseModel, ConfigDict class PetCls: def __init__(self, *, name: str) -> None: self.name = name class PersonCls: def __init__(self, *, name: str, pets: list[PetCls]) -> None: self.name = name self.pets = pets class Pet(BaseModel): model_config = ConfigDict(from_attributes=True) name: str class Person(BaseModel): model_config = ConfigDict(from_attributes=True) name: str pets: list[Pet] bones = PetCls(name='Bones') orion = PetCls(name='Orion') anna = PersonCls(name='Anna', pets=[bones, orion]) anna_model = Person.model_validate(anna) print(anna_model) #> name='Anna' pets=[Pet(name='Bones'), Pet(name='Orion')] ``` ## Model copy API Documentation [`pydantic.main.BaseModel.model_copy`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_copy) The [`model_copy()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_copy) method allows models to be duplicated (with optional updates), which is particularly useful when working with frozen models. ```python from pydantic import BaseModel class BarModel(BaseModel): whatever: int class FooBarModel(BaseModel): banana: float foo: str bar: BarModel m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123}) print(m.model_copy(update={'banana': 0})) #> banana=0 foo='hello' bar=BarModel(whatever=123) # normal copy gives the same object reference for bar: print(id(m.bar) == id(m.model_copy().bar)) #> True # deep copy gives a new object reference for `bar`: print(id(m.bar) == id(m.model_copy(deep=True).bar)) #> False ``` ## Generic models Pydantic supports the creation of generic models to make it easier to reuse a common model structure. Both the new [type parameter syntax](https://docs.python.org/3/reference/compound_stmts.html#type-params) (introduced by [PEP 695](https://peps.python.org/pep-0695/) in Python 3.12) and the old syntax are supported (refer to [the Python documentation](https://docs.python.org/3/library/typing.html#building-generic-types-and-type-aliases) for more details). Here is an example using a generic Pydantic model to create an easily-reused HTTP response payload wrapper: - [Python 3.9 and above](#tab-panel-556) - [Python 3.12 and above (new syntax)](#tab-panel-557) ```python from typing import Generic, TypeVar from pydantic import BaseModel, ValidationError DataT = TypeVar('DataT') # (1) class DataModel(BaseModel): number: int class Response(BaseModel, Generic[DataT]): # (2) data: DataT # (3) print(Response[int](data=1)) #> data=1 print(Response[str](data='value')) #> data='value' print(Response[str](data='value').model_dump()) #> {'data': 'value'} data = DataModel(number=1) print(Response[DataModel](data=data).model_dump()) #> {'data': {'number': 1}} try: Response[int](data='value') except ValidationError as e: print(e) """ 1 validation error for Response[int] data Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='value', input_type=str] """ ``` Declare one or more [type variables](https://docs.python.org/3/library/typing.html#typing.TypeVar) to use to parameterize your model. Declare a Pydantic model that inherits from [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) and [`typing.Generic`](https://docs.python.org/3/library/typing.html#typing.Generic) (in this specific order), and add the list of type variables you declared previously as parameters to the [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic) parent. Use the type variables as annotations where you will want to replace them with other types. ```python from pydantic import BaseModel, ValidationError class DataModel(BaseModel): number: int class Response[DataT](BaseModel): # (1) data: DataT # (2) print(Response[int](data=1)) #> data=1 print(Response[str](data='value')) #> data='value' print(Response[str](data='value').model_dump()) #> {'data': 'value'} data = DataModel(number=1) print(Response[DataModel](data=data).model_dump()) #> {'data': {'number': 1}} try: Response[int](data='value') except ValidationError as e: print(e) """ 1 validation error for Response[int] data Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='value', input_type=str] """ ``` Declare a Pydantic model and add the list of type variables as type parameters. Use the type variables as annotations where you will want to replace them with other types. ✦ New in v2.11 Full support for the [type parameter syntax](https://docs.python.org/3/reference/compound_stmts.html#type-params) and [type variable defaults](https://typing.python.org/en/latest/spec/generics.html#type-parameter-defaults). Caution When parametrizing a model with a concrete type, Pydantic **does not** validate that the provided type is [assignable to the type variable](https://typing.readthedocs.io/en/latest/spec/generics.html#type-variables-with-an-upper-bound) if it has an upper bound. Any [configuration](/docs/validation/latest/concepts/config), [validation](/docs/validation/latest/concepts/validators) or [serialization](/docs/validation/latest/concepts/serialization) logic set on the generic model will also be applied to the parametrized classes, in the same way as when inheriting from a model class. Any custom methods or attributes will also be inherited. Generic models also integrate properly with type checkers, so you get all the type checking you would expect if you were to declare a distinct type for each parametrization. Note Internally, Pydantic creates subclasses of the generic model at runtime when the generic model class is parametrized. These classes are cached, so there should be minimal overhead introduced by the use of generics models. To inherit from a generic model and preserve the fact that it is generic, the subclass must also inherit from [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic): ```python from typing import Generic, TypeVar from pydantic import BaseModel TypeX = TypeVar('TypeX') class BaseClass(BaseModel, Generic[TypeX]): X: TypeX class ChildClass(BaseClass[TypeX], Generic[TypeX]): pass # Parametrize `TypeX` with `int`: print(ChildClass[int](X=1)) #> X=1 ``` You can also create a generic subclass of a model that partially or fully replaces the type variables in the superclass: ```python from typing import Generic, TypeVar from pydantic import BaseModel TypeX = TypeVar('TypeX') TypeY = TypeVar('TypeY') TypeZ = TypeVar('TypeZ') class BaseClass(BaseModel, Generic[TypeX, TypeY]): x: TypeX y: TypeY class ChildClass(BaseClass[int, TypeY], Generic[TypeY, TypeZ]): z: TypeZ # Parametrize `TypeY` with `str`: print(ChildClass[str, int](x='1', y='y', z='3')) #> x=1 y='y' z=3 ``` If the name of the concrete subclasses is important, you can also override the default name generation by overriding the [`model_parametrized_name()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_parametrized_name) method: ```python from typing import Any, Generic, TypeVar from pydantic import BaseModel DataT = TypeVar('DataT') class Response(BaseModel, Generic[DataT]): data: DataT @classmethod def model_parametrized_name(cls, params: tuple[type[Any], ...]) -> str: return f'{params[0].__name__.title()}Response' print(repr(Response[int](data=1))) #> IntResponse(data=1) print(repr(Response[str](data='a'))) #> StrResponse(data='a') ``` You can use parametrized generic models as types in other models: ```python from typing import Generic, TypeVar from pydantic import BaseModel T = TypeVar('T') class ResponseModel(BaseModel, Generic[T]): content: T class Product(BaseModel): name: str price: float class Order(BaseModel): id: int product: ResponseModel[Product] product = Product(name='Apple', price=0.5) response = ResponseModel[Product](content=product) order = Order(id=1, product=response) print(repr(order)) """ Order(id=1, product=ResponseModel[Product](content=Product(name='Apple', price=0.5))) """ ``` Using the same type variable in nested models allows you to enforce typing relationships at different points in your model: ```python from typing import Generic, TypeVar from pydantic import BaseModel, ValidationError T = TypeVar('T') class InnerT(BaseModel, Generic[T]): inner: T class OuterT(BaseModel, Generic[T]): outer: T nested: InnerT[T] nested = InnerT[int](inner=1) print(OuterT[int](outer=1, nested=nested)) #> outer=1 nested=InnerT[int](inner=1) try: print(OuterT[int](outer='a', nested=InnerT(inner='a'))) # (1) except ValidationError as e: print(e) """ 2 validation errors for OuterT[int] outer Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] nested.inner Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] """ ``` The `OuterT` model is parametrized with `int`, but the data associated with the `T` annotations during validation is of type `str`, leading to validation errors. Caution While it may not raise an error, we strongly advise against using parametrized generics in [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance) checks. For example, you should not do `isinstance(my_model, MyGenericModel[int])`. However, it is fine to do `isinstance(my_model, MyGenericModel)` (note that, for standard generics, it would raise an error to do a subclass check with a parameterized generic class). If you need to perform [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance) checks against parametrized generics, you can do this by subclassing the parametrized generic class: ```python class MyIntModel(MyGenericModel[int]): ... isinstance(my_model, MyIntModel) ``` Implementation Details When using nested generic models, Pydantic sometimes performs revalidation in an attempt to produce the most intuitive validation result. Specifically, if you have a field of type `GenericModel[SomeType]` and you validate data like `GenericModel[SomeCompatibleType]` against this field, we will inspect the data, recognize that the input data is sort of a "loose" subclass of `GenericModel`, and revalidate the contained `SomeCompatibleType` data. This adds some validation overhead, but makes things more intuitive for cases like that shown below. ```python from typing import Any, Generic, TypeVar from pydantic import BaseModel T = TypeVar('T') class GenericModel(BaseModel, Generic[T]): a: T class Model(BaseModel): inner: GenericModel[Any] print(repr(Model.model_validate(Model(inner=GenericModel[int](a=1))))) #> Model(inner=GenericModel[Any](a=1)) ``` Note, validation will still fail if you, for example are validating against `GenericModel[int]` and pass in an instance `GenericModel[str](a='not an int')`. It's also worth noting that this pattern will re-trigger any custom validation as well, like additional model validators and the like. Validators will be called once on the first pass, validating directly against `GenericModel[Any]`. That validation fails, as `GenericModel[int]` is not a subclass of `GenericModel[Any]`. This relates to the warning above about the complications of using parametrized generics in `isinstance()` and `issubclass()` checks. Then, the validators will be called again on the second pass, during more lax force-revalidation phase, which succeeds. To better understand this consequence, see below: ```python from typing import Any, Generic, Self, TypeVar from pydantic import BaseModel, model_validator T = TypeVar('T') class GenericModel(BaseModel, Generic[T]): a: T @model_validator(mode='after') def validate_after(self: Self) -> Self: print('after validator running custom validation...') return self class Model(BaseModel): inner: GenericModel[Any] m = Model.model_validate(Model(inner=GenericModel[int](a=1))) #> after validator running custom validation... #> after validator running custom validation... print(repr(m)) #> Model(inner=GenericModel[Any](a=1)) ``` ### Validation of unparametrized type variables When leaving type variables unparametrized, Pydantic treats generic models similarly to how it treats built-in generic types like [`list`](https://docs.python.org/3/glossary.html#term-list) and [`dict`](https://docs.python.org/3/reference/expressions.html#dict): - If the type variable is [bound](https://typing.readthedocs.io/en/latest/reference/generics.html#type-variables-with-upper-bounds) or [constrained](https://typing.readthedocs.io/en/latest/reference/generics.html#type-variables-with-constraints) to a specific type, it will be used. - If the type variable has a default type (as specified by [PEP 696](https://peps.python.org/pep-0696/)), it will be used. - For unbound or unconstrained type variables, Pydantic will fallback to [`Any`](https://docs.python.org/3/library/typing.html#typing.Any). ```python from typing import Generic from typing_extensions import TypeVar from pydantic import BaseModel, ValidationError T = TypeVar('T') U = TypeVar('U', bound=int) V = TypeVar('V', default=str) class Model(BaseModel, Generic[T, U, V]): t: T u: U v: V print(Model(t='t', u=1, v='v')) #> t='t' u=1 v='v' try: Model(t='t', u='u', v=1) except ValidationError as exc: print(exc) """ 2 validation errors for Model u Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='u', input_type=str] v Input should be a valid string [type=string_type, input_value=1, input_type=int] """ ``` Caution In some cases, validation against an unparametrized generic model can lead to data loss. Specifically, if a subtype of the type variable upper bound, constraints, or default is being used and the model isn't explicitly parametrized, the resulting type **will not be** the one being provided: ```python from typing import Generic, TypeVar from pydantic import BaseModel ItemT = TypeVar('ItemT', bound='ItemBase') class ItemBase(BaseModel): ... class IntItem(ItemBase): value: int class ItemHolder(BaseModel, Generic[ItemT]): item: ItemT loaded_data = {'item': {'value': 1}} print(ItemHolder(**loaded_data)) # (1) #> item=ItemBase() print(ItemHolder[IntItem](**loaded_data)) # (2) #> item=IntItem(value=1) ``` When the generic isn't parametrized, the input data is validated against the `ItemT` upper bound. Given that `ItemBase` has no fields, the `item` field information is lost. In this case, the type variable is explicitly parametrized, so the input data is validated against the `IntItem` class. ### Serialization of unparametrized type variables The behavior of serialization differs when using type variables with [upper bounds](https://typing.readthedocs.io/en/latest/reference/generics.html#type-variables-with-upper-bounds), [constraints](https://typing.readthedocs.io/en/latest/reference/generics.html#type-variables-with-constraints), or a default value: If a Pydantic model is used in a type variable upper bound and the type variable is never parametrized, then Pydantic will use the upper bound for validation but treat the value as [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) in terms of serialization: ```python from typing import Generic, TypeVar from pydantic import BaseModel class ErrorDetails(BaseModel): foo: str ErrorDataT = TypeVar('ErrorDataT', bound=ErrorDetails) class Error(BaseModel, Generic[ErrorDataT]): message: str details: ErrorDataT class MyErrorDetails(ErrorDetails): bar: str # serialized as Any error = Error( message='We just had an error', details=MyErrorDetails(foo='var', bar='var2'), ) assert error.model_dump() == { 'message': 'We just had an error', 'details': { 'foo': 'var', 'bar': 'var2', }, } # serialized using the concrete parametrization # note that `'bar': 'var2'` is missing error = Error[ErrorDetails]( message='We just had an error', details=ErrorDetails(foo='var'), ) assert error.model_dump() == { 'message': 'We just had an error', 'details': { 'foo': 'var', }, } ``` Here's another example of the above behavior, enumerating all permutations regarding bound specification and generic type parametrization: ```python from typing import Generic, TypeVar from pydantic import BaseModel TBound = TypeVar('TBound', bound=BaseModel) TNoBound = TypeVar('TNoBound') class IntValue(BaseModel): value: int class ItemBound(BaseModel, Generic[TBound]): item: TBound class ItemNoBound(BaseModel, Generic[TNoBound]): item: TNoBound item_bound_inferred = ItemBound(item=IntValue(value=3)) item_bound_explicit = ItemBound[IntValue](item=IntValue(value=3)) item_no_bound_inferred = ItemNoBound(item=IntValue(value=3)) item_no_bound_explicit = ItemNoBound[IntValue](item=IntValue(value=3)) # calling `print(x.model_dump())` on any of the above instances results in the following: #> {'item': {'value': 3}} ``` However, if [constraints](https://typing.readthedocs.io/en/latest/reference/generics.html#type-variables-with-constraints) or a default value (as per [PEP 696](https://peps.python.org/pep-0696/)) is being used, then the default type or constraints will be used for both validation and serialization if the type variable is not parametrized. You can override this behavior using [`SerializeAsAny`](/docs/validation/latest/concepts/serialization#serializeasany-annotation): ```python from typing import Generic from typing_extensions import TypeVar from pydantic import BaseModel, SerializeAsAny class ErrorDetails(BaseModel): foo: str ErrorDataT = TypeVar('ErrorDataT', default=ErrorDetails) class Error(BaseModel, Generic[ErrorDataT]): message: str details: ErrorDataT class MyErrorDetails(ErrorDetails): bar: str # serialized using the default's serializer error = Error( message='We just had an error', details=MyErrorDetails(foo='var', bar='var2'), ) assert error.model_dump() == { 'message': 'We just had an error', 'details': { 'foo': 'var', }, } # If `ErrorDataT` was using an upper bound, `bar` would be present in `details`. class SerializeAsAnyError(BaseModel, Generic[ErrorDataT]): message: str details: SerializeAsAny[ErrorDataT] # serialized as Any error = SerializeAsAnyError( message='We just had an error', details=MyErrorDetails(foo='var', bar='baz'), ) assert error.model_dump() == { 'message': 'We just had an error', 'details': { 'foo': 'var', 'bar': 'baz', }, } ``` ## Dynamic model creation API Documentation [`pydantic.main.create_model`](/docs/validation/latest/api/pydantic/base_model/#pydantic.create_model) There are some occasions where it is desirable to create a model using runtime information to specify the fields. Pydantic provides the [`create_model()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.create_model) function to allow models to be created dynamically: ```python from pydantic import BaseModel, create_model DynamicFoobarModel = create_model('DynamicFoobarModel', foo=str, bar=(int, 123)) # Equivalent to: class StaticFoobarModel(BaseModel): foo: str bar: int = 123 ``` Field definitions are specified as keyword arguments, and should either be: - A single element, representing the type annotation of the field. - A two-tuple, the first element being the type and the second element the assigned value (either a default or the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function). ↻ Changed in v2.11 When providing a single element for field definitions, any type can be used (previously, only an [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) form could be provided). Here is a more advanced example: ```python from typing import Annotated from pydantic import BaseModel, Field, PrivateAttr, create_model DynamicModel = create_model( 'DynamicModel', foo=(str, Field(alias='FOO')), bar=Annotated[str, Field(description='Bar field')], _private=(int, PrivateAttr(default=1)), ) class StaticModel(BaseModel): foo: str = Field(alias='FOO') bar: Annotated[str, Field(description='Bar field')] _private: int = PrivateAttr(default=1) ``` The special keyword arguments `__config__` and `__base__` can be used to customize the new model. This includes extending a base model with extra fields. ```python from pydantic import BaseModel, create_model class FooModel(BaseModel): foo: str bar: int = 123 BarModel = create_model( 'BarModel', apple=(str, 'russet'), banana=(str, 'yellow'), __base__=FooModel, ) print(BarModel) #> print(BarModel.model_fields.keys()) #> dict_keys(['foo', 'bar', 'apple', 'banana']) ``` You can also add validators by passing a dictionary to the `__validators__` argument. ```python from pydantic import ValidationError, create_model, field_validator def alphanum(cls, v): assert v.isalnum(), 'must be alphanumeric' return v validators = { 'username_validator': field_validator('username')(alphanum) # (1) } UserModel = create_model( 'UserModel', username=(str, ...), __validators__=validators ) user = UserModel(username='scolvin') print(user) #> username='scolvin' try: UserModel(username='scolvi%n') except ValidationError as e: print(e) """ 1 validation error for UserModel username Assertion failed, must be alphanumeric [type=assertion_error, input_value='scolvi%n', input_type=str] """ ``` Make sure that the validators names do not clash with any of the field names as internally, Pydantic gathers all members into a namespace and mimics the normal creation of a class using the [`types` module utilities](https://docs.python.org/3/library/types.html#dynamic-type-creation). Note To pickle a dynamically created model: - the model must be defined globally - the `__module__` argument must be provided Caution This function may execute arbitrary code contained in field annotations, if string references need to be evaluated. See [Security implications of introspecting annotations](https://docs.python.org/3/library/annotationlib.html#annotationlib-security) for more information. See also: the [dynamic model example](/docs/validation/latest/examples/dynamic_models), providing guidelines to derive an optional model from another one. ## `RootModel` and custom root types API Documentation [`pydantic.root_model.RootModel`](/docs/validation/latest/api/pydantic/root_model/#pydantic.root_model.RootModel) Pydantic models can be defined with a "custom root type" by subclassing [`pydantic.RootModel`](/docs/validation/latest/api/pydantic/root_model/#pydantic.root_model.RootModel). The root type can be any type supported by Pydantic, and is specified by the generic parameter to `RootModel`. The root value can be passed to the model `__init__` or [`model_validate`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate) via the first and only argument. Here's an example of how this works: ```python from pydantic import RootModel Pets = RootModel[list[str]] PetsByName = RootModel[dict[str, str]] print(Pets(['dog', 'cat'])) #> root=['dog', 'cat'] print(Pets(['dog', 'cat']).model_dump_json()) #> ["dog","cat"] print(Pets.model_validate(['dog', 'cat'])) #> root=['dog', 'cat'] print(Pets.model_json_schema()) """ {'items': {'type': 'string'}, 'title': 'RootModel[list[str]]', 'type': 'array'} """ print(PetsByName({'Otis': 'dog', 'Milo': 'cat'})) #> root={'Otis': 'dog', 'Milo': 'cat'} print(PetsByName({'Otis': 'dog', 'Milo': 'cat'}).model_dump_json()) #> {"Otis":"dog","Milo":"cat"} print(PetsByName.model_validate({'Otis': 'dog', 'Milo': 'cat'})) #> root={'Otis': 'dog', 'Milo': 'cat'} ``` If you want to access items in the `root` field directly or to iterate over the items, you can implement custom `__iter__` and `__getitem__` functions, as shown in the following example. ```python from pydantic import RootModel class Pets(RootModel): root: list[str] def __iter__(self): return iter(self.root) def __getitem__(self, item): return self.root[item] pets = Pets.model_validate(['dog', 'cat']) print(pets[0]) #> dog print([pet for pet in pets]) #> ['dog', 'cat'] ``` You can also create subclasses of the parametrized root model directly: ```python from pydantic import RootModel class Pets(RootModel[list[str]]): def describe(self) -> str: return f'Pets: {", ".join(self.root)}' my_pets = Pets.model_validate(['dog', 'cat']) print(my_pets.describe()) #> Pets: dog, cat ``` ## Faux immutability Models can be configured to be immutable via `model_config['frozen'] = True`. When this is set, attempting to change the values of instance attributes will raise errors. See the [API reference](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.frozen) for more details. Note This behavior was achieved in Pydantic V1 via the config setting `allow_mutation = False`. This config flag is deprecated in Pydantic V2, and has been replaced with `frozen`. Caution In Python, immutability is not enforced. Developers have the ability to modify objects that are conventionally considered "immutable" if they choose to do so. ```python from pydantic import BaseModel, ConfigDict, ValidationError class FooBarModel(BaseModel): model_config = ConfigDict(frozen=True) a: str b: dict foobar = FooBarModel(a='hello', b={'apple': 'pear'}) try: foobar.a = 'different' except ValidationError as e: print(e) """ 1 validation error for FooBarModel a Instance is frozen [type=frozen_instance, input_value='different', input_type=str] """ print(foobar.a) #> hello print(foobar.b) #> {'apple': 'pear'} foobar.b['apple'] = 'grape' print(foobar.b) #> {'apple': 'grape'} ``` Trying to change `a` caused an error, and `a` remains unchanged. However, the dict `b` is mutable, and the immutability of `foobar` doesn't stop `b` from being changed. ## Abstract base classes Pydantic models can be used alongside Python's [Abstract Base Classes](https://docs.python.org/3/library/abc.html) (ABCs). ```python import abc from pydantic import BaseModel class FooBarModel(BaseModel, abc.ABC): a: str b: int @abc.abstractmethod def my_abstract_method(self): pass ``` ## Field ordering Field order affects models in the following ways: - field order is preserved in the model [JSON Schema](/docs/validation/latest/concepts/json_schema) - field order is preserved in [validation errors](#error-handling) - field order is preserved when [serializing data](/docs/validation/latest/concepts/serialization#serializing-data) ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): a: int b: int = 2 c: int = 1 d: int = 0 e: float print(Model.model_fields.keys()) #> dict_keys(['a', 'b', 'c', 'd', 'e']) m = Model(e=2, a=1) print(m.model_dump()) #> {'a': 1, 'b': 2, 'c': 1, 'd': 0, 'e': 2.0} try: Model(a='x', b='x', c='x', d='x', e='x') except ValidationError as err: error_locations = [e['loc'] for e in err.errors()] print(error_locations) #> [('a',), ('b',), ('c',), ('d',), ('e',)] ``` ## Automatically excluded attributes ### Class variables Attributes annotated with [`ClassVar`](https://docs.python.org/3/library/typing.html#typing.ClassVar) are properly treated by Pydantic as class variables, and will not become fields on model instances: ```python from typing import ClassVar from pydantic import BaseModel class Model(BaseModel): x: ClassVar[int] = 1 y: int = 2 m = Model() print(m) #> y=2 print(Model.x) #> 1 ``` ### Private model attributes API Documentation [`pydantic.fields.PrivateAttr`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.PrivateAttr) Attributes whose name has a leading underscore are not treated as fields by Pydantic, and are not included in the model schema. Instead, these are converted into a "private attribute" which is not validated or even set during calls to `__init__`, `model_validate`, etc. Here is an example of usage: ```python from datetime import datetime from random import randint from typing import Any from pydantic import BaseModel, PrivateAttr class TimeAwareModel(BaseModel): _processed_at: datetime = PrivateAttr(default_factory=datetime.now) _secret_value: str def model_post_init(self, context: Any) -> None: # this could also be done with `default_factory`: self._secret_value = randint(1, 5) m = TimeAwareModel() print(m._processed_at) #> 2032-01-02 03:04:05.000006 print(m._secret_value) #> 3 ``` Private attribute names must start with underscore to prevent conflicts with model fields. However, dunder names (such as `__attr__`) are not supported, and will be completely ignored from the model definition. ✦ New in v2.13 Default factories can take the validated model data as an argument. ## Model signature All Pydantic models will have their signature generated based on their fields: ```python import inspect from pydantic import BaseModel, Field class FooModel(BaseModel): id: int name: str = None description: str = 'Foo' apple: int = Field(alias='pear') print(inspect.signature(FooModel)) #> (*, id: int, name: str = None, description: str = 'Foo', pear: int) -> None ``` An accurate signature is useful for introspection purposes and libraries like `FastAPI` or `hypothesis`. The generated signature will also respect custom `__init__` functions: ```python import inspect from pydantic import BaseModel class MyModel(BaseModel): id: int info: str = 'Foo' def __init__(self, id: int = 1, *, bar: str, **data) -> None: """My custom init!""" super().__init__(id=id, bar=bar, **data) print(inspect.signature(MyModel)) #> (id: int = 1, *, bar: str, info: str = 'Foo') -> None ``` To be included in the signature, a field's alias or name must be a valid Python identifier. Pydantic will prioritize a field's alias over its name when generating the signature, but may use the field name if the alias is not a valid Python identifier. If a field's alias and name are _both_ not valid identifiers (which may be possible through exotic use of `create_model`), a `**data` argument will be added. In addition, the `**data` argument will always be present in the signature if `model_config['extra'] == 'allow'`. ## Structural pattern matching Pydantic supports structural pattern matching for models, as introduced by [PEP 636](https://peps.python.org/pep-0636/) in Python 3.10. ```python from pydantic import BaseModel class Pet(BaseModel): name: str species: str a = Pet(name='Bones', species='dog') match a: # match `species` to 'dog', declare and initialize `dog_name` case Pet(species='dog', name=dog_name): print(f'{dog_name} is a dog') #> Bones is a dog # default case case _: print('No dog matched') ``` Note A match-case statement may seem as if it creates a new model, but don't be fooled; it is just syntactic sugar for getting an attribute and either comparing it or declaring and initializing it. ## Attribute copies In many cases, arguments passed to the constructor will be copied in order to perform validation and, where necessary, coercion. In this example, note that the ID of the list changes after the class is constructed because it has been copied during validation: ```python from pydantic import BaseModel class C1: arr = [] def __init__(self, in_arr): self.arr = in_arr class C2(BaseModel): arr: list[int] arr_orig = [1, 9, 10, 3] c1 = C1(arr_orig) c2 = C2(arr=arr_orig) print(f'{id(c1.arr) == id(c2.arr)=}') #> id(c1.arr) == id(c2.arr)=False ``` Note There are some situations where Pydantic does not copy attributes, such as when passing models -- we use the model as is. You can override this behaviour by setting [`model_config['revalidate_instances'] = 'always'`](/docs/validation/latest/api/pydantic/config#pydantic.config.ConfigDict). --- # [Performance](https://pydantic.dev/docs/validation/latest/concepts/performance/) # Performance In most cases Pydantic won't be your bottleneck, only follow this if you're sure it's necessary. ## In general, use `model_validate_json()` not `model_validate(json.loads(...))` On `model_validate(json.loads(...))`, the JSON is parsed in Python, then converted to a dict, then it's validated internally. On the other hand, `model_validate_json()` already performs the validation internally. There are a few cases where `model_validate(json.loads(...))` may be faster. Specifically, when using a `'before'` or `'wrap'` validator on a model, validation may be faster with the two step method. You can read more about these special cases in [this discussion](https://github.com/pydantic/pydantic/discussions/6388#discussioncomment-8193105). Many performance improvements are currently in the works for `pydantic-core`, see [this discussion](https://github.com/pydantic/pydantic/discussions/6388#discussioncomment-8194048). Once these changes are merged, we should be at the point where `model_validate_json()` is always faster than `model_validate(json.loads(...))`. ## `TypeAdapter` instantiated once The idea here is to avoid constructing validators and serializers more than necessary. Each time a `TypeAdapter` is instantiated, it will construct a new validator and serializer. If you're using a `TypeAdapter` in a function, it will be instantiated each time the function is called. Instead, instantiate it once, and reuse it. - [:x: Bad](#tab-panel-597) - [:white\_check\_mark: Good](#tab-panel-598) ```python from pydantic import TypeAdapter def my_func(): adapter = TypeAdapter(list[int]) # do something with adapter ``` ```python from pydantic import TypeAdapter adapter = TypeAdapter(list[int]) def my_func(): ... # do something with adapter ``` ## `Sequence` vs `list` or `tuple` with `Mapping` vs `dict` When using `Sequence`, Pydantic calls `isinstance(value, Sequence)` to check if the value is a sequence. Also, Pydantic will try to validate against different types of sequences, like `list` and `tuple`. If you know the value is a `list` or `tuple`, use `list` or `tuple` instead of `Sequence`. The same applies to `Mapping` and `dict`. If you know the value is a `dict`, use `dict` instead of `Mapping`. ## Don't do validation when you don't have to, use `Any` to keep the value unchanged If you don't need to validate a value, use `Any` to keep the value unchanged. ```python from typing import Any from pydantic import BaseModel class Model(BaseModel): a: Any model = Model(a=1) ``` ## Avoid extra information via subclasses of primitives - [Don't do this](#tab-panel-599) - [Do this](#tab-panel-600) ```python class CompletedStr(str): def __init__(self, s: str): self.s = s self.done = False ``` ```python from pydantic import BaseModel class CompletedModel(BaseModel): s: str done: bool = False ``` ## Use tagged union, not union Tagged union (or discriminated union) is a union with a field that indicates which type it is. ```python from typing import Any, Literal from pydantic import BaseModel, Field class DivModel(BaseModel): el_type: Literal['div'] = 'div' class_name: str | None = None children: list[Any] | None = None class SpanModel(BaseModel): el_type: Literal['span'] = 'span' class_name: str | None = None contents: str | None = None class ButtonModel(BaseModel): el_type: Literal['button'] = 'button' class_name: str | None = None contents: str | None = None class InputModel(BaseModel): el_type: Literal['input'] = 'input' class_name: str | None = None value: str | None = None class Html(BaseModel): contents: DivModel | SpanModel | ButtonModel | InputModel = Field( discriminator='el_type' ) ``` See [Discriminated Unions](/docs/validation/latest/concepts/unions#discriminated-unions) for more details. ## Use `TypedDict` over nested models Instead of using nested models, use `TypedDict` to define the structure of the data. Performance comparison With a simple benchmark, `TypedDict` is about ~2.5x faster than nested models: ```python from timeit import timeit from typing_extensions import TypedDict from pydantic import BaseModel, TypeAdapter class A(TypedDict): a: str b: int class TypedModel(TypedDict): a: A class B(BaseModel): a: str b: int class Model(BaseModel): b: B ta = TypeAdapter(TypedModel) result1 = timeit( lambda: ta.validate_python({'a': {'a': 'a', 'b': 2}}), number=10000 ) result2 = timeit( lambda: Model.model_validate({'b': {'a': 'a', 'b': 2}}), number=10000 ) print(result2 / result1) ``` ## Avoid wrap validators if you really care about performance Wrap validators are generally slower than other validators. This is because they require that data is materialized in Python during validation. Wrap validators can be incredibly useful for complex validation logic, but if you're looking for the best performance, you should avoid them. ## Failing early with `FailFast` Starting in v2.8+, you can apply the `FailFast` annotation to sequence types to fail early if any item in the sequence fails validation. If you use this annotation, you won't get validation errors for the rest of the items in the sequence if one fails, so you're effectively trading off visibility for performance. ```python from typing import Annotated from pydantic import FailFast, TypeAdapter, ValidationError ta = TypeAdapter(Annotated[list[bool], FailFast()]) try: ta.validate_python([True, 'invalid', False, 'also invalid']) except ValidationError as exc: print(exc) """ 1 validation error for list[bool] 1 Input should be a valid boolean, unable to interpret input [type=bool_parsing, input_value='invalid', input_type=str] """ ``` Read more about `FailFast` [here](/docs/validation/latest/api/pydantic/types/#pydantic.types.FailFast). --- # [Settings Management](https://pydantic.dev/docs/validation/latest/concepts/pydantic_settings/) > Support for loading a settings or config class from environment variables or secrets files. # Settings Management [Pydantic Settings](https://github.com/pydantic/pydantic-settings) provides optional Pydantic features for loading a settings or config class from environment variables or secrets files. ## Installation Installation is as simple as: Terminal ```bash pip install pydantic-settings ``` ## Usage If you create a model that inherits from `BaseSettings`, the model initialiser will attempt to determine the values of any fields not passed as keyword arguments by reading from the environment. (Default values will still be used if the matching environment variable is not set.) This makes it easy to: - Create a clearly-defined, type-hinted application configuration class - Automatically read modifications to the configuration from environment variables - Manually override specific settings in the initialiser where desired (e.g. in unit tests) For example: ```py from collections.abc import Callable from typing import Any from pydantic import ( AliasChoices, AmqpDsn, BaseModel, Field, ImportString, PostgresDsn, RedisDsn, ) from pydantic_settings import BaseSettings, SettingsConfigDict class SubModel(BaseModel): foo: str = 'bar' apple: int = 1 class Settings(BaseSettings): auth_key: str = Field(validation_alias='my_auth_key') # (1) api_key: str = Field(alias='my_api_key') # (2) redis_dsn: RedisDsn = Field( 'redis://user:pass@localhost:6379/1', validation_alias=AliasChoices('service_redis_dsn', 'redis_url'), # (3) ) pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar' amqp_dsn: AmqpDsn = 'amqp://user:pass@localhost:5672/' special_function: ImportString[Callable[[Any], Any]] = 'math.cos' # (4) # to override domains: # export my_prefix_domains='["foo.com", "bar.com"]' domains: set[str] = set() # to override more_settings: # export my_prefix_more_settings='{"foo": "x", "apple": 1}' more_settings: SubModel = SubModel() model_config = SettingsConfigDict(env_prefix='my_prefix_') # (5) print(Settings().model_dump()) """ { 'auth_key': 'xxx', 'api_key': 'xxx', 'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1'), 'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar'), 'amqp_dsn': AmqpDsn('amqp://user:pass@localhost:5672/'), 'special_function': math.cos, 'domains': set(), 'more_settings': {'foo': 'bar', 'apple': 1}, } """ ``` The environment variable name is overridden using `validation_alias`. In this case, the environment variable `my_auth_key` will be read instead of `auth_key`. Check the [`Field` documentation](/docs/validation/latest/concepts/fields) for more information. 2. The environment variable name is overridden using `alias`. In this case, the environment variable `my_api_key` will be used for both validation and serialization instead of `api_key`. Check the [`Field` documentation](/docs/validation/latest/concepts/fields#field-aliases) for more information. 3. The [`AliasChoices`](/docs/validation/latest/api/pydantic/aliases/#pydantic.aliases.AliasChoices) class allows to have multiple environment variable names for a single field. The first environment variable that is found will be used. Check the [documentation on alias choices](/docs/validation/latest/concepts/alias#aliaspath-and-aliaschoices) for more information. 4. The [`ImportString`](/docs/validation/latest/api/pydantic/types/#pydantic.types.ImportString) class allows to import an object from a string. In this case, the environment variable `special_function` will be read and the function [`math.cos`](https://docs.python.org/3/library/math.html#math.cos) will be imported. 5. The `env_prefix` config setting allows to set a prefix for all environment variables. Check the [Environment variable names documentation](#environment-variable-names) for more information. ## Validation of default values Unlike pydantic `BaseModel`, default values of `BaseSettings` fields are validated by default. You can disable this behaviour by setting `validate_default=False` either in `model_config` or on field level by `Field(validate_default=False)`: ```py from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(validate_default=False) # default won't be validated foo: int = 'test' print(Settings()) #> foo='test' class Settings1(BaseSettings): # default won't be validated foo: int = Field('test', validate_default=False) print(Settings1()) #> foo='test' ``` Check the [validation of default values](/docs/validation/latest/concepts/fields#validate-default-values) for more information. ## Environment variable names By default, the environment variable name is the same as the field name. You can change the prefix for all environment variables by setting the `env_prefix` config setting, or via the `_env_prefix` keyword argument on instantiation: ```py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_prefix='my_prefix_') auth_key: str = 'xxx' # will be read from `my_prefix_auth_key` ``` Note The default `env_prefix` is `''` (empty string). `env_prefix` is not only for env settings but also for dotenv files, secrets, and other sources. If you want to change the environment variable name for a single field, you can use an alias. There are two ways to do this: - Using `Field(alias=...)` (see `api_key` above) - Using `Field(validation_alias=...)` (see `auth_key` above) Check the [`Field` aliases documentation](/docs/validation/latest/concepts/fields#field-aliases) for more information about aliases. To apply `env_prefix` not only to variable names but also to aliases, set `env_prefix_target='all'`. To apply `env_prefix` only to aliases and not to variable names, set `env_prefix_target='alias'`. To apply `env_prefix` only to variable names (the default behavior), set `env_prefix_target='variable'`. ```py import os from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class FooBarSettings(BaseSettings): # default model_config = SettingsConfigDict(env_prefix='TARGET_') foo: str = Field(alias='FooAlias') bar: str os.environ['FooAlias'] = 'TARGET_FOO_VALUE' # (1) os.environ['TARGET_BAR'] = 'TARGET_BAR_VALUE' print(FooBarSettings().model_dump()) #> {'foo': 'TARGET_FOO_VALUE', 'bar': 'TARGET_BAR_VALUE'} class TargetAllSettings(FooBarSettings): model_config = SettingsConfigDict( env_prefix='TARGET_ALL_', env_prefix_target='all', ) os.environ['TARGET_ALL_FooAlias'] = 'TARGET_ALL_FOO_VALUE' os.environ['TARGET_ALL_BAR'] = 'TARGET_ALL_BAR_VALUE' print(TargetAllSettings().model_dump()) #> {'foo': 'TARGET_ALL_FOO_VALUE', 'bar': 'TARGET_ALL_BAR_VALUE'} class TargetAliasSettings(FooBarSettings): model_config = SettingsConfigDict( env_prefix='TARGET_ALIAS_', env_prefix_target='alias', ) os.environ['TARGET_ALIAS_FooAlias'] = 'TARGET_ALIAS_FOO_VALUE' os.environ['BAR'] = 'TARGET_ALL_BAR_VALUE' print(TargetAliasSettings().model_dump()) #> {'foo': 'TARGET_ALIAS_FOO_VALUE', 'bar': 'TARGET_ALL_BAR_VALUE'} class TargetVarSettings(FooBarSettings): model_config = SettingsConfigDict( env_prefix='TARGET_VAR_', env_prefix_target='variable', ) os.environ['FooAlias'] = 'TARGET_VAR_FOO_VALUE' # (1) os.environ['TARGET_VAR_BAR'] = 'TARGET_VAR_BAR_VALUE' print(TargetVarSettings().model_dump()) #> {'foo': 'TARGET_VAR_FOO_VALUE', 'bar': 'TARGET_VAR_BAR_VALUE'} ``` `env_prefix` will be ignored and the value will be read from `FooAlias` environment variable. ### Case-sensitivity By default, environment variable names are case-insensitive. If you want to make environment variable names case-sensitive, you can set the `case_sensitive` config setting: ```py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(case_sensitive=True) redis_host: str = 'localhost' ``` When `case_sensitive` is `True`, the environment variable names must match field names (optionally with a prefix), so in this example `redis_host` could only be modified via `export redis_host`. If you want to name environment variables all upper-case, you should name attribute all upper-case too. You can still name environment variables anything you like through `Field(validation_alias=...)`. Case-sensitivity can also be set via the `_case_sensitive` keyword argument on instantiation. In case of nested models, the `case_sensitive` setting will be applied to all nested models. ```py import os from pydantic import BaseModel, ValidationError from pydantic_settings import BaseSettings class RedisSettings(BaseModel): host: str port: int class Settings(BaseSettings, case_sensitive=True): redis: RedisSettings os.environ['redis'] = '{"host": "localhost", "port": 6379}' print(Settings().model_dump()) #> {'redis': {'host': 'localhost', 'port': 6379}} os.environ['redis'] = '{"HOST": "localhost", "port": 6379}' # (1) try: Settings() except ValidationError as e: print(e) """ 1 validation error for Settings redis.host Field required [type=missing, input_value={'HOST': 'localhost', 'port': 6379}, input_type=dict] For further information visit https://errors.pydantic.dev/2/v/missing """ ``` Note that the `host` field is not found because the environment variable name is `HOST` (all upper-case). Note On Windows, Python's `os` module always treats environment variables as case-insensitive, so the `case_sensitive` config setting will have no effect - settings will always be updated ignoring case. ## Parsing environment variable values By default environment variables are parsed verbatim, including if the value is empty. You can choose to ignore empty environment variables by setting the `env_ignore_empty` config setting to `True`. This can be useful if you would prefer to use the default value for a field rather than an empty value from the environment. For most simple field types (such as `int`, `float`, `str`, etc.), the environment variable value is parsed the same way it would be if passed directly to the initialiser (as a string). Complex types like `list`, `set`, `dict`, and sub-models are populated from the environment by treating the environment variable's value as a JSON-encoded string. Another way to populate nested complex variables is to configure your model with the `env_nested_delimiter` config setting, then use an environment variable with a name pointing to the nested module fields. What it does is simply explodes your variable into nested models or dicts. So if you define a variable `FOO__BAR__BAZ=123` it will convert it into `FOO={'BAR': {'BAZ': 123}}` If you have multiple variables with the same structure they will be merged. Note Sub model has to inherit from `pydantic.BaseModel`, Otherwise `pydantic-settings` will initialize sub model, collects values for sub model fields separately, and you may get unexpected results. Note The `env_nested_delimiter` option applies only to variables that point to declared fields. If a variable points to an unknown field no conversion will take place. As an example, given the following environment variables: Terminal ```bash # your environment export V0=0 export SUB_MODEL='{"v1": "json-1", "v2": "json-2"}' export SUB_MODEL__V2=nested-2 export SUB_MODEL__V3=3 export SUB_MODEL__DEEP__V4=v4 ``` You could load them into the following settings model: ```py from pydantic import BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict class DeepSubModel(BaseModel): # (1) v4: str class SubModel(BaseModel): # (2) v1: str v2: bytes v3: int deep: DeepSubModel class Settings(BaseSettings): model_config = SettingsConfigDict(env_nested_delimiter='__') v0: str sub_model: SubModel print(Settings().model_dump()) """ { 'v0': '0', 'sub_model': {'v1': 'json-1', 'v2': b'nested-2', 'v3': 3, 'deep': {'v4': 'v4'}}, } """ ``` Sub model has to inherit from `pydantic.BaseModel`. Sub model has to inherit from `pydantic.BaseModel`. `env_nested_delimiter` can be configured via the `model_config` as shown above, or via the `_env_nested_delimiter` keyword argument on instantiation. By default environment variables are split by `env_nested_delimiter` into arbitrarily deep nested fields. You can limit the depth of the nested fields with the `env_nested_max_split` config setting. A common use case this is particularly useful is for two-level deep settings, where the `env_nested_delimiter` (usually a single `_`) may be a substring of model field names. For example: Terminal ```bash # your environment export GENERATION_LLM_PROVIDER='anthropic' export GENERATION_LLM_API_KEY='your-api-key' export GENERATION_LLM_API_VERSION='2024-03-15' ``` You could load them into the following settings model: ```py from pydantic import BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict class LLMConfig(BaseModel): provider: str = 'openai' api_key: str api_type: str = 'azure' api_version: str = '2023-03-15-preview' class GenerationConfig(BaseSettings): model_config = SettingsConfigDict( env_nested_delimiter='_', env_nested_max_split=1, env_prefix='GENERATION_' ) llm: LLMConfig ... print(GenerationConfig().model_dump()) """ { 'llm': { 'provider': 'anthropic', 'api_key': 'your-api-key', 'api_type': 'azure', 'api_version': '2024-03-15', } } """ ``` Without `env_nested_max_split=1` set, `GENERATION_LLM_API_KEY` would be parsed as `llm.api.key` instead of `llm.api_key` and it would raise a `ValidationError`. Nested environment variables take precedence over the top-level environment variable JSON (e.g. in the example above, `SUB_MODEL__V2` trumps `SUB_MODEL`). You may also populate a complex type by providing your own source class. ```py import json import os from typing import Any from pydantic.fields import FieldInfo from pydantic_settings import ( BaseSettings, EnvSettingsSource, PydanticBaseSettingsSource, ) class MyCustomSource(EnvSettingsSource): def prepare_field_value( self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool ) -> Any: if field_name == 'numbers': return [int(x) for x in value.split(',')] return json.loads(value) class Settings(BaseSettings): numbers: list[int] @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (MyCustomSource(settings_cls),) os.environ['numbers'] = '1,2,3' print(Settings().model_dump()) #> {'numbers': [1, 2, 3]} ``` ### Disabling JSON parsing pydantic-settings by default parses complex types from environment variables as JSON strings. If you want to disable this behavior for a field and parse the value in your own validator, you can annotate the field with [`NoDecode`](/docs/validation/latest/api/pydantic_settings#pydantic_settings.NoDecode): ```py import os from typing import Annotated from pydantic import field_validator from pydantic_settings import BaseSettings, NoDecode class Settings(BaseSettings): numbers: Annotated[list[int], NoDecode] # (1) @field_validator('numbers', mode='before') @classmethod def decode_numbers(cls, v: str) -> list[int]: return [int(x) for x in v.split(',')] os.environ['numbers'] = '1,2,3' print(Settings().model_dump()) #> {'numbers': [1, 2, 3]} ``` The `NoDecode` annotation disables JSON parsing for the `numbers` field. The `decode_numbers` field validator will be called to parse the value. You can also disable JSON parsing for all fields by setting the `enable_decoding` config setting to `False`: ```py import os from pydantic import field_validator from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(enable_decoding=False) numbers: list[int] @field_validator('numbers', mode='before') @classmethod def decode_numbers(cls, v: str) -> list[int]: return [int(x) for x in v.split(',')] os.environ['numbers'] = '1,2,3' print(Settings().model_dump()) #> {'numbers': [1, 2, 3]} ``` You can force JSON parsing for a field by annotating it with [`ForceDecode`](/docs/validation/latest/api/pydantic_settings#pydantic_settings.ForceDecode). This will bypass the `enable_decoding` config setting: ```py import os from typing import Annotated from pydantic import field_validator from pydantic_settings import BaseSettings, ForceDecode, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(enable_decoding=False) numbers: Annotated[list[int], ForceDecode] numbers1: list[int] # (1) @field_validator('numbers1', mode='before') @classmethod def decode_numbers1(cls, v: str) -> list[int]: return [int(x) for x in v.split(',')] os.environ['numbers'] = '["1","2","3"]' os.environ['numbers1'] = '1,2,3' print(Settings().model_dump()) #> {'numbers': [1, 2, 3], 'numbers1': [1, 2, 3]} ``` The `numbers1` field is not annotated with `ForceDecode`, so it will not be parsed as JSON. and we have to provide a custom validator to parse the value. ## Nested model default partial updates By default, Pydantic settings does not allow partial updates to nested model default objects. This behavior can be overriden by setting the `nested_model_default_partial_update` flag to `True`, which will allow partial updates on nested model default object fields. ```py import os from pydantic import BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict class SubModel(BaseModel): val: int = 0 flag: bool = False class SettingsPartialUpdate(BaseSettings): model_config = SettingsConfigDict( env_nested_delimiter='__', nested_model_default_partial_update=True ) nested_model: SubModel = SubModel(val=1) class SettingsNoPartialUpdate(BaseSettings): model_config = SettingsConfigDict( env_nested_delimiter='__', nested_model_default_partial_update=False ) nested_model: SubModel = SubModel(val=1) # Apply a partial update to the default object using environment variables os.environ['NESTED_MODEL__FLAG'] = 'True' # When partial update is enabled, the existing SubModel instance is updated # with nested_model.flag=True change assert SettingsPartialUpdate().model_dump() == { 'nested_model': {'val': 1, 'flag': True} } # When partial update is disabled, a new SubModel instance is instantiated # with nested_model.flag=True change assert SettingsNoPartialUpdate().model_dump() == { 'nested_model': {'val': 0, 'flag': True} } ``` ## Dotenv (.env) support Dotenv files (generally named `.env`) are a common pattern that make it easy to use environment variables in a platform-independent manner. A dotenv file follows the same general principles of all environment variables, and it looks like this: .env ```bash # ignore comment ENVIRONMENT="production" REDIS_ADDRESS=localhost:6379 MEANING_OF_LIFE=42 MY_VAR='Hello world' ``` Once you have your `.env` file filled with variables, _pydantic_ supports loading it in two ways: 1. Setting the `env_file` (and `env_file_encoding` if you don't want the default encoding of your OS) on `model_config` in the `BaseSettings` class: ```txt from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8') ``` 2. Instantiating the `BaseSettings` derived class with the `_env_file` keyword argument (and the `_env_file_encoding` if needed): ```txt from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_file='.env', env_file_encoding='utf-8') settings = Settings(_env_file='prod.env', _env_file_encoding='utf-8') ``` In either case, the value of the passed argument can be any valid path or filename, either absolute or relative to the current working directory. From there, _pydantic_ will handle everything for you by loading in your variables and validating them. Note If a filename is specified for `env_file`, Pydantic will only check the current working directory and won't check any parent directories for the `.env` file. Tip Named pipes (FIFOs) are also supported as dotenv files. This is useful for tools like [1Password Environments](https://developer.1password.com/docs/environments), which mount `.env` files as named pipes to provide secrets on demand without writing them to disk. Even when using a dotenv file, _pydantic_ will still read environment variables as well as the dotenv file, **environment variables will always take priority over values loaded from a dotenv file**. Passing a file path via the `_env_file` keyword argument on instantiation (method 2) will override the value (if any) set on the `model_config` class. If the above snippets were used in conjunction, `prod.env` would be loaded while `.env` would be ignored. If you need to load multiple dotenv files, you can pass multiple file paths as a tuple or list. The files will be loaded in order, with each file overriding the previous one. ```py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( # `.env.prod` takes priority over `.env` env_file=('.env', '.env.prod') ) ``` You can also use the keyword argument override to tell Pydantic not to load any file at all (even if one is set in the `model_config` class) by passing `None` as the instantiation keyword argument, e.g. `settings = Settings(_env_file=None)`. Because python-dotenv is used to parse the file, bash-like semantics such as `export` can be used which (depending on your OS and environment) may allow your dotenv file to also be used with `source`, see [python-dotenv's documentation](https://saurabh-kumar.com/python-dotenv/#usages) for more details. Pydantic settings consider `extra` config in case of dotenv file. It means if you set the `extra=forbid` (_default_) on `model_config` and your dotenv file contains an entry for a field that is not defined in settings model, it will raise `ValidationError` in settings construction. This behaviour can be customized by using the setting `dotenv_filtering` that supports two additional alternative modes: - `'match_prefix'`: only the variables that match the prefix will be passed to the model. Useful when used in conjunction with `env_prefix` to "scope" a single dotenv file to a specific model. - `'only_existing'`: only the variables that have a corresponding field will be passed to the model. When using this option the dotenv setting source will behave like the env settings source. For compatibility with pydantic 1.x BaseSettings you should use `extra=ignore`: ```py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(env_file='.env', extra='ignore') ``` Note Pydantic settings loads all the values from dotenv file and passes it to the model, regardless of the model's `env_prefix`, unless `dotenv_filtering` is used. So if you provide extra values in a dotenv file, whether they start with `env_prefix` or not, a `ValidationError` will be raised. ## Command Line Support Pydantic settings provides integrated CLI support, making it easy to quickly define CLI applications using Pydantic models. There are two primary use cases for Pydantic settings CLI: 1. When using a CLI to override fields in Pydantic models. 2. When using Pydantic models to define CLIs. By default, the experience is tailored towards use case #1 and builds on the foundations established in [parsing environment variables](#parsing-environment-variable-values). If your use case primarily falls into #2, you will likely want to enable most of the defaults outlined at the end of [creating CLI applications](#creating-cli-applications). ### The Basics To get started, let's revisit the example presented in [parsing environment variables](#parsing-environment-variable-values) but using a Pydantic settings CLI: ```py import sys from pydantic import BaseModel from pydantic_settings import BaseSettings, SettingsConfigDict class DeepSubModel(BaseModel): v4: str class SubModel(BaseModel): v1: str v2: bytes v3: int deep: DeepSubModel class Settings(BaseSettings): model_config = SettingsConfigDict(cli_parse_args=True) v0: str sub_model: SubModel sys.argv = [ 'example.py', '--v0=0', '--sub_model={"v1": "json-1", "v2": "json-2"}', '--sub_model.v2=nested-2', '--sub_model.v3=3', '--sub_model.deep.v4=v4', ] print(Settings().model_dump()) """ { 'v0': '0', 'sub_model': {'v1': 'json-1', 'v2': b'nested-2', 'v3': 3, 'deep': {'v4': 'v4'}}, } """ ``` To enable CLI parsing, we simply set the `cli_parse_args` flag to a valid value, which retains similar connotations as defined in `argparse`. Note that a CLI settings source is [**the topmost source**](#field-value-priority) by default unless its [priority value is customised](#customise-settings-sources): ```py import os import sys from pydantic_settings import ( BaseSettings, CliSettingsSource, PydanticBaseSettingsSource, ) class Settings(BaseSettings): my_foo: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return env_settings, CliSettingsSource(settings_cls, cli_parse_args=True) os.environ['MY_FOO'] = 'from environment' sys.argv = ['example.py', '--my_foo=from cli'] print(Settings().model_dump()) #> {'my_foo': 'from environment'} ``` #### Lists CLI argument parsing of lists supports intermixing of any of the below three styles: - JSON style `--field='[1,2]'` - Argparse style `--field 1 --field 2` - Lazy style `--field=1,2` ```py import sys from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True): my_list: list[int] sys.argv = ['example.py', '--my_list', '[1,2]'] print(Settings().model_dump()) #> {'my_list': [1, 2]} sys.argv = ['example.py', '--my_list', '1', '--my_list', '2'] print(Settings().model_dump()) #> {'my_list': [1, 2]} sys.argv = ['example.py', '--my_list', '1,2'] print(Settings().model_dump()) #> {'my_list': [1, 2]} ``` #### Dictionaries CLI argument parsing of dictionaries supports intermixing of any of the below two styles: - JSON style `--field='{"k1": 1, "k2": 2}'` - Environment variable style `--field k1=1 --field k2=2` These can be used in conjunction with list forms as well, e.g: - `--field k1=1,k2=2 --field k3=3 --field '{"k4": 4}'` etc. ```py import sys from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True): my_dict: dict[str, int] sys.argv = ['example.py', '--my_dict', '{"k1":1,"k2":2}'] print(Settings().model_dump()) #> {'my_dict': {'k1': 1, 'k2': 2}} sys.argv = ['example.py', '--my_dict', 'k1=1', '--my_dict', 'k2=2'] print(Settings().model_dump()) #> {'my_dict': {'k1': 1, 'k2': 2}} ``` #### Literals and Enums CLI argument parsing of literals and enums are converted into CLI choices. ```py import sys from enum import IntEnum from typing import Literal from pydantic_settings import BaseSettings class Fruit(IntEnum): pear = 0 kiwi = 1 lime = 2 class Settings(BaseSettings, cli_parse_args=True): fruit: Fruit pet: Literal['dog', 'cat', 'bird'] sys.argv = ['example.py', '--fruit', 'lime', '--pet', 'cat'] print(Settings().model_dump()) #> {'fruit': , 'pet': 'cat'} ``` #### Aliases Pydantic field aliases are added as CLI argument aliases. Aliases of length one are converted into short options. ```py import sys from pydantic import AliasChoices, AliasPath, Field from pydantic_settings import BaseSettings class User(BaseSettings, cli_parse_args=True): first_name: str = Field( validation_alias=AliasChoices('f', 'fname', AliasPath('fullname', 0)) ) last_name: str = Field( validation_alias=AliasChoices('l', 'lname', AliasPath('fullname', 1)) ) sys.argv = ['example.py', '--fname', 'John', '--lname', 'Doe'] print(User().model_dump()) #> {'first_name': 'John', 'last_name': 'Doe'} sys.argv = ['example.py', '-f', 'John', '-l', 'Doe'] print(User().model_dump()) #> {'first_name': 'John', 'last_name': 'Doe'} sys.argv = ['example.py', '--fullname', 'John,Doe'] print(User().model_dump()) #> {'first_name': 'John', 'last_name': 'Doe'} sys.argv = ['example.py', '--fullname', 'John', '--lname', 'Doe'] print(User().model_dump()) #> {'first_name': 'John', 'last_name': 'Doe'} ``` ### Subcommands and Positional Arguments Subcommands and positional arguments are expressed using the `CliSubCommand` and `CliPositionalArg` annotations. The subcommand annotation can only be applied to required fields (i.e. fields that do not have a default value). Furthermore, subcommands must be a valid type derived from either a pydantic `BaseModel` or pydantic.dataclasses `dataclass`. Parsed subcommands can be retrieved from model instances using the `get_subcommand` utility function. If a subcommand is not required, set the `is_required` flag to `False` to disable raising an error if no subcommand is found. Note CLI settings subcommands are limited to a single subparser per model. In other words, all subcommands for a model are grouped under a single subparser; it does not allow for multiple subparsers with each subparser having its own set of subcommands. For more information on subparsers, see [argparse subcommands](https://docs.python.org/3/library/argparse.html#sub-commands). Note `CliSubCommand` and `CliPositionalArg` are always case sensitive. ```py import sys from pydantic import BaseModel from pydantic_settings import ( BaseSettings, CliPositionalArg, CliSubCommand, SettingsError, get_subcommand, ) class Init(BaseModel): directory: CliPositionalArg[str] class Clone(BaseModel): repository: CliPositionalArg[str] directory: CliPositionalArg[str] class Git(BaseSettings, cli_parse_args=True, cli_exit_on_error=False): clone: CliSubCommand[Clone] init: CliSubCommand[Init] # Run without subcommands sys.argv = ['example.py'] cmd = Git() assert cmd.model_dump() == {'clone': None, 'init': None} try: # Will raise an error since no subcommand was provided get_subcommand(cmd).model_dump() except SettingsError as err: assert str(err) == 'Error: CLI subcommand is required {clone, init}' # Will not raise an error since subcommand is not required assert get_subcommand(cmd, is_required=False) is None # Run the clone subcommand sys.argv = ['example.py', 'clone', 'repo', 'dest'] cmd = Git() assert cmd.model_dump() == { 'clone': {'repository': 'repo', 'directory': 'dest'}, 'init': None, } # Returns the subcommand model instance (in this case, 'clone') assert get_subcommand(cmd).model_dump() == { 'directory': 'dest', 'repository': 'repo', } ``` The `CliSubCommand` and `CliPositionalArg` annotations also support union operations and aliases. For unions of Pydantic models, it is important to remember the [nuances](https://docs.pydantic.dev/latest/concepts/unions/) that can arise during validation. Specifically, for unions of subcommands that are identical in content, it is recommended to break them out into separate `CliSubCommand` fields to avoid any complications. Lastly, the derived subcommand names from unions will be the names of the Pydantic model classes themselves. When assigning aliases to `CliSubCommand` or `CliPositionalArg` fields, only a single alias can be assigned. For non-union subcommands, aliasing will change the displayed help text and subcommand name. Conversely, for union subcommands, aliasing will have no tangible effect from the perspective of the CLI settings source. Lastly, for positional arguments, aliasing will change the CLI help text displayed for the field. ```py import sys from typing import Union from pydantic import BaseModel, Field from pydantic_settings import ( BaseSettings, CliPositionalArg, CliSubCommand, get_subcommand, ) class Alpha(BaseModel): """Apha Help""" cmd_alpha: CliPositionalArg[str] = Field(alias='alpha-cmd') class Beta(BaseModel): """Beta Help""" opt_beta: str = Field(alias='opt-beta') class Gamma(BaseModel): """Gamma Help""" opt_gamma: str = Field(alias='opt-gamma') class Root(BaseSettings, cli_parse_args=True, cli_exit_on_error=False): alpha_or_beta: CliSubCommand[Union[Alpha, Beta]] = Field(alias='alpha-or-beta-cmd') gamma: CliSubCommand[Gamma] = Field(alias='gamma-cmd') sys.argv = ['example.py', 'Alpha', 'hello'] assert get_subcommand(Root()).model_dump() == {'cmd_alpha': 'hello'} sys.argv = ['example.py', 'Beta', '--opt-beta=hey'] assert get_subcommand(Root()).model_dump() == {'opt_beta': 'hey'} sys.argv = ['example.py', 'gamma-cmd', '--opt-gamma=hi'] assert get_subcommand(Root()).model_dump() == {'opt_gamma': 'hi'} ``` ### Creating CLI Applications The `CliApp` class provides two utility methods, `CliApp.run` and `CliApp.run_subcommand`, that can be used to run a Pydantic `BaseSettings`, `BaseModel`, or `pydantic.dataclasses.dataclass` as a CLI application. Primarily, the methods provide structure for running `cli_cmd` methods associated with models. `CliApp.run` can be used in directly providing the `cli_args` to be parsed, and will run the model `cli_cmd` method (if defined) after instantiation: ```py from pydantic_settings import BaseSettings, CliApp class Settings(BaseSettings): this_foo: str def cli_cmd(self) -> None: # Print the parsed data print(self.model_dump()) #> {'this_foo': 'is such a foo'} # Update the parsed data showing cli_cmd ran self.this_foo = 'ran the foo cli cmd' s = CliApp.run(Settings, cli_args=['--this_foo', 'is such a foo']) print(s.model_dump()) #> {'this_foo': 'ran the foo cli cmd'} ``` Similarly, the `CliApp.run_subcommand` can be used in recursive fashion to run the `cli_cmd` method of a subcommand: ```py from pydantic import BaseModel from pydantic_settings import CliApp, CliPositionalArg, CliSubCommand class Init(BaseModel): directory: CliPositionalArg[str] def cli_cmd(self) -> None: print(f'git init "{self.directory}"') #> git init "dir" self.directory = 'ran the git init cli cmd' class Clone(BaseModel): repository: CliPositionalArg[str] directory: CliPositionalArg[str] def cli_cmd(self) -> None: print(f'git clone from "{self.repository}" into "{self.directory}"') self.directory = 'ran the clone cli cmd' class Git(BaseModel): clone: CliSubCommand[Clone] init: CliSubCommand[Init] def cli_cmd(self) -> None: CliApp.run_subcommand(self) cmd = CliApp.run(Git, cli_args=['init', 'dir']) assert cmd.model_dump() == { 'clone': None, 'init': {'directory': 'ran the git init cli cmd'}, } ``` Note Unlike `CliApp.run`, `CliApp.run_subcommand` requires the subcommand model to have a defined `cli_cmd` method. For `BaseModel` and `pydantic.dataclasses.dataclass` types, `CliApp.run` will internally use the following `BaseSettings` configuration defaults: - `nested_model_default_partial_update=True` - `case_sensitive=True` - `cli_hide_none_type=True` - `cli_avoid_json=True` - `cli_enforce_required=True` - `cli_implicit_flags=True` - `cli_kebab_case=True` #### Asynchronous Commands Pydantic settings supports running asynchronous CLI commands via `CliApp.run` and `CliApp.run_subcommand`. With this feature, you can define async def methods within your Pydantic models (including subcommands) and have them executed just like their synchronous counterparts. Specifically: 1. Asynchronous methods are supported: You can now mark your cli\_cmd or similar CLI entrypoint methods as async def and have CliApp execute them. 2. Subcommands may also be asynchronous: If you have nested CLI subcommands, the final (lowest-level) subcommand methods can likewise be asynchronous. 3. Limit asynchronous methods to final subcommands: Defining parent commands as asynchronous is not recommended, because it can result in additional threads and event loops being created. For best performance and to avoid unnecessary resource usage, only implement your deepest (child) subcommands as async def. Below is a simple example demonstrating an asynchronous top-level command: ```py from pydantic_settings import BaseSettings, CliApp class AsyncSettings(BaseSettings): async def cli_cmd(self) -> None: print('Hello from an async CLI method!') #> Hello from an async CLI method! # If an event loop is already running, a new thread will be used; # otherwise, asyncio.run() is used to execute this async method. assert CliApp.run(AsyncSettings, cli_args=[]).model_dump() == {} ``` #### Asynchronous Subcommands As mentioned above, you can also define subcommands as async. However, only do so for the leaf (lowest-level) subcommand to avoid spawning new threads and event loops unnecessarily in parent commands: ```py from pydantic import BaseModel from pydantic_settings import ( BaseSettings, CliApp, CliPositionalArg, CliSubCommand, ) class Clone(BaseModel): repository: CliPositionalArg[str] directory: CliPositionalArg[str] async def cli_cmd(self) -> None: # Perform async tasks here, e.g. network or I/O operations print(f'Cloning async from "{self.repository}" into "{self.directory}"') #> Cloning async from "repo" into "dir" class Git(BaseSettings): clone: CliSubCommand[Clone] def cli_cmd(self) -> None: # Run the final subcommand (clone/init). It is recommended to define async methods only at the deepest level. CliApp.run_subcommand(self) CliApp.run(Git, cli_args=['clone', 'repo', 'dir']).model_dump() == { 'repository': 'repo', 'directory': 'dir', } ``` When executing a subcommand with an asynchronous cli\_cmd, Pydantic settings automatically detects whether the current thread already has an active event loop. If so, the async command is run in a fresh thread to avoid conflicts. Otherwise, it uses asyncio.run() in the current thread. This handling ensures your asynchronous subcommands "just work" without additional manual setup. #### Printing Help The `print_help` and `format_help` methods are available for printing or formatting help. ```python from pydantic_settings import BaseSettings, CliApp class Settings(BaseSettings, cli_prog_name='example'): def cli_cmd(self) -> None: # Will print help for the current command or subcommand instance. CliApp.print_help(self) # Will return formatted help for the current command or subcommand instance. CliApp.format_help(self) CliApp.run(Settings, cli_args=[]) """ usage: example [-h] options: -h, --help show this help message and exit """ # You can also print or format help on the class itself. print(CliApp.format_help(Settings)) """ usage: example [-h] options: -h, --help show this help message and exit """ ``` #### Serializing Arguments An instantiated Pydantic model can be serialized into its CLI arguments using the `CliApp.serialize` method. Serialization styles can be controlled using the `list_style`, `dict_style`, and `positionals_first` flags. ```py from pydantic import BaseModel from pydantic_settings import CliApp, CliPositionalArg class Nested(BaseModel): that: dict[str, int] class Settings(BaseModel): positional_arg: CliPositionalArg[str] this: list[str] nested: Nested settings = Settings( positional_arg='arg', this=['hello', 'world'], nested=Nested(that={'a': 1, 'b': 2}) ) print(CliApp.serialize(settings)) #> ['--this', '["hello", "world"]', '--nested.that', '{"a": 1, "b": 2}', 'arg'] print(CliApp.serialize(settings, positionals_first=True)) #> ['arg', '--this', '["hello", "world"]', '--nested.that', '{"a": 1, "b": 2}'] print(CliApp.serialize(settings, list_style='lazy')) #> ['--this', 'hello,world', '--nested.that', '{"a": 1, "b": 2}', 'arg'] print(CliApp.serialize(settings, list_style='argparse')) #> ['--this', 'hello', '--this', 'world', '--nested.that', '{"a": 1, "b": 2}', 'arg'] print(CliApp.serialize(settings, dict_style='env')) """ ['--this', '["hello", "world"]', '--nested.that', 'a=1', '--nested.that', 'b=2', 'arg'] """ ``` ### Mutually Exclusive Groups CLI mutually exclusive groups can be created by inheriting from the `CliMutuallyExclusiveGroup` class. Note A `CliMutuallyExclusiveGroup` cannot be used in a union or contain nested models. ```py from typing import Optional from pydantic import BaseModel from pydantic_settings import CliApp, CliMutuallyExclusiveGroup, SettingsError class Circle(CliMutuallyExclusiveGroup): radius: Optional[float] = None diameter: Optional[float] = None perimeter: Optional[float] = None class Settings(BaseModel): circle: Circle try: CliApp.run( Settings, cli_args=['--circle.radius=1', '--circle.diameter=2'], cli_exit_on_error=False, ) except SettingsError as e: print(e) """ error parsing CLI: argument --circle.diameter: not allowed with argument --circle.radius """ ``` ### Customizing the CLI Experience The below flags can be used to customise the CLI experience to your needs. #### Change the Displayed Program Name Change the default program name displayed in the help text usage by setting `cli_prog_name`. By default, it will derive the name of the currently executing program from `sys.argv[0]`, just like argparse. ```py import sys from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True, cli_prog_name='appdantic'): pass try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: appdantic [-h] options: -h, --help show this help message and exit """ ``` #### CLI Boolean Flags Change whether boolean fields should be explicit or implicit by default using the `cli_implicit_flags` setting. By default, boolean fields are "explicit", meaning a boolean value must be explicitly provided on the CLI, e.g. `--flag=True`. Conversely, boolean fields that are "implicit" derive the value from the flag itself, e.g. `--flag,--no-flag`, which removes the need for an explicit value to be passed. Additionally, the provided `CliImplicitFlag` and `CliExplicitFlag` annotations can be used for more granular control when necessary. ```py from pydantic_settings import BaseSettings, CliExplicitFlag, CliImplicitFlag class ExplicitSettings(BaseSettings, cli_parse_args=True): """Boolean fields are explicit by default.""" explicit_req: bool """ --explicit_req bool (required) """ explicit_opt: bool = False """ --explicit_opt bool (default: False) """ # Booleans are explicit by default, so must override implicit flags with annotation implicit_req: CliImplicitFlag[bool] """ --implicit_req, --no-implicit_req (required) """ implicit_opt: CliImplicitFlag[bool] = False """ --implicit_opt, --no-implicit_opt (default: False) """ class ImplicitSettings(BaseSettings, cli_parse_args=True, cli_implicit_flags=True): """With cli_implicit_flags=True, boolean fields are implicit by default.""" # Booleans are implicit by default, so must override explicit flags with annotation explicit_req: CliExplicitFlag[bool] """ --explicit_req bool (required) """ explicit_opt: CliExplicitFlag[bool] = False """ --explicit_opt bool (default: False) """ implicit_req: bool """ --implicit_req, --no-implicit_req (required) """ implicit_opt: bool = False """ --implicit_opt, --no-implicit_opt (default: False) """ ``` Implicit flag behavior can be further refined using the "toggle" or "dual" mode settings. Similarly, the provided `CliToggleFlag` and `CliDualFlag` annotations can be used for more granular control. For "toggle" flags, if default=`False`, `--flag` will store `True`. Otherwise, if default=`True`, `--no-flag` will store `False`. ```py from pydantic_settings import BaseSettings, CliDualFlag, CliToggleFlag class ImplicitDualSettings( BaseSettings, cli_parse_args=True, cli_implicit_flags='dual' ): """With cli_implicit_flags='dual', implicit flags are dual by default.""" implicit_req: bool """ --implicit_req, --no-implicit_req (required) """ implicit_dual_opt: bool = False """ --implicit_dual_opt, --no-implicit_dual_opt (default: False) """ # Implicit flags are dual by default, so must override toggle flags with annotation flag_a: CliToggleFlag[bool] = False """ --flag_a (default: False) """ # Implicit flags are dual by default, so must override toggle flags with annotation flag_b: CliToggleFlag[bool] = True """ --no-flag_b (default: True) """ class ImplicitToggleSettings( BaseSettings, cli_parse_args=True, cli_implicit_flags='toggle' ): """With cli_implicit_flags='toggle', implicit flags are toggle by default.""" implicit_req: bool """ --implicit_req, --no-implicit_req (required) """ # Implicit flags are toggle by default, so must override dual flags with annotation implicit_dual_opt: CliDualFlag[bool] = False """ --implicit_dual_opt, --no-implicit_dual_opt (default: False) """ flag_a: bool = False """ --flag_a (default: False) """ flag_b: bool = True """ --no-flag_b (default: True) """ ``` #### Ignore and Retrieve Unknown Arguments Change whether to ignore unknown CLI arguments and only parse known ones using `cli_ignore_unknown_args`. By default, the CLI does not ignore any args. Ignored arguments can then be retrieved using the `CliUnknownArgs` annotation. ```py import sys from pydantic_settings import BaseSettings, CliUnknownArgs class Settings(BaseSettings, cli_parse_args=True, cli_ignore_unknown_args=True): good_arg: str ignored_args: CliUnknownArgs sys.argv = ['example.py', '--bad-arg=bad', 'ANOTHER_BAD_ARG', '--good_arg=hello world'] print(Settings().model_dump()) #> {'good_arg': 'hello world', 'ignored_args': ['--bad-arg=bad', 'ANOTHER_BAD_ARG']} ``` #### CLI Kebab Case for Arguments Change whether CLI arguments should use kebab case by enabling `cli_kebab_case`. By default, `cli_kebab_case=True` will ignore enum fields, and is equivalent to `cli_kebab_case='no_enums'`. To apply kebab case to everything, including enums, use `cli_kebab_case='all'`. ```py import sys from pydantic import Field from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True, cli_kebab_case=True): my_option: str = Field(description='will show as kebab case on CLI') try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: example.py [-h] [--my-option str] options: -h, --help show this help message and exit --my-option str will show as kebab case on CLI (required) """ ``` #### Change Whether CLI Should Exit on Error Change whether the CLI internal parser will exit on error or raise a `SettingsError` exception by using `cli_exit_on_error`. By default, the CLI internal parser will exit on error. ```py import sys from pydantic_settings import BaseSettings, SettingsError class Settings(BaseSettings, cli_parse_args=True, cli_exit_on_error=False): ... try: sys.argv = ['example.py', '--bad-arg'] Settings() except SettingsError as e: print(e) #> error parsing CLI: unrecognized arguments: --bad-arg ``` #### Enforce Required Arguments at CLI Pydantic settings is designed to pull values in from various sources when instantating a model. This means a field that is required is not strictly required from any single source (e.g. the CLI). Instead, all that matters is that one of the sources provides the required value. However, if your use case [aligns more with #2](#command-line-support), using Pydantic models to define CLIs, you will likely want required fields to be _strictly required at the CLI_. We can enable this behavior by using `cli_enforce_required`. Note A required `CliPositionalArg` field is always strictly required (enforced) at the CLI. ```py import os import sys from pydantic import Field from pydantic_settings import BaseSettings, SettingsError class Settings( BaseSettings, cli_parse_args=True, cli_enforce_required=True, cli_exit_on_error=False, ): my_required_field: str = Field(description='a top level required field') os.environ['MY_REQUIRED_FIELD'] = 'hello from environment' try: sys.argv = ['example.py'] Settings() except SettingsError as e: print(e) #> error parsing CLI: the following arguments are required: --my_required_field ``` #### Change the None Type Parse String Change the CLI string value that will be parsed (e.g. "null", "void", "None", etc.) into `None` by setting `cli_parse_none_str`. By default it will use the `env_parse_none_str` value if set. Otherwise, it will default to "null" if `cli_avoid_json` is `False`, and "None" if `cli_avoid_json` is `True`. ```py import sys from typing import Optional from pydantic import Field from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True, cli_parse_none_str='void'): v1: Optional[int] = Field(description='the top level v0 option') sys.argv = ['example.py', '--v1', 'void'] print(Settings().model_dump()) #> {'v1': None} ``` #### Hide None Type Values Hide `None` values from the CLI help text by enabling `cli_hide_none_type`. ```py import sys from typing import Optional from pydantic import Field from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True, cli_hide_none_type=True): v0: Optional[str] = Field(description='the top level v0 option') try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: example.py [-h] [--v0 str] options: -h, --help show this help message and exit --v0 str the top level v0 option (required) """ ``` #### Avoid Adding JSON CLI Options Avoid adding complex fields that result in JSON strings at the CLI by enabling `cli_avoid_json`. ```py import sys from pydantic import BaseModel, Field from pydantic_settings import BaseSettings class SubModel(BaseModel): v1: int = Field(description='the sub model v1 option') class Settings(BaseSettings, cli_parse_args=True, cli_avoid_json=True): sub_model: SubModel = Field( description='The help summary for SubModel related options' ) try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: example.py [-h] [--sub_model.v1 int] options: -h, --help show this help message and exit sub_model options: The help summary for SubModel related options --sub_model.v1 int the sub model v1 option (required) """ ``` #### Use Class Docstring for Group Help Text By default, when populating the group help text for nested models it will pull from the field descriptions. Alternatively, we can also configure CLI settings to pull from the class docstring instead. Note If the field is a union of nested models the group help text will always be pulled from the field description; even if `cli_use_class_docs_for_groups` is set to `True`. ```py import sys from pydantic import BaseModel, Field from pydantic_settings import BaseSettings class SubModel(BaseModel): """The help text from the class docstring.""" v1: int = Field(description='the sub model v1 option') class Settings(BaseSettings, cli_parse_args=True, cli_use_class_docs_for_groups=True): """My application help text.""" sub_model: SubModel = Field(description='The help text from the field description') try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: example.py [-h] [--sub_model JSON] [--sub_model.v1 int] My application help text. options: -h, --help show this help message and exit sub_model options: The help text from the class docstring. --sub_model JSON set sub_model from JSON string --sub_model.v1 int the sub model v1 option (required) """ ``` #### Change the CLI Flag Prefix Character Change The CLI flag prefix character used in CLI optional arguments by settings `cli_flag_prefix_char`. ```py import sys from pydantic import AliasChoices, Field from pydantic_settings import BaseSettings class Settings(BaseSettings, cli_parse_args=True, cli_flag_prefix_char='+'): my_arg: str = Field(validation_alias=AliasChoices('m', 'my-arg')) sys.argv = ['example.py', '++my-arg', 'hi'] print(Settings().model_dump()) #> {'my_arg': 'hi'} sys.argv = ['example.py', '+m', 'hi'] print(Settings().model_dump()) #> {'my_arg': 'hi'} ``` #### Suppressing Fields from CLI Help Text To suppress a field from the CLI help text, the `CliSuppress` annotation can be used for field types, or the `CLI_SUPPRESS` string constant can be used for field descriptions. ```py import sys from pydantic import Field from pydantic_settings import CLI_SUPPRESS, BaseSettings, CliSuppress class Settings(BaseSettings, cli_parse_args=True): """Suppress fields from CLI help text.""" field_a: CliSuppress[int] = 0 field_b: str = Field(default=1, description=CLI_SUPPRESS) try: sys.argv = ['example.py', '--help'] Settings() except SystemExit as e: print(e) #> 0 """ usage: example.py [-h] Suppress fields from CLI help text. options: -h, --help show this help message and exit """ ``` #### CLI Shortcuts for Arguments Add alternative CLI argument names (shortcuts) for fields using the `cli_shortcuts` option in `SettingsConfigDict`. This allows you to define additional names for CLI arguments, which can be especially useful for providing more user-friendly or shorter aliases for deeply nested or verbose field names. The `cli_shortcuts` option takes a dictionary mapping the target field name (using dot notation for nested fields) to one or more shortcut names. If multiple fields share the same shortcut, the first matching field will take precedence. **Flat Example:** ```py from pydantic import Field from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): option: str = Field(default='foo') list_option: str = Field(default='fizz') model_config = SettingsConfigDict( cli_shortcuts={'option': 'option2', 'list_option': ['list_option2']} ) # Now you can use the shortcuts on the CLI: # --option2 sets 'option', --list_option2 sets 'list_option' ``` **Nested Example:** ```py from pydantic import BaseModel, Field from pydantic_settings import BaseSettings, SettingsConfigDict class TwiceNested(BaseModel): option: str = Field(default='foo') class Nested(BaseModel): twice_nested_option: TwiceNested = TwiceNested() option: str = Field(default='foo') class Settings(BaseSettings): nested: Nested = Nested() model_config = SettingsConfigDict( cli_shortcuts={ 'nested.option': 'option2', 'nested.twice_nested_option.option': 'twice_nested_option', } ) # Now you can use --option2 to set nested.option and --twice_nested_option to set nested.twice_nested_option.option ``` If a shortcut collides (is mapped to multiple fields), it will apply to the first matching field in the model. ### Integrating with Existing Parsers A CLI settings source can be integrated with existing parsers by overriding the default CLI settings source with a user defined one that specifies the `root_parser` object. ```py import sys from argparse import ArgumentParser from pydantic_settings import BaseSettings, CliApp, CliSettingsSource parser = ArgumentParser() parser.add_argument('--food', choices=['pear', 'kiwi', 'lime']) class Settings(BaseSettings): name: str = 'Bob' # Set existing `parser` as the `root_parser` object for the user defined settings source cli_settings = CliSettingsSource(Settings, root_parser=parser) # Parse and load CLI settings from the command line into the settings source. sys.argv = ['example.py', '--food', 'kiwi', '--name', 'waldo'] s = CliApp.run(Settings, cli_settings_source=cli_settings) print(s.model_dump()) #> {'name': 'waldo'} # Load CLI settings from pre-parsed arguments. i.e., the parsing occurs elsewhere and we # just need to load the pre-parsed args into the settings source. parsed_args = parser.parse_args(['--food', 'kiwi', '--name', 'ralph']) s = CliApp.run(Settings, cli_args=parsed_args, cli_settings_source=cli_settings) print(s.model_dump()) #> {'name': 'ralph'} ``` A `CliSettingsSource` connects with a `root_parser` object by using parser methods to add `settings_cls` fields as command line arguments. The `CliSettingsSource` internal parser representation is based on the `argparse` library, and therefore, requires parser methods that support the same attributes as their `argparse` counterparts. The available parser methods that can be customised, along with their argparse counterparts (the defaults), are listed below: - `parse_args_method` - (`argparse.ArgumentParser.parse_args`) - `add_argument_method` - (`argparse.ArgumentParser.add_argument`) - `add_argument_group_method` - (`argparse.ArgumentParser.add_argument_group`) - `add_parser_method` - (`argparse._SubParsersAction.add_parser`) - `add_subparsers_method` - (`argparse.ArgumentParser.add_subparsers`) - `format_help_method` - (`argparse.ArgumentParser.format_help`) - `formatter_class` - (`argparse.RawDescriptionHelpFormatter`) For a non-argparse parser the parser methods can be set to `None` if not supported. The CLI settings will only raise an error when connecting to the root parser if a parser method is necessary but set to `None`. Note The `formatter_class` is only applied to subcommands. The `CliSettingsSource` never touches or modifies any of the external parser settings to avoid breaking changes. Since subcommands reside on their own internal parser trees, we can safely apply the `formatter_class` settings without breaking the external parser logic. ## Secrets Placing secret values in files is a common pattern to provide sensitive configuration to an application. A secret file follows the same principal as a dotenv file except it only contains a single value and the file name is used as the key. A secret file will look like the following: /var/run/database\_password ```txt super_secret_database_password ``` Once you have your secret files, _pydantic_ supports loading it in two ways: 1. Setting the `secrets_dir` on `model_config` in a `BaseSettings` class to the directory where your secret files are stored. ```txt from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(secrets_dir='/var/run') database_password: str ``` 2. Instantiating the `BaseSettings` derived class with the `_secrets_dir` keyword argument: ``` settings = Settings(_secrets_dir='/var/run') ``` In either case, the value of the passed argument can be any valid directory, either absolute or relative to the current working directory. **Note that a non existent directory will only generate a warning**. From there, _pydantic_ will handle everything for you by loading in your variables and validating them. Even when using a secrets directory, _pydantic_ will still read environment variables from a dotenv file or the environment, **a dotenv file and environment variables will always take priority over values loaded from the secrets directory**. Passing a file path via the `_secrets_dir` keyword argument on instantiation (method 2) will override the value (if any) set on the `model_config` class. If you need to load settings from multiple secrets directories, you can pass multiple paths as a tuple or list. Just like for `env_file`, values from subsequent paths override previous ones. ```python from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): # files in '/run/secrets' take priority over '/var/run' model_config = SettingsConfigDict(secrets_dir=('/var/run', '/run/secrets')) database_password: str ``` If any of `secrets_dir` is missing, it is ignored, and warning is shown. If any of `secrets_dir` is a file, error is raised. ### Use Case: Docker Secrets Docker Secrets can be used to provide sensitive configuration to an application running in a Docker container. To use these secrets in a _pydantic_ application the process is simple. More information regarding creating, managing and using secrets in Docker see the official [Docker documentation](https://docs.docker.com/engine/reference/commandline/secret/). First, define your `Settings` class with a `SettingsConfigDict` that specifies the secrets directory. ```py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict(secrets_dir='/run/secrets') my_secret_data: str ``` Note By default [Docker uses `/run/secrets`](https://docs.docker.com/engine/swarm/secrets/#how-docker-manages-secrets) as the target mount point. If you want to use a different location, change `Config.secrets_dir` accordingly. Then, create your secret via the Docker CLI Terminal ```bash printf "This is a secret" | docker secret create my_secret_data - ``` Last, run your application inside a Docker container and supply your newly created secret Terminal ```bash docker service create --name pydantic-with-secrets --secret my_secret_data pydantic-app:latest ``` ## Nested Secrets The default secrets implementation, `SecretsSettingsSource`, has behaviour that is not always desired or sufficient. For example, the default implementation does not support secret fields in nested submodels. `NestedSecretsSettingsSource` can be used as a drop-in replacement to `SecretsSettingsSource` to adjust the default behaviour. All differences are summarized in the table below. `SecretsSettingsSource` `NestedSecretsSettingsSourcee` Secret fields must belong to a top level model. Secrets can be fields of nested models. Secret files can be placed in `secrets_dir`s only. Secret files can be placed in subdirectories for nested models. Secret files discovery is based on the same configuration options that are used by `EnvSettingsSource`: `case_sensitive`, `env_nested_delimiter`, `env_prefix`. Default options are respected, but can be overridden with `secrets_case_sensitive`, `secrets_nested_delimiter`, `secrets_prefix`. When `secrets_dir` is missing on the file system, a warning is generated. Use `secrets_dir_missing` options to choose whether to issue warning, raise error, or silently ignore. ### Use Case: Plain Directory Layout ```text 📂 secrets ├── 📄 app_key └── 📄 db_passwd ``` In the example below, secrets nested delimiter `'_'` is different from env nested delimiter `'__'`. Value for `Settings.db.user` can be passed in env variable `MY_DB__USER`. ```py from pydantic import BaseModel, SecretStr from pydantic_settings import ( BaseSettings, NestedSecretsSettingsSource, SettingsConfigDict, ) class AppSettings(BaseModel): key: SecretStr class DbSettings(BaseModel): user: str passwd: SecretStr class Settings(BaseSettings): app: AppSettings db: DbSettings model_config = SettingsConfigDict( env_prefix='MY_', env_nested_delimiter='__', secrets_dir='secrets', secrets_nested_delimiter='_', ) @classmethod def settings_customise_sources( cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings, ): return ( init_settings, env_settings, dotenv_settings, NestedSecretsSettingsSource(file_secret_settings), ) ``` ### Use Case: Nested Directory Layout ```text 📂 secrets ├── 📂 app │ └── 📄 key └── 📂 db └── 📄 passwd ``` ```py from pydantic import BaseModel, SecretStr from pydantic_settings import ( BaseSettings, NestedSecretsSettingsSource, SettingsConfigDict, ) class AppSettings(BaseModel): key: SecretStr class DbSettings(BaseModel): user: str passwd: SecretStr class Settings(BaseSettings): app: AppSettings db: DbSettings model_config = SettingsConfigDict( env_prefix='MY_', env_nested_delimiter='__', secrets_dir='secrets', secrets_nested_subdir=True, ) @classmethod def settings_customise_sources( cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings, ): return ( init_settings, env_settings, dotenv_settings, NestedSecretsSettingsSource(file_secret_settings), ) ``` ### Use Case: Multiple Nested Directories ```text 📂 secrets ├── 📂 default │ ├── 📂 app │ │ └── 📄 key │ └── 📂 db │ └── 📄 passwd └── 📂 override ├── 📂 app │ └── 📄 key └── 📂 db └── 📄 passwd ``` ```py from pydantic import BaseModel, SecretStr from pydantic_settings import ( BaseSettings, NestedSecretsSettingsSource, SettingsConfigDict, ) class AppSettings(BaseModel): key: SecretStr class DbSettings(BaseModel): user: str passwd: SecretStr class Settings(BaseSettings): app: AppSettings db: DbSettings model_config = SettingsConfigDict( env_prefix='MY_', env_nested_delimiter='__', secrets_dir=['secrets/default', 'secrets/override'], secrets_nested_subdir=True, ) @classmethod def settings_customise_sources( cls, settings_cls, init_settings, env_settings, dotenv_settings, file_secret_settings, ): return ( init_settings, env_settings, dotenv_settings, NestedSecretsSettingsSource(file_secret_settings), ) ``` ### Configuration Options #### secrets\_dir Path to secrets directory, same as `SecretsSettingsSource.secrets_dir`. If `list`, the last match wins. If `secrets_dir` is passed in both source constructor and model config, values are not merged (constructor wins). #### secrets\_dir\_missing If `secrets_dir` does not exist, original `SecretsSettingsSource` issues a warning. However, this may be undesirable, for example if we don't mount Docker Secrets in e.g. dev environment. Use `secrets_dir_missing` to choose: - `'ok'` -- do nothing if `secrets_dir` does not exist - `'warn'` (default) -- print warning, same as `SecretsSettingsSource` - `'error'` -- raise `SettingsError` If multiple `secrets_dir` passed, the same `secrets_dir_missing` action applies to each of them. #### secrets\_dir\_max\_size Limit the size of `secrets_dir` for security reasons, defaults to `SECRETS_DIR_MAX_SIZE` equal to 16 MiB. `NestedSecretsSettingsSource` is a thin wrapper around `EnvSettingsSource`, which loads all potential secrets on initialization. This could lead to `MemoryError` if we mount a large file under `secrets_dir`. If multiple `secrets_dir` passed, the limit applies to each directory independently. #### secrets\_case\_sensitive Same as `case_sensitive`, but works for secrets only. If not specified, defaults to `case_sensitive`. #### secrets\_nested\_delimiter Same as `env_nested_delimiter`, but works for secrets only. If not specified, defaults to `env_nested_delimiter`. This option is used to implement _nested secrets directory_ layout and allows to do even nasty things like `/run/secrets/model/delim/nested1/delim/nested2`. #### secrets\_nested\_subdir Boolean flag to turn on _nested secrets directory_ mode, `False` by default. If `True`, sets `secrets_nested_delimiter` to `os.sep`. Raises `SettingsError` if `secrets_nested_delimiter` is already specified. #### secrets\_prefix Secret path prefix, similar to `env_prefix`, but works for secrets only. Defaults to `env_prefix` if not specified. Works in both plain and nested directory modes, like `'/run/secrets/prefix_model__nested'` and `'/run/secrets/prefix_model/nested'`. ## AWS Secrets Manager You must set one parameter: - `secret_id`: The AWS secret id You must have the same naming convention in the key value in secret as in the field name. For example, if the key in secret is named `SqlServerPassword`, the field name must be the same. You can use an alias too. In AWS Secrets Manager, nested models are supported with the `--` separator in the key name. For example, `SqlServer--Password`. Arrays (e.g. `MySecret--0`, `MySecret--1`) are not supported. ```py import os from pydantic import BaseModel from pydantic_settings import ( AWSSecretsManagerSettingsSource, BaseSettings, PydanticBaseSettingsSource, ) class SubModel(BaseModel): a: str class AWSSecretsManagerSettings(BaseSettings): foo: str bar: int sub: SubModel @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: aws_secrets_manager_settings = AWSSecretsManagerSettingsSource( settings_cls, os.environ['AWS_SECRETS_MANAGER_SECRET_ID'], ) return ( init_settings, env_settings, dotenv_settings, file_secret_settings, aws_secrets_manager_settings, ) ``` ## Azure Key Vault You must set two parameters: - `url`: For example, `https://my-resource.vault.azure.net/`. - `credential`: If you use `DefaultAzureCredential`, in local you can execute `az login` to get your identity credentials. The identity must have a role assignment (the recommended one is `Key Vault Secrets User`), so you can access the secrets. You must have the same naming convention in the field name as in the Key Vault secret name. For example, if the secret is named `SqlServerPassword`, the field name must be the same. You can use an alias too. In Key Vault, nested models are supported with the `--` separator. For example, `SqlServer--Password`. Key Vault arrays (e.g. `MySecret--0`, `MySecret--1`) are not supported. ```py import os from azure.identity import DefaultAzureCredential from pydantic import BaseModel from pydantic_settings import ( AzureKeyVaultSettingsSource, BaseSettings, PydanticBaseSettingsSource, ) class SubModel(BaseModel): a: str class AzureKeyVaultSettings(BaseSettings): foo: str bar: int sub: SubModel @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: az_key_vault_settings = AzureKeyVaultSettingsSource( settings_cls, os.environ['AZURE_KEY_VAULT_URL'], DefaultAzureCredential(), ) return ( init_settings, env_settings, dotenv_settings, file_secret_settings, az_key_vault_settings, ) ``` ### Snake case conversion The Azure Key Vault source accepts a `snake_case_conversion` option, disabled by default, to convert Key Vault secret names by mapping them to Python's snake\_case field names, without the need to use aliases. ```py import os from azure.identity import DefaultAzureCredential from pydantic_settings import ( AzureKeyVaultSettingsSource, BaseSettings, PydanticBaseSettingsSource, ) class AzureKeyVaultSettings(BaseSettings): my_setting: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: az_key_vault_settings = AzureKeyVaultSettingsSource( settings_cls, os.environ['AZURE_KEY_VAULT_URL'], DefaultAzureCredential(), snake_case_conversion=True, ) return (az_key_vault_settings,) ``` This setup will load Azure Key Vault secrets (e.g., `MySetting`, `mySetting`, `my-secret` or `MY-SECRET`), mapping them to the snake case version (`my_setting` in this case). ### Dash to underscore mapping The Azure Key Vault source accepts a `dash_to_underscore` option, disabled by default, to support Key Vault kebab-case secret names by mapping them to Python's snake\_case field names. When enabled, dashes (`-`) in secret names are mapped to underscores (`_`) in field names during validation. This mapping applies only to _field names_, not to aliases. Consider snake case conversion if you need aliases or nested fields. ```py import os from azure.identity import DefaultAzureCredential from pydantic import Field from pydantic_settings import ( AzureKeyVaultSettingsSource, BaseSettings, PydanticBaseSettingsSource, ) class AzureKeyVaultSettings(BaseSettings): field_with_underscore: str field_with_alias: str = Field(..., alias='Alias-With-Dashes') @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: az_key_vault_settings = AzureKeyVaultSettingsSource( settings_cls, os.environ['AZURE_KEY_VAULT_URL'], DefaultAzureCredential(), dash_to_underscore=True, ) return (az_key_vault_settings,) ``` This setup will load Azure Key Vault secrets named `field-with-underscore` and `Alias-With-Dashes`, mapping them to the `field_with_underscore` and `field_with_alias` fields, respectively. Tip Alternatively, you can configure an [alias\_generator](/docs/validation/latest/concepts/alias#using-alias-generators) to map PascalCase secrets. ## Google Cloud Secret Manager Google Cloud Secret Manager allows you to store, manage, and access sensitive information as secrets in Google Cloud Platform. This integration lets you retrieve secrets directly from GCP Secret Manager for use in your Pydantic settings. ### Installation The Google Cloud Secret Manager integration requires additional dependencies: Terminal ```bash pip install "pydantic-settings[gcp-secret-manager]" ``` ### Basic Usage To use Google Cloud Secret Manager, you need to: 1. Create a `GoogleSecretManagerSettingsSource`. (See [GCP Authentication](#gcp-authentication) for authentication options.) 2. Add this source to your settings customization pipeline ```py from pydantic import BaseModel from pydantic_settings import ( BaseSettings, GoogleSecretManagerSettingsSource, PydanticBaseSettingsSource, SettingsConfigDict, ) class Database(BaseModel): password: str user: str class Settings(BaseSettings): database: Database model_config = SettingsConfigDict(env_nested_delimiter='__') @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: # Create the GCP Secret Manager settings source gcp_settings = GoogleSecretManagerSettingsSource( settings_cls, # If not provided, will use google.auth.default() # to get credentials from the environemnt # credentials=your_credentials, # If not provided, will use google.auth.default() # to get project_id from the environemnt project_id='your-gcp-project-id', ) return ( init_settings, env_settings, dotenv_settings, file_secret_settings, gcp_settings, ) ``` ### GCP Authentication The `GoogleSecretManagerSettingsSource` supports several authentication methods: 1. **Default credentials** - If you don't provide credentials or project ID, it will use [`google.auth.default()`](https://google-auth.readthedocs.io/en/master/reference/google.auth.html#google.auth.default) to obtain them. This works with: - Service account credentials from `GOOGLE_APPLICATION_CREDENTIALS` environment variable - User credentials from `gcloud auth application-default login` - Compute Engine, GKE, Cloud Run, or Cloud Functions default service accounts 2. **Explicit credentials** - You can also provide `credentials` directly. e.g. `sa_credentials = google.oauth2.service_account.Credentials.from_service_account_file('path/to/service-account.json')` and then `GoogleSecretManagerSettingsSource(credentials=sa_credentials)` ### Nested Models For nested models, Secret Manager supports the `env_nested_delimiter` setting as long as it complies with the [naming rules](https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets#create-a-secret). In the example above, you would create secrets named `database__password` and `database__user` in Secret Manager. ### Secret Versions By default, `GoogleSecretManagerSettingsSource` uses the "latest" version of secrets. You can specify a different version using the `SecretVersion` annotation. ```py from typing import Annotated from pydantic import Field from pydantic_settings import ( BaseSettings, GoogleSecretManagerSettingsSource, PydanticBaseSettingsSource, ) from pydantic_settings.sources.types import SecretVersion class Settings(BaseSettings): # This will use the "latest" version my_secret: str = Field(alias='my-secret') # This will use version "1" my_secret_v1: Annotated[str, Field(alias='my-secret'), SecretVersion('1')] @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return ( GoogleSecretManagerSettingsSource(settings_cls, project_id='my-project'), init_settings, env_settings, dotenv_settings, file_secret_settings, ) ``` Note If you have multiple fields pointing to the same secret (alias) but with different versions, you MUST enable `populate_by_name=True` in `SettingsConfigDict`. ### Important Notes 1. **Case Sensitivity**: By default, secret names are case-sensitive. - If you set `case_sensitive=False`, `pydantic-settings` will attempt to resolve secrets in a case-insensitive manner. It prioritizes exact matches over case-insensitive matches. For some examples of this, imagine `case_sensitive=False` and the model attribute is named `my_secret`: - If Google Secret Manager has both `MY_SECRET` and `my_secret` defined - the value of `my_secret` will be returned. - If Google Secret Manager has `MY_SECRET`, `My_Secret`, and `my_Secret` defined - a warning will be raised and the value of `my_Secret` will be returned - as the secret names are first sorted in ASCII sort order (where lowercased letters are greater than upper case letters) and the last one is chosen (which would be `my_Secret` in this case). 2. **Secret Naming**: Create secrets in Google Secret Manager with names that match your field names (including any prefix). According to the [Secret Manager documentation](https://cloud.google.com/secret-manager/docs/creating-and-accessing-secrets#create-a-secret), a secret name can contain uppercase and lowercase letters, numerals, hyphens, and underscores. The maximum allowed length for a name is 255 characters. For more details on creating and managing secrets in Google Cloud Secret Manager, see the [official Google Cloud documentation](https://cloud.google.com/secret-manager/docs). ## Other settings source Other settings sources are available for common configuration files: - `JsonConfigSettingsSource` using `json_file` and `json_file_encoding` arguments - `PyprojectTomlConfigSettingsSource` using _(optional)_ `pyproject_toml_depth` and _(optional)_ `pyproject_toml_table_header` arguments - `TomlConfigSettingsSource` using `toml_file` argument - `YamlConfigSettingsSource` using `yaml_file` and yaml\_file\_encoding arguments To use them, you can use the same mechanism described [here](#customise-settings-sources). ```py from pydantic import BaseModel from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, TomlConfigSettingsSource, ) class Nested(BaseModel): nested_field: str class Settings(BaseSettings): foobar: str nested: Nested model_config = SettingsConfigDict(toml_file='config.toml') @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (TomlConfigSettingsSource(settings_cls),) ``` This will be able to read the following "config.toml" file, located in your working directory: ```toml foobar = "Hello" [nested] nested_field = "world!" ``` You can also provide multiple files by providing a list of paths. ```py from pydantic import BaseModel from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, TomlConfigSettingsSource, ) class Nested(BaseModel): foo: int bar: int = 0 class Settings(BaseSettings): hello: str nested: Nested model_config = SettingsConfigDict( toml_file=['config.default.toml', 'config.custom.toml'] ) @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (TomlConfigSettingsSource(settings_cls),) ``` The following two configuration files ```toml # config.default.toml hello = "World" [nested] foo = 1 bar = 2 ``` ```toml # config.custom.toml [nested] foo = 3 ``` are equivalent to ```toml hello = "world" [nested] foo = 3 ``` The files are merged shallowly in increasing order of priority. To enable deep merging, set `deep_merge=True` on the source directly. Caution The `deep_merge` option is **not available** through the `SettingsConfigDict`. ```py from pydantic import BaseModel from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, TomlConfigSettingsSource, ) class Nested(BaseModel): foo: int bar: int = 0 class Settings(BaseSettings): hello: str nested: Nested model_config = SettingsConfigDict( toml_file=['config.default.toml', 'config.custom.toml'] ) @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (TomlConfigSettingsSource(settings_cls, deep_merge=True),) ``` With deep merge enabled, the following two configuration files ```toml # config.default.toml hello = "World" [nested] foo = 1 bar = 2 ``` ```toml # config.custom.toml [nested] foo = 3 ``` are equivalent to ```toml hello = "world" [nested] foo = 3 bar = 2 ``` ### pyproject.toml "pyproject.toml" is a standardized file for providing configuration values in Python projects. [PEP 518](https://peps.python.org/pep-0518/#tool-table) defines a `[tool]` table that can be used to provide arbitrary tool configuration. While encouraged to use the `[tool]` table, `PyprojectTomlConfigSettingsSource` can be used to load variables from any location with in "pyproject.toml" file. This is controlled by providing `SettingsConfigDict(pyproject_toml_table_header=tuple[str, ...])` where the value is a tuple of header parts. By default, `pyproject_toml_table_header=('tool', 'pydantic-settings')` which will load variables from the `[tool.pydantic-settings]` table. ```python from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, PyprojectTomlConfigSettingsSource, SettingsConfigDict, ) class Settings(BaseSettings): """Example loading values from the table used by default.""" field: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (PyprojectTomlConfigSettingsSource(settings_cls),) class SomeTableSettings(Settings): """Example loading values from a user defined table.""" model_config = SettingsConfigDict( pyproject_toml_table_header=('tool', 'some-table') ) class RootSettings(Settings): """Example loading values from the root of a pyproject.toml file.""" model_config = SettingsConfigDict(extra='ignore', pyproject_toml_table_header=()) ``` This will be able to read the following "pyproject.toml" file, located in your working directory, resulting in `Settings(field='default-table')`, `SomeTableSettings(field='some-table')`, & `RootSettings(field='root')`: ```toml field = "root" [tool.pydantic-settings] field = "default-table" [tool.some-table] field = "some-table" ``` By default, `PyprojectTomlConfigSettingsSource` will only look for a "pyproject.toml" in the your current working directory. However, there are two options to change this behavior. - `SettingsConfigDict(pyproject_toml_depth=)` can be provided to check `` number of directories **up** in the directory tree for a "pyproject.toml" if one is not found in the current working directory. By default, no parent directories are checked. - An explicit file path can be provided to the source when it is instantiated (e.g. `PyprojectTomlConfigSettingsSource(settings_cls, Path('~/.config').resolve() / 'pyproject.toml')`). If a file path is provided this way, it will be treated as absolute (no other locations are checked). ```python from pathlib import Path from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, PyprojectTomlConfigSettingsSource, SettingsConfigDict, ) class DiscoverSettings(BaseSettings): """Example of discovering a pyproject.toml in parent directories in not in `Path.cwd()`.""" model_config = SettingsConfigDict(pyproject_toml_depth=2) @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return (PyprojectTomlConfigSettingsSource(settings_cls),) class ExplicitFilePathSettings(BaseSettings): """Example of explicitly providing the path to the file to load.""" field: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return ( PyprojectTomlConfigSettingsSource( settings_cls, Path('~/.config').resolve() / 'pyproject.toml' ), ) ``` ## Field value priority In the case where a value is specified for the same `Settings` field in multiple ways, the selected value is determined as follows (in descending order of priority): 1. If `cli_parse_args` is enabled, arguments passed in at the CLI. 2. Arguments passed to the `Settings` class initialiser. 3. Environment variables, e.g. `my_prefix_special_function` as described above. 4. Variables loaded from a dotenv (`.env`) file. 5. Variables loaded from the secrets directory. 6. The default field values for the `Settings` model. ## Customise settings sources If the default order of priority doesn't match your needs, it's possible to change it by overriding the `settings_customise_sources` method of your `Settings` . `settings_customise_sources` takes four callables as arguments and returns any number of callables as a tuple. In turn these callables are called to build the inputs to the fields of the settings class. Each callable should take an instance of the settings class as its sole argument and return a `dict`. ### Changing Priority The order of the returned callables decides the priority of inputs; first item is the highest priority. ```py from pydantic import PostgresDsn from pydantic_settings import BaseSettings, PydanticBaseSettingsSource class Settings(BaseSettings): database_dsn: PostgresDsn @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return env_settings, init_settings, file_secret_settings print(Settings(database_dsn='postgres://postgres@localhost:5432/kwargs_db')) #> database_dsn=PostgresDsn('postgres://postgres@localhost:5432/kwargs_db') ``` By flipping `env_settings` and `init_settings`, environment variables now have precedence over `__init__` kwargs. ### Adding sources As explained earlier, _pydantic_ ships with multiples built-in settings sources. However, you may occasionally need to add your own custom sources, `settings_customise_sources` makes this very easy: ```py import json from pathlib import Path from typing import Any from pydantic.fields import FieldInfo from pydantic_settings import ( BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict, ) class JsonConfigSettingsSource(PydanticBaseSettingsSource): """ A simple settings source class that loads variables from a JSON file at the project's root. Here we happen to choose to use the `env_file_encoding` from Config when reading `config.json` """ def get_field_value( self, field: FieldInfo, field_name: str ) -> tuple[Any, str, bool]: encoding = self.config.get('env_file_encoding') file_content_json = json.loads( Path('tests/example_test_config.json').read_text(encoding) ) field_value = file_content_json.get(field_name) return field_value, field_name, False def prepare_field_value( self, field_name: str, field: FieldInfo, value: Any, value_is_complex: bool ) -> Any: return value def __call__(self) -> dict[str, Any]: d: dict[str, Any] = {} for field_name, field in self.settings_cls.model_fields.items(): field_value, field_key, value_is_complex = self.get_field_value( field, field_name ) field_value = self.prepare_field_value( field_name, field, field_value, value_is_complex ) if field_value is not None: d[field_key] = field_value return d class Settings(BaseSettings): model_config = SettingsConfigDict(env_file_encoding='utf-8') foobar: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: return ( init_settings, JsonConfigSettingsSource(settings_cls), env_settings, file_secret_settings, ) print(Settings()) #> foobar='test' ``` #### Accessing the result of previous sources Each source of settings can access the output of the previous ones. ```python from typing import Any from pydantic.fields import FieldInfo from pydantic_settings import PydanticBaseSettingsSource class MyCustomSource(PydanticBaseSettingsSource): def get_field_value( self, field: FieldInfo, field_name: str ) -> tuple[Any, str, bool]: ... def __call__(self) -> dict[str, Any]: # Retrieve the aggregated settings from previous sources current_state = self.current_state current_state.get('some_setting') # Retrive settings from all sources individually # self.settings_sources_data["SettingsSourceName"]: dict[str, Any] settings_sources_data = self.settings_sources_data settings_sources_data['SomeSettingsSource'].get('some_setting') # Your code here... ``` ### Removing sources You might also want to disable a source: ```py from pydantic import ValidationError from pydantic_settings import BaseSettings, PydanticBaseSettingsSource class Settings(BaseSettings): my_api_key: str @classmethod def settings_customise_sources( cls, settings_cls: type[BaseSettings], init_settings: PydanticBaseSettingsSource, env_settings: PydanticBaseSettingsSource, dotenv_settings: PydanticBaseSettingsSource, file_secret_settings: PydanticBaseSettingsSource, ) -> tuple[PydanticBaseSettingsSource, ...]: # here we choose to ignore arguments from init_settings return env_settings, file_secret_settings try: Settings(my_api_key='this is ignored') except ValidationError as exc_info: print(exc_info) """ 1 validation error for Settings my_api_key Field required [type=missing, input_value={}, input_type=dict] For further information visit https://errors.pydantic.dev/2/v/missing """ ``` ## In-place reloading In case you want to reload in-place an existing setting, you can do it by using its `__init__` method : ```py import os from pydantic import Field from pydantic_settings import BaseSettings class Settings(BaseSettings): foo: str = Field('foo') mutable_settings = Settings() print(mutable_settings.foo) #> foo os.environ['foo'] = 'bar' print(mutable_settings.foo) #> foo mutable_settings.__init__() print(mutable_settings.foo) #> bar os.environ.pop('foo') mutable_settings.__init__() print(mutable_settings.foo) #> foo ``` --- # [Serialization](https://pydantic.dev/docs/validation/latest/concepts/serialization/) # Serialization Beyond accessing model attributes directly via their field names (e.g. `model.foobar`), models can be converted, dumped, serialized, and exported in a number of ways. Serialization can be customized for the whole model, or on a per-field or per-type basis. Serialize versus dump Pydantic uses the terms "serialize" and "dump" interchangeably. Both refer to the process of converting a model to a dictionary or JSON-encoded string. Outside of Pydantic, the word "serialize" usually refers to converting in-memory data into a string or bytes. However, in the context of Pydantic, there is a very close relationship between converting an object from a more structured form -- such as a Pydantic model, a dataclass, etc. -- into a less structured form comprised of Python built-ins such as dict. While we could (and on occasion, do) distinguish between these scenarios by using the word "dump" when converting to primitives and "serialize" when converting to string, for practical purposes, we frequently use the word "serialize" to refer to both of these situations, even though it does not always imply conversion to a string or bytes. Tip Want to quickly jump to the relevant serializer section? - Field serializer * * * - [field _plain_ serializer](#field-plain-serializer) - [field _wrap_ serializer](#field-wrap-serializer) - Model serializer * * * - [model _plain_ serializer](#model-plain-serializer) - [model _wrap_ serializer](#model-wrap-serializer) ## Serializing data Pydantic allows models (and any other type using [type adapters](/docs/validation/latest/concepts/type_adapter)) to be serialized in _two_ modes: [Python](#python-mode) and [JSON](#json-mode). The Python output may contain non-JSON serializable data (although this can be emulated). ### Python mode When using the Python mode, Pydantic models (and model-like types such as [dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses)) will be (recursively) converted to dictionaries. This is achievable by using the [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) method: With the exception of [root models](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types), where the root value is dumped directly. ```python from typing import Optional from pydantic import BaseModel, Field class BarModel(BaseModel): whatever: tuple[int, ...] class FooBarModel(BaseModel): banana: Optional[float] = 1.1 foo: str = Field(serialization_alias='foo_alias') bar: BarModel m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': (1, 2)}) # returns a dictionary: print(m.model_dump()) #> {'banana': 3.14, 'foo': 'hello', 'bar': {'whatever': (1, 2)}} print(m.model_dump(by_alias=True)) #> {'banana': 3.14, 'foo_alias': 'hello', 'bar': {'whatever': (1, 2)}} ``` Notice that the value of `whatever` was dumped as tuple, which isn't a known JSON type. The `mode` argument can be set to `'json'` to ensure JSON-compatible types are used: ```python print(m.model_dump(mode='json')) #> {'banana': 3.14, 'foo': 'hello', 'bar': {'whatever': [1, 2]}} ``` See also The [`TypeAdapter.dump_python()`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_python) method, useful when _not_ dealing with Pydantic models. ### JSON mode Pydantic allows data to be serialized directly to a JSON-encoded string, by trying its best to convert Python values to valid JSON data. This is achievable by using the [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) method: ```python from datetime import datetime from pydantic import BaseModel class BarModel(BaseModel): whatever: tuple[int, ...] class FooBarModel(BaseModel): foo: datetime bar: BarModel m = FooBarModel(foo=datetime(2032, 6, 1, 12, 13, 14), bar={'whatever': (1, 2)}) print(m.model_dump_json(indent=2)) ``` **JSON output:** ```json { "foo": "2032-06-01T12:13:14", "bar": { "whatever": [ 1, 2 ] } } ``` In addition to the [supported types](https://docs.python.org/3/library/json.html#json.JSONEncoder) by the standard library [`json`](https://docs.python.org/3/library/json.html#module-json) module, Pydantic supports a wide variety of types ([date and time types](https://docs.python.org/3/library/datetime.html#module-datetime), [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) objects, [sets](https://docs.python.org/3/reference/expressions.html#set), etc). If an unsupported type is used and can't be serialized to JSON, a [`PydanticSerializationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticSerializationError) exception is raised. See also The [`TypeAdapter.dump_json()`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_json) method, useful when _not_ dealing with Pydantic models. ## Iterating over models Pydantic models can also be iterated over, yielding `(field_name, field_value)` pairs. Note that field values are left as is, so sub-models will _not_ be converted to dictionaries: ```python from pydantic import BaseModel class BarModel(BaseModel): whatever: int class FooBarModel(BaseModel): banana: float foo: str bar: BarModel m = FooBarModel(banana=3.14, foo='hello', bar={'whatever': 123}) for name, value in m: print(f'{name}: {value}') #> banana: 3.14 #> foo: hello #> bar: whatever=123 ``` This means that calling [`dict()`](https://docs.python.org/3/reference/expressions.html#dict) on a model can be used to construct a dictionary of the model: ```python print(dict(m)) #> {'banana': 3.14, 'foo': 'hello', 'bar': BarModel(whatever=123)} ``` Note [Root models](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types) _does_ get converted to a dictionary with the key `'root'`. ## Pickling support Pydantic models support efficient pickling and unpickling. ```python import pickle from pydantic import BaseModel class FooBarModel(BaseModel): a: str b: int m = FooBarModel(a='hello', b=123) print(m) #> a='hello' b=123 data = pickle.dumps(m) print(data[:20]) #> b'\x80\x04\x95\x95\x00\x00\x00\x00\x00\x00\x00\x8c\x08__main_' m2 = pickle.loads(data) print(m2) #> a='hello' b=123 ``` ## Serializers Similar to [custom validators](/docs/validation/latest/concepts/validators), you can leverage custom serializers at the field and model levels to further control the serialization behavior. Caution Only _one_ serializer can be defined per field/model. It is not possible to combine multiple serializers together (including _plain_ and _wrap_ serializers). ### Field serializers API Documentation [`pydantic.functional_serializers.PlainSerializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.PlainSerializer) [`pydantic.functional_serializers.WrapSerializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.WrapSerializer) [`pydantic.functional_serializers.field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.field_serializer) In its simplest form, a field serializer is a callable taking the value to be serialized as an argument and **returning the serialized value**. If the `return_type` argument is provided to the serializer (or if a return type annotation is available on the serializer function), it will be used to build an extra serializer, to ensure that the serialized field value complies with this return type. **Two** different types of serializers can be used. They can all be defined using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) or using the [`@field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.field_serializer) decorator, applied on instance or [static methods](https://docs.python.org/3/library/functions.html#staticmethod). - **_Plain_ serializers**: are called unconditionally to serialize a field. The serialization logic for types supported by Pydantic will _not_ be called. Using such serializers is also useful to specify the logic for arbitrary types. - [Annotated pattern](#tab-panel-578) - [Decorator](#tab-panel-579) ```python from typing import Annotated, Any from pydantic import BaseModel, PlainSerializer def ser_number(value: Any) -> Any: if isinstance(value, int): return value * 2 else: return value class Model(BaseModel): number: Annotated[int, PlainSerializer(ser_number)] print(Model(number=4).model_dump()) #> {'number': 8} m = Model(number=1) m.number = 'invalid' print(m.model_dump()) # (1) #> {'number': 'invalid'} ``` Pydantic will _not_ validate that the serialized value complies with the `int` type. ```python from typing import Any from pydantic import BaseModel, field_serializer class Model(BaseModel): number: int @field_serializer('number', mode='plain') # (1) def ser_number(self, value: Any) -> Any: if isinstance(value, int): return value * 2 else: return value print(Model(number=4).model_dump()) #> {'number': 8} m = Model(number=1) m.number = 'invalid' print(m.model_dump()) # (2) #> {'number': 'invalid'} ``` `'plain'` is the default mode for the decorator, and can be omitted. Pydantic will _not_ validate that the serialized value complies with the `int` type. - **_Wrap_ serializers**: give more flexibility to customize the serialization behavior. You can run code before or after the Pydantic serialization logic. Such serializers must be defined with a **mandatory** extra _handler_ parameter: a callable taking the value to be serialized as an argument. Internally, this handler will delegate serialization of the value to Pydantic. You are free to _not_ call the handler at all. - [Annotated pattern](#tab-panel-576) - [Decorator](#tab-panel-577) ```python from typing import Annotated, Any from pydantic import BaseModel, SerializerFunctionWrapHandler, WrapSerializer def ser_number(value: Any, handler: SerializerFunctionWrapHandler) -> int: return handler(value) + 1 class Model(BaseModel): number: Annotated[int, WrapSerializer(ser_number)] print(Model(number=4).model_dump()) #> {'number': 5} ``` ```python from typing import Any from pydantic import BaseModel, SerializerFunctionWrapHandler, field_serializer class Model(BaseModel): number: int @field_serializer('number', mode='wrap') def ser_number( self, value: Any, handler: SerializerFunctionWrapHandler ) -> int: return handler(value) + 1 print(Model(number=4).model_dump()) #> {'number': 5} ``` #### Which serializer pattern to use While both approaches can achieve the same thing, each pattern provides different benefits. ##### Using the annotated pattern One of the key benefits of using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) is to make serializers reusable: ```python from typing import Annotated from pydantic import BaseModel, Field, PlainSerializer DoubleNumber = Annotated[int, PlainSerializer(lambda v: v * 2)] class Model1(BaseModel): my_number: DoubleNumber class Model2(BaseModel): other_number: Annotated[DoubleNumber, Field(description='My other number')] class Model3(BaseModel): list_of_even_numbers: list[DoubleNumber] # (1) ``` As mentioned in the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) documentation, we can also make use of serializers for specific parts of the annotation (in this case, serialization is applied for list items, but not the whole list). It is also easier to understand which serializers are applied to a type, by just looking at the field annotation. ##### Using the decorator pattern One of the key benefits of using the [`@field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.field_serializer) decorator is to apply the function to multiple fields: ```python from pydantic import BaseModel, field_serializer class Model(BaseModel): f1: str f2: str @field_serializer('f1', 'f2', mode='plain') def capitalize(self, value: str) -> str: return value.capitalize() ``` Here are a couple additional notes about the decorator usage: - If you want the serializer to apply to all fields (including the ones defined in subclasses), you can pass `'*'` as the field name argument. - By default, the decorator will ensure the provided field name(s) are defined on the model. If you want to disable this check during class creation, you can do so by passing `False` to the `check_fields` argument. This is useful when the field serializer is defined on a base class, and the field is expected to exist on subclasses. ### Model serializers API Documentation [`pydantic.functional_serializers.model_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.model_serializer) Serialization can also be customized on the entire model using the [`@model_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.model_serializer) decorator. If the `return_type` argument is provided to the [`@model_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.model_serializer) decorator (or if a return type annotation is available on the serializer function), it will be used to build an extra serializer, to ensure that the serialized model value complies with this return type. As with [field serializers](#field-serializers), **two** different types of model serializers can be used: - **_Plain_ serializers**: are called unconditionally to serialize the model. ```python from pydantic import BaseModel, model_serializer class UserModel(BaseModel): username: str password: str @model_serializer(mode='plain') # (1) def serialize_model(self) -> str: # (2) return f'{self.username} - {self.password}' print(UserModel(username='foo', password='bar').model_dump()) #> foo - bar ``` `'plain'` is the default mode for the decorator, and can be omitted. You are free to return a value that _isn't_ a dictionary. - **_Wrap_ serializers**: give more flexibility to customize the serialization behavior. You can run code before or after the Pydantic serialization logic. Such serializers must be defined with a **mandatory** extra _handler_ parameter: a callable taking the instance of the model as an argument. Internally, this handler will delegate serialization of the model to Pydantic. You are free to _not_ call the handler at all. ```python from pydantic import BaseModel, SerializerFunctionWrapHandler, model_serializer class UserModel(BaseModel): username: str password: str @model_serializer(mode='wrap') def serialize_model( self, handler: SerializerFunctionWrapHandler ) -> dict[str, object]: serialized = handler(self) serialized['fields'] = list(serialized) return serialized print(UserModel(username='foo', password='bar').model_dump()) #> {'username': 'foo', 'password': 'bar', 'fields': ['username', 'password']} ``` ## Serialization info Both the field and model serializers callables (in all modes) can optionally take an extra `info` argument, providing useful extra information, such as: - [user defined context](#serialization-context) - the current serialization mode: either `'python'` or `'json'` (see the [`mode`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.mode) property) - the various parameters set during serialization using the [serialization methods](#serializing-data) (e.g. [`exclude_unset`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.exclude_unset), [`serialize_as_any`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.serialize_as_any)) - the current field name, if using a [field serializer](#field-serializers) (see the [`field_name`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.FieldSerializationInfo.field_name) property). ### Serialization context You can pass a context object to the [serialization methods](#serializing-data), which can be accessed inside the serializer functions using the [`context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.SerializationInfo.context) property: ```python from pydantic import BaseModel, FieldSerializationInfo, field_serializer class Model(BaseModel): text: str @field_serializer('text', mode='plain') @classmethod def remove_stopwords(cls, v: str, info: FieldSerializationInfo) -> str: if isinstance(info.context, dict): stopwords = info.context.get('stopwords', set()) v = ' '.join(w for w in v.split() if w.lower() not in stopwords) return v model = Model(text='This is an example document') print(model.model_dump()) # no context #> {'text': 'This is an example document'} print(model.model_dump(context={'stopwords': ['this', 'is', 'an']})) #> {'text': 'example document'} ``` Similarly, you can [use a context for validation](/docs/validation/latest/concepts/validators#validation-context). ## Serializing subclasses ### Subclasses of supported types Subclasses of supported types are serialized according to their super class: ```python from datetime import date from pydantic import BaseModel class MyDate(date): @property def my_date_format(self) -> str: return self.strftime('%d/%m/%Y') class FooModel(BaseModel): date: date m = FooModel(date=MyDate(2023, 1, 1)) print(m.model_dump_json()) #> {"date":"2023-01-01"} ``` ### Subclasses of model-like types When using model-like classes (Pydantic models, [dataclasses](/docs/validation/latest/concepts/dataclasses), etc.) as field annotations, the default behavior is to serialize the field value as though it was an instance of the class used as the annotation, even if it is a subclass. More specifically, only the fields declared on the type annotation will be included in the serialization result: ```python from pydantic import BaseModel class User(BaseModel): name: str class UserLogin(User): password: str class OuterModel(BaseModel): user: User user = UserLogin(name='pydantic', password='hunter2') m = OuterModel(user=user) print(m) #> user=UserLogin(name='pydantic', password='hunter2') print(m.model_dump()) # (1) #> {'user': {'name': 'pydantic'}} ``` Note: the password field is not included Migration Warning This behavior is different from how things worked in Pydantic V1, where we would always include all (subclass) fields when recursively serializing models to dictionaries. The motivation behind this change in behavior is that it helps ensure that you know precisely which fields could be included when serializing, even if subclasses get passed when instantiating the object. In particular, this can help prevent surprises when adding sensitive information like secrets as fields of subclasses. To enable the old V1 behavior, refer to the next section. ### Polymorphic serialization ✦ New in v2.13 Polymorphic serialization was added as an better alternative to the [serialize as any](#serializing-as-any) behavior, and only applies to Pydantic models and Pydantic dataclasses. Polymorphic serialization is the behavior of serializing a model (or [Pydantic dataclass](/docs/validation/latest/concepts/dataclasses)) instance according to the serialization schema of such instance, rather that the schema of the class used as the type. This will expose all the data defined on the subclass in the serialized payload. This behavior can be configured in the following ways: - Configuration level: use the [`polymorphic_serialization`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.polymorphic_serialization) setting in the model/dataclass [configuration](/docs/validation/latest/concepts/config). - Runtime level: use the `polymorphic_serialization` argument when calling the [serialization methods](#serializing-data). This will apply to all (nested) types, overriding any configuration. Duck-typed serialization This behavior (and the ["any" serialization](#serializing-as-any) discussed below) was previously referred to as duck-typed serialization. This was a misnomer; it did not function like [duck typing](https://en.wikipedia.org/wiki/Duck_typing) in the conventional programming language sense. Polymorphic serialization of standard library dataclasses Polymorphic serialization is only supported for Pydantic models and [Pydantic dataclasses](/docs/validation/latest/concepts/dataclasses). When using [standard library dataclasses](https://docs.python.org/3/library/dataclasses.html#module-dataclasses), polymorphic serialization is _not_ supported, even if the dataclass is a subclass of a Pydantic dataclass. This may be fixed in a future Pydantic release. The example below defines a type `User` and a subclass of it, `UserLogin`. A second pair of types, `PolymorphicUser` and `PolymorphicUserLogin` are defined as equivalents with `polymorphic_serialization` enabled. We can then see the effect of serializing each of these types, and the interaction of this config with the runtime `polymorphic_serialization` setting: ```python from pydantic import BaseModel class User(BaseModel): name: str class UserLogin(User): password: str class OuterModel(BaseModel): user: User outer_model = OuterModel( user=UserLogin(name='pydantic', password='password'), ) print(outer_model.model_dump()) # (1) #> {'user': {'name': 'pydantic'}} print(outer_model.model_dump(polymorphic_serialization=True)) # (2) #> {'user': {'name': 'pydantic', 'password': 'password'}} ``` With polymorphic serialization disabled, `user` serializes as the base type. With polymorphic serialization enabled, `user` serializes as the actual runtime subclass. As seen in the example, by having polymorphic serialization enabled, the `User.model_dump()` method will by respect the value of the `UserLogin` subclass when it is provided instead of a `User` value, and serialize the full `UserLogin` type. This behavior can be globally overridden with the `polymorphic_serialization` runtime setting; in this case setting it to `False` causes the `UserLogin` value to serialize just as a `User` value, ignoring the subclass' `password` field. ## Serializing "as Any" A more extreme form of [polymorphic serialization](#polymorphic-serialization) is "any" serialization. In this mode, Pydantic does _not_ make use of any type annotation (more precisely, the serialization schema derived from the type) to infer how the value should be serialized, but instead inspects the actual type of the value at runtime to do so (and this applies to _all_ types, not only Pydantic models and dataclasses). This means that every value will be serialized exactly based on its runtime type and any knowledge Pydantic has of how to serialize the type. Pydantic can infer how to serialize the following types: - Many Python standard library types (exact set may be expanded depending on Pydantic version). - Types with a `__pydantic_serializer__` attribute. - Any type serializable with the `fallback` function passed as an argument to [serialization methods](#serializing-data). In most cases, you will want to use the [polymorphic serialization](#polymorphic-serialization) behavior instead. This behavior can be configured at the field level and at runtime, for a specific serialization call: - Field level: use the [`SerializeAsAny`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.SerializeAsAny) annotation. - Runtime level: use the `serialize_as_any` argument when calling the [serialization methods](#serializing-data). These options are discussed below in more detail. ### `SerializeAsAny` annotation If you want duck typing serialization behavior, this can be done using the [`SerializeAsAny`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.SerializeAsAny) annotation on a type: ```python from pydantic import BaseModel, SerializeAsAny class User(BaseModel): name: str class UserLogin(User): password: str class OuterModel(BaseModel): as_any: SerializeAsAny[User] as_user: User user = UserLogin(name='pydantic', password='password') print(OuterModel(as_any=user, as_user=user).model_dump()) """ { 'as_any': {'name': 'pydantic', 'password': 'password'}, 'as_user': {'name': 'pydantic'}, } """ ``` When a type is annotated as `SerializeAsAny[]`, the validation behavior will be the same as if it was annotated as ``, and static type checkers will treat the annotation as if it was simply ``. When serializing, the field will be serialized as though the type hint for the field was [`Any`](https://docs.python.org/3/library/typing.html#typing.Any), which is where the name comes from. ### `serialize_as_any` runtime setting The `serialize_as_any` runtime setting can be used to serialize model data with or without duck typed serialization behavior. `serialize_as_any` can be passed as a keyword argument to the various [serialization methods](#serializing-data) (such as [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump) and [`model_dump_json()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump_json) on Pydantic models). ```python from pydantic import BaseModel class User(BaseModel): name: str class UserLogin(User): password: str class OuterModel(BaseModel): user1: User user2: User user = UserLogin(name='pydantic', password='password') outer_model = OuterModel(user1=user, user2=user) print(outer_model.model_dump(serialize_as_any=True)) # (1) """ { 'user1': {'name': 'pydantic', 'password': 'password'}, 'user2': {'name': 'pydantic', 'password': 'password'}, } """ print(outer_model.model_dump(serialize_as_any=False)) # (2) #> {'user1': {'name': 'pydantic'}, 'user2': {'name': 'pydantic'}} ``` With `serialize_as_any` set to `True`, the result matches that of V1. With `serialize_as_any` set to `False` (the V2 default), fields present on the subclass, but not the base class, are not included in serialization. However, do note that the _serialize as any_ behavior will apply to _all_ values, not only the values where duck typing is relevant. You may want to prefer using the `SerializeAsAny` annotation when required instead. ## Field inclusion and exclusion For serialization, field inclusion and exclusion can be configured in two ways: - at the field level, using the `exclude` and `exclude_if` parameters on [the `Field()` function](/docs/validation/latest/concepts/fields). - using the various serialization parameters on the [serialization methods](#serializing-data). ### At the field level At the field level, the `exclude` and `exclude_if` parameters can be used: ```python from pydantic import BaseModel, Field class Transaction(BaseModel): id: int private_id: int = Field(exclude=True) value: int = Field(ge=0, exclude_if=lambda v: v == 0) print(Transaction(id=1, private_id=2, value=0).model_dump()) #> {'id': 1} ``` Exclusion at the field level takes priority over the `include` serialization parameter described below. ### As parameters to the serialization methods When using the [serialization methods](#serializing-data) (such as [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump)), several parameters can be used to exclude or include fields. #### Excluding and including specific fields Consider the following models: ```python from pydantic import BaseModel, Field, SecretStr class User(BaseModel): id: int username: str password: SecretStr class Transaction(BaseModel): id: str private_id: str = Field(exclude=True) user: User value: int t = Transaction( id='1234567890', private_id='123', user=User(id=42, username='JohnDoe', password='hashedpassword'), value=9876543210, ) ``` The `exclude` parameter can be used to specify which fields should be excluded (including the others), and vice-versa using the `include` parameter. ```python # using a set: print(t.model_dump(exclude={'user', 'value'})) #> {'id': '1234567890'} # using a dictionary: print(t.model_dump(exclude={'user': {'username', 'password'}, 'value': True})) #> {'id': '1234567890', 'user': {'id': 42}} # same configuration using `include`: print(t.model_dump(include={'id': True, 'user': {'id'}})) #> {'id': '1234567890', 'user': {'id': 42}} ``` Note that using `False` to _include_ a field in `exclude` (or to _exclude_ a field in `include`) is not supported. It is also possible to exclude or include specific items from sequence and dictionaries: ```python from pydantic import BaseModel class Hobby(BaseModel): name: str info: str class User(BaseModel): hobbies: list[Hobby] user = User( hobbies=[ Hobby(name='Programming', info='Writing code and stuff'), Hobby(name='Gaming', info='Hell Yeah!!!'), ], ) print(user.model_dump(exclude={'hobbies': {-1: {'info'}}})) # (1) """ { 'hobbies': [ {'name': 'Programming', 'info': 'Writing code and stuff'}, {'name': 'Gaming'}, ] } """ ``` The equivalent call with `include` would be: ```python user.model_dump( include={'hobbies': {0: True, -1: {'name'}}} ) ``` The special key `'__all__'` can be used to apply an exclusion/inclusion pattern to all members: ```python print(user.model_dump(exclude={'hobbies': {'__all__': {'info'}}})) #> {'hobbies': [{'name': 'Programming'}, {'name': 'Gaming'}]} ``` #### Excluding and including fields based on their value When using the [serialization methods](#serializing-data), it is possible to exclude fields based on their value, using the following parameters: - `exclude_defaults`: Exclude all fields whose value compares equal to the default value (using the equality (`==`) comparison operator). - `exclude_none`: Exclude all fields whose value is `None`. - `exclude_unset`: Pydantic keeps track of fields that were _explicitly_ set during instantiation (using the [`model_fields_set`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields_set) property). Using `exclude_unset`, any field that was not explicitly provided will be excluded: ```python from pydantic import BaseModel class UserModel(BaseModel): name: str age: int = 18 user = UserModel(name='John') print(user.model_fields_set) #> {'name'} print(user.model_dump(exclude_unset=True)) #> {'name': 'John'} ``` Note that altering a field _after_ the instance has been created will remove it from the unset fields: ```python user.age = 21 print(user.model_dump(exclude_unset=True)) #> {'name': 'John', 'age': 21} ``` Tip The experimental [`MISSING` sentinel](/docs/validation/latest/concepts/experimental#missing-sentinel) can be used as an alternative to `exclude_unset`. Any field with `MISSING` as a value is automatically excluded from the serialization output. --- # [Strict Mode](https://pydantic.dev/docs/validation/latest/concepts/strict_mode/) # Strict Mode API Documentation [`pydantic.types.Strict`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Strict) By default, Pydantic will attempt to coerce values to the desired type when possible. For example, you can pass the string `'123'` as the input for the [`int` number type](/docs/validation/latest/api/pydantic/standard_library_types#integers), and it will be converted to the value `123`. This coercion behavior is useful in many scenarios -- think: UUIDs, URL parameters, HTTP headers, environment variables, dates, etc. However, there are also situations where this is not desirable, and you want Pydantic to error instead of coercing data. To better support this use case, Pydantic provides a "strict mode". When strict mode is enabled, Pydantic will be much less lenient when coercing data, and will instead error if the data is not of the correct type. Most of the time, strict mode will only allow instances of the type to be provided, although looser rules may apply to JSON input (for instance, the [date and time types](/docs/validation/latest/api/pydantic/standard_library_types#date-and-time-types) allow strings even in strict mode). The strict behavior for each type can be found in the [standard library types](/docs/validation/latest/api/pydantic/standard_library_types) documentation, and is summarized in the [conversion table](/docs/validation/latest/concepts/conversion_table). Here is a brief example showing the validation behavior difference in strict and the default lax mode: ```python from pydantic import BaseModel, ValidationError class MyModel(BaseModel): x: int print(MyModel.model_validate({'x': '123'})) # lax mode #> x=123 try: MyModel.model_validate({'x': '123'}, strict=True) # strict mode except ValidationError as exc: print(exc) """ 1 validation error for MyModel x Input should be a valid integer [type=int_type, input_value='123', input_type=str] """ ``` Strict mode can be enabled in various ways: - [As a validation parameter](#as-a-validation-parameter), such as when using [`model_validate()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate), on Pydantic models. - [At the field level](#at-the-field-level). - [At the configuration level](#as-a-configuration-value) (with the possibility to override at the field level). ## As a validation parameter Strict mode can be enaled on a per-validation-call basis, when using the [validation methods](/docs/validation/latest/concepts/models#validating-data) on [Pydantic models](/docs/validation/latest/concepts/models) and [type adapters](/docs/validation/latest/concepts/type_adapter). ```python from datetime import date from pydantic import TypeAdapter, ValidationError print(TypeAdapter(date).validate_python('2000-01-01')) # OK: lax #> 2000-01-01 try: # Not OK: strict: TypeAdapter(date).validate_python('2000-01-01', strict=True) except ValidationError as exc: print(exc) """ 1 validation error for date Input should be a valid date [type=date_type, input_value='2000-01-01', input_type=str] """ TypeAdapter(date).validate_json('"2000-01-01"', strict=True) # (1) #> 2000-01-01 ``` As mentioned, strict mode is looser when validating from JSON. ## At the field level Strict mode can be enabled on specific fields, by setting the `strict` parameter of the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function to `True`. Strict mode will be applied for such fields, even when the [validation methods](/docs/validation/latest/concepts/models#validating-data) are called in lax mode. ```python from pydantic import BaseModel, Field, ValidationError class User(BaseModel): name: str age: int = Field(strict=True) # (1) user = User(name='John', age=42) print(user) #> name='John' age=42 try: another_user = User(name='John', age='42') except ValidationError as e: print(e) """ 1 validation error for User age Input should be a valid integer [type=int_type, input_value='42', input_type=str] """ ``` The strict constraint can also be applied using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern): `Annotated[int, Field(strict=True)]` ### Using the `Strict()` metadata class API Documentation [`pydantic.types.Strict`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Strict) As an alternative to the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function, Pydantic provides the [`Strict`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Strict) metadata class, meant to be used with the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern). It also provides convenience aliases for the most common types (namely [`StrictBool`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictBool), [`StrictInt`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictInt), [`StrictFloat`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictFloat), [`StrictStr`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictStr) and [`StrictBytes`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StrictBytes)). ```python from typing import Annotated from uuid import UUID from pydantic import BaseModel, Strict, StrictInt class User(BaseModel): id: Annotated[UUID, Strict()] age: StrictInt # (1) ``` Equivalent to `Annotated[int, Strict()]`. ## As a configuration value Strict mode behavior can be controlled at the [configuration](/docs/validation/latest/concepts/config) level. When used on a Pydantic model (or model like class such as [dataclasses](/docs/validation/latest/concepts/dataclasses)), strictness can still be overridden at the [field level](#at-the-field-level): ```python from pydantic import BaseModel, ConfigDict, Field class User(BaseModel): model_config = ConfigDict(strict=True) name: str age: int = Field(strict=False) print(User(name='John', age='18')) #> name='John' age=18 ``` --- # [Type Adapter](https://pydantic.dev/docs/validation/latest/concepts/type_adapter/) # Type Adapter You may have types that are not `BaseModel`s that you want to validate data against. Or you may want to validate a `list[SomeModel]`, or dump it to JSON. API Documentation [`pydantic.type_adapter.TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) For use cases like this, Pydantic provides [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter), which can be used for type validation, serialization, and JSON schema generation without needing to create a [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). A [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) instance exposes some of the functionality from [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) instance methods for types that do not have such methods (such as dataclasses, primitive types, and more): ```python from typing_extensions import TypedDict from pydantic import TypeAdapter, ValidationError class User(TypedDict): name: str id: int user_list_adapter = TypeAdapter(list[User]) user_list = user_list_adapter.validate_python([{'name': 'Fred', 'id': '3'}]) print(repr(user_list)) #> [{'name': 'Fred', 'id': 3}] try: user_list_adapter.validate_python( [{'name': 'Fred', 'id': 'wrong', 'other': 'no'}] ) except ValidationError as e: print(e) """ 1 validation error for list[User] 0.id Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='wrong', input_type=str] """ print(repr(user_list_adapter.dump_json(user_list))) #> b'[{"name":"Fred","id":3}]' ``` `dump_json` returns `bytes` `TypeAdapter`'s `dump_json` methods returns a `bytes` object, unlike the corresponding method for `BaseModel`, `model_dump_json`, which returns a `str`. The reason for this discrepancy is that in V1, model dumping returned a str type, so this behavior is retained in V2 for backwards compatibility. For the `BaseModel` case, `bytes` are coerced to `str` types, but `bytes` are often the desired end type. Hence, for the new `TypeAdapter` class in V2, the return type is simply `bytes`, which can easily be coerced to a `str` type if desired. Note Despite some overlap in use cases with [`RootModel`](/docs/validation/latest/api/pydantic/root_model/#pydantic.root_model.RootModel), [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) should not be used as a type annotation for specifying fields of a `BaseModel`, etc. ## Parsing data into a specified type [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) can be used to apply the parsing logic to populate Pydantic models in a more ad-hoc way. This function behaves similarly to [`BaseModel.model_validate`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_validate), but works with arbitrary Pydantic-compatible types. This is especially useful when you want to parse results into a type that is not a direct subclass of [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). For example: ```python from pydantic import BaseModel, TypeAdapter class Item(BaseModel): id: int name: str # `item_data` could come from an API call, eg., via something like: # item_data = requests.get('https://my-api.com/items').json() item_data = [{'id': 1, 'name': 'My Item'}] items = TypeAdapter(list[Item]).validate_python(item_data) print(items) #> [Item(id=1, name='My Item')] ``` [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) is capable of parsing data into any of the types Pydantic can handle as fields of a [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel). Performance considerations When creating an instance of [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter), the provided type must be analyzed and converted into a pydantic-core schema. This comes with some non-trivial overhead, so it is recommended to create a `TypeAdapter` for a given type just once and reuse it in loops or other performance-critical code. ## Rebuilding a `TypeAdapter`'s schema ✦ New in v2.10 [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter)'s support deferred schema building and manual rebuilds. This is helpful for the case of: - Types with forward references - Types for which core schema builds are expensive When you initialize a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) with a type, Pydantic analyzes the type and creates a core schema for it. This core schema contains the information needed to validate and serialize data for that type. See the [architecture documentation](/docs/validation/latest/internals/architecture) for more information on core schemas. If you set [`defer_build`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.defer_build) to `True` when initializing a `TypeAdapter`, Pydantic will defer building the core schema until the first time it is needed (for validation or serialization). In order to manually trigger the building of the core schema, you can call the [`rebuild`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.rebuild) method on the [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) instance: ```python from pydantic import ConfigDict, TypeAdapter ta = TypeAdapter('MyInt', config=ConfigDict(defer_build=True)) # some time later, the forward reference is defined MyInt = int ta.rebuild() assert ta.validate_python(1) == 1 ``` --- # [Types](https://pydantic.dev/docs/validation/latest/concepts/types/) # Types Pydantic uses types to define how validation and serialization should be performed. [Built-in and standard library types](/docs/validation/latest/api/pydantic/standard_library_types) (such as [`int`](https://docs.python.org/3/library/functions.html#int), [`str`](https://docs.python.org/3/library/stdtypes.html#str), [`date`](https://docs.python.org/3/library/datetime.html#datetime.date)) can be used as is. [Strictness](/docs/validation/latest/concepts/strict_mode) can be controlled and constraints can be applied on them. On top of these, Pydantic provides extra types, either [directly in the library](/docs/validation/latest/api/pydantic/types) (e.g. [`SecretStr`](/docs/validation/latest/api/pydantic/types/#pydantic.types.SecretStr)) or in the [`pydantic-extra-types`](https://github.com/pydantic/pydantic-extra-types) external library. These are implemented using the patterns described in the [custom types](#custom-types) section. Strictness and constraints _can't_ be applied on them. The [built-in and standard library types](/docs/validation/latest/api/pydantic/standard_library_types) documentation goes over the supported types: the allowed values, the possible validation constraints, and whether [strictness](/docs/validation/latest/concepts/strict_mode) can be configured. See also the [conversion table](/docs/validation/latest/concepts/conversion_table) for a summary of the allowed values for each type. This page will go over defining your own custom types. ## Custom Types There are several ways to define your custom types. ### Using the annotated pattern The [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) can be used to make types reusable across your code base. For example, to create a type representing a positive integer: ```python from typing import Annotated from pydantic import Field, TypeAdapter, ValidationError PositiveInt = Annotated[int, Field(gt=0)] # (1) ta = TypeAdapter(PositiveInt) print(ta.validate_python(1)) #> 1 try: ta.validate_python(-1) except ValidationError as exc: print(exc) """ 1 validation error for constrained-int Input should be greater than 0 [type=greater_than, input_value=-1, input_type=int] """ ``` Note that you can also use constraints from the [annotated-types](https://github.com/annotated-types/annotated-types) library to make this Pydantic-agnostic: ```python from annotated_types import Gt PositiveInt = Annotated[int, Gt(0)] ``` #### Adding validation and serialization You can add or override validation, serialization, and JSON schemas to an arbitrary type using the markers that Pydantic exports: ```python from typing import Annotated from pydantic import ( AfterValidator, PlainSerializer, TypeAdapter, WithJsonSchema, ) TruncatedFloat = Annotated[ float, AfterValidator(lambda x: round(x, 1)), PlainSerializer(lambda x: f'{x:.1e}', return_type=str), WithJsonSchema({'type': 'string'}, mode='serialization'), ] ta = TypeAdapter(TruncatedFloat) input = 1.02345 assert input != 1.0 assert ta.validate_python(input) == 1.0 assert ta.dump_json(input) == b'"1.0e+00"' assert ta.json_schema(mode='validation') == {'type': 'number'} assert ta.json_schema(mode='serialization') == {'type': 'string'} ``` #### Generics [Type variables](https://docs.python.org/3/library/typing.html#typing.TypeVar) can be used within the [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) type: ```python from typing import Annotated, TypeVar from annotated_types import Gt, Len from pydantic import TypeAdapter, ValidationError T = TypeVar('T') ShortList = Annotated[list[T], Len(max_length=4)] ta = TypeAdapter(ShortList[int]) v = ta.validate_python([1, 2, 3, 4]) assert v == [1, 2, 3, 4] try: ta.validate_python([1, 2, 3, 4, 5]) except ValidationError as exc: print(exc) """ 1 validation error for list[int] List should have at most 4 items after validation, not 5 [type=too_long, input_value=[1, 2, 3, 4, 5], input_type=list] """ PositiveList = list[Annotated[T, Gt(0)]] ta = TypeAdapter(PositiveList[float]) v = ta.validate_python([1.0]) assert type(v[0]) is float try: ta.validate_python([-1.0]) except ValidationError as exc: print(exc) """ 1 validation error for list[constrained-float] 0 Input should be greater than 0 [type=greater_than, input_value=-1.0, input_type=float] """ ``` ### Named type aliases ✦ New in v2.11 Named type aliases are now fully supported. The above examples make use of _implicit_ type aliases, assigned to a variable. At runtime, Pydantic has no way of knowing the name of the variable it was assigned to, and this can be problematic for two reasons: - The [JSON Schema](/docs/validation/latest/concepts/json_schema) of the alias won't be converted into a [definition](https://json-schema.org/understanding-json-schema/structuring#defs). This is mostly useful when you are using the alias more than once in a model definition. - In most cases, [recursive type aliases](#named-recursive-types) won't work. By leveraging the new [`type` statement](https://typing.readthedocs.io/en/latest/spec/aliases.html#type-statement) (introduced in [PEP 695](https://peps.python.org/pep-0695/)), you can define aliases as follows: - [Python 3.9 and above](#tab-panel-564) - [Python 3.12 and above (new syntax)](#tab-panel-565) ```python from typing import Annotated from annotated_types import Gt from typing_extensions import TypeAliasType from pydantic import BaseModel PositiveIntList = TypeAliasType('PositiveIntList', list[Annotated[int, Gt(0)]]) class Model(BaseModel): x: PositiveIntList y: PositiveIntList print(Model.model_json_schema()) # (1) """ { '$defs': { 'PositiveIntList': { 'items': {'exclusiveMinimum': 0, 'type': 'integer'}, 'type': 'array', } }, 'properties': { 'x': {'$ref': '#/$defs/PositiveIntList'}, 'y': {'$ref': '#/$defs/PositiveIntList'}, }, 'required': ['x', 'y'], 'title': 'Model', 'type': 'object', } """ ``` If `PositiveIntList` were to be defined as an implicit type alias, its definition would have been duplicated in both `'x'` and `'y'`. ```python from typing import Annotated from annotated_types import Gt from pydantic import BaseModel type PositiveIntList = list[Annotated[int, Gt(0)]] class Model(BaseModel): x: PositiveIntList y: PositiveIntList print(Model.model_json_schema()) # (1) """ { '$defs': { 'PositiveIntList': { 'items': {'exclusiveMinimum': 0, 'type': 'integer'}, 'type': 'array', } }, 'properties': { 'x': {'$ref': '#/$defs/PositiveIntList'}, 'y': {'$ref': '#/$defs/PositiveIntList'}, }, 'required': ['x', 'y'], 'title': 'Model', 'type': 'object', } """ ``` If `PositiveIntList` were to be defined as an implicit type alias, its definition would have been duplicated in both `'x'` and `'y'`. When to use named type aliases While (named) PEP 695 and implicit type aliases are meant to be equivalent for static type checkers, Pydantic will _not_ understand field-specific metadata inside named aliases. That is, metadata such as `alias`, `default`, `deprecated`, _cannot_ be used: - [Python 3.9 and above](#tab-panel-560) - [Python 3.12 and above (new syntax)](#tab-panel-561) ```python from typing import Annotated from typing_extensions import TypeAliasType from pydantic import BaseModel, Field MyAlias = TypeAliasType('MyAlias', Annotated[int, Field(default=1)]) class Model(BaseModel): x: MyAlias # This is not allowed ``` ```python from typing import Annotated from pydantic import BaseModel, Field type MyAlias = Annotated[int, Field(default=1)] class Model(BaseModel): x: MyAlias # This is not allowed ``` Only metadata that can be applied to the annotated type itself is allowed (e.g. [validation constraints](/docs/validation/latest/concepts/fields#field-constraints) and JSON metadata). Trying to support field-specific metadata would require eagerly inspecting the type alias's [`__value__`](https://docs.python.org/3/library/typing.html#typing.TypeAliasType.__value__), and as such Pydantic wouldn't be able to have the alias stored as a JSON Schema definition. Note As with implicit type aliases, [type variables](https://docs.python.org/3/library/typing.html#typing.TypeVar) can also be used inside the generic alias: - [Python 3.9 and above](#tab-panel-562) - [Python 3.12 and above (new syntax)](#tab-panel-563) ```python from typing import Annotated, TypeVar from annotated_types import Len from typing_extensions import TypeAliasType T = TypeVar('T') ShortList = TypeAliasType( 'ShortList', Annotated[list[T], Len(max_length=4)], type_params=(T,) ) ``` ```python from typing import Annotated, TypeVar from annotated_types import Len type ShortList[T] = Annotated[list[T], Len(max_length=4)] ``` #### Named recursive types Named type aliases should be used whenever you need to define recursive type aliases . For several reasons, Pydantic isn't able to support implicit recursive aliases. For instance, it won't be able to resolve [forward annotations](/docs/validation/latest/concepts/forward_annotations) across modules. For instance, here is an example definition of a JSON type: - [Python 3.9 and above](#tab-panel-566) - [Python 3.12 and above (new syntax)](#tab-panel-567) ```python from typing import Union from typing_extensions import TypeAliasType from pydantic import TypeAdapter Json = TypeAliasType( 'Json', 'Union[dict[str, Json], list[Json], str, int, float, bool, None]', # (1) ) ta = TypeAdapter(Json) print(ta.json_schema()) """ { '$defs': { 'Json': { 'anyOf': [ { 'additionalProperties': {'$ref': '#/$defs/Json'}, 'type': 'object', }, {'items': {'$ref': '#/$defs/Json'}, 'type': 'array'}, {'type': 'string'}, {'type': 'integer'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}, ] } }, '$ref': '#/$defs/Json', } """ ``` Wrapping the annotation in quotes is necessary as it is eagerly evaluated (and `Json` has yet to be defined). ```python from pydantic import TypeAdapter type Json = dict[str, Json] | list[Json] | str | int | float | bool | None # (1) ta = TypeAdapter(Json) print(ta.json_schema()) """ { '$defs': { 'Json': { 'anyOf': [ { 'additionalProperties': {'$ref': '#/$defs/Json'}, 'type': 'object', }, {'items': {'$ref': '#/$defs/Json'}, 'type': 'array'}, {'type': 'string'}, {'type': 'integer'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}, ] } }, '$ref': '#/$defs/Json', } """ ``` The value of a named type alias is lazily evaluated, so there's no need to use forward annotations. Tip Pydantic defines a [`JsonValue`](/docs/validation/latest/api/pydantic/types/#pydantic.types.JsonValue) type as a convenience. ### Customizing validation with `__get_pydantic_core_schema__` To do more extensive customization of how Pydantic handles custom classes, and in particular when you have access to the class or can subclass it, you can implement a special `__get_pydantic_core_schema__` to tell Pydantic how to generate the `pydantic-core` schema. While `pydantic` uses `pydantic-core` internally to handle validation and serialization, it is a new API for Pydantic V2, thus it is one of the areas most likely to be tweaked in the future and you should try to stick to the built-in constructs like those provided by `annotated-types`, `pydantic.Field`, or `BeforeValidator` and so on. You can implement `__get_pydantic_core_schema__` both on a custom type and on metadata intended to be put in `Annotated`. In both cases the API is middleware-like and similar to that of "wrap" validators: you get a `source_type` (which isn't necessarily the same as the class, in particular for generics) and a `handler` that you can call with a type to either call the next metadata in `Annotated` or call into Pydantic's internal schema generation. The simplest no-op implementation calls the handler with the type you are given, then returns that as the result. You can also choose to modify the type before calling the handler, modify the core schema returned by the handler, or not call the handler at all. #### As a method on a custom type The following is an example of a type that uses `__get_pydantic_core_schema__` to customize how it gets validated. This is equivalent to implementing `__get_validators__` in Pydantic V1. ```python from typing import Any from pydantic_core import CoreSchema, core_schema from pydantic import GetCoreSchemaHandler, TypeAdapter class Username(str): @classmethod def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> CoreSchema: return core_schema.no_info_after_validator_function(cls, handler(str)) ta = TypeAdapter(Username) res = ta.validate_python('abc') assert isinstance(res, Username) assert res == 'abc' ``` See [JSON Schema](/docs/validation/latest/concepts/json_schema) for more details on how to customize JSON schemas for custom types. #### As an annotation Often you'll want to parametrize your custom type by more than just generic type parameters (which you can do via the type system and will be discussed later). Or you may not actually care (or want to) make an instance of your subclass; you actually want the original type, just with some extra validation done. For example, if you were to implement `pydantic.AfterValidator` (see [Adding validation and serialization](#adding-validation-and-serialization)) yourself, you'd do something similar to the following: ```python from dataclasses import dataclass from typing import Annotated, Any, Callable from pydantic_core import CoreSchema, core_schema from pydantic import BaseModel, GetCoreSchemaHandler @dataclass(frozen=True) # (1) class MyAfterValidator: func: Callable[[Any], Any] def __get_pydantic_core_schema__( self, source_type: Any, handler: GetCoreSchemaHandler ) -> CoreSchema: return core_schema.no_info_after_validator_function( self.func, handler(source_type) ) Username = Annotated[str, MyAfterValidator(str.lower)] class Model(BaseModel): name: Username assert Model(name='ABC').name == 'abc' # (2) ``` The `frozen=True` specification makes `MyAfterValidator` hashable. Without this, a union such as `Username | None` will raise an error. Notice that type checkers will not complain about assigning `'ABC'` to `Username` like they did in the previous example because they do not consider `Username` to be a distinct type from `str`. #### Handling third-party types Another use case for the pattern in the previous section is to handle third party types. ```python from typing import Annotated, Any from pydantic_core import core_schema from pydantic import ( BaseModel, GetCoreSchemaHandler, GetJsonSchemaHandler, ValidationError, ) from pydantic.json_schema import JsonSchemaValue class ThirdPartyType: """ This is meant to represent a type from a third-party library that wasn't designed with Pydantic integration in mind, and so doesn't have a `pydantic_core.CoreSchema` or anything. """ x: int def __init__(self): self.x = 0 class _ThirdPartyTypePydanticAnnotation: @classmethod def __get_pydantic_core_schema__( cls, _source_type: Any, _handler: GetCoreSchemaHandler, ) -> core_schema.CoreSchema: """ We return a pydantic_core.CoreSchema that behaves in the following ways: * ints will be parsed as `ThirdPartyType` instances with the int as the x attribute * `ThirdPartyType` instances will be parsed as `ThirdPartyType` instances without any changes * Nothing else will pass validation * Serialization will always return just an int """ def validate_from_int(value: int) -> ThirdPartyType: result = ThirdPartyType() result.x = value return result from_int_schema = core_schema.chain_schema( [ core_schema.int_schema(), core_schema.no_info_plain_validator_function(validate_from_int), ] ) return core_schema.json_or_python_schema( json_schema=from_int_schema, python_schema=core_schema.union_schema( [ # check if it's an instance first before doing any further work core_schema.is_instance_schema(ThirdPartyType), from_int_schema, ] ), serialization=core_schema.plain_serializer_function_ser_schema( lambda instance: instance.x ), ) @classmethod def __get_pydantic_json_schema__( cls, _core_schema: core_schema.CoreSchema, handler: GetJsonSchemaHandler ) -> JsonSchemaValue: # Use the same schema that would be used for `int` return handler(core_schema.int_schema()) # We now create an `Annotated` wrapper that we'll use as the annotation for fields on `BaseModel`s, etc. PydanticThirdPartyType = Annotated[ ThirdPartyType, _ThirdPartyTypePydanticAnnotation ] # Create a model class that uses this annotation as a field class Model(BaseModel): third_party_type: PydanticThirdPartyType # Demonstrate that this field is handled correctly, that ints are parsed into `ThirdPartyType`, and that # these instances are also "dumped" directly into ints as expected. m_int = Model(third_party_type=1) assert isinstance(m_int.third_party_type, ThirdPartyType) assert m_int.third_party_type.x == 1 assert m_int.model_dump() == {'third_party_type': 1} # Do the same thing where an instance of ThirdPartyType is passed in instance = ThirdPartyType() assert instance.x == 0 instance.x = 10 m_instance = Model(third_party_type=instance) assert isinstance(m_instance.third_party_type, ThirdPartyType) assert m_instance.third_party_type.x == 10 assert m_instance.model_dump() == {'third_party_type': 10} # Demonstrate that validation errors are raised as expected for invalid inputs try: Model(third_party_type='a') except ValidationError as e: print(e) """ 2 validation errors for Model third_party_type.is-instance[ThirdPartyType] Input should be an instance of ThirdPartyType [type=is_instance_of, input_value='a', input_type=str] third_party_type.chain[int,function-plain[validate_from_int()]] Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] """ assert Model.model_json_schema() == { 'properties': { 'third_party_type': {'title': 'Third Party Type', 'type': 'integer'} }, 'required': ['third_party_type'], 'title': 'Model', 'type': 'object', } ``` You can use this approach to e.g. define behavior for Pandas or Numpy types. #### Using `GetPydanticSchema` to reduce boilerplate API Documentation [`pydantic.types.GetPydanticSchema`](/docs/validation/latest/api/pydantic/types/#pydantic.types.GetPydanticSchema) You may notice that the above examples where we create a marker class require a good amount of boilerplate. For many simple cases you can greatly minimize this by using `pydantic.GetPydanticSchema`: ```python from typing import Annotated from pydantic_core import core_schema from pydantic import BaseModel, GetPydanticSchema class Model(BaseModel): y: Annotated[ str, GetPydanticSchema( lambda tp, handler: core_schema.no_info_after_validator_function( lambda x: x * 2, handler(tp) ) ), ] assert Model(y='ab').y == 'abab' ``` #### Summary Let's recap: 1. Pydantic provides high level hooks to customize types via `Annotated` like `AfterValidator` and `Field`. Use these when possible. 2. Under the hood these use `pydantic-core` to customize validation, and you can hook into that directly using `GetPydanticSchema` or a marker class with `__get_pydantic_core_schema__`. 3. If you really want a custom type you can implement `__get_pydantic_core_schema__` on the type itself. ### Handling custom generic classes Caution This is an advanced technique that you might not need in the beginning. In most of the cases you will probably be fine with standard Pydantic models. You can use [Generic Classes](https://docs.python.org/3/library/typing.html#typing.Generic) as field types and perform custom validation based on the "type parameters" (or sub-types) with `__get_pydantic_core_schema__`. If the Generic class that you are using as a sub-type has a classmethod `__get_pydantic_core_schema__`, you don't need to use [`arbitrary_types_allowed`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.arbitrary_types_allowed) for it to work. Because the `source_type` parameter is not the same as the `cls` parameter, you can use `typing.get_args` (or `typing_extensions.get_args`) to extract the generic parameters. Then you can use the `handler` to generate a schema for them by calling `handler.generate_schema`. Note that we do not do something like `handler(get_args(source_type)[0])` because we want to generate an unrelated schema for that generic parameter, not one that is influenced by the current context of `Annotated` metadata and such. This is less important for custom types, but crucial for annotated metadata that modifies schema building. ```python from dataclasses import dataclass from typing import Any, Generic, TypeVar from pydantic_core import CoreSchema, core_schema from typing_extensions import get_args, get_origin from pydantic import ( BaseModel, GetCoreSchemaHandler, ValidationError, ValidatorFunctionWrapHandler, ) ItemType = TypeVar('ItemType') # This is not a pydantic model, it's an arbitrary generic class @dataclass class Owner(Generic[ItemType]): name: str item: ItemType @classmethod def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> CoreSchema: origin = get_origin(source_type) if origin is None: # used as `x: Owner` without params origin = source_type item_tp = Any else: item_tp = get_args(source_type)[0] # both calling handler(...) and handler.generate_schema(...) # would work, but prefer the latter for conceptual and consistency reasons item_schema = handler.generate_schema(item_tp) def val_item( v: Owner[Any], handler: ValidatorFunctionWrapHandler ) -> Owner[Any]: v.item = handler(v.item) return v python_schema = core_schema.chain_schema( # `chain_schema` means do the following steps in order: [ # Ensure the value is an instance of Owner core_schema.is_instance_schema(cls), # Use the item_schema to validate `items` core_schema.no_info_wrap_validator_function( val_item, item_schema ), ] ) return core_schema.json_or_python_schema( # for JSON accept an object with name and item keys json_schema=core_schema.chain_schema( [ core_schema.typed_dict_schema( { 'name': core_schema.typed_dict_field( core_schema.str_schema() ), 'item': core_schema.typed_dict_field(item_schema), } ), # after validating the json data convert it to python core_schema.no_info_before_validator_function( lambda data: Owner( name=data['name'], item=data['item'] ), # note that we reuse the same schema here as below python_schema, ), ] ), python_schema=python_schema, ) class Car(BaseModel): color: str class House(BaseModel): rooms: int class Model(BaseModel): car_owner: Owner[Car] home_owner: Owner[House] model = Model( car_owner=Owner(name='John', item=Car(color='black')), home_owner=Owner(name='James', item=House(rooms=3)), ) print(model) """ car_owner=Owner(name='John', item=Car(color='black')) home_owner=Owner(name='James', item=House(rooms=3)) """ try: # If the values of the sub-types are invalid, we get an error Model( car_owner=Owner(name='John', item=House(rooms=3)), home_owner=Owner(name='James', item=Car(color='black')), ) except ValidationError as e: print(e) """ 2 validation errors for Model wine Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='Kinda good', input_type=str] cheese Input should be a valid boolean, unable to interpret input [type=bool_parsing, input_value='yeah', input_type=str] """ # Similarly with JSON model = Model.model_validate_json( '{"car_owner":{"name":"John","item":{"color":"black"}},"home_owner":{"name":"James","item":{"rooms":3}}}' ) print(model) """ car_owner=Owner(name='John', item=Car(color='black')) home_owner=Owner(name='James', item=House(rooms=3)) """ try: Model.model_validate_json( '{"car_owner":{"name":"John","item":{"rooms":3}},"home_owner":{"name":"James","item":{"color":"black"}}}' ) except ValidationError as e: print(e) """ 2 validation errors for Model car_owner.item.color Field required [type=missing, input_value={'rooms': 3}, input_type=dict] home_owner.item.rooms Field required [type=missing, input_value={'color': 'black'}, input_type=dict] """ ``` #### Generic containers The same idea can be applied to create generic container types, like a custom `Sequence` type: ```python from collections.abc import Sequence from typing import Any, TypeVar from pydantic_core import ValidationError, core_schema from typing_extensions import get_args from pydantic import BaseModel, GetCoreSchemaHandler T = TypeVar('T') class MySequence(Sequence[T]): def __init__(self, v: Sequence[T]): self.v = v def __getitem__(self, i): return self.v[i] def __len__(self): return len(self.v) @classmethod def __get_pydantic_core_schema__( cls, source: Any, handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: instance_schema = core_schema.is_instance_schema(cls) args = get_args(source) if args: # replace the type and rely on Pydantic to generate the right schema # for `Sequence` sequence_t_schema = handler.generate_schema(Sequence[args[0]]) else: sequence_t_schema = handler.generate_schema(Sequence) non_instance_schema = core_schema.no_info_after_validator_function( MySequence, sequence_t_schema ) return core_schema.union_schema([instance_schema, non_instance_schema]) class M(BaseModel): model_config = dict(validate_default=True) s1: MySequence = [3] m = M() print(m) #> s1=<__main__.MySequence object at 0x0123456789ab> print(m.s1.v) #> [3] class M(BaseModel): s1: MySequence[int] M(s1=[1]) try: M(s1=['a']) except ValidationError as exc: print(exc) """ 2 validation errors for M s1.is-instance[MySequence] Input should be an instance of MySequence [type=is_instance_of, input_value=['a'], input_type=list] s1.function-after[MySequence(), json-or-python[json=list[int],python=chain[is-instance[Sequence],function-wrap[sequence_validator()]]]].0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] """ ``` ### Access to field name Note This was not possible with Pydantic V2 to V2.3, it was [re-added](https://github.com/pydantic/pydantic/pull/7542) in Pydantic V2.4. As of Pydantic V2.4, you can access the field name via the `handler.field_name` within `__get_pydantic_core_schema__` and thereby set the field name which will be available from `info.field_name`. ```python from typing import Any from pydantic_core import core_schema from pydantic import BaseModel, GetCoreSchemaHandler, ValidationInfo class CustomType: """Custom type that stores the field it was used in.""" def __init__(self, value: int, field_name: str): self.value = value self.field_name = field_name def __repr__(self): return f'CustomType<{self.value} {self.field_name!r}>' @classmethod def validate(cls, value: int, info: ValidationInfo): return cls(value, info.field_name) @classmethod def __get_pydantic_core_schema__( cls, source_type: Any, handler: GetCoreSchemaHandler ) -> core_schema.CoreSchema: return core_schema.with_info_after_validator_function( cls.validate, handler(int) ) class MyModel(BaseModel): my_field: CustomType m = MyModel(my_field=1) print(m.my_field) #> CustomType<1 'my_field'> ``` You can also access `field_name` from the markers used with `Annotated`, like [`AfterValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.AfterValidator). ```python from typing import Annotated from pydantic import AfterValidator, BaseModel, ValidationInfo def my_validators(value: int, info: ValidationInfo): return f'<{value} {info.field_name!r}>' class MyModel(BaseModel): my_field: Annotated[int, AfterValidator(my_validators)] m = MyModel(my_field=1) print(m.my_field) #> <1 'my_field'> ``` --- # [Unions](https://pydantic.dev/docs/validation/latest/concepts/unions/) # Unions Unions are fundamentally different to all other types Pydantic validates - instead of requiring all fields/items/values to be valid, unions require only one member to be valid. This leads to some nuance around how to validate unions: - which member(s) of the union should you validate data against, and in which order? - which errors to raise when validation fails? Validating unions feels like adding another orthogonal dimension to the validation process. To solve these problems, Pydantic supports three fundamental approaches to validating unions: 1. [left to right mode](#left-to-right-mode) - the simplest approach, each member of the union is tried in order and the first match is returned 2. [smart mode](#smart-mode) - similar to "left to right mode" members are tried in order; however, validation will proceed past the first match to attempt to find a better match, this is the default mode for most union validation 3. [discriminated unions](#discriminated-unions) - only one member of the union is tried, based on a discriminator Tip In general, we recommend using [discriminated unions](#discriminated-unions). They are both more performant and more predictable than untagged unions, as they allow you to control which member of the union to validate against. For complex cases, if you're using untagged unions, it's recommended to use `union_mode='left_to_right'` if you need guarantees about the order of validation attempts against the union members. If you're looking for incredibly specialized behavior, you can use a [custom validator](/docs/validation/latest/concepts/validators#field-validators). ## Union Modes ### Left to Right Mode Note Because this mode often leads to unexpected validation results, it is not the default in Pydantic >=2, instead `union_mode='smart'` is the default. With this approach, validation is attempted against each member of the union in their order they're defined, and the first successful validation is accepted as input. If validation fails on all members, the validation error includes the errors from all members of the union. `union_mode='left_to_right'` must be set as a [`Field`](/docs/validation/latest/concepts/fields) parameter on union fields where you want to use it. Union with left to right mode ```python from typing import Union from pydantic import BaseModel, Field, ValidationError class User(BaseModel): id: Union[str, int] = Field(union_mode='left_to_right') print(User(id=123)) #> id=123 print(User(id='hello')) #> id='hello' try: User(id=[]) except ValidationError as e: print(e) """ 2 validation errors for User id.str Input should be a valid string [type=string_type, input_value=[], input_type=list] id.int Input should be a valid integer [type=int_type, input_value=[], input_type=list] """ ``` The order of members is very important in this case, as demonstrated by tweak the above example: Union with left to right - unexpected results ```python from typing import Union from pydantic import BaseModel, Field class User(BaseModel): id: Union[int, str] = Field(union_mode='left_to_right') print(User(id=123)) # (1) #> id=123 print(User(id='456')) # (2) #> id=456 ``` 1. As expected the input is validated against the `int` member and the result is as expected. 2. We're in lax mode and the numeric string `'123'` is valid as input to the first member of the union, `int`. Since that is tried first, we get the surprising result of `id` being an `int` instead of a `str`. ### Smart Mode Because of the potentially surprising results of `union_mode='left_to_right'`, in Pydantic >=2 the default mode for `Union` validation is `union_mode='smart'`. In this mode, pydantic attempts to select the best match for the input from the union members. The exact algorithm may change between Pydantic minor releases to allow for improvements in both performance and accuracy. Note We reserve the right to tweak the internal `smart` matching algorithm in future versions of Pydantic. If you rely on very specific matching behavior, it's recommended to use `union_mode='left_to_right'` or [discriminated unions](#discriminated-unions). Smart Mode Algorithm The smart mode algorithm uses two metrics to determine the best match for the input: 1. The number of valid fields set (relevant for models, dataclasses, and typed dicts) 2. The exactness of the match (relevant for all types) #### Number of valid fields set Note This metric was introduced in Pydantic v2.8.0. Prior to this version, only exactness was used to determine the best match. This metric is currently only relevant for models, dataclasses, and typed dicts. The greater the number of valid fields set, the better the match. The number of fields set on nested models is also taken into account. These counts bubble up to the top-level union, where the union member with the highest count is considered the best match. For data types where this metric is relevant, we prioritize this count over exactness. For all other types, we use solely exactness. #### Exactness For `exactness`, Pydantic scores a match of a union member into one of the following three groups (from highest score to lowest score): - An exact type match, for example an `int` input to a `float | int` union validation is an exact type match for the `int` member - Validation would have succeeded in [`strict` mode](/docs/validation/latest/concepts/strict_mode) - Validation would have succeeded in lax mode The union match which produced the highest exactness score will be considered the best match. In smart mode, the following steps are taken to try to select the best match for the input: - [BaseModel, dataclass, and TypedDict](#tab-panel-568) - [All other data types](#tab-panel-569) 1. Union members are attempted left to right, with any successful matches scored into one of the three exactness categories described above, with the valid fields set count also tallied. 2. After all members have been evaluated, the member with the highest "valid fields set" count is returned. 3. If there's a tie for the highest "valid fields set" count, the exactness score is used as a tiebreaker, and the member with the highest exactness score is returned. 4. If validation failed on all the members, return all the errors. 1. Union members are attempted left to right, with any successful matches scored into one of the three exactness categories described above. - If validation succeeds with an exact type match, that member is returned immediately and following members will not be attempted. 2. If validation succeeded on at least one member as a "strict" match, the leftmost of those "strict" matches is returned. 3. If validation succeeded on at least one member in "lax" mode, the leftmost match is returned. 4. Validation failed on all the members, return all the errors. ```python from typing import Union from uuid import UUID from pydantic import BaseModel class User(BaseModel): id: Union[int, str, UUID] name: str user_01 = User(id=123, name='John Doe') print(user_01) #> id=123 name='John Doe' print(user_01.id) #> 123 user_02 = User(id='1234', name='John Doe') print(user_02) #> id='1234' name='John Doe' print(user_02.id) #> 1234 user_03_uuid = UUID('cf57432e-809e-4353-adbd-9d5c0d733868') user_03 = User(id=user_03_uuid, name='John Doe') print(user_03) #> id=UUID('cf57432e-809e-4353-adbd-9d5c0d733868') name='John Doe' print(user_03.id) #> cf57432e-809e-4353-adbd-9d5c0d733868 print(user_03_uuid.int) #> 275603287559914445491632874575877060712 ``` ## Discriminated unions **Discriminated unions are sometimes referred to as "Tagged unions".** Unions can be validated more efficiently using a discriminator, by specifically choosing which member of the union to validate against. This makes validation more efficient and also avoids a proliferation of errors when validation fails. Adding discriminator to unions also means the generated JSON schema implements the `discriminator` attribute from the [OpenAPI specification](https://swagger.io/specification/#discriminator-object). ### Discriminated unions with string discriminators Frequently, in the case of a union with multiple models, there is a common field to all members of the union that can be used to distinguish which union case the data should be validated against. To validate models based on that information, you can set a common field on each model of the union (`pet_type` in the example below), typed as accepting one or multiple literal values. When defining the discriminated union type, the `discriminator` parameter of [the `Field()` function](/docs/validation/latest/concepts/fields) must be specified (the [`Discriminator`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Discriminator) type can also be used). ```python from typing import Literal, Union from pydantic import BaseModel, Field, ValidationError class Cat(BaseModel): pet_type: Literal['cat'] meows: int class Dog(BaseModel): pet_type: Literal['dog'] barks: float class Lizard(BaseModel): pet_type: Literal['reptile', 'lizard'] scales: bool class Model(BaseModel): pet: Union[Cat, Dog, Lizard] = Field(discriminator='pet_type') n: int print(Model(pet={'pet_type': 'dog', 'barks': 3.14}, n=1)) #> pet=Dog(pet_type='dog', barks=3.14) n=1 try: Model(pet={'pet_type': 'dog'}, n=1) except ValidationError as e: print(e) """ 1 validation error for Model pet.dog.barks Field required [type=missing, input_value={'pet_type': 'dog'}, input_type=dict] """ ``` ✦ New in v2.13 [Root models](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types) with a [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) root type can be used in place of [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) types. ### Discriminated Unions with callable `Discriminator` API Documentation [`pydantic.types.Discriminator`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Discriminator) In the case of a `Union` with multiple models, sometimes there isn't a single uniform field across all models that you can use as a discriminator. This is the perfect use case for a callable `Discriminator`. Tip When you're designing callable discriminators, remember that you might have to account for both `dict` and model type inputs. This pattern is similar to that of `mode='before'` validators, where you have to anticipate various forms of input. But wait! You ask, I only anticipate passing in `dict` types, why do I need to account for models? Pydantic uses callable discriminators for serialization as well, at which point the input to your callable is very likely to be a model instance. In the following examples, you'll see that the callable discriminators are designed to handle both `dict` and model inputs. If you don't follow this practice, it's likely that you'll, in the best case, get warnings during serialization, and in the worst case, get runtime errors during validation. ```python from typing import Annotated, Any, Literal, Optional, Union from pydantic import BaseModel, Discriminator, Tag class Pie(BaseModel): time_to_cook: int num_ingredients: int class ApplePie(Pie): fruit: Literal['apple'] = 'apple' class PumpkinPie(Pie): filling: Literal['pumpkin'] = 'pumpkin' def get_discriminator_value(v: Any) -> Optional[str]: if isinstance(v, dict): return v.get('fruit', v.get('filling')) return getattr(v, 'fruit', getattr(v, 'filling', None)) class ThanksgivingDinner(BaseModel): dessert: Annotated[ Union[ Annotated[ApplePie, Tag('apple')], Annotated[PumpkinPie, Tag('pumpkin')], ], Discriminator(get_discriminator_value), ] apple_variation = ThanksgivingDinner.model_validate( {'dessert': {'fruit': 'apple', 'time_to_cook': 60, 'num_ingredients': 8}} ) print(repr(apple_variation)) """ ThanksgivingDinner(dessert=ApplePie(time_to_cook=60, num_ingredients=8, fruit='apple')) """ pumpkin_variation = ThanksgivingDinner.model_validate( { 'dessert': { 'filling': 'pumpkin', 'time_to_cook': 40, 'num_ingredients': 6, } } ) print(repr(pumpkin_variation)) """ ThanksgivingDinner(dessert=PumpkinPie(time_to_cook=40, num_ingredients=6, filling='pumpkin')) """ ``` `Discriminator`s can also be used to validate `Union` types with combinations of models and primitive types. For example: ```python from typing import Annotated, Any, Optional, Union from pydantic import BaseModel, Discriminator, Tag, ValidationError def model_x_discriminator(v: Any) -> Optional[str]: if isinstance(v, int): return 'int' if isinstance(v, (dict, BaseModel)): return 'model' else: # return None if the discriminator value isn't found return None class SpecialValue(BaseModel): value: int class DiscriminatedModel(BaseModel): value: Annotated[ Union[ Annotated[int, Tag('int')], Annotated['SpecialValue', Tag('model')], ], Discriminator(model_x_discriminator), ] model_data = {'value': {'value': 1}} m = DiscriminatedModel.model_validate(model_data) print(m) #> value=SpecialValue(value=1) int_data = {'value': 123} m = DiscriminatedModel.model_validate(int_data) print(m) #> value=123 try: DiscriminatedModel.model_validate({'value': 'not an int or a model'}) except ValidationError as e: print(e) # (1) """ 1 validation error for DiscriminatedModel value Unable to extract tag using discriminator model_x_discriminator() [type=union_tag_not_found, input_value='not an int or a model', input_type=str] """ ``` Notice the callable discriminator function returns `None` if a discriminator value is not found. When `None` is returned, this `union_tag_not_found` error is raised. Note Using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) can be handy to regroup the `Union` and `discriminator` information. See the next example for more details. There are a few ways to set a discriminator for a field, all varying slightly in syntax. For `str` discriminators: ```python some_field: Union[...] = Field(discriminator='my_discriminator') some_field: Annotated[Union[...], Field(discriminator='my_discriminator')] ``` For callable `Discriminator`s: ```python some_field: Union[...] = Field(discriminator=Discriminator(...)) some_field: Annotated[Union[...], Discriminator(...)] some_field: Annotated[Union[...], Field(discriminator=Discriminator(...))] ``` Caution Discriminated unions cannot be used with only a single variant, such as `Union[Cat]`. Python changes `Union[T]` into `T` at interpretation time, so it is not possible for `pydantic` to distinguish fields of `Union[T]` from `T`. ### Nested Discriminated Unions Only one discriminator can be set for a field but sometimes you want to combine multiple discriminators. You can do it by creating nested `Annotated` types, e.g.: ```python from typing import Annotated, Literal, Union from pydantic import BaseModel, Field, ValidationError class BlackCat(BaseModel): pet_type: Literal['cat'] color: Literal['black'] black_name: str class WhiteCat(BaseModel): pet_type: Literal['cat'] color: Literal['white'] white_name: str Cat = Annotated[Union[BlackCat, WhiteCat], Field(discriminator='color')] class Dog(BaseModel): pet_type: Literal['dog'] name: str Pet = Annotated[Union[Cat, Dog], Field(discriminator='pet_type')] class Model(BaseModel): pet: Pet n: int m = Model(pet={'pet_type': 'cat', 'color': 'black', 'black_name': 'felix'}, n=1) print(m) #> pet=BlackCat(pet_type='cat', color='black', black_name='felix') n=1 try: Model(pet={'pet_type': 'cat', 'color': 'red'}, n='1') except ValidationError as e: print(e) """ 1 validation error for Model pet.cat Input tag 'red' found using 'color' does not match any of the expected tags: 'black', 'white' [type=union_tag_invalid, input_value={'pet_type': 'cat', 'color': 'red'}, input_type=dict] """ try: Model(pet={'pet_type': 'cat', 'color': 'black'}, n='1') except ValidationError as e: print(e) """ 1 validation error for Model pet.cat.black.black_name Field required [type=missing, input_value={'pet_type': 'cat', 'color': 'black'}, input_type=dict] """ ``` Tip If you want to validate data against a union, and solely a union, you can use pydantic's [`TypeAdapter`](/docs/validation/latest/concepts/type_adapter) construct instead of inheriting from the standard `BaseModel`. In the context of the previous example, we have the following: ```python type_adapter = TypeAdapter(Pet) pet = type_adapter.validate_python( {'pet_type': 'cat', 'color': 'black', 'black_name': 'felix'} ) print(repr(pet)) #> BlackCat(pet_type='cat', color='black', black_name='felix') ``` ## Union Validation Errors When `Union` validation fails, error messages can be quite verbose, as they will produce validation errors for each case in the union. This is especially noticeable when dealing with recursive models, where reasons may be generated at each level of recursion. Discriminated unions help to simplify error messages in this case, as validation errors are only produced for the case with a matching discriminator value. You can also customize the error type, message, and context for a `Discriminator` by passing these specifications as parameters to the `Discriminator` constructor, as seen in the example below. ```python from typing import Annotated, Union from pydantic import BaseModel, Discriminator, Tag, ValidationError # Errors are quite verbose with a normal Union: class Model(BaseModel): x: Union[str, 'Model'] try: Model.model_validate({'x': {'x': {'x': 1}}}) except ValidationError as e: print(e) """ 4 validation errors for Model x.str Input should be a valid string [type=string_type, input_value={'x': {'x': 1}}, input_type=dict] x.Model.x.str Input should be a valid string [type=string_type, input_value={'x': 1}, input_type=dict] x.Model.x.Model.x.str Input should be a valid string [type=string_type, input_value=1, input_type=int] x.Model.x.Model.x.Model Input should be a valid dictionary or instance of Model [type=model_type, input_value=1, input_type=int] """ try: Model.model_validate({'x': {'x': {'x': {}}}}) except ValidationError as e: print(e) """ 4 validation errors for Model x.str Input should be a valid string [type=string_type, input_value={'x': {'x': {}}}, input_type=dict] x.Model.x.str Input should be a valid string [type=string_type, input_value={'x': {}}, input_type=dict] x.Model.x.Model.x.str Input should be a valid string [type=string_type, input_value={}, input_type=dict] x.Model.x.Model.x.Model.x Field required [type=missing, input_value={}, input_type=dict] """ # Errors are much simpler with a discriminated union: def model_x_discriminator(v): if isinstance(v, str): return 'str' if isinstance(v, (dict, BaseModel)): return 'model' class DiscriminatedModel(BaseModel): x: Annotated[ Union[ Annotated[str, Tag('str')], Annotated['DiscriminatedModel', Tag('model')], ], Discriminator( model_x_discriminator, custom_error_type='invalid_union_member', # (1) custom_error_message='Invalid union member', # (2) custom_error_context={'discriminator': 'str_or_model'}, # (3) ), ] try: DiscriminatedModel.model_validate({'x': {'x': {'x': 1}}}) except ValidationError as e: print(e) """ 1 validation error for DiscriminatedModel x.model.x.model.x Invalid union member [type=invalid_union_member, input_value=1, input_type=int] """ try: DiscriminatedModel.model_validate({'x': {'x': {'x': {}}}}) except ValidationError as e: print(e) """ 1 validation error for DiscriminatedModel x.model.x.model.x.model.x Field required [type=missing, input_value={}, input_type=dict] """ # The data is still handled properly when valid: data = {'x': {'x': {'x': 'a'}}} m = DiscriminatedModel.model_validate(data) print(m.model_dump()) #> {'x': {'x': {'x': 'a'}}} ``` `custom_error_type` is the `type` attribute of the `ValidationError` raised when validation fails. `custom_error_message` is the `msg` attribute of the `ValidationError` raised when validation fails. `custom_error_context` is the `ctx` attribute of the `ValidationError` raised when validation fails. You can also simplify error messages by labeling each case with a [`Tag`](/docs/validation/latest/api/pydantic/types/#pydantic.types.Tag). This is especially useful when you have complex types like those in this example: ```python from typing import Annotated, Union from pydantic import AfterValidator, Tag, TypeAdapter, ValidationError DoubledList = Annotated[list[int], AfterValidator(lambda x: x * 2)] StringsMap = dict[str, str] # Not using any `Tag`s for each union case, the errors are not so nice to look at adapter = TypeAdapter(Union[DoubledList, StringsMap]) try: adapter.validate_python(['a']) except ValidationError as exc_info: print(exc_info) """ 2 validation errors for union[function-after[(), list[int]],dict[str,str]] function-after[(), list[int]].0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] dict[str,str] Input should be a valid dictionary [type=dict_type, input_value=['a'], input_type=list] """ tag_adapter = TypeAdapter( Union[ Annotated[DoubledList, Tag('DoubledList')], Annotated[StringsMap, Tag('StringsMap')], ] ) try: tag_adapter.validate_python(['a']) except ValidationError as exc_info: print(exc_info) """ 2 validation errors for union[DoubledList,StringsMap] DoubledList.0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='a', input_type=str] StringsMap Input should be a valid dictionary [type=dict_type, input_value=['a'], input_type=list] """ ``` --- # [Validation Decorator](https://pydantic.dev/docs/validation/latest/concepts/validation_decorator/) # Validation Decorator API Documentation [`pydantic.validate_call_decorator.validate_call`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) The [`validate_call()`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) decorator allows the arguments passed to a function to be parsed and validated using the function's annotations before the function is called. While under the hood this uses the same approach of model creation and initialisation (see [Validators](/docs/validation/latest/concepts/validators) for more details), it provides an extremely easy way to apply validation to your code with minimal boilerplate. Example of usage: ```python from pydantic import ValidationError, validate_call @validate_call def repeat(s: str, count: int, *, separator: bytes = b'') -> bytes: b = s.encode() return separator.join(b for _ in range(count)) a = repeat('hello', 3) print(a) #> b'hellohellohello' b = repeat('x', '4', separator=b' ') print(b) #> b'x x x x' try: c = repeat('hello', 'wrong') except ValidationError as exc: print(exc) """ 1 validation error for repeat 1 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='wrong', input_type=str] """ ``` ## Parameter types Parameter types are inferred from type annotations on the function, or as [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) if not annotated. All types listed in [types](/docs/validation/latest/concepts/types) can be validated, including Pydantic models and [custom types](/docs/validation/latest/concepts/types#custom-types). As with the rest of Pydantic, types are by default coerced by the decorator before they're passed to the actual function: ```python from datetime import date from pydantic import validate_call @validate_call def greater_than(d1: date, d2: date, *, include_equal=False) -> date: # (1) if include_equal: return d1 >= d2 else: return d1 > d2 d1 = '2000-01-01' # (2) d2 = date(2001, 1, 1) greater_than(d1, d2, include_equal=True) ``` Because `include_equal` has no type annotation, it will be inferred as [`Any`](https://docs.python.org/3/library/typing.html#typing.Any). Although `d1` is a string, it will be converted to a [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) object. Type coercion like this can be extremely helpful, but also confusing or not desired (see [model data conversion](/docs/validation/latest/concepts/models#data-conversion)). [Strict mode](/docs/validation/latest/concepts/strict_mode) can be enabled by using a [custom configuration](#custom-configuration). Validating the return value By default, the return value of the function is **not** validated. To do so, the `validate_return` argument of the decorator can be set to `True`. ## Function signatures The [`validate_call()`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) decorator is designed to work with functions using all possible [parameter configurations](https://docs.python.org/3/glossary.html#term-parameter) and all possible combinations of these: - Positional or keyword parameters with or without defaults. - Keyword-only parameters: parameters after `*,`. - Positional-only parameters: parameters before `, /`. - Variable positional parameters defined via `*` (often `*args`). - Variable keyword parameters defined via `**` (often `**kwargs`). Example ```python from pydantic import validate_call @validate_call def pos_or_kw(a: int, b: int = 2) -> str: return f'a={a} b={b}' print(pos_or_kw(1, b=3)) #> a=1 b=3 @validate_call def kw_only(*, a: int, b: int = 2) -> str: return f'a={a} b={b}' print(kw_only(a=1)) #> a=1 b=2 print(kw_only(a=1, b=3)) #> a=1 b=3 @validate_call def pos_only(a: int, b: int = 2, /) -> str: return f'a={a} b={b}' print(pos_only(1)) #> a=1 b=2 @validate_call def var_args(*args: int) -> str: return str(args) print(var_args(1)) #> (1,) print(var_args(1, 2, 3)) #> (1, 2, 3) @validate_call def var_kwargs(**kwargs: int) -> str: return str(kwargs) print(var_kwargs(a=1)) #> {'a': 1} print(var_kwargs(a=1, b=2)) #> {'a': 1, 'b': 2} @validate_call def armageddon( a: int, /, b: int, *c: int, d: int, e: int = None, **f: int, ) -> str: return f'a={a} b={b} c={c} d={d} e={e} f={f}' print(armageddon(1, 2, d=3)) #> a=1 b=2 c=() d=3 e=None f={} print(armageddon(1, 2, 3, 4, 5, 6, d=8, e=9, f=10, spam=11)) #> a=1 b=2 c=(3, 4, 5, 6) d=8 e=9 f={'f': 10, 'spam': 11} ``` [`Unpack`](https://docs.python.org/3/library/typing.html#typing.Unpack) for keyword parameters [`Unpack`](https://docs.python.org/3/library/typing.html#typing.Unpack) and typed dictionaries can be used to annotate the variable keyword parameters of a function: ```python from typing_extensions import TypedDict, Unpack from pydantic import validate_call class Point(TypedDict): x: int y: int @validate_call def add_coords(**kwargs: Unpack[Point]) -> int: return kwargs['x'] + kwargs['y'] add_coords(x=1, y=2) ``` For reference, see the [related specification section](https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-for-keyword-arguments) and [PEP 692](https://peps.python.org/pep-0692/). /// version-added | v2.10 /// ## Using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function to describe function parameters The [`Field()` function](/docs/validation/latest/concepts/fields) can also be used with the decorator to provide extra information about the field and validations. If you don't make use of the `default` or `default_factory` parameter, it is recommended to use the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) (so that type checkers infer the parameter as being required). Otherwise, the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function can be used as a default value (again, to trick type checkers into thinking a default value is provided for the parameter). ```python from typing import Annotated from pydantic import Field, ValidationError, validate_call @validate_call def how_many(num: Annotated[int, Field(gt=10)]): return num try: how_many(1) except ValidationError as e: print(e) """ 1 validation error for how_many 0 Input should be greater than 10 [type=greater_than, input_value=1, input_type=int] """ @validate_call def return_value(value: str = Field(default='default value')): return value print(return_value()) #> default value ``` [Aliases](/docs/validation/latest/concepts/fields#field-aliases) can be used with the decorator as normal: ```python from typing import Annotated from pydantic import Field, validate_call @validate_call def how_many(num: Annotated[int, Field(gt=10, alias='number')]): return num how_many(number=42) ``` ## Accessing the original function The original function which was decorated can still be accessed by using the `raw_function` attribute. This is useful if in some scenarios you trust your input arguments and want to call the function in the most efficient way (see [notes on performance](#performance) below): ```python from pydantic import validate_call @validate_call def repeat(s: str, count: int, *, separator: bytes = b'') -> bytes: b = s.encode() return separator.join(b for _ in range(count)) a = repeat('hello', 3) print(a) #> b'hellohellohello' b = repeat.raw_function('good bye', 2, separator=b', ') print(b) #> b'good bye, good bye' ``` ## Async functions [`validate_call()`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) can also be used on async functions: ```python class Connection: async def execute(self, sql, *args): return 'testing@example.com' conn = Connection() # ignore-above import asyncio from pydantic import PositiveInt, ValidationError, validate_call @validate_call async def get_user_email(user_id: PositiveInt): # `conn` is some fictional connection to a database email = await conn.execute('select email from users where id=$1', user_id) if email is None: raise RuntimeError('user not found') else: return email async def main(): email = await get_user_email(123) print(email) #> testing@example.com try: await get_user_email(-4) except ValidationError as exc: print(exc.errors()) """ [ { 'type': 'greater_than', 'loc': (0,), 'msg': 'Input should be greater than 0', 'input': -4, 'ctx': {'gt': 0}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', } ] """ asyncio.run(main()) # requires: `conn.execute()` that will return `'testing@example.com'` ``` ## Compatibility with type checkers As the [`validate_call()`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) decorator preserves the decorated function's signature, it should be compatible with type checkers (such as mypy and pyright). However, due to current limitations in the Python type system, the [`raw_function`](#accessing-the-original-function) or other attributes won't be recognized and you will need to suppress the error using (usually with a `# type: ignore` comment). ## Custom configuration Similarly to Pydantic models, the `config` parameter of the decorator can be used to specify a custom configuration: ```python from pydantic import ConfigDict, ValidationError, validate_call class Foobar: def __init__(self, v: str): self.v = v def __add__(self, other: 'Foobar') -> str: return f'{self} + {other}' def __str__(self) -> str: return f'Foobar({self.v})' @validate_call(config=ConfigDict(arbitrary_types_allowed=True)) def add_foobars(a: Foobar, b: Foobar): return a + b c = add_foobars(Foobar('a'), Foobar('b')) print(c) #> Foobar(a) + Foobar(b) try: add_foobars(1, 2) except ValidationError as e: print(e) """ 2 validation errors for add_foobars 0 Input should be an instance of Foobar [type=is_instance_of, input_value=1, input_type=int] 1 Input should be an instance of Foobar [type=is_instance_of, input_value=2, input_type=int] """ ``` ## Extension -- validating arguments before calling a function In some cases, it may be helpful to separate validation of a function's arguments from the function call itself. This might be useful when a particular function is costly/time consuming. Here's an example of a workaround you can use for that pattern: ```python from pydantic import validate_call @validate_call def validate_foo(a: int, b: int): def foo(): return a + b return foo foo = validate_foo(a=1, b=2) print(foo()) #> 3 ``` ## Limitations ### Validation exception Currently upon validation failure, a standard Pydantic [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) is raised (see [model error handling](/docs/validation/latest/concepts/models#error-handling) for details). This is also true for missing required arguments, where Python normally raises a [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError). ### Performance We've made a big effort to make Pydantic as performant as possible. While the inspection of the decorated function is only performed once, there will still be a performance impact when making calls to the function compared to using the original function. In many situations, this will have little or no noticeable effect. However, be aware that [`validate_call()`](/docs/validation/latest/api/pydantic/validate_call/#pydantic.validate_call_decorator.validate_call) is not an equivalent or alternative to function definitions in strongly typed languages, and it never will be. --- # [Validators](https://pydantic.dev/docs/validation/latest/concepts/validators/) # Validators In addition to Pydantic's [built-in validation capabilities](/docs/validation/latest/concepts/fields#field-constraints), you can leverage custom validators at the field and model levels to enforce more complex constraints and ensure the integrity of your data. Tip Want to quickly jump to the relevant validator section? - Field validators * * * - [field _after_ validators](#field-after-validator) - [field _before_ validators](#field-before-validator) - [field _plain_ validators](#field-plain-validator) - [field _wrap_ validators](#field-wrap-validator) - Model validators * * * - [model _before_ validators](#model-before-validator) - [model _after_ validators](#model-after-validator) - [model _wrap_ validators](#model-wrap-validator) ## Field validators API Documentation [`pydantic.functional_validators.WrapValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.WrapValidator) [`pydantic.functional_validators.PlainValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.PlainValidator) [`pydantic.functional_validators.BeforeValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.BeforeValidator) [`pydantic.functional_validators.AfterValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.AfterValidator) [`pydantic.functional_validators.field_validator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.field_validator) In its simplest form, a field validator is a callable taking the value to be validated as an argument and **returning the validated value**. The callable can perform checks for specific conditions (see [raising validation errors](#raising-validation-errors)) and make changes to the validated value (coercion or mutation). **Four** different types of validators can be used. They can all be defined using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) or using the [`@field_validator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.field_validator) decorator, applied on a [class method](https://docs.python.org/3/library/functions.html#classmethod): - **_After_ validators**: run after Pydantic's internal validation. They are generally more type safe and thus easier to implement. - [Annotated pattern](#tab-panel-588) - [Decorator](#tab-panel-589) Here is an example of a validator performing a validation check, and returning the value unchanged. ```python from typing import Annotated from pydantic import AfterValidator, BaseModel, ValidationError def is_even(value: int) -> int: if value % 2 == 1: raise ValueError(f'{value} is not an even number') return value # (1) class Model(BaseModel): number: Annotated[int, AfterValidator(is_even)] try: Model(number=1) except ValidationError as err: print(err) """ 1 validation error for Model number Value error, 1 is not an even number [type=value_error, input_value=1, input_type=int] """ ``` Note that it is important to return the validated value. Here is an example of a validator performing a validation check, and returning the value unchanged, this time using the [`field_validator()`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.field_validator) decorator. ```python from pydantic import BaseModel, ValidationError, field_validator class Model(BaseModel): number: int @field_validator('number', mode='after') # (1) @classmethod def is_even(cls, value: int) -> int: if value % 2 == 1: raise ValueError(f'{value} is not an even number') return value # (2) try: Model(number=1) except ValidationError as err: print(err) """ 1 validation error for Model number Value error, 1 is not an even number [type=value_error, input_value=1, input_type=int] """ ``` `'after'` is the default mode for the decorator, and can be omitted. Note that it is important to return the validated value. Example mutating the value Here is an example of a validator making changes to the validated value (no exception is raised). - [Annotated pattern](#tab-panel-582) - [Decorator](#tab-panel-583) ```python from typing import Annotated from pydantic import AfterValidator, BaseModel def double_number(value: int) -> int: return value * 2 class Model(BaseModel): number: Annotated[int, AfterValidator(double_number)] print(Model(number=2)) #> number=4 ``` ```python from pydantic import BaseModel, field_validator class Model(BaseModel): number: int @field_validator('number', mode='after') # (1) @classmethod def double_number(cls, value: int) -> int: return value * 2 print(Model(number=2)) #> number=4 ``` `'after'` is the default mode for the decorator, and can be omitted. - **_Before_ validators**: run before Pydantic's internal parsing and validation (e.g. coercion of a `str` to an `int`). These are more flexible than [_after_ validators](#field-after-validator), but they also have to deal with the raw input, which in theory could be any arbitrary object. You should also avoid mutating the value directly if you are raising a [validation error](#raising-validation-errors) later in your validator function, as the mutated value may be passed to other validators if using [unions](/docs/validation/latest/concepts/unions). The value returned from this callable is then validated against the provided type annotation by Pydantic. - [Annotated pattern](#tab-panel-584) - [Decorator](#tab-panel-585) ```python from typing import Annotated, Any from pydantic import BaseModel, BeforeValidator, ValidationError def ensure_list(value: Any) -> Any: # (1) if not isinstance(value, list): # (2) return [value] else: return value class Model(BaseModel): numbers: Annotated[list[int], BeforeValidator(ensure_list)] print(Model(numbers=2)) #> numbers=[2] try: Model(numbers='str') except ValidationError as err: print(err) # (3) """ 1 validation error for Model numbers.0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='str', input_type=str] """ ``` Notice the use of [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) as a type hint for `value`. _Before_ validators take the raw input, which can be anything. Note that you might want to check for other sequence types (such as tuples) that would normally successfully validate against the `list` type. _Before_ validators give you more flexibility, but you have to account for every possible case. Pydantic still performs validation against the `int` type, no matter if our `ensure_list` validator did operations on the original input type. ```python from typing import Any from pydantic import BaseModel, ValidationError, field_validator class Model(BaseModel): numbers: list[int] @field_validator('numbers', mode='before') @classmethod def ensure_list(cls, value: Any) -> Any: # (1) if not isinstance(value, list): # (2) return [value] else: return value print(Model(numbers=2)) #> numbers=[2] try: Model(numbers='str') except ValidationError as err: print(err) # (3) """ 1 validation error for Model numbers.0 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='str', input_type=str] """ ``` Notice the use of [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) as a type hint for `value`. _Before_ validators take the raw input, which can be anything. Note that you might want to check for other sequence types (such as tuples) that would normally successfully validate against the `list` type. _Before_ validators give you more flexibility, but you have to account for every possible case. Pydantic still performs validation against the `int` type, no matter if our `ensure_list` validator did operations on the original input type. - **_Plain_ validators**: act similarly to _before_ validators but they **terminate validation immediately** after returning, so no further validators are called and Pydantic does not do any of its internal validation against the field type. - [Annotated pattern](#tab-panel-586) - [Decorator](#tab-panel-587) ```python from typing import Annotated, Any from pydantic import BaseModel, PlainValidator def val_number(value: Any) -> Any: if isinstance(value, int): return value * 2 else: return value class Model(BaseModel): number: Annotated[int, PlainValidator(val_number)] print(Model(number=4)) #> number=8 print(Model(number='invalid')) # (1) #> number='invalid' ``` Although `'invalid'` shouldn't validate against the `int` type, Pydantic accepts the input. ```python from typing import Any from pydantic import BaseModel, field_validator class Model(BaseModel): number: int @field_validator('number', mode='plain') @classmethod def val_number(cls, value: Any) -> Any: if isinstance(value, int): return value * 2 else: return value print(Model(number=4)) #> number=8 print(Model(number='invalid')) # (1) #> number='invalid' ``` Although `'invalid'` shouldn't validate against the `int` type, Pydantic accepts the input. - **_Wrap_ validators**: are the most flexible of all. You can run code before or after Pydantic and other validators process the input, or you can terminate validation immediately, either by returning the value early or by raising an error. Such validators must be defined with a **mandatory** extra _handler_ parameter: a callable taking the value to be validated as an argument. Internally, this handler will delegate validation of the value to Pydantic. You are free to wrap the call to the handler in a `try..except` block, or not call it at all. - [Annotated pattern](#tab-panel-580) - [Decorator](#tab-panel-581) ```python from typing import Any from typing import Annotated from pydantic import BaseModel, Field, ValidationError, ValidatorFunctionWrapHandler, WrapValidator def truncate(value: Any, handler: ValidatorFunctionWrapHandler) -> str: try: return handler(value) except ValidationError as err: if err.errors()[0]['type'] == 'string_too_long': return handler(value[:5]) else: raise class Model(BaseModel): my_string: Annotated[str, Field(max_length=5), WrapValidator(truncate)] print(Model(my_string='abcde')) #> my_string='abcde' print(Model(my_string='abcdef')) #> my_string='abcde' ``` ```python from typing import Any from typing import Annotated from pydantic import BaseModel, Field, ValidationError, ValidatorFunctionWrapHandler, field_validator class Model(BaseModel): my_string: Annotated[str, Field(max_length=5)] @field_validator('my_string', mode='wrap') @classmethod def truncate(cls, value: Any, handler: ValidatorFunctionWrapHandler) -> str: try: return handler(value) except ValidationError as err: if err.errors()[0]['type'] == 'string_too_long': return handler(value[:5]) else: raise print(Model(my_string='abcde')) #> my_string='abcde' print(Model(my_string='abcdef')) #> my_string='abcde' ``` Validation of default values As mentioned in the [fields documentation](/docs/validation/latest/concepts/fields#validate-default-values), default values of fields are _not_ validated unless configured to do so, and thus custom validators will not be applied as well. ### Which validator pattern to use While both approaches can achieve the same thing, each pattern provides different benefits. #### Using the annotated pattern One of the key benefits of using the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) is to make validators reusable: ```python from typing import Annotated from pydantic import AfterValidator, BaseModel def is_even(value: int) -> int: if value % 2 == 1: raise ValueError(f'{value} is not an even number') return value EvenNumber = Annotated[int, AfterValidator(is_even)] class Model1(BaseModel): my_number: EvenNumber class Model2(BaseModel): other_number: Annotated[EvenNumber, AfterValidator(lambda v: v + 2)] class Model3(BaseModel): list_of_even_numbers: list[EvenNumber] # (1) ``` As mentioned in the [annotated pattern](/docs/validation/latest/concepts/fields#the-annotated-pattern) documentation, we can also make use of validators for specific parts of the annotation (in this case, validation is applied for list items, but not the whole list). It is also easier to understand which validators are applied to a type, by just looking at the field annotation. #### Using the decorator pattern One of the key benefits of using the [`field_validator()`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.field_validator) decorator is to apply the function to multiple fields: ```python from pydantic import BaseModel, field_validator class Model(BaseModel): f1: str f2: str @field_validator('f1', 'f2', mode='before') @classmethod def capitalize(cls, value: str) -> str: return value.capitalize() ``` Here are a couple additional notes about the decorator usage: - If you want the validator to apply to all fields (including the ones defined in subclasses), you can pass `'*'` as the field name argument. - By default, the decorator will ensure the provided field name(s) are defined on the model. If you want to disable this check during class creation, you can do so by passing `False` to the `check_fields` argument. This is useful when the field validator is defined on a base class, and the field is expected to exist on subclasses. ## Model validators API Documentation [`pydantic.functional_validators.model_validator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.model_validator) Validation can also be performed on the entire model's data using the [`model_validator()`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.model_validator) decorator. **Three** different types of model validators can be used: - **_After_ validators**: run after the whole model has been validated. As such, they are defined as _instance_ methods and can be seen as post-initialization hooks. Important note: the validated instance should be returned. ```python from typing_extensions import Self from pydantic import BaseModel, model_validator class UserModel(BaseModel): username: str password: str password_repeat: str @model_validator(mode='after') def check_passwords_match(self) -> Self: if self.password != self.password_repeat: raise ValueError('Passwords do not match') return self ``` - **_Before_ validators**: are run before the model is instantiated. These are more flexible than _after_ validators, but they also have to deal with the raw input, which in theory could be any arbitrary object. You should also avoid mutating the value directly if you are raising a [validation error](#raising-validation-errors) later in your validator function, as the mutated value may be passed to other validators if using [unions](/docs/validation/latest/concepts/unions). ```python from typing import Any from pydantic import BaseModel, model_validator class UserModel(BaseModel): username: str @model_validator(mode='before') @classmethod def check_card_number_not_present(cls, data: Any) -> Any: # (1) if isinstance(data, dict): # (2) if 'card_number' in data: raise ValueError("'card_number' should not be included") return data ``` Notice the use of [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) as a type hint for `data`. _Before_ validators take the raw input, which can be anything. Most of the time, the input data will be a dictionary (e.g. when calling `UserModel(username='...')`). However, this is not always the case. For instance, if the [`from_attributes`](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.from_attributes) configuration value is set, you might receive an arbitrary class instance for the `data` argument. - **_Wrap_ validators**: are the most flexible of all. You can run code before or after Pydantic and other validators process the input data, or you can terminate validation immediately, either by returning the data early or by raising an error. ```python import logging from typing import Any from typing_extensions import Self from pydantic import BaseModel, ModelWrapValidatorHandler, ValidationError, model_validator class UserModel(BaseModel): username: str @model_validator(mode='wrap') @classmethod def log_failed_validation(cls, data: Any, handler: ModelWrapValidatorHandler[Self]) -> Self: try: return handler(data) except ValidationError: logging.error('Model %s failed to validate with data %s', cls, data) raise ``` On inheritance A model validator defined in a base class will be called during the validation of a subclass instance. Overriding a model validator in a subclass will override the base class' validator, and thus only the subclass' version of said validator will be called. ## Raising validation errors To raise a validation error, three types of exceptions can be used: - [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError): this is the most common exception raised inside validators. - [`AssertionError`](https://docs.python.org/3/library/exceptions.html#AssertionError): using the [assert](https://docs.python.org/3/reference/simple_stmts.html#assert) statement also works, but be aware that these statements are skipped when Python is run with the [\-O](https://docs.python.org/3/using/cmdline.html#cmdoption-O) optimization flag. - [`PydanticCustomError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticCustomError): a bit more verbose, but provides extra flexibility: ```python from pydantic_core import PydanticCustomError from pydantic import BaseModel, ValidationError, field_validator class Model(BaseModel): x: int @field_validator('x', mode='after') @classmethod def validate_x(cls, v: int) -> int: if v % 42 == 0: raise PydanticCustomError( 'the_answer_error', '{number} is the answer!', {'number': v}, ) return v try: Model(x=42 * 2) except ValidationError as e: print(e) """ 1 validation error for Model x 84 is the answer! [type=the_answer_error, input_value=84, input_type=int] """ ``` ## Validation info Both the field and model validators callables (in all modes) can optionally take an extra [`ValidationInfo`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo) argument, providing useful extra information, such as: - [already validated data](#validation-data) - [user defined context](#validation-context) - the current [validation mode](/docs/validation/latest/concepts/models#validating-data): either `'python'`, `'json'` or `'strings'` (see the [`mode`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.mode) property) - the current field name, if using a [field validator](#field-validators) (see the [`field_name`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.field_name) property). ### Validation data For field validators, the already validated data can be accessed using the [`data`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.data) property. Here is an example than can be used as an alternative to the [_after_ model validator](#model-after-validator) example: ```python from pydantic import BaseModel, ValidationInfo, field_validator class UserModel(BaseModel): password: str password_repeat: str username: str @field_validator('password_repeat', mode='after') @classmethod def check_passwords_match(cls, value: str, info: ValidationInfo) -> str: if value != info.data['password']: raise ValueError('Passwords do not match') return value ``` Caution As validation is performed in the [order fields are defined](/docs/validation/latest/concepts/models#field-ordering), you have to make sure you are not accessing a field that hasn't been validated yet. In the code above, for example, the `username` validated value is not available yet, as it is defined _after_ `password_repeat`. The [`data`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.data) property is `None` for [model validators](#model-validators). ### Validation context You can pass a context object to the [validation methods](/docs/validation/latest/concepts/models#validating-data), which can be accessed inside the validator functions using the [`context`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.ValidationInfo.context) property: ```python from pydantic import BaseModel, ValidationInfo, field_validator class Model(BaseModel): text: str @field_validator('text', mode='after') @classmethod def remove_stopwords(cls, v: str, info: ValidationInfo) -> str: if isinstance(info.context, dict): stopwords = info.context.get('stopwords', set()) v = ' '.join(w for w in v.split() if w.lower() not in stopwords) return v data = {'text': 'This is an example document'} print(Model.model_validate(data)) # no context #> text='This is an example document' print(Model.model_validate(data, context={'stopwords': ['this', 'is', 'an']})) #> text='example document' ``` Similarly, you can [use a context for serialization](/docs/validation/latest/concepts/serialization#serialization-context). Providing context when directly instantiating a model It is currently not possible to provide a context when directly instantiating a model (i.e. when calling `Model(...)`). You can work around this through the use of a [`ContextVar`](https://docs.python.org/3/library/contextvars.html#contextvars.ContextVar) and a custom `__init__` method: ```python from __future__ import annotations from collections.abc import Generator from contextlib import contextmanager from contextvars import ContextVar from typing import Any from pydantic import BaseModel, ValidationInfo, field_validator _init_context_var = ContextVar('_init_context_var', default=None) @contextmanager def init_context(value: dict[str, Any]) -> Generator[None]: token = _init_context_var.set(value) try: yield finally: _init_context_var.reset(token) class Model(BaseModel): my_number: int def __init__(self, /, **data: Any) -> None: self.__pydantic_validator__.validate_python( data, self_instance=self, context=_init_context_var.get(), ) @field_validator('my_number') @classmethod def multiply_with_context(cls, value: int, info: ValidationInfo) -> int: if isinstance(info.context, dict): multiplier = info.context.get('multiplier', 1) value = value * multiplier return value print(Model(my_number=2)) #> my_number=2 with init_context({'multiplier': 3}): print(Model(my_number=2)) #> my_number=6 print(Model(my_number=2)) #> my_number=2 ``` ## Ordering of validators When using the [annotated pattern](#using-the-annotated-pattern), the order in which validators are applied is defined as follows: [_before_](#field-before-validator) and [_wrap_](#field-wrap-validator) validators are run from right to left, and [_after_](#field-after-validator) validators are then run from left to right: ```python from pydantic import AfterValidator, BaseModel, BeforeValidator, WrapValidator class Model(BaseModel): name: Annotated[ str, AfterValidator(runs_3rd), AfterValidator(runs_4th), BeforeValidator(runs_2nd), WrapValidator(runs_1st), ] ``` Internally, validators defined using [the decorator](#using-the-decorator-pattern) are converted to their annotated form counterpart and added last after the existing metadata for the field. This means that the same ordering logic applies. ## Special types Pydantic provides a few special utilities that can be used to customize validation. - [`InstanceOf`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.InstanceOf) can be used to validate that a value is an instance of a given class. ```python from pydantic import BaseModel, InstanceOf, ValidationError class Fruit: def __repr__(self): return self.__class__.__name__ class Banana(Fruit): ... class Apple(Fruit): ... class Basket(BaseModel): fruits: list[InstanceOf[Fruit]] print(Basket(fruits=[Banana(), Apple()])) #> fruits=[Banana, Apple] try: Basket(fruits=[Banana(), 'Apple']) except ValidationError as e: print(e) """ 1 validation error for Basket fruits.1 Input should be an instance of Fruit [type=is_instance_of, input_value='Apple', input_type=str] """ ``` - [`SkipValidation`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.SkipValidation) can be used to skip validation on a field. ```python from pydantic import BaseModel, SkipValidation class Model(BaseModel): names: list[SkipValidation[str]] m = Model(names=['foo', 'bar']) print(m) #> names=['foo', 'bar'] m = Model(names=['foo', 123]) # (1) print(m) #> names=['foo', 123] ``` Note that the validation of the second item is skipped. If it has the wrong type it will emit a warning during serialization. - [`ValidateAs`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.ValidateAs) can be used to validate an custom type from a type natively supported by Pydantic. This is particularly useful when using custom types with multiple fields. ```python from typing import Annotated from pydantic import BaseModel, TypeAdapter, ValidateAs class MyCls: def __init__(self, a: int) -> None: self.a = a def __repr__(self) -> str: return f"MyCls(a={self.a})" class ValModel(BaseModel): a: int ta = TypeAdapter( Annotated[MyCls, ValidateAs(ValModel, lambda v: MyCls(a=v.a))] ) print(ta.validate_python({'a': 1})) #> MyCls(a=1) ``` - [`PydanticUseDefault`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.PydanticUseDefault) can be used to notify Pydantic that the default value should be used. ```python from typing import Annotated, Any from pydantic_core import PydanticUseDefault from pydantic import BaseModel, BeforeValidator def default_if_none(value: Any) -> Any: if value is None: raise PydanticUseDefault() return value class Model(BaseModel): name: Annotated[str, BeforeValidator(default_if_none)] = 'default_name' print(Model(name=None)) #> name='default_name' ``` ## JSON Schema and field validators When using [_before_](#field-before-validator), [_plain_](#field-plain-validator) or [_wrap_](#field-wrap-validator) field validators, the accepted input type may be different from the field annotation. Consider the following example: ```python from typing import Any from pydantic import BaseModel, field_validator class Model(BaseModel): value: str @field_validator('value', mode='before') @classmethod def cast_ints(cls, value: Any) -> Any: if isinstance(value, int): return str(value) else: return value print(Model(value='a')) #> value='a' print(Model(value=1)) #> value='1' ``` While the type hint for `value` is `str`, the `cast_ints` validator also allows integers. To specify the correct input type, the `json_schema_input_type` argument can be provided: ```python from typing import Any, Union from pydantic import BaseModel, field_validator class Model(BaseModel): value: str @field_validator( 'value', mode='before', json_schema_input_type=Union[int, str] ) @classmethod def cast_ints(cls, value: Any) -> Any: if isinstance(value, int): return str(value) else: return value print(Model.model_json_schema()['properties']['value']) #> {'anyOf': [{'type': 'integer'}, {'type': 'string'}], 'title': 'Value'} ``` As a convenience, Pydantic will use the field type if the argument is not provided (unless you are using a [_plain_](#field-plain-validator) validator, in which case `json_schema_input_type` defaults to [`Any`](https://docs.python.org/3/library/typing.html#typing.Any) as the field type is completely discarded). --- # [Error Handling](https://pydantic.dev/docs/validation/latest/errors/errors/) # Error Handling Pydantic will raise a `ValidationError` whenever it finds an error in the data it's validating. Note Validation code should not raise the `ValidationError` itself, but rather raise a `ValueError` or a `AssertionError` (or subclass thereof) which will be caught and used to populate the final `ValidationError`. For more details, refer to the [dedicated section](/docs/validation/latest/concepts/validators#raising-validation-errors) of the validators documentation. That `ValidationError` will contain information about all the errors and how they happened. You can access these errors in several ways: Method Description `errors()` Returns a list of `ErrorDetails` errors found in the input data. `error_count()` Returns the number of errors. `json()` Returns a JSON representation of the list errors. `str(e)` Returns a human-readable representation of the errors. The `ErrorDetails` object is a dictionary. It contains the following: Property Description `ctx` An optional object which contains values required to render the error message. `input` The input provided for validation. `loc` The error's location as a list. `msg` A human-readable explanation of the error. `type` A computer-readable identifier of the error type. `url` The documentation URL giving information about the error. The first item in the `loc` list will be the field where the error occurred, and if the field is a [sub-model](/docs/validation/latest/concepts/models#nested-models), subsequent items will be present to indicate the nested location of the error. As a demonstration: ```python from pydantic import BaseModel, Field, ValidationError, field_validator class Location(BaseModel): lat: float = 0.1 lng: float = 10.1 class Model(BaseModel): is_required: float gt_int: int = Field(gt=42) list_of_ints: list[int] a_float: float recursive_model: Location @field_validator('a_float', mode='after') @classmethod def validate_float(cls, value: float) -> float: if value > 2.0: raise ValueError('Invalid float value') return value data = { 'list_of_ints': ['1', 2, 'bad'], 'a_float': 3.0, 'recursive_model': {'lat': 4.2, 'lng': 'New York'}, 'gt_int': 21, } try: Model(**data) except ValidationError as e: print(e) """ 5 validation errors for Model is_required Field required [type=missing, input_value={'list_of_ints': ['1', 2,...ew York'}, 'gt_int': 21}, input_type=dict] gt_int Input should be greater than 42 [type=greater_than, input_value=21, input_type=int] list_of_ints.2 Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='bad', input_type=str] a_float Value error, Invalid float value [type=value_error, input_value=3.0, input_type=float] recursive_model.lng Input should be a valid number, unable to parse string as a number [type=float_parsing, input_value='New York', input_type=str] """ try: Model(**data) except ValidationError as e: print(e.errors()) """ [ { 'type': 'missing', 'loc': ('is_required',), 'msg': 'Field required', 'input': { 'list_of_ints': ['1', 2, 'bad'], 'a_float': 3.0, 'recursive_model': {'lat': 4.2, 'lng': 'New York'}, 'gt_int': 21, }, 'url': 'https://errors.pydantic.dev/2/v/missing', }, { 'type': 'greater_than', 'loc': ('gt_int',), 'msg': 'Input should be greater than 42', 'input': 21, 'ctx': {'gt': 42}, 'url': 'https://errors.pydantic.dev/2/v/greater_than', }, { 'type': 'int_parsing', 'loc': ('list_of_ints', 2), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'bad', 'url': 'https://errors.pydantic.dev/2/v/int_parsing', }, { 'type': 'value_error', 'loc': ('a_float',), 'msg': 'Value error, Invalid float value', 'input': 3.0, 'ctx': {'error': ValueError('Invalid float value')}, 'url': 'https://errors.pydantic.dev/2/v/value_error', }, { 'type': 'float_parsing', 'loc': ('recursive_model', 'lng'), 'msg': 'Input should be a valid number, unable to parse string as a number', 'input': 'New York', 'url': 'https://errors.pydantic.dev/2/v/float_parsing', }, ] """ ``` ## Error messages Pydantic attempts to provide useful default error messages for validation and usage errors, which can be found here: - [Validation Errors](/docs/validation/latest/errors/validation_errors): Errors that happen during data validation. - [Usage Errors](/docs/validation/latest/errors/usage_errors): Errors that happen when using Pydantic. ### Customize error messages You can customize error messages by creating a custom error handler. ```python from pydantic_core import ErrorDetails from pydantic import BaseModel, HttpUrl, ValidationError CUSTOM_MESSAGES = { 'int_parsing': 'This is not an integer! 🤦', 'url_scheme': 'Hey, use the right URL scheme! I wanted {expected_schemes}.', } def convert_errors( e: ValidationError, custom_messages: dict[str, str] ) -> list[ErrorDetails]: new_errors: list[ErrorDetails] = [] for error in e.errors(): custom_message = custom_messages.get(error['type']) if custom_message: ctx = error.get('ctx') error['msg'] = ( custom_message.format(**ctx) if ctx else custom_message ) new_errors.append(error) return new_errors class Model(BaseModel): a: int b: HttpUrl try: Model(a='wrong', b='ftp://example.com') except ValidationError as e: errors = convert_errors(e, CUSTOM_MESSAGES) print(errors) """ [ { 'type': 'int_parsing', 'loc': ('a',), 'msg': 'This is not an integer! 🤦', 'input': 'wrong', 'url': 'https://errors.pydantic.dev/2/v/int_parsing', }, { 'type': 'url_scheme', 'loc': ('b',), 'msg': "Hey, use the right URL scheme! I wanted 'http' or 'https'.", 'input': 'ftp://example.com', 'ctx': {'expected_schemes': "'http' or 'https'"}, 'url': 'https://errors.pydantic.dev/2/v/url_scheme', }, ] """ ``` A common use case would be to translate error messages. For example, in the above example, we could translate the error messages replacing the `CUSTOM_MESSAGES` dictionary with a dictionary of translations. Another example is customizing the way that the `'loc'` value of an error is represented. ```python from typing import Any, Union from pydantic import BaseModel, ValidationError def loc_to_dot_sep(loc: tuple[Union[str, int], ...]) -> str: path = '' for i, x in enumerate(loc): if isinstance(x, str): if i > 0: path += '.' path += x elif isinstance(x, int): path += f'[{x}]' else: raise TypeError('Unexpected type') return path def convert_errors(e: ValidationError) -> list[dict[str, Any]]: new_errors: list[dict[str, Any]] = e.errors() for error in new_errors: error['loc'] = loc_to_dot_sep(error['loc']) return new_errors class TestNestedModel(BaseModel): key: str value: str class TestModel(BaseModel): items: list[TestNestedModel] data = {'items': [{'key': 'foo', 'value': 'bar'}, {'key': 'baz'}]} try: TestModel.model_validate(data) except ValidationError as e: print(e.errors()) # (1) """ [ { 'type': 'missing', 'loc': ('items', 1, 'value'), 'msg': 'Field required', 'input': {'key': 'baz'}, 'url': 'https://errors.pydantic.dev/2/v/missing', } ] """ pretty_errors = convert_errors(e) print(pretty_errors) # (2) """ [ { 'type': 'missing', 'loc': 'items[1].value', 'msg': 'Field required', 'input': {'key': 'baz'}, 'url': 'https://errors.pydantic.dev/2/v/missing', } ] """ ``` By default, `e.errors()` produces a list of errors with `loc` values that take the form of tuples. With our custom `loc_to_dot_sep` function, we've modified the form of the `loc` representation. --- # [Usage Errors](https://pydantic.dev/docs/validation/latest/errors/usage_errors/) # Usage Errors Pydantic attempts to provide useful errors. The following sections provide details on common errors developers may encounter when working with Pydantic, along with suggestions for addressing the error condition. ## Class not fully defined This error is raised when a type referenced in an annotation of a pydantic-validated type (such as a subclass of `BaseModel`, or a pydantic `dataclass`) is not defined: ```python from typing import ForwardRef from pydantic import BaseModel, PydanticUserError UndefinedType = ForwardRef('UndefinedType') class Foobar(BaseModel): a: UndefinedType try: Foobar(a=1) except PydanticUserError as exc_info: assert exc_info.code == 'class-not-fully-defined' ``` Or when the type has been defined after usage: ```python from typing import Optional from pydantic import BaseModel, PydanticUserError class Foo(BaseModel): a: Optional['Bar'] = None try: # this doesn't work, see raised error foo = Foo(a={'b': {'a': None}}) except PydanticUserError as exc_info: assert exc_info.code == 'class-not-fully-defined' class Bar(BaseModel): b: 'Foo' # this works, though foo = Foo(a={'b': {'a': None}}) ``` For BaseModel subclasses, it can be fixed by defining the type and then calling `.model_rebuild()`: ```python from typing import Optional from pydantic import BaseModel class Foo(BaseModel): a: Optional['Bar'] = None class Bar(BaseModel): b: 'Foo' Foo.model_rebuild() foo = Foo(a={'b': {'a': None}}) ``` In other cases, the error message should indicate how to rebuild the class with the appropriate type defined. ## Custom JSON Schema The `__modify_schema__` method is no longer supported in V2. You should use the `__get_pydantic_json_schema__` method instead. The `__modify_schema__` used to receive a single argument representing the JSON schema. See the example below: Old way ```python from pydantic import BaseModel, PydanticUserError try: class Model(BaseModel): @classmethod def __modify_schema__(cls, field_schema): field_schema.update(examples=['example']) except PydanticUserError as exc_info: assert exc_info.code == 'custom-json-schema' ``` The new method `__get_pydantic_json_schema__` receives two arguments: the first is a dictionary denoted as `CoreSchema`, and the second a callable `handler` that receives a `CoreSchema` as parameter, and returns a JSON schema. See the example below: New way ```python from typing import Any from pydantic_core import CoreSchema from pydantic import BaseModel, GetJsonSchemaHandler class Model(BaseModel): @classmethod def __get_pydantic_json_schema__( cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler ) -> dict[str, Any]: json_schema = super().__get_pydantic_json_schema__(core_schema, handler) json_schema = handler.resolve_ref_schema(json_schema) json_schema.update(examples=['example']) return json_schema print(Model.model_json_schema()) """ {'examples': ['example'], 'properties': {}, 'title': 'Model', 'type': 'object'} """ ``` ## Invalid decorator fields This error is raised when the field names provided to the `@field_validator` or `@field_serializer` decorators are not strings. ```python from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: str b: str @field_validator(['a', 'b']) @classmethod def check_fields(cls, v): return v except PydanticUserError as exc_info: assert exc_info.code == 'decorator-invalid-fields' ``` Fields should be provided as separate string arguments: ```python from pydantic import BaseModel, field_validator class Model(BaseModel): a: str b: str @field_validator('a', 'b') @classmethod def check_fields(cls, v): return v ``` ## Decorator with no fields This error is raised when the `@field_validator` or `@field_serializer` decorators are used bare, without any arguments. ```python from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: str @field_validator @classmethod def checker(cls, v): return v except PydanticUserError as exc_info: assert exc_info.code == 'decorator-missing-arguments' ``` At least one field name (and optionally other field names and keyword arguments) should be provided. ```python from pydantic import BaseModel, field_validator class Model(BaseModel): a: str @field_validator('a') @classmethod def checker(cls, v): return v ``` ## Decorator on missing field This error is raised when you define a decorator with a field that is not valid. ```python from typing import Any from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: str @field_validator('b') def check_b(cls, v: Any): return v except PydanticUserError as exc_info: assert exc_info.code == 'decorator-missing-field' ``` You can use `check_fields=False` if you're inheriting from the model and intended this. ```python from typing import Any from pydantic import BaseModel, create_model, field_validator class Model(BaseModel): @field_validator('a', check_fields=False) def check_a(cls, v: Any): return v model = create_model('FooModel', a=(str, 'cake'), __base__=Model) ``` ## Discriminator no field This error is raised when a model in discriminated unions doesn't define a discriminator field. ```python from typing import Literal, Union from pydantic import BaseModel, Field, PydanticUserError class Cat(BaseModel): c: str class Dog(BaseModel): pet_type: Literal['dog'] d: str try: class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') number: int except PydanticUserError as exc_info: assert exc_info.code == 'discriminator-no-field' ``` ## Discriminator alias type This error is raised when you define a non-string alias on a discriminator field. ```python from typing import Literal, Union from pydantic import AliasChoices, BaseModel, Field, PydanticUserError class Cat(BaseModel): pet_type: Literal['cat'] = Field( validation_alias=AliasChoices('Pet', 'PET') ) c: str class Dog(BaseModel): pet_type: Literal['dog'] d: str try: class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') number: int except PydanticUserError as exc_info: assert exc_info.code == 'discriminator-alias-type' ``` ## Discriminator needs literal This error is raised when you define a non-`Literal` type on a discriminator field. ```python from typing import Literal, Union from pydantic import BaseModel, Field, PydanticUserError class Cat(BaseModel): pet_type: int c: str class Dog(BaseModel): pet_type: Literal['dog'] d: str try: class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') number: int except PydanticUserError as exc_info: assert exc_info.code == 'discriminator-needs-literal' ``` ## Discriminator alias This error is raised when you define different aliases on discriminator fields. ```python from typing import Literal, Union from pydantic import BaseModel, Field, PydanticUserError class Cat(BaseModel): pet_type: Literal['cat'] = Field(validation_alias='PET') c: str class Dog(BaseModel): pet_type: Literal['dog'] = Field(validation_alias='Pet') d: str try: class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') number: int except PydanticUserError as exc_info: assert exc_info.code == 'discriminator-alias' ``` ## Invalid discriminator validator This error is raised when you use a before, wrap, or plain validator on a discriminator field. This is disallowed because the discriminator field is used to determine the type of the model to use for validation, so you can't use a validator that might change its value. ```python from typing import Literal, Union from pydantic import BaseModel, Field, PydanticUserError, field_validator class Cat(BaseModel): pet_type: Literal['cat'] @field_validator('pet_type', mode='before') @classmethod def validate_pet_type(cls, v): if v == 'kitten': return 'cat' return v class Dog(BaseModel): pet_type: Literal['dog'] try: class Model(BaseModel): pet: Union[Cat, Dog] = Field(discriminator='pet_type') number: int except PydanticUserError as exc_info: assert exc_info.code == 'discriminator-validator' ``` This can be worked around by using a standard `Union`, dropping the discriminator: ```python from typing import Literal, Union from pydantic import BaseModel, field_validator class Cat(BaseModel): pet_type: Literal['cat'] @field_validator('pet_type', mode='before') @classmethod def validate_pet_type(cls, v): if v == 'kitten': return 'cat' return v class Dog(BaseModel): pet_type: Literal['dog'] class Model(BaseModel): pet: Union[Cat, Dog] assert Model(pet={'pet_type': 'kitten'}).pet.pet_type == 'cat' ``` ## Callable discriminator case with no tag This error is raised when a `Union` that uses a callable `Discriminator` doesn't have `Tag` annotations for all cases. ```python from typing import Annotated, Union from pydantic import BaseModel, Discriminator, PydanticUserError, Tag def model_x_discriminator(v): if isinstance(v, str): return 'str' if isinstance(v, (dict, BaseModel)): return 'model' # tag missing for both union choices try: class DiscriminatedModel(BaseModel): x: Annotated[ Union[str, 'DiscriminatedModel'], Discriminator(model_x_discriminator), ] except PydanticUserError as exc_info: assert exc_info.code == 'callable-discriminator-no-tag' # tag missing for `'DiscriminatedModel'` union choice try: class DiscriminatedModel(BaseModel): x: Annotated[ Union[Annotated[str, Tag('str')], 'DiscriminatedModel'], Discriminator(model_x_discriminator), ] except PydanticUserError as exc_info: assert exc_info.code == 'callable-discriminator-no-tag' # tag missing for `str` union choice try: class DiscriminatedModel(BaseModel): x: Annotated[ Union[str, Annotated['DiscriminatedModel', Tag('model')]], Discriminator(model_x_discriminator), ] except PydanticUserError as exc_info: assert exc_info.code == 'callable-discriminator-no-tag' ``` ## `TypedDict` version This error is raised when you use typing.TypedDict instead of `typing_extensions.TypedDict` on Python < 3.12. ## Model parent field overridden This error is raised when a field defined on a base class was overridden by a non-annotated attribute. ```python from pydantic import BaseModel, PydanticUserError class Foo(BaseModel): a: float try: class Bar(Foo): x: float = 12.3 a = 123.0 except PydanticUserError as exc_info: assert exc_info.code == 'model-field-overridden' ``` ## Model field missing annotation This error is raised when a field doesn't have an annotation. ```python from pydantic import BaseModel, Field, PydanticUserError try: class Model(BaseModel): a = Field('foobar') b = None except PydanticUserError as exc_info: assert exc_info.code == 'model-field-missing-annotation' ``` If the field is not meant to be a field, you may be able to resolve the error by annotating it as a `ClassVar`: ```python from typing import ClassVar from pydantic import BaseModel class Model(BaseModel): a: ClassVar[str] ``` Or updating `model_config['ignored_types']`: ```python from pydantic import BaseModel, ConfigDict class IgnoredType: pass class MyModel(BaseModel): model_config = ConfigDict(ignored_types=(IgnoredType,)) _a = IgnoredType() _b: int = IgnoredType() _c: IgnoredType _d: IgnoredType = IgnoredType() ``` ## `Config` and `model_config` both defined This error is raised when `class Config` and `model_config` are used together. ```python from pydantic import BaseModel, ConfigDict, PydanticUserError try: class Model(BaseModel): model_config = ConfigDict(from_attributes=True) a: str class Config: from_attributes = True except PydanticUserError as exc_info: assert exc_info.code == 'config-both' ``` ## Keyword arguments removed This error is raised when the keyword arguments are not available in Pydantic V2. For example, `regex` is removed from Pydantic V2: ```python from pydantic import BaseModel, Field, PydanticUserError try: class Model(BaseModel): x: str = Field(regex='test') except PydanticUserError as exc_info: assert exc_info.code == 'removed-kwargs' ``` ## Circular reference schema This error is raised when a circular reference is found that would otherwise result in an infinite recursion. For example, this is a valid type alias: ```python type A = list[A] | None ``` while these are not: ```python type A = A type B = C type C = B ``` ## JSON schema invalid type This error is raised when Pydantic fails to generate a JSON schema for some `CoreSchema`. ```python from pydantic import BaseModel, ImportString, PydanticUserError class Model(BaseModel): a: ImportString try: Model.model_json_schema() except PydanticUserError as exc_info: assert exc_info.code == 'invalid-for-json-schema' ``` ## JSON schema already used This error is raised when the JSON schema generator has already been used to generate a JSON schema. You must create a new instance to generate a new JSON schema. ## BaseModel instantiated This error is raised when you instantiate `BaseModel` directly. Pydantic models should inherit from `BaseModel`. ```python from pydantic import BaseModel, PydanticUserError try: BaseModel() except PydanticUserError as exc_info: assert exc_info.code == 'base-model-instantiated' ``` ## Undefined annotation This error is raised when handling undefined annotations during `CoreSchema` generation. ```python from pydantic import BaseModel, PydanticUndefinedAnnotation class Model(BaseModel): a: 'B' # noqa F821 try: Model.model_rebuild() except PydanticUndefinedAnnotation as exc_info: assert exc_info.code == 'undefined-annotation' ``` ## Schema for unknown type This error is raised when Pydantic fails to generate a `CoreSchema` for some type. ```python from pydantic import BaseModel, PydanticUserError try: class Model(BaseModel): x: 43 = 123 except PydanticUserError as exc_info: assert exc_info.code == 'schema-for-unknown-type' ``` ## Import error This error is raised when you try to import an object that was available in Pydantic V1, but has been removed in Pydantic V2. See the [Migration Guide](/docs/validation/latest/get-started/migration) for more information. ## `create_model` field definitions This error is raised when you provide invalid field definitions in `create_model()`. ```python from pydantic import PydanticUserError, create_model try: create_model('FooModel', foo=(str, 'default value', 'more')) except PydanticUserError as exc_info: assert exc_info.code == 'create-model-field-definitions' ``` The fields definition syntax can be found in the [dynamic model creation](/docs/validation/latest/concepts/models#dynamic-model-creation) documentation. ## Validator on instance method This error is raised when you apply a validator on an instance method. ```python from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: int = 1 @field_validator('a') def check_a(self, value): return value except PydanticUserError as exc_info: assert exc_info.code == 'validator-instance-method' ``` ## `json_schema_input_type` used with the wrong mode This error is raised when you explicitly specify a value for the `json_schema_input_type` argument and `mode` isn't set to either `'before'`, `'plain'` or `'wrap'`. ```python from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: int = 1 @field_validator('a', mode='after', json_schema_input_type=int) @classmethod def check_a(self, value): return value except PydanticUserError as exc_info: assert exc_info.code == 'validator-input-type' ``` Documenting the JSON Schema input type is only possible for validators where the given value can be anything. That is why it isn't available for `after` validators, where the value is first validated against the type annotation. ## Root validator, `pre`, `skip_on_failure` If you use `@root_validator` with `pre=False` (the default) you MUST specify `skip_on_failure=True`. The `skip_on_failure=False` option is no longer available. If you were not trying to set `skip_on_failure=False`, you can safely set `skip_on_failure=True`. If you do, this root validator will no longer be called if validation fails for any of the fields. Please see the [Migration Guide](/docs/validation/latest/get-started/migration) for more details. ## `model_serializer` instance methods `@model_serializer` must be applied to instance methods. This error is raised when you apply `model_serializer` on an instance method without `self`: ```python from pydantic import BaseModel, PydanticUserError, model_serializer try: class MyModel(BaseModel): a: int @model_serializer def _serialize(slf, x, y, z): return slf except PydanticUserError as exc_info: assert exc_info.code == 'model-serializer-instance-method' ``` Or on a class method: ```python from pydantic import BaseModel, PydanticUserError, model_serializer try: class MyModel(BaseModel): a: int @model_serializer @classmethod def _serialize(self, x, y, z): return self except PydanticUserError as exc_info: assert exc_info.code == 'model-serializer-instance-method' ``` ## `validator`, `field`, `config`, and `info` The `field` and `config` parameters are not available in Pydantic V2. Please use the `info` parameter instead. You can access the configuration via `info.config`, but it is a dictionary instead of an object like it was in Pydantic V1. The `field` argument is no longer available. ## Pydantic V1 validator signature This error is raised when you use an unsupported signature for Pydantic V1-style validator. ```python import warnings from pydantic import BaseModel, PydanticUserError, validator warnings.filterwarnings('ignore', category=DeprecationWarning) try: class Model(BaseModel): a: int @validator('a') def check_a(cls, value, foo): return value except PydanticUserError as exc_info: assert exc_info.code == 'validator-v1-signature' ``` ## Unrecognized `field_validator` signature This error is raised when a `field_validator` or `model_validator` function has the wrong signature. ```python from pydantic import BaseModel, PydanticUserError, field_validator try: class Model(BaseModel): a: str @field_validator('a') @classmethod def check_a(cls): return 'a' except PydanticUserError as exc_info: assert exc_info.code == 'validator-signature' ``` ## Unrecognized `field_serializer` signature This error is raised when the `field_serializer` function has the wrong signature. ```python from pydantic import BaseModel, PydanticUserError, field_serializer try: class Model(BaseModel): x: int @field_serializer('x') def no_args(): return 'x' except PydanticUserError as exc_info: assert exc_info.code == 'field-serializer-signature' ``` Valid field serializer signatures are: ```python from pydantic import FieldSerializationInfo, SerializerFunctionWrapHandler, field_serializer # an instance method with the default mode or `mode='plain'` @field_serializer('x') # or @field_serializer('x', mode='plain') def ser_x(self, value: Any, info: FieldSerializationInfo): ... # a static method or function with the default mode or `mode='plain'` @field_serializer('x') # or @field_serializer('x', mode='plain') @staticmethod def ser_x(value: Any, info: FieldSerializationInfo): ... # equivalent to def ser_x(value: Any, info: FieldSerializationInfo): ... serializer('x')(ser_x) # an instance method with `mode='wrap'` @field_serializer('x', mode='wrap') def ser_x(self, value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ... # a static method or function with `mode='wrap'` @field_serializer('x', mode='wrap') @staticmethod def ser_x(value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ... # equivalent to def ser_x(value: Any, nxt: SerializerFunctionWrapHandler, info: FieldSerializationInfo): ... serializer('x')(ser_x) # For all of these, you can also choose to omit the `info` argument, for example: @field_serializer('x') def ser_x(self, value: Any): ... @field_serializer('x', mode='wrap') def ser_x(self, value: Any, handler: SerializerFunctionWrapHandler): ... ``` ## Unrecognized `model_serializer` signature This error is raised when the `model_serializer` function has the wrong signature. ```python from pydantic import BaseModel, PydanticUserError, model_serializer try: class MyModel(BaseModel): a: int @model_serializer def _serialize(self, x, y, z): return self except PydanticUserError as exc_info: assert exc_info.code == 'model-serializer-signature' ``` Valid model serializer signatures are: ```python from pydantic import SerializerFunctionWrapHandler, SerializationInfo, model_serializer # an instance method with the default mode or `mode='plain'` @model_serializer # or model_serializer(mode='plain') def mod_ser(self, info: SerializationInfo): ... # an instance method with `mode='wrap'` @model_serializer(mode='wrap') def mod_ser(self, handler: SerializerFunctionWrapHandler, info: SerializationInfo): # For all of these, you can also choose to omit the `info` argument, for example: @model_serializer(mode='plain') def mod_ser(self): ... @model_serializer(mode='wrap') def mod_ser(self, handler: SerializerFunctionWrapHandler): ... ``` ## Multiple field serializers This error is raised when multiple `model_serializer` functions are defined for a field. ```python from pydantic import BaseModel, PydanticUserError, field_serializer try: class MyModel(BaseModel): x: int y: int @field_serializer('x', 'y') def serializer1(v): return f'{v:,}' @field_serializer('x') def serializer2(v): return v except PydanticUserError as exc_info: assert exc_info.code == 'multiple-field-serializers' ``` ## Invalid annotated type This error is raised when an annotation cannot annotate a type. ```python from typing import Annotated from pydantic import BaseModel, FutureDate, PydanticUserError try: class Model(BaseModel): foo: Annotated[str, FutureDate()] except PydanticUserError as exc_info: assert exc_info.code == 'invalid-annotated-type' ``` ## `config` is unused with `TypeAdapter` You will get this error if you try to pass `config` to `TypeAdapter` when the type is a type that has its own config that cannot be overridden (currently this is only `BaseModel`, `TypedDict` and `dataclass`): ```python from typing_extensions import TypedDict from pydantic import ConfigDict, PydanticUserError, TypeAdapter class MyTypedDict(TypedDict): x: int try: TypeAdapter(MyTypedDict, config=ConfigDict(strict=True)) except PydanticUserError as exc_info: assert exc_info.code == 'type-adapter-config-unused' ``` Instead you'll need to subclass the type and override or set the config on it: ```python from typing_extensions import TypedDict from pydantic import ConfigDict, TypeAdapter class MyTypedDict(TypedDict): x: int # or `model_config = ...` for BaseModel __pydantic_config__ = ConfigDict(strict=True) TypeAdapter(MyTypedDict) # ok ``` ## Cannot specify `model_config['extra']` with `RootModel` Because `RootModel` is not capable of storing or even accepting extra fields during initialization, we raise an error if you try to specify a value for the config setting `'extra'` when creating a subclass of `RootModel`: ```python from pydantic import PydanticUserError, RootModel try: class MyRootModel(RootModel): model_config = {'extra': 'allow'} root: int except PydanticUserError as exc_info: assert exc_info.code == 'root-model-extra' ``` ## Cannot evaluate type annotation Because type annotations are evaluated _after_ assignments, you might get unexpected results when using a type annotation name that clashes with one of your fields. We raise an error in the following case: ```python from datetime import date from pydantic import BaseModel, Field class Model(BaseModel): date: date = Field(description='A date') ``` As a workaround, you can either use an alias or change your import: ```python import datetime # Or `from datetime import date as _date` from pydantic import BaseModel, Field class Model(BaseModel): date: datetime.date = Field(description='A date') ``` ## Incompatible `dataclass` `init` and `extra` settings Pydantic does not allow the specification of the `extra='allow'` setting on a dataclass while any of the fields have `init=False` set. Thus, you may not do something like the following: ```python from pydantic import ConfigDict, Field from pydantic.dataclasses import dataclass @dataclass(config=ConfigDict(extra='allow')) class A: a: int = Field(init=False, default=1) ``` The above snippet results in the following error during schema building for the `A` dataclass: ```text pydantic.errors.PydanticUserError: Field a has `init=False` and dataclass has config setting `extra="allow"`. This combination is not allowed. ``` ## Incompatible `init` and `init_var` settings on `dataclass` field The `init=False` and `init_var=True` settings are mutually exclusive. Doing so results in the `PydanticUserError` shown in the example below. ```python from pydantic import Field from pydantic.dataclasses import dataclass @dataclass class Foo: bar: str = Field(init=False, init_var=True) """ pydantic.errors.PydanticUserError: Dataclass field bar has init=False and init_var=True, but these are mutually exclusive. """ ``` ## `model_config` is used as a model field This error is raised when `model_config` is used as the name of a field. ```python from pydantic import BaseModel, PydanticUserError try: class Model(BaseModel): model_config: str except PydanticUserError as exc_info: assert exc_info.code == 'model-config-invalid-field-name' ``` ## `with_config` is used on a `BaseModel` subclass This error is raised when the `with_config` decorator is used on a class which is already a Pydantic model (use the `model_config` attribute instead). ```python from pydantic import BaseModel, PydanticUserError, with_config try: @with_config({'allow_inf_nan': True}) class Model(BaseModel): bar: str except PydanticUserError as exc_info: assert exc_info.code == 'with-config-on-model' ``` ## `dataclass` is used on a `BaseModel` subclass This error is raised when the Pydantic `dataclass` decorator is used on a class which is already a Pydantic model. ```python from pydantic import BaseModel, PydanticUserError from pydantic.dataclasses import dataclass try: @dataclass class Model(BaseModel): bar: str except PydanticUserError as exc_info: assert exc_info.code == 'dataclass-on-model' ``` ## Unsupported type for `validate_call` `validate_call` has some limitations on the callables it can validate. This error is raised when you try to use it with an unsupported callable. Currently the supported callables are functions (including lambdas, but not built-ins) and methods and instances of `partial`. In the case of `partial`, the function being partially applied must be one of the supported callables. ### `@classmethod`, `@staticmethod`, and `@property` These decorators must be put before `validate_call`. ```python from pydantic import PydanticUserError, validate_call # error try: class A: @validate_call @classmethod def f1(cls): ... except PydanticUserError as exc_info: assert exc_info.code == 'validate-call-type' # correct @classmethod @validate_call def f2(cls): ... ``` ### Classes While classes are callables themselves, `validate_call` can't be applied on them, as it needs to know about which method to use (`__init__` or `__new__`) to fetch type annotations. If you want to validate the constructor of a class, you should put `validate_call` on top of the appropriate method instead. ```python from pydantic import PydanticUserError, validate_call # error try: @validate_call class A1: ... except PydanticUserError as exc_info: assert exc_info.code == 'validate-call-type' # correct class A2: @validate_call def __init__(self): ... @validate_call def __new__(cls): ... ``` ### Callable instances Although instances can be callable by implementing a `__call__` method, currently the instances of these types cannot be validated with `validate_call`. This may change in the future, but for now, you should use `validate_call` explicitly on `__call__` instead. ```python from pydantic import PydanticUserError, validate_call # error try: class A1: def __call__(self): ... validate_call(A1()) except PydanticUserError as exc_info: assert exc_info.code == 'validate-call-type' # correct class A2: @validate_call def __call__(self): ... ``` ### Invalid signature This is generally less common, but a possible reason is that you are trying to validate a method that doesn't have at least one argument (usually `self`). ```python from pydantic import PydanticUserError, validate_call try: class A: def f(): ... validate_call(A().f) except PydanticUserError as exc_info: assert exc_info.code == 'validate-call-type' ``` ## `Unpack` used without a `TypedDict` This error is raised when `Unpack` is used with something other than a `TypedDict` class object to type hint variadic keyword parameters. For reference, see the [related specification section](https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-for-keyword-arguments) and [PEP 692](https://peps.python.org/pep-0692/). ```python from typing_extensions import Unpack from pydantic import PydanticUserError, validate_call try: @validate_call def func(**kwargs: Unpack[int]): pass except PydanticUserError as exc_info: assert exc_info.code == 'unpack-typed-dict' ``` ## Overlapping unpacked `TypedDict` fields and arguments This error is raised when the typed dictionary used to type hint variadic keywords parameters has field names overlapping with other parameters (unless positional only). For reference, see the [related specification section](https://typing.readthedocs.io/en/latest/spec/callables.html#unpack-for-keyword-arguments) and [PEP 692](https://peps.python.org/pep-0692/). ```python from typing_extensions import TypedDict, Unpack from pydantic import PydanticUserError, validate_call class TD(TypedDict): a: int try: @validate_call def func(a: int, **kwargs: Unpack[TD]): pass except PydanticUserError as exc_info: assert exc_info.code == 'overlapping-unpack-typed-dict' ``` ## Invalid `Self` type Currently, `Self` can only be used to annotate a field of a class (specifically, subclasses of `BaseModel`, `NamedTuple`, `TypedDict`, or dataclasses). Attempting to use `Self` in any other ways will raise this error. ```python from typing_extensions import Self from pydantic import PydanticUserError, validate_call try: @validate_call def func(self: Self): pass except PydanticUserError as exc_info: assert exc_info.code == 'invalid-self-type' ``` The following example of `validate_call()` will also raise this error, even though it is correct from a type-checking perspective. This may be supported in the future. ```python from typing_extensions import Self from pydantic import BaseModel, PydanticUserError, validate_call try: class A(BaseModel): @validate_call def func(self, arg: Self): pass except PydanticUserError as exc_info: assert exc_info.code == 'invalid-self-type' ``` ## `validate_by_alias` and `validate_by_name` both set to `False` This error is raised when you set `validate_by_alias` and `validate_by_name` to `False` in the configuration. This is not allowed because it would make it impossible to populate attributes. ```python from pydantic import BaseModel, ConfigDict, Field, PydanticUserError try: class Model(BaseModel): a: int = Field(alias='A') model_config = ConfigDict( validate_by_alias=False, validate_by_name=False ) except PydanticUserError as exc_info: assert exc_info.code == 'validate-by-alias-and-name-false' ``` --- # [Validation Errors](https://pydantic.dev/docs/validation/latest/errors/validation_errors/) # Validation Errors Pydantic attempts to provide useful validation errors. Below are details on common validation errors users may encounter when working with pydantic, together with some suggestions on how to fix them. ## `arguments_type` This error is raised when an object that would be passed as arguments to a function during validation is not a `tuple`, `list`, or `dict`. Because `NamedTuple` uses function calls in its implementation, that is one way to produce this error: ```python from typing import NamedTuple from pydantic import BaseModel, ValidationError class MyNamedTuple(NamedTuple): x: int class MyModel(BaseModel): field: MyNamedTuple try: MyModel.model_validate({'field': 'invalid'}) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'arguments_type' ``` ## `assertion_error` This error is raised when a failing `assert` statement is encountered during validation: ```python from pydantic import BaseModel, ValidationError, field_validator class Model(BaseModel): x: int @field_validator('x') @classmethod def force_x_positive(cls, v): assert v > 0 return v try: Model(x=-1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'assertion_error' ``` ## `bool_parsing` This error is raised when the input value is a string that is not valid for coercion to a boolean: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: bool Model(x='true') # OK try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bool_parsing' ``` ## `bool_type` This error is raised when the input value's type is not valid for a `bool` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: bool try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bool_type' ``` This error is also raised for strict fields when the input value is not an instance of `bool`. ## `bytes_invalid_encoding` This error is raised when a `bytes` value is invalid under the configured encoding. In the following example, `'a'` is invalid hex (odd number of digits). ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: bytes model_config = {'val_json_bytes': 'hex'} try: Model(x='a') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bytes_invalid_encoding' ``` ## `bytes_too_long` This error is raised when the length of a `bytes` value is greater than the field's `max_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: bytes = Field(max_length=3) try: Model(x=b'test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bytes_too_long' ``` ## `bytes_too_short` This error is raised when the length of a `bytes` value is less than the field's `min_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: bytes = Field(min_length=3) try: Model(x=b't') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bytes_too_short' ``` ## `bytes_type` This error is raised when the input value's type is not valid for a `bytes` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: bytes try: Model(x=123) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'bytes_type' ``` This error is also raised for strict fields when the input value is not an instance of `bytes`. ## `callable_type` This error is raised when the input value is not valid as a `Callable`: ```python from typing import Any, Callable from pydantic import BaseModel, ImportString, ValidationError class Model(BaseModel): x: ImportString[Callable[[Any], Any]] Model(x='math:cos') # OK try: Model(x='os.path') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'callable_type' ``` ## `complex_str_parsing` This error is raised when the input value is a string but cannot be parsed as a complex number because it does not follow the [rule](https://docs.python.org/3/library/functions.html#complex) in Python: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): num: complex try: # Complex numbers in json are expected to be valid complex strings. # This value `abc` is not a valid complex string. Model.model_validate_json('{"num": "abc"}') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'complex_str_parsing' ``` ## `complex_type` This error is raised when the input value cannot be interpreted as a complex number: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): num: complex try: Model(num=False) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'complex_type' ``` ## `dataclass_exact_type` This error is raised when validating a dataclass with `strict=True` and the input is not an instance of the dataclass: ```python import pydantic.dataclasses from pydantic import TypeAdapter, ValidationError @pydantic.dataclasses.dataclass class MyDataclass: x: str adapter = TypeAdapter(MyDataclass) print(adapter.validate_python(MyDataclass(x='test'), strict=True)) #> MyDataclass(x='test') print(adapter.validate_python({'x': 'test'})) #> MyDataclass(x='test') try: adapter.validate_python({'x': 'test'}, strict=True) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'dataclass_exact_type' ``` ## `dataclass_type` This error is raised when the input value is not valid for a `dataclass` field: ```python from pydantic import ValidationError, dataclasses @dataclasses.dataclass class Inner: x: int @dataclasses.dataclass class Outer: y: Inner Outer(y=Inner(x=1)) # OK try: Outer(y=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'dataclass_type' ``` ## `date_from_datetime_inexact` This error is raised when the input `datetime` value provided for a `date` field has a nonzero time component. For a timestamp to parse into a field of type `date`, the time components must all be zero: ```python from datetime import date, datetime from pydantic import BaseModel, ValidationError class Model(BaseModel): x: date Model(x='2023-01-01') # OK Model(x=datetime(2023, 1, 1)) # OK try: Model(x=datetime(2023, 1, 1, 12)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_from_datetime_inexact' ``` ## `date_from_datetime_parsing` This error is raised when the input value is a string that cannot be parsed for a `date` field: ```python from datetime import date from pydantic import BaseModel, ValidationError class Model(BaseModel): x: date try: Model(x='XX1494012000') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_from_datetime_parsing' ``` ## `date_future` This error is raised when the input value provided for a `FutureDate` field is not in the future: ```python from datetime import date from pydantic import BaseModel, FutureDate, ValidationError class Model(BaseModel): x: FutureDate try: Model(x=date(2000, 1, 1)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_future' ``` ## `date_parsing` This error is raised when validating JSON where the input value is string that cannot be parsed for a `date` field: ```python import json from datetime import date from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: date = Field(strict=True) try: Model.model_validate_json(json.dumps({'x': '1'})) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_parsing' ``` ## `date_past` This error is raised when the value provided for a `PastDate` field is not in the past: ```python from datetime import date, timedelta from pydantic import BaseModel, PastDate, ValidationError class Model(BaseModel): x: PastDate try: Model(x=date.today() + timedelta(1)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_past' ``` ## `date_type` This error is raised when the input value's type is not valid for a `date` field: ```python from datetime import date from pydantic import BaseModel, ValidationError class Model(BaseModel): x: date try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'date_type' ``` This error is also raised for strict fields when the input value is not an instance of `date`. ## `datetime_from_date_parsing` This error is raised when the input value is a string that cannot be parsed for a `datetime` field: ```python from datetime import datetime from pydantic import BaseModel, ValidationError class Model(BaseModel): x: datetime try: # there is no 13th month Model(x='2023-13-01') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_from_date_parsing' ``` ## `datetime_future` This error is raised when the value provided for a `FutureDatetime` field is not in the future: ```python from datetime import datetime from pydantic import BaseModel, FutureDatetime, ValidationError class Model(BaseModel): x: FutureDatetime try: Model(x=datetime(2000, 1, 1)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_future' ``` ## `datetime_object_invalid` This error is raised when something about the `datetime` object is not valid: ```python from datetime import datetime, tzinfo from pydantic import AwareDatetime, BaseModel, ValidationError class CustomTz(tzinfo): # utcoffset is not implemented! def tzname(self, _dt): return 'CustomTZ' class Model(BaseModel): x: AwareDatetime try: Model(x=datetime(2023, 1, 1, tzinfo=CustomTz())) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_object_invalid' ``` ## `datetime_parsing` This error is raised when the value is a string that cannot be parsed for a `datetime` field: ```python import json from datetime import datetime from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: datetime = Field(strict=True) try: Model.model_validate_json(json.dumps({'x': 'not a datetime'})) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_parsing' ``` ## `datetime_past` This error is raised when the value provided for a `PastDatetime` field is not in the past: ```python from datetime import datetime, timedelta from pydantic import BaseModel, PastDatetime, ValidationError class Model(BaseModel): x: PastDatetime try: Model(x=datetime.now() + timedelta(100)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_past' ``` ## `datetime_type` This error is raised when the input value's type is not valid for a `datetime` field: ```python from datetime import datetime from pydantic import BaseModel, ValidationError class Model(BaseModel): x: datetime try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'datetime_type' ``` This error is also raised for strict fields when the input value is not an instance of `datetime`. ## `decimal_max_digits` This error is raised when the value provided for a `Decimal` has too many digits: ```python from decimal import Decimal from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: Decimal = Field(max_digits=3) try: Model(x='42.1234') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'decimal_max_digits' ``` ## `decimal_max_places` This error is raised when the value provided for a `Decimal` has too many digits after the decimal point: ```python from decimal import Decimal from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: Decimal = Field(decimal_places=3) try: Model(x='42.1234') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'decimal_max_places' ``` ## `decimal_parsing` This error is raised when the value provided for a `Decimal` could not be parsed as a decimal number: ```python from decimal import Decimal from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: Decimal = Field(decimal_places=3) try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'decimal_parsing' ``` ## `decimal_type` This error is raised when the value provided for a `Decimal` is of the wrong type: ```python from decimal import Decimal from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: Decimal = Field(decimal_places=3) try: Model(x=[1, 2, 3]) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'decimal_type' ``` This error is also raised for strict fields when the input value is not an instance of `Decimal`. ## `decimal_whole_digits` This error is raised when the value provided for a `Decimal` has more digits before the decimal point than `max_digits` - `decimal_places` (as long as both are specified): ```python from decimal import Decimal from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: Decimal = Field(max_digits=6, decimal_places=3) try: Model(x='12345.6') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'decimal_whole_digits' ``` ## `default_factory_not_called` This error is raised when a [default factory taking validated data](/docs/validation/latest/concepts/fields#default-factory-validated-data) can't be called, because validation failed on previous fields: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): a: int = Field(gt=10) b: int = Field(default_factory=lambda data: data['a']) try: Model(a=1) except ValidationError as exc: print(exc) """ 2 validation errors for Model a Input should be greater than 10 [type=greater_than, input_value=1, input_type=int] b The default factory uses validated data, but at least one validation error occurred [type=default_factory_not_called] """ print(repr(exc.errors()[1]['type'])) #> 'default_factory_not_called' ``` ## `dict_type` This error is raised when the input value's type is not `dict` for a `dict` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: dict try: Model(x=['1', '2']) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'dict_type' ``` ## `enum` This error is raised when the input value does not exist in an `enum` field members: ```python from enum import Enum from pydantic import BaseModel, ValidationError class MyEnum(str, Enum): option = 'option' class Model(BaseModel): x: MyEnum try: Model(x='other_option') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'enum' ``` ## `extra_forbidden` This error is raised when the input value contains extra fields, but `model_config['extra'] == 'forbid'`: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: str model_config = ConfigDict(extra='forbid') try: Model(x='test', y='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'extra_forbidden' ``` You can read more about the `extra` configuration in the Extra Attributes section. ## `finite_number` This error is raised when the value is infinite, or too large to be represented as a 64-bit floating point number during validation: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int try: Model(x=2.2250738585072011e308) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'finite_number' ``` ## `float_parsing` This error is raised when the value is a string that can't be parsed as a `float`: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: float try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'float_parsing' ``` ## `float_type` This error is raised when the input value's type is not valid for a `float` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: float try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'float_type' ``` ## `frozen_field` This error is raised when you attempt to assign a value to a field with `frozen=True`, or to delete such a field: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: str = Field('test', frozen=True) model = Model() try: model.x = 'test1' except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'frozen_field' try: del model.x except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'frozen_field' ``` ## `frozen_instance` This error is raised when `frozen` is set in the [configuration](/docs/validation/latest/concepts/config) and you attempt to delete or assign a new value to any of the fields: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: int model_config = ConfigDict(frozen=True) m = Model(x=1) try: m.x = 2 except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'frozen_instance' try: del m.x except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'frozen_instance' ``` ## `frozen_set_type` This error is raised when the input value's type is not valid for a `frozenset` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: frozenset try: model = Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'frozen_set_type' ``` ## `get_attribute_error` This error is raised when `model_config['from_attributes'] == True` and an error is raised while reading the attributes: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Foobar: def __init__(self): self.x = 1 @property def y(self): raise RuntimeError('intentional error') class Model(BaseModel): x: int y: str model_config = ConfigDict(from_attributes=True) try: Model.model_validate(Foobar()) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'get_attribute_error' ``` ## `greater_than` This error is raised when the value is not greater than the field's `gt` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: int = Field(gt=10) try: Model(x=10) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'greater_than' ``` ## `greater_than_equal` This error is raised when the value is not greater than or equal to the field's `ge` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: int = Field(ge=10) try: Model(x=9) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'greater_than_equal' ``` ## `int_from_float` This error is raised when you provide a `float` value for an `int` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int try: Model(x=0.5) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'int_from_float' ``` ## `int_parsing` This error is raised when the value can't be parsed as `int`: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'int_parsing' ``` ## `int_parsing_size` This error is raised when attempting to parse a python or JSON value from a string outside the maximum range that Python `str` to `int` parsing permits: ```python import json from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int # from Python assert Model(x='1' * 4_300).x == int('1' * 4_300) # OK too_long = '1' * 4_301 try: Model(x=too_long) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'int_parsing_size' # from JSON try: Model.model_validate_json(json.dumps({'x': too_long})) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'int_parsing_size' ``` ## `int_type` This error is raised when the input value's type is not valid for an `int` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'int_type' ``` ## `invalid_key` This error is raised when attempting to validate a `dict` that has a key that is not an instance of `str`: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Model(BaseModel): x: int model_config = ConfigDict(extra='allow') try: Model.model_validate({'x': 1, b'y': 2}) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'invalid_key' ``` ## `is_instance_of` This error is raised when the input value is not an instance of the expected type: ```python from pydantic import BaseModel, ConfigDict, ValidationError class Nested: x: str class Model(BaseModel): y: Nested model_config = ConfigDict(arbitrary_types_allowed=True) try: Model(y='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'is_instance_of' ``` ## `is_subclass_of` This error is raised when the input value is not a subclass of the expected type: ```python from pydantic import BaseModel, ValidationError class Nested: x: str class Model(BaseModel): y: type[Nested] try: Model(y='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'is_subclass_of' ``` ## `iterable_type` This error is raised when the input value is not valid as an `Iterable`: ```python from collections.abc import Iterable from pydantic import BaseModel, ValidationError class Model(BaseModel): y: Iterable[str] try: Model(y=123) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'iterable_type' ``` ## `iteration_error` This error is raised when an error occurs during iteration: ```python from pydantic import BaseModel, ValidationError def gen(): yield 1 raise RuntimeError('error') class Model(BaseModel): x: list[int] try: Model(x=gen()) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'iteration_error' ``` ## `json_invalid` This error is raised when the input value is not a valid JSON string: ```python from pydantic import BaseModel, Json, ValidationError class Model(BaseModel): x: Json try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'json_invalid' ``` ## `json_type` This error is raised when the input value is of a type that cannot be parsed as JSON: ```python from pydantic import BaseModel, Json, ValidationError class Model(BaseModel): x: Json try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'json_type' ``` ## `less_than` This error is raised when the input value is not less than the field's `lt` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: int = Field(lt=10) try: Model(x=10) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'less_than' ``` ## `less_than_equal` This error is raised when the input value is not less than or equal to the field's `le` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: int = Field(le=10) try: Model(x=11) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'less_than_equal' ``` ## `list_type` This error is raised when the input value's type is not valid for a `list` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: list[int] try: Model(x=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'list_type' ``` ## `literal_error` This error is raised when the input value is not one of the expected literal values: ```python from typing import Literal from pydantic import BaseModel, ValidationError class Model(BaseModel): x: Literal['a', 'b'] Model(x='a') # OK try: Model(x='c') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'literal_error' ``` ## `mapping_type` This error is raised when a problem occurs during validation due to a failure in a call to the methods from the `Mapping` protocol, such as `.items()`: ```python from collections.abc import Mapping from pydantic import BaseModel, ValidationError class BadMapping(Mapping): def items(self): raise ValueError() def __iter__(self): raise ValueError() def __getitem__(self, key): raise ValueError() def __len__(self): return 1 class Model(BaseModel): x: dict[str, str] try: Model(x=BadMapping()) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'mapping_type' ``` ## `missing` This error is raised when there are required fields missing from the input value: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: str try: Model() except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'missing' ``` ## `missing_argument` This error is raised when a required positional-or-keyword argument is not passed to a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(a: int): return a try: foo() except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'missing_argument' ``` ## `missing_keyword_only_argument` This error is raised when a required keyword-only argument is not passed to a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(*, a: int): return a try: foo() except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'missing_keyword_only_argument' ``` ## `missing_positional_only_argument` This error is raised when a required positional-only argument is not passed to a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(a: int, /): return a try: foo() except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'missing_positional_only_argument' ``` ## `missing_sentinel_error` This error is raised when the experimental `MISSING` sentinel is the only value allowed, and wasn't provided during validation: ```python from pydantic import BaseModel, ValidationError from pydantic.experimental.missing_sentinel import MISSING class Model(BaseModel): f: MISSING try: Model(f=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'missing_sentinel_error' ``` ## `model_attributes_type` This error is raised when the input value is not a valid dictionary, model instance, or instance that fields can be extracted from: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): a: int b: int # simply validating a dict print(Model.model_validate({'a': 1, 'b': 2})) #> a=1 b=2 class CustomObj: def __init__(self, a, b): self.a = a self.b = b # using from attributes to extract fields from an objects print(Model.model_validate(CustomObj(3, 4), from_attributes=True)) #> a=3 b=4 try: Model.model_validate('not an object', from_attributes=True) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'model_attributes_type' ``` ## `model_type` This error is raised when the input to a model is not an instance of the model or dict: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): a: int b: int # simply validating a dict m = Model.model_validate({'a': 1, 'b': 2}) print(m) #> a=1 b=2 # validating an existing model instance print(Model.model_validate(m)) #> a=1 b=2 try: Model.model_validate('not an object') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'model_type' ``` ## `multiple_argument_values` This error is raised when you provide multiple values for a single argument while calling a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(a: int): return a try: foo(1, a=2) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'multiple_argument_values' ``` ## `multiple_of` This error is raised when the input is not a multiple of a field's `multiple_of` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: int = Field(multiple_of=5) try: Model(x=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'multiple_of' ``` ## `needs_python_object` This type of error is raised when validation is attempted from a format that cannot be converted to a Python object. For example, we cannot check `isinstance` or `issubclass` from JSON: ```python import json from pydantic import BaseModel, ValidationError class Model(BaseModel): bm: type[BaseModel] try: Model.model_validate_json(json.dumps({'bm': 'not a basemodel class'})) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'needs_python_object' ``` ## `no_such_attribute` This error is raised when `validate_assignment=True` in the config, and you attempt to assign a value to an attribute that is not an existing field: ```python from pydantic import ConfigDict, ValidationError, dataclasses @dataclasses.dataclass(config=ConfigDict(validate_assignment=True)) class MyDataclass: x: int m = MyDataclass(x=1) try: m.y = 10 except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'no_such_attribute' ``` ## `none_required` This error is raised when the input value is not `None` for a field that requires `None`: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: None try: Model(x=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'none_required' ``` Note You may encounter this error when there is a naming collision in your model between a field name and its type. More specifically, this error is likely to be thrown when the default value of that field is `None`. For example, the following would yield the `none_required` validation error since the field `int` is set to a default value of `None` and has the exact same name as its type, which causes problems with validation. ```python from typing import Optional from pydantic import BaseModel class M1(BaseModel): int: Optional[int] = None m = M1(int=123) # errors ``` ## `recursion_loop` This error is raised when a cyclic reference is detected: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: list['Model'] d = {'x': []} d['x'].append(d) try: Model(**d) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'recursion_loop' ``` ## `set_item_not_hashable` This error is raised when an unhashable value is validated against a `set` or a `frozenset`: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: set[object] class Unhashable: __hash__ = None try: Model(x=[{'a': 'b'}, Unhashable()]) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'set_item_not_hashable' print(repr(exc.errors()[1]['type'])) #> 'set_item_not_hashable' ``` ## `set_type` This error is raised when the value type is not valid for a `set` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: set[int] try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'set_type' ``` ## `string_not_ascii` This error is raised when the input string contains non-ASCII characters: ```python from typing import Annotated from pydantic import BaseModel, StringConstraints, ValidationError class Model(BaseModel): v: Annotated[str, StringConstraints(ascii_only=True)] try: Model(v='caf\u00e9') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_not_ascii' ``` ## `string_pattern_mismatch` This error is raised when the input value doesn't match the field's `pattern` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: str = Field(pattern='test') try: Model(x='1') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_pattern_mismatch' ``` ## `string_sub_type` This error is raised when the value is an instance of a strict subtype of `str` when the field is strict: ```python from enum import Enum from pydantic import BaseModel, Field, ValidationError class MyEnum(str, Enum): foo = 'foo' class Model(BaseModel): x: str = Field(strict=True) try: Model(x=MyEnum.foo) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_sub_type' ``` ## `string_too_long` This error is raised when the input value is a string whose length is greater than the field's `max_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: str = Field(max_length=3) try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_too_long' ``` ## `string_too_short` This error is raised when the input value is a string whose length is less than the field's `min_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: str = Field(min_length=3) try: Model(x='t') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_too_short' ``` ## `string_type` This error is raised when the input value's type is not valid for a `str` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: str try: Model(x=1) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_type' ``` This error is also raised for strict fields when the input value is not an instance of `str`. ## `string_unicode` This error is raised when the value cannot be parsed as a Unicode string: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: str try: Model(x=b'\x81') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'string_unicode' ``` ## `time_delta_parsing` This error is raised when the input value is a string that cannot be parsed for a `timedelta` field: ```python from datetime import timedelta from pydantic import BaseModel, ValidationError class Model(BaseModel): x: timedelta try: Model(x='t') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'time_delta_parsing' ``` ## `time_delta_type` This error is raised when the input value's type is not valid for a `timedelta` field: ```python from datetime import timedelta from pydantic import BaseModel, ValidationError class Model(BaseModel): x: timedelta try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'time_delta_type' ``` This error is also raised for strict fields when the input value is not an instance of `timedelta`. ## `time_parsing` This error is raised when the input value is a string that cannot be parsed for a `time` field: ```python from datetime import time from pydantic import BaseModel, ValidationError class Model(BaseModel): x: time try: Model(x='25:20:30.400') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'time_parsing' ``` ## `time_type` This error is raised when the value type is not valid for a `time` field: ```python from datetime import time from pydantic import BaseModel, ValidationError class Model(BaseModel): x: time try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'time_type' ``` This error is also raised for strict fields when the input value is not an instance of `time`. ## `timezone_aware` This error is raised when the `datetime` value provided for a timezone-aware `datetime` field doesn't have timezone information: ```python from datetime import datetime from pydantic import AwareDatetime, BaseModel, ValidationError class Model(BaseModel): x: AwareDatetime try: Model(x=datetime.now()) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'timezone_aware' ``` ## `timezone_naive` This error is raised when the `datetime` value provided for a timezone-naive `datetime` field has timezone info: ```python from datetime import datetime, timezone from pydantic import BaseModel, NaiveDatetime, ValidationError class Model(BaseModel): x: NaiveDatetime try: Model(x=datetime.now(tz=timezone.utc)) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'timezone_naive' ``` ## `too_long` This error is raised when the input value's length is greater than the field's `max_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: list[int] = Field(max_length=3) try: Model(x=[1, 2, 3, 4]) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'too_long' ``` ## `too_short` This error is raised when the value length is less than the field's `min_length` constraint: ```python from pydantic import BaseModel, Field, ValidationError class Model(BaseModel): x: list[int] = Field(min_length=3) try: Model(x=[1, 2]) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'too_short' ``` ## `tuple_type` This error is raised when the input value's type is not valid for a `tuple` field: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: tuple[int] try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'tuple_type' ``` This error is also raised for strict fields when the input value is not an instance of `tuple`. ## `unexpected_keyword_argument` This error is raised when you provide a value by keyword for a positional-only argument while calling a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(a: int, /): return a try: foo(a=2) except ValidationError as exc: print(repr(exc.errors()[1]['type'])) #> 'unexpected_keyword_argument' ``` It is also raised when using pydantic.dataclasses and `extra=forbid`: ```python from pydantic import TypeAdapter, ValidationError from pydantic.dataclasses import dataclass @dataclass(config={'extra': 'forbid'}) class Foo: bar: int try: TypeAdapter(Foo).validate_python({'bar': 1, 'foobar': 2}) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'unexpected_keyword_argument' ``` ## `unexpected_positional_argument` This error is raised when you provide a positional value for a keyword-only argument while calling a function decorated with `validate_call`: ```python from pydantic import ValidationError, validate_call @validate_call def foo(*, a: int): return a try: foo(2) except ValidationError as exc: print(repr(exc.errors()[1]['type'])) #> 'unexpected_positional_argument' ``` ## `union_tag_invalid` This error is raised when the input's discriminator is not one of the expected values: ```python from typing import Literal, Union from pydantic import BaseModel, Field, ValidationError class BlackCat(BaseModel): pet_type: Literal['blackcat'] class WhiteCat(BaseModel): pet_type: Literal['whitecat'] class Model(BaseModel): cat: Union[BlackCat, WhiteCat] = Field(discriminator='pet_type') try: Model(cat={'pet_type': 'dog'}) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'union_tag_invalid' ``` ## `union_tag_not_found` This error is raised when it is not possible to extract a discriminator value from the input: ```python from typing import Literal, Union from pydantic import BaseModel, Field, ValidationError class BlackCat(BaseModel): pet_type: Literal['blackcat'] class WhiteCat(BaseModel): pet_type: Literal['whitecat'] class Model(BaseModel): cat: Union[BlackCat, WhiteCat] = Field(discriminator='pet_type') try: Model(cat={'name': 'blackcat'}) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'union_tag_not_found' ``` ## `url_parsing` This error is raised when the input value cannot be parsed as a URL: ```python from pydantic import AnyUrl, BaseModel, ValidationError class Model(BaseModel): x: AnyUrl try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'url_parsing' ``` ## `url_scheme` This error is raised when the URL scheme is not valid for the URL type of the field: ```python from pydantic import BaseModel, HttpUrl, ValidationError class Model(BaseModel): x: HttpUrl try: Model(x='ftp://example.com') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'url_scheme' ``` ## `url_syntax_violation` This error is raised when the URL syntax is not valid: ```python from pydantic import BaseModel, Field, HttpUrl, ValidationError class Model(BaseModel): x: HttpUrl = Field(strict=True) try: Model(x='http:////example.com') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'url_syntax_violation' ``` ## `url_too_long` This error is raised when the URL length is greater than 2083: ```python from pydantic import BaseModel, HttpUrl, ValidationError class Model(BaseModel): x: HttpUrl try: Model(x='x' * 2084) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'url_too_long' ``` ## `url_type` This error is raised when the input value's type is not valid for a URL field: ```python from pydantic import BaseModel, HttpUrl, ValidationError class Model(BaseModel): x: HttpUrl try: Model(x=None) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'url_type' ``` ## `uuid_parsing` This error is raised when the input value's type is not valid for a UUID field: ```python from uuid import UUID from pydantic import BaseModel, ValidationError class Model(BaseModel): u: UUID try: Model(u='12345678-124-1234-1234-567812345678') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'uuid_parsing' ``` ## `uuid_type` This error is raised when the input value's type is not valid instance for a UUID field (str, bytes or UUID): ```python from uuid import UUID from pydantic import BaseModel, ValidationError class Model(BaseModel): u: UUID try: Model(u=1234567812412341234567812345678) except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'uuid_type' ``` ## `uuid_version` This error is raised when the input value's type is not match UUID version: ```python from pydantic import UUID5, BaseModel, ValidationError class Model(BaseModel): u: UUID5 try: Model(u='a6cc5730-2261-11ee-9c43-2eb5a363657c') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'uuid_version' ``` ## `value_error` This error is raised when a `ValueError` is raised during validation: ```python from pydantic import BaseModel, ValidationError, field_validator class Model(BaseModel): x: str @field_validator('x') @classmethod def repeat_b(cls, v): raise ValueError() try: Model(x='test') except ValidationError as exc: print(repr(exc.errors()[0]['type'])) #> 'value_error' ``` --- # [Custom Validators](https://pydantic.dev/docs/validation/latest/examples/custom_validators/) # Custom Validators This page provides example snippets for creating more complex, custom validators in Pydantic. Many of these examples are adapted from Pydantic issues and discussions, and are intended to showcase the flexibility and power of Pydantic's validation system. ## Custom `datetime` Validator via [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) Metadata In this example, we'll construct a custom validator, attached to an [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) type, that ensures a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object adheres to a given timezone constraint. The custom validator supports string specification of the timezone, and will raise an error if the [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object does not have the correct timezone. We use `__get_pydantic_core_schema__` in the validator to customize the schema of the annotated type (in this case, [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime)), which allows us to add custom validation logic. Notably, we use a `wrap` validator function so that we can perform operations both before and after the default `pydantic` validation of a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime). ```python import datetime as dt from dataclasses import dataclass from pprint import pprint from typing import Annotated, Any, Callable, Optional import pytz from pydantic_core import CoreSchema, core_schema from pydantic import ( GetCoreSchemaHandler, PydanticUserError, TypeAdapter, ValidationError, ) @dataclass(frozen=True) class MyDatetimeValidator: tz_constraint: Optional[str] = None def tz_constraint_validator( self, value: dt.datetime, handler: Callable, # (1) ): """Validate tz_constraint and tz_info.""" # handle naive datetimes if self.tz_constraint is None: assert ( value.tzinfo is None ), 'tz_constraint is None, but provided value is tz-aware.' return handler(value) # validate tz_constraint and tz-aware tzinfo if self.tz_constraint not in pytz.all_timezones: raise PydanticUserError( f'Invalid tz_constraint: {self.tz_constraint}', code='unevaluable-type-annotation', ) result = handler(value) # (2) assert self.tz_constraint == str( result.tzinfo ), f'Invalid tzinfo: {str(result.tzinfo)}, expected: {self.tz_constraint}' return result def __get_pydantic_core_schema__( self, source_type: Any, handler: GetCoreSchemaHandler, ) -> CoreSchema: return core_schema.no_info_wrap_validator_function( self.tz_constraint_validator, handler(source_type), ) LA = 'America/Los_Angeles' ta = TypeAdapter(Annotated[dt.datetime, MyDatetimeValidator(LA)]) print( ta.validate_python(dt.datetime(2023, 1, 1, 0, 0, tzinfo=pytz.timezone(LA))) ) #> 2023-01-01 00:00:00-07:53 LONDON = 'Europe/London' try: ta.validate_python( dt.datetime(2023, 1, 1, 0, 0, tzinfo=pytz.timezone(LONDON)) ) except ValidationError as ve: pprint(ve.errors(), width=100) """ [{'ctx': {'error': AssertionError('Invalid tzinfo: Europe/London, expected: America/Los_Angeles')}, 'input': datetime.datetime(2023, 1, 1, 0, 0, tzinfo=), 'loc': (), 'msg': 'Assertion failed, Invalid tzinfo: Europe/London, expected: America/Los_Angeles', 'type': 'assertion_error', 'url': 'https://errors.pydantic.dev/2.8/v/assertion_error'}] """ ``` The `handler` function is what we call to validate the input with standard `pydantic` validation We call the `handler` function to validate the input with standard `pydantic` validation in this wrap validator We can also enforce UTC offset constraints in a similar way. Assuming we have a `lower_bound` and an `upper_bound`, we can create a custom validator to ensure our `datetime` has a UTC offset that is inclusive within the boundary we define: ```python import datetime as dt from dataclasses import dataclass from pprint import pprint from typing import Annotated, Any, Callable import pytz from pydantic_core import CoreSchema, core_schema from pydantic import GetCoreSchemaHandler, TypeAdapter, ValidationError @dataclass(frozen=True) class MyDatetimeValidator: lower_bound: int upper_bound: int def validate_tz_bounds(self, value: dt.datetime, handler: Callable): """Validate and test bounds""" assert value.utcoffset() is not None, 'UTC offset must exist' assert self.lower_bound <= self.upper_bound, 'Invalid bounds' result = handler(value) hours_offset = value.utcoffset().total_seconds() / 3600 assert ( self.lower_bound <= hours_offset <= self.upper_bound ), 'Value out of bounds' return result def __get_pydantic_core_schema__( self, source_type: Any, handler: GetCoreSchemaHandler, ) -> CoreSchema: return core_schema.no_info_wrap_validator_function( self.validate_tz_bounds, handler(source_type), ) LA = 'America/Los_Angeles' # UTC-7 or UTC-8 ta = TypeAdapter(Annotated[dt.datetime, MyDatetimeValidator(-10, -5)]) print( ta.validate_python(dt.datetime(2023, 1, 1, 0, 0, tzinfo=pytz.timezone(LA))) ) #> 2023-01-01 00:00:00-07:53 LONDON = 'Europe/London' try: print( ta.validate_python( dt.datetime(2023, 1, 1, 0, 0, tzinfo=pytz.timezone(LONDON)) ) ) except ValidationError as e: pprint(e.errors(), width=100) """ [{'ctx': {'error': AssertionError('Value out of bounds')}, 'input': datetime.datetime(2023, 1, 1, 0, 0, tzinfo=), 'loc': (), 'msg': 'Assertion failed, Value out of bounds', 'type': 'assertion_error', 'url': 'https://errors.pydantic.dev/2.8/v/assertion_error'}] """ ``` ## Validating Nested Model Fields Here, we demonstrate two ways to validate a field of a nested model, where the validator utilizes data from the parent model. In this example, we construct a validator that checks that each user's password is not in a list of forbidden passwords specified by the parent model. One way to do this is to place a custom validator on the outer model: ```python from typing_extensions import Self from pydantic import BaseModel, ValidationError, model_validator class User(BaseModel): username: str password: str class Organization(BaseModel): forbidden_passwords: list[str] users: list[User] @model_validator(mode='after') def validate_user_passwords(self) -> Self: """Check that user password is not in forbidden list. Raise a validation error if a forbidden password is encountered.""" for user in self.users: current_pw = user.password if current_pw in self.forbidden_passwords: raise ValueError( f'Password {current_pw} is forbidden. Please choose another password for user {user.username}.' ) return self data = { 'forbidden_passwords': ['123'], 'users': [ {'username': 'Spartacat', 'password': '123'}, {'username': 'Iceburgh', 'password': '87'}, ], } try: org = Organization(**data) except ValidationError as e: print(e) """ 1 validation error for Organization Value error, Password 123 is forbidden. Please choose another password for user Spartacat. [type=value_error, input_value={'forbidden_passwords': [...gh', 'password': '87'}]}, input_type=dict] """ ``` Alternatively, a custom validator can be used in the nested model class (`User`), with the forbidden passwords data from the parent model being passed in via validation context. Caution The ability to mutate the context within a validator adds a lot of power to nested validation, but can also lead to confusing or hard-to-debug code. Use this approach at your own risk! ```python from pydantic import BaseModel, ValidationError, ValidationInfo, field_validator class User(BaseModel): username: str password: str @field_validator('password', mode='after') @classmethod def validate_user_passwords( cls, password: str, info: ValidationInfo ) -> str: """Check that user password is not in forbidden list.""" forbidden_passwords = ( info.context.get('forbidden_passwords', []) if info.context else [] ) if password in forbidden_passwords: raise ValueError(f'Password {password} is forbidden.') return password class Organization(BaseModel): forbidden_passwords: list[str] users: list[User] @field_validator('forbidden_passwords', mode='after') @classmethod def add_context(cls, v: list[str], info: ValidationInfo) -> list[str]: if info.context is not None: info.context.update({'forbidden_passwords': v}) return v data = { 'forbidden_passwords': ['123'], 'users': [ {'username': 'Spartacat', 'password': '123'}, {'username': 'Iceburgh', 'password': '87'}, ], } try: org = Organization.model_validate(data, context={}) except ValidationError as e: print(e) """ 1 validation error for Organization users.0.password Value error, Password 123 is forbidden. [type=value_error, input_value='123', input_type=str] """ ``` Note that if the context property is not included in `model_validate`, then `info.context` will be `None` and the forbidden passwords list will not get added to the context in the above implementation. As such, `validate_user_passwords` would not carry out the desired password validation. More details about validation context can be found in the [validators documentation](/docs/validation/latest/concepts/validators#validation-context). --- # [Dynamic models](https://pydantic.dev/docs/validation/latest/examples/dynamic_models/) # Dynamic models Models can be [created dynamically](/docs/validation/latest/concepts/models#dynamic-model-creation) using the [`create_model()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.create_model) factory function. In this example, we will show how to dynamically derive a model from an existing one, making every field optional. To achieve this, we will make use of the [`model_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields) model class attribute, and derive new annotations from the field definitions to be passed to the [`create_model()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.create_model) factory. Of course, this example can apply to any use case where you need to derive a new model from another (remove default values, add aliases, etc). - [Python 3.9](#tab-panel-605) - [Python 3.10](#tab-panel-606) - [Python 3.11 and above](#tab-panel-607) ```python from typing import Annotated, Union from pydantic import BaseModel, Field, create_model def make_fields_optional(model_cls: type[BaseModel]) -> type[BaseModel]: new_fields = {} for f_name, f_info in model_cls.model_fields.items(): f_dct = f_info.asdict() new_fields[f_name] = ( Annotated[(Union[f_dct['annotation'], None], *f_dct['metadata'], Field(**f_dct['attributes']))], None, ) return create_model( f'{model_cls.__name__}Optional', __base__=model_cls, # (1) **new_fields, ) ``` Using the original model as a base will inherit the [validators](/docs/validation/latest/concepts/validators), [computed fields](/docs/validation/latest/concepts/fields#the-computed_field-decorator), etc. The parent fields are overridden by the ones we define. ```python from typing import Annotated from pydantic import BaseModel, Field, create_model def make_fields_optional(model_cls: type[BaseModel]) -> type[BaseModel]: new_fields = {} for f_name, f_info in model_cls.model_fields.items(): f_dct = f_info.asdict() new_fields[f_name] = ( Annotated[(f_dct['annotation'] | None, *f_dct['metadata'], Field(**f_dct['attributes']))], None, ) return create_model( f'{model_cls.__name__}Optional', __base__=model_cls, # (1) **new_fields, ) ``` Using the original model as a base will inherit the [validators](/docs/validation/latest/concepts/validators), [computed fields](/docs/validation/latest/concepts/fields#the-computed_field-decorator), etc. The parent fields are overridden by the ones we define. ```python from typing import Annotated from pydantic import BaseModel, Field, create_model def make_fields_optional(model_cls: type[BaseModel]) -> type[BaseModel]: new_fields = {} for f_name, f_info in model_cls.model_fields.items(): f_dct = f_info.asdict() new_fields[f_name] = ( Annotated[f_dct['annotation'] | None, *f_dct['metadata'], Field(**f_dct['attributes'])], None, ) return create_model( f'{model_cls.__name__}Optional', __base__=model_cls, # (1) **new_fields, ) ``` Using the original model as a base will inherit the [validators](/docs/validation/latest/concepts/validators), [computed fields](/docs/validation/latest/concepts/fields#the-computed_field-decorator), etc. The parent fields are overridden by the ones we define. For each field, we generate a dictionary representation of the [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instance using the [`asdict()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo.asdict) method, containing the annotation, metadata and attributes. With the following model: ```python class Model(BaseModel): f: Annotated[int, Field(gt=1), WithJsonSchema({'extra': 'data'}), Field(title='F')] = 1 ``` The [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instance of `f` will have three items in its dictionary representation: - `annotation`: `int`. - `metadata`: A list containing the type-specific constraints and other metadata: `[Gt(1), WithJsonSchema({'extra': 'data'})]`. - `attributes`: The remaining field-specific attributes: `{'title': 'F'}`. With that in mind, we can recreate an annotation that "simulates" the one from the original model: - [Python 3.9 and above](#tab-panel-603) - [Python 3.11 and above](#tab-panel-604) ```python new_annotation = Annotated[( f_dct['annotation'] | None, # (1) *f_dct['metadata'], # (2) Field(**f_dct['attributes']), # (3) )] ``` We create a new annotation from the existing one, but adding `None` as an allowed value (in our previous example, this is equivalent to `int | None`). We unpack the metadata to be reused (in our previous example, this is equivalent to specifying `Field(gt=1)` and `WithJsonSchema({'extra': 'data'})` as [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata). We specify the field-specific attributes by using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function (in our previous example, this is equivalent to `Field(title='F')`). ```python new_annotation = Annotated[ f_dct['annotation'] | None, # (1) *f_dct['metadata'], # (2) Field(**f_dct['attributes']), # (3) ] ``` We create a new annotation from the existing one, but adding `None` as an allowed value (in our previous example, this is equivalent to `int | None`). We unpack the metadata to be reused (in our previous example, this is equivalent to specifying `Field(gt=1)` and `WithJsonSchema({'extra': 'data'})` as [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata). We specify the field-specific attributes by using the [`Field()`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.Field) function (in our previous example, this is equivalent to `Field(title='F')`). and specify `None` as a default value (the second element of the tuple for the field definition accepted by [`create_model()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.create_model)). Here is a demonstration of our factory function: ```python from pydantic import BaseModel, Field class Model(BaseModel): a: Annotated[int, Field(gt=1)] ModelOptional = make_fields_optional(Model) m = ModelOptional() print(m.a) #> None ``` A couple notes on the implementation: - Our `make_fields_optional()` function is defined as returning an arbitrary Pydantic model class (`-> type[BaseModel]`). An alternative solution can be to use a type variable to preserve the input class: - [Python 3.9 and above](#tab-panel-601) - [Python 3.12 and above](#tab-panel-602) ```python ModelTypeT = TypeVar('ModelTypeT', bound=type[BaseModel]) def make_fields_optional(model_cls: ModelTypeT) -> ModelTypeT: ... ``` ```python def make_fields_optional[ModelTypeT: type[BaseModel]](model_cls: ModelTypeT) -> ModelTypeT: ... ``` However, note that static type checkers _won't_ be able to understand that all fields are now optional. - The experimental [`MISSING` sentinel](/docs/validation/latest/concepts/experimental#missing-sentinel) can be used as an alternative to `None` for the default values. Simply replace `None` by `MISSING` in the new annotation and default value. - You might be tempted to make a copy of the original [`FieldInfo`](/docs/validation/latest/api/pydantic/fields/#pydantic.fields.FieldInfo) instances, add a default and/or perform other mutations, to then reuse it as [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) metadata. While this may work in some cases, it is **not** a supported pattern, and could break or be deprecated at any point. We strongly encourage using the pattern from this example instead. --- # [Validating File Data](https://pydantic.dev/docs/validation/latest/examples/files/) # Validating File Data `pydantic` is a great tool for validating data coming from various sources. In this section, we will look at how to validate data from different types of files. Note If you're using any of the below file formats to parse configuration / settings, you might want to consider using the [`pydantic-settings`](/docs/validation/latest/api/pydantic_settings/#pydantic_settings) library, which offers builtin support for parsing this type of data. ## JSON data `.json` files are a common way to store key / value data in a human-readable format. Here is an example of a `.json` file: ```json { "name": "John Doe", "age": 30, "email": "john@example.com" } ``` To validate this data, we can use a `pydantic` model: ```python import pathlib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_string = pathlib.Path('person.json').read_text() person = Person.model_validate_json(json_string) print(person) #> name='John Doe' age=30 email='john@example.com' ``` If the data in the file is not valid, `pydantic` will raise a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError). Let's say we have the following `.json` file: ```json { "age": -30, "email": "not-an-email-address" } ``` This data is flawed for three reasons: 1. It's missing the `name` field. 2. The `age` field is negative. 3. The `email` field is not a valid email address. When we try to validate this data, `pydantic` raises a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) with all of the above issues: ```python import pathlib from pydantic import BaseModel, EmailStr, PositiveInt, ValidationError class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_string = pathlib.Path('person.json').read_text() try: person = Person.model_validate_json(json_string) except ValidationError as err: print(err) """ 3 validation errors for Person name Field required [type=missing, input_value={'age': -30, 'email': 'not-an-email-address'}, input_type=dict] For further information visit https://errors.pydantic.dev/2.10/v/missing age Input should be greater than 0 [type=greater_than, input_value=-30, input_type=int] For further information visit https://errors.pydantic.dev/2.10/v/greater_than email value is not a valid email address: An email address must have an @-sign. [type=value_error, input_value='not-an-email-address', input_type=str] """ ``` Often, it's the case that you have an abundance of a certain type of data within a `.json` file. For example, you might have a list of people: ```json [ { "name": "John Doe", "age": 30, "email": "john@example.com" }, { "name": "Jane Doe", "age": 25, "email": "jane@example.com" } ] ``` In this case, you can validate the data against a `list[Person]` model: ```python import pathlib from pydantic import BaseModel, EmailStr, PositiveInt, TypeAdapter class Person(BaseModel): name: str age: PositiveInt email: EmailStr person_list_adapter = TypeAdapter(list[Person]) # (1) json_string = pathlib.Path('people.json').read_text() people = person_list_adapter.validate_json(json_string) print(people) #> [Person(name='John Doe', age=30, email='john@example.com'), Person(name='Jane Doe', age=25, email='jane@example.com')] ``` We use [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) to validate a list of `Person` objects. [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) is a Pydantic construct used to validate data against a single type. ## JSON lines files Similar to validating a list of objects from a `.json` file, you can validate a list of objects from a `.jsonl` file. `.jsonl` files are a sequence of JSON objects separated by newlines. Consider the following `.jsonl` file: ```json {"name": "John Doe", "age": 30, "email": "john@example.com"} {"name": "Jane Doe", "age": 25, "email": "jane@example.com"} ``` We can validate this data with a similar approach to the one we used for `.json` files: ```python import pathlib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_lines = pathlib.Path('people.jsonl').read_text().splitlines() people = [Person.model_validate_json(line) for line in json_lines] print(people) #> [Person(name='John Doe', age=30, email='john@example.com'), Person(name='Jane Doe', age=25, email='jane@example.com')] ``` ## CSV files CSV is one of the most common file formats for storing tabular data. To validate data from a CSV file, you can use the `csv` module from the Python standard library to load the data and validate it against a Pydantic model. Consider the following CSV file: ```csv name,age,email John Doe,30,john@example.com Jane Doe,25,jane@example.com ``` Here's how we validate that data: ```python import csv from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open('people.csv') as f: reader = csv.DictReader(f) people = [Person.model_validate(row) for row in reader] print(people) #> [Person(name='John Doe', age=30, email='john@example.com'), Person(name='Jane Doe', age=25, email='jane@example.com')] ``` ## TOML files TOML files are often used for configuration due to their simplicity and readability. Consider the following TOML file: ```toml name = "John Doe" age = 30 email = "john@example.com" ``` Here's how we validate that data: ```python import tomllib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open('person.toml', 'rb') as f: data = tomllib.load(f) person = Person.model_validate(data) print(person) #> name='John Doe' age=30 email='john@example.com' ``` ## YAML files YAML (YAML Ain't Markup Language) is a human-readable data serialization format that is often used for configuration files. Consider the following YAML file: ```yaml name: John Doe age: 30 email: john@example.com ``` Here's how we validate that data: ```python import yaml from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open('person.yaml') as f: data = yaml.safe_load(f) person = Person.model_validate(data) print(person) #> name='John Doe' age=30 email='john@example.com' ``` ## XML files XML (eXtensible Markup Language) is a markup language that defines a set of rules for encoding documents in a format that is both human-readable and machine-readable. Consider the following XML file: ```xml John Doe 30 john@example.com ``` Here's how we validate that data: ```python import xml.etree.ElementTree as ET from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr tree = ET.parse('person.xml').getroot() data = {child.tag: child.text for child in tree} person = Person.model_validate(data) print(person) #> name='John Doe' age=30 email='john@example.com' ``` ## INI files INI files are a simple configuration file format that uses sections and key-value pairs. They are commonly used in Windows applications and older software. Consider the following INI file: ```ini [PERSON] name = John Doe age = 30 email = john@example.com ``` Here's how we validate that data: ```python import configparser from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr config = configparser.ConfigParser() config.read('person.ini') person = Person.model_validate(config['PERSON']) print(person) #> name='John Doe' age=30 email='john@example.com' ``` --- # [Databases](https://pydantic.dev/docs/validation/latest/examples/orms/) # Databases Pydantic serves as a great tool for defining models for ORM (object relational mapping) libraries. ORMs are used to map objects to database tables, and vice versa. ## SQLAlchemy Pydantic can pair with SQLAlchemy, as it can be used to define the schema of the database models. Code Duplication If you use Pydantic with SQLAlchemy, you might experience some frustration with code duplication. If you find yourself experiencing this difficulty, you might also consider [`SQLModel`](https://sqlmodel.tiangolo.com/) which integrates Pydantic with SQLAlchemy such that much of the code duplication is eliminated. If you'd prefer to use pure Pydantic with SQLAlchemy, we recommend using Pydantic models alongside of SQLAlchemy models as shown in the example below. In this case, we take advantage of Pydantic's aliases feature to name a `Column` after a reserved SQLAlchemy field, thus avoiding conflicts. ```python import sqlalchemy as sa from sqlalchemy.orm import declarative_base from pydantic import BaseModel, ConfigDict, Field class MyModel(BaseModel): model_config = ConfigDict(from_attributes=True) metadata: dict[str, str] = Field(alias='metadata_') Base = declarative_base() class MyTableModel(Base): __tablename__ = 'my_table' id = sa.Column('id', sa.Integer, primary_key=True) # 'metadata' is reserved by SQLAlchemy, hence the '_' metadata_ = sa.Column('metadata', sa.JSON) sql_model = MyTableModel(metadata_={'key': 'val'}, id=1) pydantic_model = MyModel.model_validate(sql_model) print(pydantic_model.model_dump()) #> {'metadata': {'key': 'val'}} print(pydantic_model.model_dump(by_alias=True)) #> {'metadata_': {'key': 'val'}} ``` Note The example above works because aliases have priority over field names for field population. Accessing `SQLModel`'s `metadata` attribute would lead to a `ValidationError`. --- # [Agent libraries – Pydantic AI](https://pydantic.dev/docs/validation/latest/examples/pydantic_ai/) # Agent libraries - Pydantic AI [Pydantic AI](https://ai.pydantic.dev/) is a Python agent framework built by the Pydantic team that uses Pydantic validation for [structured output](https://ai.pydantic.dev/output/#structured-output) schema generation and validation. By specifying an `output_type` on an Agent, you can constrain the LLM to return data that matches your Pydantic model schema. ## LLM Structured Output ```python from pydantic_ai import Agent from pydantic import BaseModel, Field, ValidationInfo, field_validator class City(BaseModel): name: str country: str population: int = Field(description='Estimated population', gt=0) @field_validator('country') @classmethod def country_must_be_valid(cls, v: str, info: ValidationInfo) -> str: valid_countries: list[str] = info.context or [] if v not in valid_countries: raise ValueError(f'Unknown country: {v!r}') return v agent = Agent( 'openai:gpt-5-mini', output_type=list[City], # Pydantic validation context (not sent to the model) validation_context=['Japan', 'United States', 'Germany'], ) result = agent.run_sync('List the 3 largest cities in Japan') print(result.output) #> [City(name='Tokyo', country='Japan', population=13960000), ...] ``` --- # [Queues](https://pydantic.dev/docs/validation/latest/examples/queues/) # Queues Pydantic is quite helpful for validating data that goes into and comes out of queues. Below, we'll explore how to validate / serialize data with various queue systems. ## Redis queue Redis is a popular in-memory data structure store. In order to run this example locally, you'll first need to [install Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) and start your server up locally. Here's a simple example of how you can use Pydantic to: 1. Serialize data to push to the queue 2. Deserialize and validate data when it's popped from the queue ```python import redis from pydantic import BaseModel, EmailStr class User(BaseModel): id: int name: str email: EmailStr r = redis.Redis(host='localhost', port=6379, db=0) QUEUE_NAME = 'user_queue' def push_to_queue(user_data: User) -> None: serialized_data = user_data.model_dump_json() r.rpush(QUEUE_NAME, serialized_data) print(f'Added to queue: {serialized_data}') user1 = User(id=1, name='John Doe', email='john@example.com') user2 = User(id=2, name='Jane Doe', email='jane@example.com') push_to_queue(user1) #> Added to queue: {"id":1,"name":"John Doe","email":"john@example.com"} push_to_queue(user2) #> Added to queue: {"id":2,"name":"Jane Doe","email":"jane@example.com"} def pop_from_queue() -> None: data = r.lpop(QUEUE_NAME) if data: user = User.model_validate_json(data) print(f'Validated user: {repr(user)}') else: print('Queue is empty') pop_from_queue() #> Validated user: User(id=1, name='John Doe', email='john@example.com') pop_from_queue() #> Validated user: User(id=2, name='Jane Doe', email='jane@example.com') pop_from_queue() #> Queue is empty ``` ## RabbitMQ RabbitMQ is a popular message broker that implements the AMQP protocol. In order to run this example locally, you'll first need to [install RabbitMQ](https://www.rabbitmq.com/download.html) and start your server. Here's a simple example of how you can use Pydantic to: 1. Serialize data to push to the queue 2. Deserialize and validate data when it's popped from the queue First, let's create a sender script. ```python import pika from pydantic import BaseModel, EmailStr class User(BaseModel): id: int name: str email: EmailStr connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() QUEUE_NAME = 'user_queue' channel.queue_declare(queue=QUEUE_NAME) def push_to_queue(user_data: User) -> None: serialized_data = user_data.model_dump_json() channel.basic_publish( exchange='', routing_key=QUEUE_NAME, body=serialized_data, ) print(f'Added to queue: {serialized_data}') user1 = User(id=1, name='John Doe', email='john@example.com') user2 = User(id=2, name='Jane Doe', email='jane@example.com') push_to_queue(user1) #> Added to queue: {"id":1,"name":"John Doe","email":"john@example.com"} push_to_queue(user2) #> Added to queue: {"id":2,"name":"Jane Doe","email":"jane@example.com"} connection.close() ``` And here's the receiver script. ```python import pika from pydantic import BaseModel, EmailStr class User(BaseModel): id: int name: str email: EmailStr def main(): connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() QUEUE_NAME = 'user_queue' channel.queue_declare(queue=QUEUE_NAME) def process_message( ch: pika.channel.Channel, method: pika.spec.Basic.Deliver, properties: pika.spec.BasicProperties, body: bytes, ): user = User.model_validate_json(body) print(f'Validated user: {repr(user)}') ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_consume(queue=QUEUE_NAME, on_message_callback=process_message) channel.start_consuming() if __name__ == '__main__': try: main() except KeyboardInterrupt: pass ``` To test this example: 1. Run the receiver script in one terminal to start the consumer. 2. Run the sender script in another terminal to send messages. ## ARQ ARQ is a fast Redis-based job queue for Python. It's built on top of Redis and provides a simple way to handle background tasks. In order to run this example locally, you'll need to [Install Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/) and start your server. Here's a simple example of how you can use Pydantic with ARQ to: 1. Define a model for your job data 2. Serialize data when enqueueing jobs 3. Validate and deserialize data when processing jobs ```python import asyncio from typing import Any from arq import create_pool from arq.connections import RedisSettings from pydantic import BaseModel, EmailStr class User(BaseModel): id: int name: str email: EmailStr REDIS_SETTINGS = RedisSettings() async def process_user(ctx: dict[str, Any], user_data: dict[str, Any]) -> None: user = User.model_validate(user_data) print(f'Processing user: {repr(user)}') async def enqueue_jobs(redis): user1 = User(id=1, name='John Doe', email='john@example.com') user2 = User(id=2, name='Jane Doe', email='jane@example.com') await redis.enqueue_job('process_user', user1.model_dump()) print(f'Enqueued user: {repr(user1)}') await redis.enqueue_job('process_user', user2.model_dump()) print(f'Enqueued user: {repr(user2)}') class WorkerSettings: functions = [process_user] redis_settings = REDIS_SETTINGS async def main(): redis = await create_pool(REDIS_SETTINGS) await enqueue_jobs(redis) if __name__ == '__main__': asyncio.run(main()) ``` This script is complete. It should run "as is" both to enqueue jobs and to process them. --- # [Web and API Requests](https://pydantic.dev/docs/validation/latest/examples/requests/) # Web and API Requests Pydantic models are a great way to validate and serialize data for requests and responses. Pydantic is instrumental in many web frameworks and libraries, such as FastAPI, Django, Flask, and HTTPX. ## `httpx` requests [`httpx`](https://www.python-httpx.org/) is an HTTP client for Python 3 with synchronous and asynchronous APIs. In the below example, we query the [JSONPlaceholder API](https://jsonplaceholder.typicode.com/) to get a user's data and validate it with a Pydantic model. ```python import httpx from pydantic import BaseModel, EmailStr class User(BaseModel): id: int name: str email: EmailStr url = 'https://jsonplaceholder.typicode.com/users/1' response = httpx.get(url) response.raise_for_status() user = User.model_validate(response.json()) print(repr(user)) #> User(id=1, name='Leanne Graham', email='Sincere@april.biz') ``` The [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) tool from Pydantic often comes in quite handy when working with HTTP requests. Consider a similar example where we are validating a list of users: ```python from pprint import pprint import httpx from pydantic import BaseModel, EmailStr, TypeAdapter class User(BaseModel): id: int name: str email: EmailStr url = 'https://jsonplaceholder.typicode.com/users/' # (1) response = httpx.get(url) response.raise_for_status() users_list_adapter = TypeAdapter(list[User]) users = users_list_adapter.validate_python(response.json()) pprint([u.name for u in users]) """ ['Leanne Graham', 'Ervin Howell', 'Clementine Bauch', 'Patricia Lebsack', 'Chelsey Dietrich', 'Mrs. Dennis Schulist', 'Kurtis Weissnat', 'Nicholas Runolfsdottir V', 'Glenna Reichert', 'Clementina DuBuque'] """ ``` Note, we're querying the `/users/` endpoint here to get a list of users. --- # [Changelog](https://pydantic.dev/docs/validation/latest/get-started/changelog/) # Changelog ## v2.13.4 (2026-05-06) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.4) ### What's Changed #### Packaging - Bump libc from 0.2.155 to 0.2.185 by [@Viicos](https://github.com/Viicos) in [#13109](https://github.com/pydantic/pydantic/pull/13109) - Adapt `pydantic-core` linker flags on macOS by [@washingtoneg](https://github.com/washingtoneg) and [@Viicos](https://github.com/Viicos) in [#13147](https://github.com/pydantic/pydantic/pull/13147) #### Fixes - Preserve `RootModel` core metadata by [@Viicos](https://github.com/Viicos) in [#13129](https://github.com/pydantic/pydantic/pull/13129) ## v2.13.3 (2026-04-20) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.3) ### What's Changed #### Fixes - Handle `AttributeError` subclasses with `from_attributes` by [@Viicos](https://github.com/Viicos) in [#13096](https://github.com/pydantic/pydantic/pull/13096) ## v2.13.2 (2026-04-17) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.2) ### What's Changed #### Fixes - Fix `ValidationInfo.field_name` missing with `model_validate_json()` by [@Viicos](https://github.com/Viicos) in [#13084](https://github.com/pydantic/pydantic/pull/13084) ## v2.13.1 (2026-04-15) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.1) ### What's Changed #### Fixes - Fix `ValidationInfo.data` missing with `model_validate_json()` by [@davidhewitt](https://github.com/davidhewitt) in [#13079](https://github.com/pydantic/pydantic/pull/13079) ## v2.13.0 (2026-04-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.0) The highlights of the v2.13 release are available in the [blog post](https://pydantic.dev/articles/pydantic-v2-13-release). Several minor changes (considered non-breaking changes according to our [versioning policy](https://pydantic.dev/docs/validation/2.13/get-started/version-policy/#pydantic-v2)) are also included in this release. Make sure to look into them before upgrading. This release contains the updated `pydantic.v1` namespace, matching version 1.10.26 which includes support for Python 3.14. ### What's Changed See the beta releases for all changes sinces 2.12. #### New Features - Allow default factories of private attributes to take validated model data by [@Viicos](https://github.com/Viicos) in [#13013](https://github.com/pydantic/pydantic/pull/13013) #### Changes - Warn when serializing fixed length tuples with too few items by [@arvindsaripalli](https://github.com/arvindsaripalli) in [#13016](https://github.com/pydantic/pydantic/pull/13016) #### Fixes - Change type of `Any` when synthesizing `_build_sources` for `BaseSettings.__init__()` signature in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#13049](https://github.com/pydantic/pydantic/pull/13049) - Fix model equality when using runtime `extra` configuration by [@Viicos](https://github.com/Viicos) in [#13062](https://github.com/pydantic/pydantic/pull/13062) #### Packaging - Add zizmor for GitHub Actions workflow linting by [@Viicos](https://github.com/Viicos) in [#13039](https://github.com/pydantic/pydantic/pull/13039) - Update jiter to v0.14.0 to fix a segmentation fault on musl Linux by [@Viicos](https://github.com/Viicos) in [#13064](https://github.com/pydantic/pydantic/pull/13064) ### New Contributors - [@arvindsaripalli](https://github.com/arvindsaripalli) made their first contribution in [#13016](https://github.com/pydantic/pydantic/pull/13016) ## v2.13.0b3 (2026-03-31) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.0b3) ### What's Changed #### New Features - Add `ascii_only` option to `StringConstraints` by [@ai-man-codes](https://github.com/ai-man-codes) in [#12907](https://github.com/pydantic/pydantic/pull/12907) - Support `exclude_if` in computed fields by [@andresliszt](https://github.com/andresliszt) in [#12748](https://github.com/pydantic/pydantic/pull/12748) - Push down constraints in unions involving `MISSING` sentinel by [@Viicos](https://github.com/Viicos) in [#12908](https://github.com/pydantic/pydantic/pull/12908) #### Changes - Track extra fields set after init in `model_fields_set` by [@navalprakhar](https://github.com/navalprakhar) in [#12817](https://github.com/pydantic/pydantic/pull/12817) - Do not include annotations that are not part of named tuple fields by [@galuszkak](https://github.com/galuszkak) in [#12951](https://github.com/pydantic/pydantic/pull/12951) - No longer fall back to trying all union members when the variant selected by discriminator fails to serialize by [@navalprakhar](https://github.com/navalprakhar) in [#12825](https://github.com/pydantic/pydantic/pull/12825) #### Fixes - Support discriminator metadata outside union type alias by [@Viicos](https://github.com/Viicos) in [#12785](https://github.com/pydantic/pydantic/pull/12785) - Respect `extras_schema` when only `extra_fields_behavior` is set on the config in JSON Schema generation for typed dictionaries by [@Viicos](https://github.com/Viicos) in [#12810](https://github.com/pydantic/pydantic/pull/12810) - Ensure `__pydantic_private__` is set in `model_construct()` with user-defined `model_post_init()` by [@nightcityblade](https://github.com/nightcityblade) in [#12816](https://github.com/pydantic/pydantic/pull/12816) - Handle all schema generation errors in `InstanceOf` by [@Viicos](https://github.com/Viicos) in [#12705](https://github.com/pydantic/pydantic/pull/12705) - Allow dynamic models created with `create_model()` to be used as annotations in the Mypy plugin by [@Br1an67](https://github.com/Br1an67) in [#12879](https://github.com/pydantic/pydantic/pull/12879) - Check for `PlaceholderNode` in Mypy plugin by [@Viicos](https://github.com/Viicos) in [#12929](https://github.com/pydantic/pydantic/pull/12929) - Try other branches in smart union in case of omit errors by [@mikeedjones](https://github.com/mikeedjones) in [#12758](https://github.com/pydantic/pydantic/pull/12758) - Patch unset attributes with `MISSING` during model serialization with `exclude_unset` by [@davidhewitt](https://github.com/davidhewitt) in [#12905](https://github.com/pydantic/pydantic/pull/12905) - Ensure custom `__init__()` is called when using `model_validate_strings()` by [@siewcapital](https://github.com/siewcapital) in [#12897](https://github.com/pydantic/pydantic/pull/12897) #### Packaging - Add riscv64 build target for manylinux by [@boosterl](https://github.com/boosterl) in [#12723](https://github.com/pydantic/pydantic/pull/12723) ### New Contributors - [@kelsonbrito50](https://github.com/kelsonbrito50) made their first contribution in [#12860](https://github.com/pydantic/pydantic/pull/12860) - [@boosterl](https://github.com/boosterl) made their first contribution in [#12723](https://github.com/pydantic/pydantic/pull/12723) - [@adityagiri3600](https://github.com/adityagiri3600) made their first contribution in [#12868](https://github.com/pydantic/pydantic/pull/12868) - [@navalprakhar](https://github.com/navalprakhar) made their first contribution in [#12817](https://github.com/pydantic/pydantic/pull/12817) - [@Br1an67](https://github.com/Br1an67) made their first contribution in [#12879](https://github.com/pydantic/pydantic/pull/12879) - [@rmorshea](https://github.com/rmorshea) made their first contribution in [#12910](https://github.com/pydantic/pydantic/pull/12910) - [@N3XT3R1337](https://github.com/N3XT3R1337) made their first contribution in [#12922](https://github.com/pydantic/pydantic/pull/12922) - [@ai-man-codes](https://github.com/ai-man-codes) made their first contribution in [#12907](https://github.com/pydantic/pydantic/pull/12907) - [@Yume05-dev](https://github.com/Yume05-dev) made their first contribution in [#12953](https://github.com/pydantic/pydantic/pull/12953) - [@galuszkak](https://github.com/galuszkak) made their first contribution in [#12951](https://github.com/pydantic/pydantic/pull/12951) - [@siewcapital](https://github.com/siewcapital) made their first contribution in [#12897](https://github.com/pydantic/pydantic/pull/12897) ## v2.13.0b2 (2026-02-24) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.0b2) ### What's Changed #### Fixes - Fix backported V1 namespace by [@Viicos](https://github.com/Viicos) in [#12855](https://github.com/pydantic/pydantic/pull/12855) - Allow any type form to be used in `validate_as()` by [@bledden](https://github.com/bledden) in [#12846](https://github.com/pydantic/pydantic/pull/12846) - Fix walrus operator precedence in `UrlConstraints.__get_pydantic_core_schema__()` by [@bysiber](https://github.com/bysiber) in [#12826](https://github.com/pydantic/pydantic/pull/12826) ### New Contributors - [@bledden](https://github.com/bledden) made their first contribution in [#12846](https://github.com/pydantic/pydantic/pull/12846) - [@bysiber](https://github.com/bysiber) made their first contribution in [#12827](https://github.com/pydantic/pydantic/pull/12827) ## v2.13.0b1 (2026-02-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.0b1) This is the first beta release of the 2.13 version, mainly providing bug fixes and performance improvements for validation and serialization. Notable changes include: - Add a new `polymorphic_serialization` option, solving issues with `serialize_as_any` introduced in 2.12. - Latest V1.10.26 release under the `pydantic.v1` namespace. This version includes support for Python 3.14. - The [`pydantic-core`](https://github.com/pydantic/pydantic-core/) repository was merged inside the main `pydantic` one. ### What's Changed #### New Features - Add `polymorphic_serialization` option by [@davidhewitt](https://github.com/davidhewitt) in [#12518](https://github.com/pydantic/pydantic/pull/12518) - Support Root models with `Literal` root types as discriminator field types by [@YassinNouh21](https://github.com/YassinNouh21) in [#12680](https://github.com/pydantic/pydantic/pull/12680) #### Changes - Migrate `pydantic-core` CI by [@Viicos](https://github.com/Viicos) in [#12752](https://github.com/pydantic/pydantic/pull/12752) - Import `pydantic-core` into pydantic by [@davidhewitt](https://github.com/davidhewitt) in [#12481](https://github.com/pydantic/pydantic/pull/12481) - Backport V1 changes up to v1.10.26 by [@Viicos](https://github.com/Viicos) in [#12663](https://github.com/pydantic/pydantic/pull/12663) - Use the `complex()` constructor unconditionally when validating `complex` Python data by [@tanmaymunjal](https://github.com/tanmaymunjal) in [#12498](https://github.com/pydantic/pydantic/pull/12498) - Add support for three-tuple input for `Decimal` by [@tanmaymunjal](https://github.com/tanmaymunjal) in [#12500](https://github.com/pydantic/pydantic/pull/12500) - Align `@field_serializer` logic with `@field_validator` by [@Viicos](https://github.com/Viicos) in [#12577](https://github.com/pydantic/pydantic/pull/12577) - Make `PydanticUserError` a `RuntimeError` instead of a `TypeError` by [@poliakovva](https://github.com/poliakovva) in [#12579](https://github.com/pydantic/pydantic/pull/12579) - Remove redundant serialization attempts in nested unions by [@davidhewitt](https://github.com/davidhewitt) in [#12604](https://github.com/pydantic/pydantic/pull/12604) - Copy `root` value when making root model shallow copies by [@YassinNouh21](https://github.com/YassinNouh21) in [#12679](https://github.com/pydantic/pydantic/pull/12679) - Ensure deterministic JSON schema defaults by sorting sets by [@drshvik](https://github.com/drshvik) in [#12760](https://github.com/pydantic/pydantic/pull/12760) #### Performance - Refactor `DecoratorInfos.build()` implementation by [@Viicos](https://github.com/Viicos) in [#12536](https://github.com/pydantic/pydantic/pull/12536) - Cache compiled regex in `pydantic-core` by [@Viicos](https://github.com/Viicos) in [#12549](https://github.com/pydantic/pydantic/pull/12549) - Optimize creation of `Literal` validators by [@davidhewitt](https://github.com/davidhewitt) in [#12569](https://github.com/pydantic/pydantic/pull/12569) - Optimize implementation of `LookupKey` by [@davidhewitt](https://github.com/davidhewitt) in [#12571](https://github.com/pydantic/pydantic/pull/12571) - Use python strings for field names by [@davidhewitt](https://github.com/davidhewitt) in [#12631](https://github.com/pydantic/pydantic/pull/12631) - Optimize datetime formatting code by [@davidhewitt](https://github.com/davidhewitt) in [#12626](https://github.com/pydantic/pydantic/pull/12626) - Validate JSON model data by iteration by [@davidhewitt](https://github.com/davidhewitt) in [#12550](https://github.com/pydantic/pydantic/pull/12550) - Optimize annotations evaluation of Pydantic models by [@Viicos](https://github.com/Viicos) in [#12681](https://github.com/pydantic/pydantic/pull/12681) - Optimize `FieldInfo._copy()` by [@Viicos](https://github.com/Viicos) in [#12727](https://github.com/pydantic/pydantic/pull/12727) #### Fixes - Fix `FieldInfo` rebuilding when parameterizing generic models with an `Annotated` type by [@Viicos](https://github.com/Viicos) in [#12463](https://github.com/pydantic/pydantic/pull/12463) - Fix nested model schema deduplication in JSON schema generation by [@marwan-alloreview](https://github.com/marwan-alloreview) in [#12494](https://github.com/pydantic/pydantic/pull/12494) - Fix `InitVar` being ignored when using with the `pydantic.Field()` function by [@Viicos](https://github.com/Viicos) in [#12495](https://github.com/pydantic/pydantic/pull/12495) - Fix support for enums with `NamedTuple` as values by [@Viicos](https://github.com/Viicos) in [#12506](https://github.com/pydantic/pydantic/pull/12506) - Do not delete mock validator/serializer in `rebuild_dataclass()` by [@Viicos](https://github.com/Viicos) in [#12513](https://github.com/pydantic/pydantic/pull/12513) - Require test suite to pass with free threading, switch back to global generic types cache by [@davidhewitt](https://github.com/davidhewitt) in [#12537](https://github.com/pydantic/pydantic/pull/12537) - Refactor `__pydantic_extra__` annotation handling by [@Viicos](https://github.com/Viicos) in [#12563](https://github.com/pydantic/pydantic/pull/12563) - Do not add claim of UUID "safety" provision by [@davidhewitt](https://github.com/davidhewitt) in [#12567](https://github.com/pydantic/pydantic/pull/12567) - Use Python hash to perform lookup in tagged union serializer by [@davidhewitt](https://github.com/davidhewitt) in [#12594](https://github.com/pydantic/pydantic/pull/12594) - Do not emit serialization warning `MISSING` sentinel is present in a nested model by [@Viicos](https://github.com/Viicos) in [#12635](https://github.com/pydantic/pydantic/pull/12635) - Do not eagerly evaluate annotations in signature logic by [@Viicos](https://github.com/Viicos) in [#12660](https://github.com/pydantic/pydantic/pull/12660) - Fix serialization of typed dict unions when `exclude_none` is set by [@davidhewitt](https://github.com/davidhewitt) in [#12677](https://github.com/pydantic/pydantic/pull/12677) - Do not reuse prebuilt serializers/validators on rebuilds by [@lmmx](https://github.com/lmmx) in [#12689](https://github.com/pydantic/pydantic/pull/12689) - Fix type annotation of `field_definitions` in `create_model()` by [@lehmann-hqs](https://github.com/lehmann-hqs) in [#12734](https://github.com/pydantic/pydantic/pull/12734) - Fix incorrect dataclass constructor signature when overriding class `kw_only` with `Field()` by [@jfadia](https://github.com/jfadia) in [#12741](https://github.com/pydantic/pydantic/pull/12741) - Use `typing.Union` when replacing types under Python 3.14 by [@Viicos](https://github.com/Viicos) in [#12733](https://github.com/pydantic/pydantic/pull/12733) - Improve ImportString error when internal imports fail by [@tsembp](https://github.com/tsembp) in [#12740](https://github.com/pydantic/pydantic/pull/12740) - Fix serializing complex numbers with negative zero imaginary part by [@lhnwrk](https://github.com/lhnwrk) in [#12770](https://github.com/pydantic/pydantic/pull/12770) - Preserve custom docstrings on stdlib dataclasses in JSON schema by [@nightcityblade](https://github.com/nightcityblade) in [#12815](https://github.com/pydantic/pydantic/pull/12815) #### Packaging - Bump Rust url dependency from 2.5.4 to 2.5.7 in `pydantic-core` by [@dependabot](https://github.com/dependabot)\[bot\] in [#12508](https://github.com/pydantic/pydantic/pull/12508) - Bump Rust minimum version to 1.88, use edition 2024 by [@davidhewitt](https://github.com/davidhewitt) and [@Viicos](https://github.com/Viicos) in [#12551](https://github.com/pydantic/pydantic/pull/12551) and [#12752](https://github.com/pydantic/pydantic/pull/12752) - Bump PyO3 to 0.28, jiter to 0.13 by [@davidhewitt](https://github.com/davidhewitt) in [#12767](https://github.com/pydantic/pydantic/pull/12767) ### New Contributors - [@marwan-alloreview](https://github.com/marwan-alloreview) made their first contribution in [#12494](https://github.com/pydantic/pydantic/pull/12494) - [@tanmaymunjal](https://github.com/tanmaymunjal) made their first contribution in [#12498](https://github.com/pydantic/pydantic/pull/12498) - [@poliakovva](https://github.com/poliakovva) made their first contribution in [#12579](https://github.com/pydantic/pydantic/pull/12579) - [@lehmann-hqs](https://github.com/lehmann-hqs) made their first contribution in [#12734](https://github.com/pydantic/pydantic/pull/12734) - [@jfadia](https://github.com/jfadia) made their first contribution in [#12741](https://github.com/pydantic/pydantic/pull/12741) - [@tsembp](https://github.com/tsembp) made their first contribution in [#12740](https://github.com/pydantic/pydantic/pull/12740) - [@drshvik](https://github.com/drshvik) made their first contribution in [#12760](https://github.com/pydantic/pydantic/pull/12760) - [@lhnwrk](https://github.com/lhnwrk) made their first contribution in [#12770](https://github.com/pydantic/pydantic/pull/12770) - [@nightcityblade](https://github.com/nightcityblade) made their first contribution in [#12815](https://github.com/pydantic/pydantic/pull/12811) ## v2.12.5 (2025-11-26) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.5) This is the fifth 2.12 patch release, addressing an issue with the `MISSING` sentinel and providing several documentation improvements. The next 2.13 minor release will be published in a couple weeks, and will include a new _polymorphic serialization_ feature addressing the remaining unexpected changes to the _serialize as any_ behavior. - Fix pickle error when using `model_construct()` on a model with `MISSING` as a default value by [@ornariece](https://github.com/ornariece) in [#12522](https://github.com/pydantic/pydantic/pull/12522). - Several updates to the documentation by [@Viicos](https://github.com/Viicos). ## v2.12.4 (2025-11-05) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.4) This is the fourth 2.12 patch release, fixing more regressions, and reverting a change in the `build()` method of the [`AnyUrl` and Dsn types](https://docs.pydantic.dev/latest/api/networks/). This patch release also fixes an issue with the serialization of IP address types, when `serialize_as_any` is used. The next patch release will try to address the remaining issues with _serialize as any_ behavior by introducing a new _polymorphic serialization_ feature, that should be used in most cases in place of _serialize as any_. - Fix issue with forward references in parent `TypedDict` classes by [@Viicos](https://github.com/Viicos) in [#12427](https://github.com/pydantic/pydantic/pull/12427). This issue is only relevant on Python 3.14 and greater. - Exclude fields with `exclude_if` from JSON Schema required fields by [@Viicos](https://github.com/Viicos) in [#12430](https://github.com/pydantic/pydantic/pull/12430) - Revert URL percent-encoding of credentials in the `build()` method of the [`AnyUrl` and Dsn types](https://docs.pydantic.dev/latest/api/networks/) by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1833](https://github.com/pydantic/pydantic-core/pull/1833). This was initially considered as a bugfix, but caused regressions and as such was fully reverted. The next release will include an opt-in option to percent-encode components of the URL. - Add type inference for IP address types by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1868](https://github.com/pydantic/pydantic-core/pull/1868). The 2.12 changes to the `serialize_as_any` behavior made it so that IP address types could not properly serialize to JSON. - Avoid getting default values from defaultdict by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1853](https://github.com/pydantic/pydantic-core/pull/1853). This fixes a subtle regression in the validation behavior of the [`collections.defaultdict`](https://docs.python.org/3/library/collections.html#collections.defaultdict) type. - Fix issue with field serializers on nested typed dictionaries by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1879](https://github.com/pydantic/pydantic-core/pull/1879). - Add more `pydantic-core` builds for the three-threaded version of Python 3.14 by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1864](https://github.com/pydantic/pydantic-core/pull/1864). ## v2.12.3 (2025-10-17) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.3) ### What's Changed This is the third 2.12 patch release, fixing issues related to the `FieldInfo` class, and reverting a change to the supported [_after_ model validator](https://docs.pydantic.dev/latest/concepts/validators/#model-validators) function signatures. - Raise a warning when an invalid after model validator function signature is raised by [@Viicos](https://github.com/Viicos) in [#12414](https://github.com/pydantic/pydantic/pull/12414). Starting in 2.12.0, using class methods for _after_ model validators raised an error, but the error wasn't raised concistently. We decided to emit a deprecation warning instead. - Add [`FieldInfo.asdict()`](https://docs.pydantic.dev/latest/api/fields/#pydantic.fields.FieldInfo.asdict) method, improve documentation around `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#12411](https://github.com/pydantic/pydantic/pull/12411). This also add back support for mutations on `FieldInfo` classes, that are reused as `Annotated` metadata. **However**, note that this is still _not_ a supported pattern. Instead, please refer to the [added example](https://docs.pydantic.dev/latest/examples/dynamic_models/) in the documentation. The [blog post](https://pydantic.dev/articles/pydantic-v2-12-release#changes) section on changes was also updated to document the changes related to `serialize_as_any`. ## v2.12.2 (2025-10-14) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.2) ### What's Changed #### Fixes - Release a new `pydantic-core` version, as a corrupted CPython 3.10 `manylinux2014_aarch64` wheel got uploaded ([pydantic-core#1843](https://github.com/pydantic/pydantic-core/pull/1843)). - Fix issue with recursive generic models with a parent model class by [@Viicos](https://github.com/Viicos) in [#12398](https://github.com/pydantic/pydantic/pull/12398) ## v2.12.1 (2025-10-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.1) ### What's Changed This is the first 2.12 patch release, addressing most (but not all yet) regressions from the initial 2.12.0 release. #### Fixes - Do not evaluate annotations when inspecting validators and serializers by [@Viicos](https://github.com/Viicos) in [#12355](https://github.com/pydantic/pydantic/pull/12355) - Make sure `None` is converted as `NoneType` in Python 3.14 by [@Viicos](https://github.com/Viicos) in [#12370](https://github.com/pydantic/pydantic/pull/12370) - Backport V1 runtime warning when using Python 3.14 by [@Viicos](https://github.com/Viicos) in [#12367](https://github.com/pydantic/pydantic/pull/12367) - Fix error message for invalid validator signatures by [@Viicos](https://github.com/Viicos) in [#12366](https://github.com/pydantic/pydantic/pull/12366) - Populate field name in `ValidationInfo` for validation of default value by [@Viicos](https://github.com/Viicos) in [pydantic-core#1826](https://github.com/pydantic/pydantic-core/pull/1826) - Encode credentials in `MultiHostUrl` builder by [@willswire](https://github.com/willswire) in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) - Respect field serializers when using `serialize_as_any` serialization flag by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) - Fix various `RootModel` serialization issues by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1836](https://github.com/pydantic/pydantic-core/pull/1836) ### New Contributors - [@willswire](https://github.com/willswire) made their first contribution in [pydantic-core#1829](https://github.com/pydantic/pydantic-core/pull/1829) ## v2.12.0 (2025-10-07) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0) This is the final 2.12 release. It features the work of 20 external contributors and provides useful new features, along with initial Python 3.14 support. Several minor changes (considered non-breaking changes according to our [versioning policy](https://docs.pydantic.dev/2.12/version-policy/#pydantic-v2)) are also included in this release. Make sure to look into them before upgrading. **Note that Pydantic V1 is not compatible with Python 3.14 and greater**. ### What's Changed See the beta releases for all changes sinces 2.11. #### New Features - Add `extra` parameter to the validate functions by [@anvilpete](https://github.com/anvilpete) in [#12233](https://github.com/pydantic/pydantic/pull/12233) - Add `exclude_computed_fields` serialization option by [@Viicos](https://github.com/Viicos) in [#12334](https://github.com/pydantic/pydantic/pull/12334) - Add `preverse_empty_path` URL options by [@Viicos](https://github.com/Viicos) in [#12336](https://github.com/pydantic/pydantic/pull/12336) - Add `union_format` parameter to JSON Schema generation by [@Viicos](https://github.com/Viicos) in [#12147](https://github.com/pydantic/pydantic/pull/12147) - Add `__qualname__` parameter for `create_model` by [@Atry](https://github.com/Atry) in [#12001](https://github.com/pydantic/pydantic/pull/12001) #### Fixes - Do not try to infer name from lambda definitions in pipelines API by [@Viicos](https://github.com/Viicos) in [#12289](https://github.com/pydantic/pydantic/pull/12289) - Use proper namespace for functions in `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [#12324](https://github.com/pydantic/pydantic/pull/12324) - Use `Any` for context type annotation in `TypeAdapter` by [@inducer](https://github.com/inducer) in [#12279](https://github.com/pydantic/pydantic/pull/12279) - Expose `FieldInfo` in `pydantic.fields.__all__` by [@Viicos](https://github.com/Viicos) in [#12339](https://github.com/pydantic/pydantic/pull/12339) - Respect `validation_alias` in `@validate_call` by [@Viicos](https://github.com/Viicos) in [#12340](https://github.com/pydantic/pydantic/pull/12340) - Use `Any` as context annotation in plugin API by [@Viicos](https://github.com/Viicos) in [#12341](https://github.com/pydantic/pydantic/pull/12341) - Use proper `stacklevel` in warnings when possible by [@Viicos](https://github.com/Viicos) in [#12342](https://github.com/pydantic/pydantic/pull/12342) #### Packaging - Update V1 copy to v1.10.24 by [@Viicos](https://github.com/Viicos) in [#12338](https://github.com/pydantic/pydantic/pull/12338) ### New Contributors - [@anvilpete](https://github.com/anvilpete) made their first contribution in [#12233](https://github.com/pydantic/pydantic/pull/12233) - [@JonathanWindell](https://github.com/JonathanWindell) made their first contribution in [#12327](https://github.com/pydantic/pydantic/pull/12327) - [@inducer](https://github.com/inducer) made their first contribution in [#12279](https://github.com/pydantic/pydantic/pull/12279) - [@Atry](https://github.com/Atry) made their first contribution in [#12001](https://github.com/pydantic/pydantic/pull/12001) ## v2.12.0b1 (2025-10-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0b1) This is the first beta release of the upcoming 2.12 release. ### What's Changed #### New Features - Add support for `exclude_if` at the field level by [@andresliszt](https://github.com/andresliszt) in [#12141](https://github.com/pydantic/pydantic/pull/12141) - Add `ValidateAs` annotation helper by [@Viicos](https://github.com/Viicos) in [#11942](https://github.com/pydantic/pydantic/pull/11942) - Add configuration options for validation and JSON serialization of temporal types by [@ollz272](https://github.com/ollz272) in [#12068](https://github.com/pydantic/pydantic/pull/12068) - Add support for PEP 728 by [@Viicos](https://github.com/Viicos) in [#12179](https://github.com/pydantic/pydantic/pull/12179) - Add field name in serialization error by [@NicolasPllr1](https://github.com/NicolasPllr1) in [pydantic-core#1799](https://github.com/pydantic/pydantic-core/pull/1799) - Add option to preserve empty URL paths by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1789](https://github.com/pydantic/pydantic-core/pull/1789) #### Changes - Raise error if an incompatible `pydantic-core` version is installed by [@Viicos](https://github.com/Viicos) in [#12196](https://github.com/pydantic/pydantic/pull/12196) - Remove runtime warning for experimental features by [@Viicos](https://github.com/Viicos) in [#12265](https://github.com/pydantic/pydantic/pull/12265) - Warn if registering virtual subclasses on Pydantic models by [@Viicos](https://github.com/Viicos) in [#11669](https://github.com/pydantic/pydantic/pull/11669) #### Fixes - Fix `__getattr__()` behavior on Pydantic models when a property raised an `AttributeError` and extra values are present by [@raspuchin](https://github.com/raspuchin) in [#12106](https://github.com/pydantic/pydantic/pull/12106) - Add test to prevent regression with Pydantic models used as annotated metadata by [@Viicos](https://github.com/Viicos) in [#12133](https://github.com/pydantic/pydantic/pull/12133) - Allow to use property setters on Pydantic dataclasses with `validate_assignment` set by [@Viicos](https://github.com/Viicos) in [#12173](https://github.com/pydantic/pydantic/pull/12173) - Fix mypy v2 plugin for upcoming mypy release by [@cdce8p](https://github.com/cdce8p) in [#12209](https://github.com/pydantic/pydantic/pull/12209) - Respect custom title in functions JSON Schema by [@Viicos](https://github.com/Viicos) in [#11892](https://github.com/pydantic/pydantic/pull/11892) - Fix `ImportString` JSON serialization for objects with a `name` attribute by [@chr1sj0nes](https://github.com/chr1sj0nes) in [#12219](https://github.com/pydantic/pydantic/pull/12219) - Do not error on fields overridden by methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#12290](https://github.com/pydantic/pydantic/pull/12290) #### Packaging - Bump `pydantic-core` to v2.40.1 by [@Viicos](https://github.com/Viicos) in [#12314](https://github.com/pydantic/pydantic/pull/12314) ### New Contributors - [@raspuchin](https://github.com/raspuchin) made their first contribution in [#12106](https://github.com/pydantic/pydantic/pull/12106) - [@chr1sj0nes](https://github.com/chr1sj0nes) made their first contribution in [#12219](https://github.com/pydantic/pydantic/pull/12219) ## v2.12.0a1 (2025-07-26) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.12.0a1) This is the first alpha release of the upcoming 2.12 release, which adds initial support for Python 3.14. ### What's Changed #### New Features - Add `__pydantic_on_complete__()` hook that is called once model is fully ready to be used by [@DouweM](https://github.com/DouweM) in [#11762](https://github.com/pydantic/pydantic/pull/11762) - Add initial support for Python 3.14 by [@Viicos](https://github.com/Viicos) in [#11991](https://github.com/pydantic/pydantic/pull/11991) - Add regex patterns to JSON schema for `Decimal` type by [@Dima-Bulavenko](https://github.com/Dima-Bulavenko) in [#11987](https://github.com/pydantic/pydantic/pull/11987) - Add support for `doc` attribute on dataclass fields by [@Viicos](https://github.com/Viicos) in [#12077](https://github.com/pydantic/pydantic/pull/12077) - Add experimental `MISSING` sentinel by [@Viicos](https://github.com/Viicos) in [#11883](https://github.com/pydantic/pydantic/pull/11883) #### Changes - Allow config and bases to be specified together in `create_model()` by [@Viicos](https://github.com/Viicos) in [#11714](https://github.com/pydantic/pydantic/pull/11714) - Move some field logic out of the `GenerateSchema` class by [@Viicos](https://github.com/Viicos) in [#11733](https://github.com/pydantic/pydantic/pull/11733) - Always make use of `inspect.getsourcelines()` for docstring extraction on Python 3.13 and greater by [@Viicos](https://github.com/Viicos) in [#11829](https://github.com/pydantic/pydantic/pull/11829) - Only support the latest Mypy version by [@Viicos](https://github.com/Viicos) in [#11832](https://github.com/pydantic/pydantic/pull/11832) - Do not implicitly convert after model validators to class methods by [@Viicos](https://github.com/Viicos) in [#11957](https://github.com/pydantic/pydantic/pull/11957) - Refactor `FieldInfo` creation implementation by [@Viicos](https://github.com/Viicos) in [#11898](https://github.com/pydantic/pydantic/pull/11898) - Make `Secret` covariant by [@bluenote10](https://github.com/bluenote10) in [#12008](https://github.com/pydantic/pydantic/pull/12008) - Emit warning when field-specific metadata is used in invalid contexts by [@Viicos](https://github.com/Viicos) in [#12028](https://github.com/pydantic/pydantic/pull/12028) #### Fixes - Properly fetch plain serializer function when serializing default value in JSON Schema by [@Viicos](https://github.com/Viicos) in [#11721](https://github.com/pydantic/pydantic/pull/11721) - Remove generics cache workaround by [@Viicos](https://github.com/Viicos) in [#11755](https://github.com/pydantic/pydantic/pull/11755) - Remove coercion of decimal constraints by [@Viicos](https://github.com/Viicos) in [#11772](https://github.com/pydantic/pydantic/pull/11772) - Fix crash when expanding root type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11735](https://github.com/pydantic/pydantic/pull/11735) - Only mark model as complete once all fields are complete by [@DouweM](https://github.com/DouweM) in [#11759](https://github.com/pydantic/pydantic/pull/11759) - Do not provide `field_name` in validator core schemas by [@DouweM](https://github.com/DouweM) in [#11761](https://github.com/pydantic/pydantic/pull/11761) - Fix issue with recursive generic models by [@Viicos](https://github.com/Viicos) in [#11775](https://github.com/pydantic/pydantic/pull/11775) - Fix qualified name comparison of private attributes during namespace inspection by [@karta9821](https://github.com/karta9821) in [#11803](https://github.com/pydantic/pydantic/pull/11803) - Make sure Pydantic dataclasses with slots and `validate_assignment` can be unpickled by [@Viicos](https://github.com/Viicos) in [#11769](https://github.com/pydantic/pydantic/pull/11769) - Traverse `function-before` schemas during schema gathering by [@Viicos](https://github.com/Viicos) in [#11801](https://github.com/pydantic/pydantic/pull/11801) - Fix check for stdlib dataclasses by [@Viicos](https://github.com/Viicos) in [#11822](https://github.com/pydantic/pydantic/pull/11822) - Check if `FieldInfo` is complete after applying type variable map by [@Viicos](https://github.com/Viicos) in [#11855](https://github.com/pydantic/pydantic/pull/11855) - Do not delete mock validator/serializer in `model_rebuild()` by [@Viicos](https://github.com/Viicos) in [#11890](https://github.com/pydantic/pydantic/pull/11890) - Rebuild dataclass fields before schema generation by [@Viicos](https://github.com/Viicos) in [#11949](https://github.com/pydantic/pydantic/pull/11949) - Always store the original field assignment on `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11946](https://github.com/pydantic/pydantic/pull/11946) - Do not use deprecated methods as default field values by [@Viicos](https://github.com/Viicos) in [#11914](https://github.com/pydantic/pydantic/pull/11914) - Allow callable discriminator to be applied on PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in [#11941](https://github.com/pydantic/pydantic/pull/11941) - Suppress core schema generation warning when using `SkipValidation` by [@ygsh0816](https://github.com/ygsh0816) in [#12002](https://github.com/pydantic/pydantic/pull/12002) - Do not emit typechecking error for invalid `Field()` default with `validate_default` set to `True` by [@Viicos](https://github.com/Viicos) in [#11988](https://github.com/pydantic/pydantic/pull/11988) - Refactor logic to support Pydantic's `Field()` function in dataclasses by [@Viicos](https://github.com/Viicos) in [#12051](https://github.com/pydantic/pydantic/pull/12051) #### Packaging - Update project metadata to use PEP 639 by [@Viicos](https://github.com/Viicos) in [#11694](https://github.com/pydantic/pydantic/pull/11694) - Bump `mkdocs-llmstxt` to v0.2.0 by [@Viicos](https://github.com/Viicos) in [#11725](https://github.com/pydantic/pydantic/pull/11725) - Bump `pydantic-core` to v2.35.1 by [@Viicos](https://github.com/Viicos) in [#11963](https://github.com/pydantic/pydantic/pull/11963) - Bump dawidd6/action-download-artifact from 10 to 11 by [@dependabot](https://github.com/dependabot)\[bot\] in [#12033](https://github.com/pydantic/pydantic/pull/12033) - Bump astral-sh/setup-uv from 5 to 6 by [@dependabot](https://github.com/dependabot)\[bot\] in [#11826](https://github.com/pydantic/pydantic/pull/11826) - Update mypy to 1.17.0 by [@Viicos](https://github.com/Viicos) in [#12076](https://github.com/pydantic/pydantic/pull/12076) ### New Contributors - [@parth-paradkar](https://github.com/parth-paradkar) made their first contribution in [#11695](https://github.com/pydantic/pydantic/pull/11695) - [@dqkqd](https://github.com/dqkqd) made their first contribution in [#11739](https://github.com/pydantic/pydantic/pull/11739) - [@fhightower](https://github.com/fhightower) made their first contribution in [#11722](https://github.com/pydantic/pydantic/pull/11722) - [@gbaian10](https://github.com/gbaian10) made their first contribution in [#11766](https://github.com/pydantic/pydantic/pull/11766) - [@DouweM](https://github.com/DouweM) made their first contribution in [#11759](https://github.com/pydantic/pydantic/pull/11759) - [@bowenliang123](https://github.com/bowenliang123) made their first contribution in [#11719](https://github.com/pydantic/pydantic/pull/11719) - [@rawwar](https://github.com/rawwar) made their first contribution in [#11799](https://github.com/pydantic/pydantic/pull/11799) - [@karta9821](https://github.com/karta9821) made their first contribution in [#11803](https://github.com/pydantic/pydantic/pull/11803) - [@jinnovation](https://github.com/jinnovation) made their first contribution in [#11834](https://github.com/pydantic/pydantic/pull/11834) - [@zmievsa](https://github.com/zmievsa) made their first contribution in [#11861](https://github.com/pydantic/pydantic/pull/11861) - [@Otto-AA](https://github.com/Otto-AA) made their first contribution in [#11860](https://github.com/pydantic/pydantic/pull/11860) - [@ygsh0816](https://github.com/ygsh0816) made their first contribution in [#12002](https://github.com/pydantic/pydantic/pull/12002) - [@lukland](https://github.com/lukland) made their first contribution in [#12015](https://github.com/pydantic/pydantic/pull/12015) - [@Dima-Bulavenko](https://github.com/Dima-Bulavenko) made their first contribution in [#11987](https://github.com/pydantic/pydantic/pull/11987) - [@GSemikozov](https://github.com/GSemikozov) made their first contribution in [#12050](https://github.com/pydantic/pydantic/pull/12050) - [@hannah-heywa](https://github.com/hannah-heywa) made their first contribution in [#12082](https://github.com/pydantic/pydantic/pull/12082) ## v2.11.10 (2025-10-04) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.10) ### What's Changed #### Fixes - Backport v1.10.24 changes by [@Viicos](https://github.com/Viicos) ## v2.11.9 (2025-09-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.9) ### What's Changed #### Fixes - Backport v1.10.23 changes by [@Viicos](https://github.com/Viicos) ## v2.11.8 (2025-09-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.8) ### What's Changed #### Fixes - Fix mypy plugin for mypy 1.18 by [@cdce8p](https://github.com/cdce8p) in [#12209](https://github.com/pydantic/pydantic/pull/12209) ## v2.11.7 (2025-06-14) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.7) ### What's Changed #### Fixes - Copy `FieldInfo` instance if necessary during `FieldInfo` build by [@Viicos](https://github.com/Viicos) in [#11898](https://github.com/pydantic/pydantic/pull/11898) ## v2.11.6 (2025-06-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.6) ### What's Changed #### Fixes - Rebuild dataclass fields before schema generation by [@Viicos](https://github.com/Viicos) in [#11949](https://github.com/pydantic/pydantic/pull/11949) - Always store the original field assignment on `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11946](https://github.com/pydantic/pydantic/pull/11946) ## v2.11.5 (2025-05-22) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.5) ### What's Changed #### Fixes - Check if `FieldInfo` is complete after applying type variable map by [@Viicos](https://github.com/Viicos) in [#11855](https://github.com/pydantic/pydantic/pull/11855) - Do not delete mock validator/serializer in `model_rebuild()` by [@Viicos](https://github.com/Viicos) in [#11890](https://github.com/pydantic/pydantic/pull/11890) - Do not duplicate metadata on model rebuild by [@Viicos](https://github.com/Viicos) in [#11902](https://github.com/pydantic/pydantic/pull/11902) ## v2.11.4 (2025-04-29) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.4) ### What's Changed #### Changes - Allow config and bases to be specified together in `create_model()` by [@Viicos](https://github.com/Viicos) in [#11714](https://github.com/pydantic/pydantic/pull/11714). This change was backported as it was previously possible (although not meant to be supported) to provide `model_config` as a field, which would make it possible to provide both configuration and bases. #### Fixes - Remove generics cache workaround by [@Viicos](https://github.com/Viicos) in [#11755](https://github.com/pydantic/pydantic/pull/11755) - Remove coercion of decimal constraints by [@Viicos](https://github.com/Viicos) in [#11772](https://github.com/pydantic/pydantic/pull/11772) - Fix crash when expanding root type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11735](https://github.com/pydantic/pydantic/pull/11735) - Fix issue with recursive generic models by [@Viicos](https://github.com/Viicos) in [#11775](https://github.com/pydantic/pydantic/pull/11775) - Traverse `function-before` schemas during schema gathering by [@Viicos](https://github.com/Viicos) in [#11801](https://github.com/pydantic/pydantic/pull/11801) #### Packaging - Bump `mkdocs-llmstxt` to v0.2.0 by [@Viicos](https://github.com/Viicos) in [#11725](https://github.com/pydantic/pydantic/pull/11725) ## v2.11.3 (2025-04-08) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.3) ### What's Changed #### Fixes - Preserve field description when rebuilding model fields by [@Viicos](https://github.com/Viicos) in [#11698](https://github.com/pydantic/pydantic/pull/11698) #### Packaging - Update V1 copy to v1.10.21 by [@Viicos](https://github.com/Viicos) in [#11706](https://github.com/pydantic/pydantic/pull/11706) ## v2.11.2 (2025-04-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.2) ### What's Changed #### Fixes - Bump `pydantic-core` to v2.33.1 by [@Viicos](https://github.com/Viicos) in [#11678](https://github.com/pydantic/pydantic/pull/11678) - Make sure `__pydantic_private__` exists before setting private attributes by [@Viicos](https://github.com/Viicos) in [#11666](https://github.com/pydantic/pydantic/pull/11666) - Do not override `FieldInfo._complete` when using field from parent class by [@Viicos](https://github.com/Viicos) in [#11668](https://github.com/pydantic/pydantic/pull/11668) - Provide the available definitions when applying discriminated unions by [@Viicos](https://github.com/Viicos) in [#11670](https://github.com/pydantic/pydantic/pull/11670) - Do not expand root type in the mypy plugin for variables by [@Viicos](https://github.com/Viicos) in [#11676](https://github.com/pydantic/pydantic/pull/11676) - Mention the attribute name in model fields deprecation message by [@Viicos](https://github.com/Viicos) in [#11674](https://github.com/pydantic/pydantic/pull/11674) - Properly validate parameterized mappings by [@Viicos](https://github.com/Viicos) in [#11658](https://github.com/pydantic/pydantic/pull/11658) ## v2.11.1 (2025-03-28) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.1) ### What's Changed #### Fixes - Do not override `'definitions-ref'` schemas containing serialization schemas or metadata by [@Viicos](https://github.com/Viicos) in [#11644](https://github.com/pydantic/pydantic/pull/11644) ## v2.11.0 (2025-03-27) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0) ### What's Changed Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). See the [blog post](https://pydantic.dev/articles/pydantic-v2-11-release) for more details. #### New Features - Add `encoded_string()` method to the URL types by [@YassinNouh21](https://github.com/YassinNouh21) in [#11580](https://github.com/pydantic/pydantic/pull/11580) - Add support for `defer_build` with `@validate_call` decorator by [@Viicos](https://github.com/Viicos) in [#11584](https://github.com/pydantic/pydantic/pull/11584) - Allow `@with_config` decorator to be used with keyword arguments by [@Viicos](https://github.com/Viicos) in [#11608](https://github.com/pydantic/pydantic/pull/11608) - Simplify customization of default value inclusion in JSON Schema generation by [@Viicos](https://github.com/Viicos) in [#11634](https://github.com/pydantic/pydantic/pull/11634) - Add `generate_arguments_schema()` function by [@Viicos](https://github.com/Viicos) in [#11572](https://github.com/pydantic/pydantic/pull/11572) #### Fixes - Allow generic typed dictionaries to be used for unpacked variadic keyword parameters by [@Viicos](https://github.com/Viicos) in [#11571](https://github.com/pydantic/pydantic/pull/11571) - Fix runtime error when computing model string representation involving cached properties and self-referenced models by [@Viicos](https://github.com/Viicos) in [#11579](https://github.com/pydantic/pydantic/pull/11579) - Preserve other steps when using the ellipsis in the pipeline API by [@Viicos](https://github.com/Viicos) in [#11626](https://github.com/pydantic/pydantic/pull/11626) - Fix deferred discriminator application logic by [@Viicos](https://github.com/Viicos) in [#11591](https://github.com/pydantic/pydantic/pull/11591) #### Packaging - Bump `pydantic-core` to v2.33.0 by [@Viicos](https://github.com/Viicos) in [#11631](https://github.com/pydantic/pydantic/pull/11631) ### New Contributors - [@cmenon12](https://github.com/cmenon12) made their first contribution in [#11562](https://github.com/pydantic/pydantic/pull/11562) - [@Jeukoh](https://github.com/Jeukoh) made their first contribution in [#11611](https://github.com/pydantic/pydantic/pull/11611) ## v2.11.0b2 (2025-03-17) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0b2) ### What's Changed #### New Features - Add experimental support for free threading by [@Viicos](https://github.com/Viicos) in [#11516](https://github.com/pydantic/pydantic/pull/11516) #### Fixes - Fix `NotRequired` qualifier not taken into account in stringified annotation by [@Viicos](https://github.com/Viicos) in [#11559](https://github.com/pydantic/pydantic/pull/11559) #### Packaging - Bump `pydantic-core` to v2.32.0 by [@Viicos](https://github.com/Viicos) in [#11567](https://github.com/pydantic/pydantic/pull/11567) ### New Contributors - [@joren485](https://github.com/joren485) made their first contribution in [#11547](https://github.com/pydantic/pydantic/pull/11547) ## v2.11.0b1 (2025-03-06) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0b1) ### What's Changed #### New Features - Support unsubstituted type variables with both a default and a bound or constraints by [@FyZzyss](https://github.com/FyZzyss) in [https://github.com/pydantic/pydantic/pull/10789](https://github.com/pydantic/pydantic/pull/10789) - Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11034](https://github.com/pydantic/pydantic/pull/11034) - Raise a better error when a generic alias is used inside `type[]` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11088](https://github.com/pydantic/pydantic/pull/11088) - Properly support PEP 695 generics syntax by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11189](https://github.com/pydantic/pydantic/pull/11189) - Properly support type variable defaults by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11332](https://github.com/pydantic/pydantic/pull/11332) - Add support for validating v6, v7, v8 UUIDs by [@astei](https://github.com/astei) in [https://github.com/pydantic/pydantic/pull/11436](https://github.com/pydantic/pydantic/pull/11436) - Improve alias configuration APIs by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11468](https://github.com/pydantic/pydantic/pull/11468) #### Changes - Rework `create_model` field definitions format by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11032](https://github.com/pydantic/pydantic/pull/11032) - Raise a deprecation warning when a field is annotated as final with a default value by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11168](https://github.com/pydantic/pydantic/pull/11168) - Deprecate accessing `model_fields` and `model_computed_fields` on instances by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11169](https://github.com/pydantic/pydantic/pull/11169) - **Breaking Change:** Move core schema generation logic for path types inside the `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/10846](https://github.com/pydantic/pydantic/pull/10846) - Remove Python 3.8 Support by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11258](https://github.com/pydantic/pydantic/pull/11258) - Optimize calls to `get_type_ref` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/10863](https://github.com/pydantic/pydantic/pull/10863) - Disable `pydantic-core` core schema validation by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11271](https://github.com/pydantic/pydantic/pull/11271) #### Performance - Only evaluate `FieldInfo` annotations if required during schema building by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/10769](https://github.com/pydantic/pydantic/pull/10769) - Improve `__setattr__` performance of Pydantic models by caching setter functions by [@MarkusSintonen](https://github.com/MarkusSintonen) in [https://github.com/pydantic/pydantic/pull/10868](https://github.com/pydantic/pydantic/pull/10868) - Improve annotation application performance by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11186](https://github.com/pydantic/pydantic/pull/11186) - Improve performance of `_typing_extra` module by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11255](https://github.com/pydantic/pydantic/pull/11255) - Refactor and optimize schema cleaning logic by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11244](https://github.com/pydantic/pydantic/pull/11244) - Create a single dictionary when creating a `CoreConfig` instance by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11384](https://github.com/pydantic/pydantic/pull/11384) - Bump `pydantic-core` and thus use `SchemaValidator` and `SchemaSerializer` caching by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11402](https://github.com/pydantic/pydantic/pull/11402) - Reuse cached core schemas for parametrized generic Pydantic models by [@MarkusSintonen](https://github.com/MarkusSintonen) in [https://github.com/pydantic/pydantic/pull/11434](https://github.com/pydantic/pydantic/pull/11434) #### Fixes - Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/10872](https://github.com/pydantic/pydantic/pull/10872) - Use the correct frame when instantiating a parametrized `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/10893](https://github.com/pydantic/pydantic/pull/10893) - Infer final fields with a default value as class variables in the mypy plugin by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11121](https://github.com/pydantic/pydantic/pull/11121) - Recursively unpack `Literal` values if using PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11114](https://github.com/pydantic/pydantic/pull/11114) - Override `__subclasscheck__` on `ModelMetaclass` to avoid memory leak and performance issues by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11116](https://github.com/pydantic/pydantic/pull/11116) - Remove unused `_extract_get_pydantic_json_schema()` parameter by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11155](https://github.com/pydantic/pydantic/pull/11155) - Improve discriminated union error message for invalid union variants by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11161](https://github.com/pydantic/pydantic/pull/11161) - Unpack PEP 695 type aliases if using the `Annotated` form by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11109](https://github.com/pydantic/pydantic/pull/11109) - Add missing stacklevel in `deprecated_instance_property` warning by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11200](https://github.com/pydantic/pydantic/pull/11200) - Copy `WithJsonSchema` schema to avoid sharing mutated data by [@thejcannon](https://github.com/thejcannon) in [https://github.com/pydantic/pydantic/pull/11014](https://github.com/pydantic/pydantic/pull/11014) - Do not cache parametrized models when in the process of parametrizing another model by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/10704](https://github.com/pydantic/pydantic/pull/10704) - Add discriminated union related metadata entries to the `CoreMetadata` definition by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11216](https://github.com/pydantic/pydantic/pull/11216) - Consolidate schema definitions logic in the `_Definitions` class by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11208](https://github.com/pydantic/pydantic/pull/11208) - Support initializing root model fields with values of the `root` type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11212](https://github.com/pydantic/pydantic/pull/11212) - Fix various issues with dataclasses and `use_attribute_docstrings` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11246](https://github.com/pydantic/pydantic/pull/11246) - Only compute normalized decimal places if necessary in `decimal_places_validator` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [https://github.com/pydantic/pydantic/pull/11281](https://github.com/pydantic/pydantic/pull/11281) - Add support for `validation_alias` in the mypy plugin by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11295](https://github.com/pydantic/pydantic/pull/11295) - Fix JSON Schema reference collection with `"examples"` keys by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11305](https://github.com/pydantic/pydantic/pull/11305) - Do not transform model serializer functions as class methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11298](https://github.com/pydantic/pydantic/pull/11298) - Simplify `GenerateJsonSchema.literal_schema()` implementation by [@misrasaurabh1](https://github.com/misrasaurabh1) in [https://github.com/pydantic/pydantic/pull/11321](https://github.com/pydantic/pydantic/pull/11321) - Add additional allowed schemes for `ClickHouseDsn` by [@Maze21127](https://github.com/Maze21127) in [https://github.com/pydantic/pydantic/pull/11319](https://github.com/pydantic/pydantic/pull/11319) - Coerce decimal constraints to `Decimal` instances by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11350](https://github.com/pydantic/pydantic/pull/11350) - Use the correct JSON Schema mode when handling function schemas by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11367](https://github.com/pydantic/pydantic/pull/11367) - Improve exception message when encountering recursion errors during type evaluation by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11356](https://github.com/pydantic/pydantic/pull/11356) - Always include `additionalProperties: True` for arbitrary dictionary schemas by [@austinyu](https://github.com/austinyu) in [https://github.com/pydantic/pydantic/pull/11392](https://github.com/pydantic/pydantic/pull/11392) - Expose `fallback` parameter in serialization methods by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11398](https://github.com/pydantic/pydantic/pull/11398) - Fix path serialization behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11416](https://github.com/pydantic/pydantic/pull/11416) - Do not reuse validators and serializers during model rebuild by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11429](https://github.com/pydantic/pydantic/pull/11429) - Collect model fields when rebuilding a model by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11388](https://github.com/pydantic/pydantic/pull/11388) - Allow cached properties to be altered on frozen models by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11432](https://github.com/pydantic/pydantic/pull/11432) - Fix tuple serialization for `Sequence` types by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11435](https://github.com/pydantic/pydantic/pull/11435) - Fix: do not check for `__get_validators__` on classes where `__get_pydantic_core_schema__` is also defined by [@tlambert03](https://github.com/tlambert03) in [https://github.com/pydantic/pydantic/pull/11444](https://github.com/pydantic/pydantic/pull/11444) - Allow callable instances to be used as serializers by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11451](https://github.com/pydantic/pydantic/pull/11451) - Improve error thrown when overriding field with a property by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11459](https://github.com/pydantic/pydantic/pull/11459) - Fix JSON Schema generation with referenceable core schemas holding JSON metadata by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11475](https://github.com/pydantic/pydantic/pull/11475) - Support strict specification on union member types by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11481](https://github.com/pydantic/pydantic/pull/11481) - Implicitly set `validate_by_name` to `True` when `validate_by_alias` is `False` by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11503](https://github.com/pydantic/pydantic/pull/11503) - Change type of `Any` when synthesizing `BaseSettings.__init__` signature in the mypy plugin by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11497](https://github.com/pydantic/pydantic/pull/11497) - Support type variable defaults referencing other type variables by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11520](https://github.com/pydantic/pydantic/pull/11520) - Fix `ValueError` on year zero by [@davidhewitt](https://github.com/davidhewitt) in [https://github.com/pydantic/pydantic-core/pull/1583](https://github.com/pydantic/pydantic-core/pull/1583) - `dataclass` `InitVar` shouldn't be required on serialization by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic-core/pull/1602](https://github.com/pydantic/pydantic-core/pull/1602) #### Packaging - Add a `check_pydantic_core_version()` function by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11324](https://github.com/pydantic/pydantic/pull/11324) - Remove `greenlet` development dependency by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11351](https://github.com/pydantic/pydantic/pull/11351) - Use the `typing-inspection` library by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11479](https://github.com/pydantic/pydantic/pull/11479) - Bump `pydantic-core` to `v2.31.1` by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/11526](https://github.com/pydantic/pydantic/pull/11526) ## New Contributors - [@FyZzyss](https://github.com/FyZzyss) made their first contribution in [https://github.com/pydantic/pydantic/pull/10789](https://github.com/pydantic/pydantic/pull/10789) - [@tamird](https://github.com/tamird) made their first contribution in [https://github.com/pydantic/pydantic/pull/10948](https://github.com/pydantic/pydantic/pull/10948) - [@felixxm](https://github.com/felixxm) made their first contribution in [https://github.com/pydantic/pydantic/pull/11077](https://github.com/pydantic/pydantic/pull/11077) - [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in [https://github.com/pydantic/pydantic/pull/11082](https://github.com/pydantic/pydantic/pull/11082) - [@Kharianne](https://github.com/Kharianne) made their first contribution in [https://github.com/pydantic/pydantic/pull/11111](https://github.com/pydantic/pydantic/pull/11111) - [@mdaffad](https://github.com/mdaffad) made their first contribution in [https://github.com/pydantic/pydantic/pull/11177](https://github.com/pydantic/pydantic/pull/11177) - [@thejcannon](https://github.com/thejcannon) made their first contribution in [https://github.com/pydantic/pydantic/pull/11014](https://github.com/pydantic/pydantic/pull/11014) - [@thomasfrimannkoren](https://github.com/thomasfrimannkoren) made their first contribution in [https://github.com/pydantic/pydantic/pull/11251](https://github.com/pydantic/pydantic/pull/11251) - [@usernameMAI](https://github.com/usernameMAI) made their first contribution in [https://github.com/pydantic/pydantic/pull/11275](https://github.com/pydantic/pydantic/pull/11275) - [@ananiavito](https://github.com/ananiavito) made their first contribution in [https://github.com/pydantic/pydantic/pull/11302](https://github.com/pydantic/pydantic/pull/11302) - [@pawamoy](https://github.com/pawamoy) made their first contribution in [https://github.com/pydantic/pydantic/pull/11311](https://github.com/pydantic/pydantic/pull/11311) - [@Maze21127](https://github.com/Maze21127) made their first contribution in [https://github.com/pydantic/pydantic/pull/11319](https://github.com/pydantic/pydantic/pull/11319) - [@kauabh](https://github.com/kauabh) made their first contribution in [https://github.com/pydantic/pydantic/pull/11369](https://github.com/pydantic/pydantic/pull/11369) - [@jaceklaskowski](https://github.com/jaceklaskowski) made their first contribution in [https://github.com/pydantic/pydantic/pull/11353](https://github.com/pydantic/pydantic/pull/11353) - [@tmpbeing](https://github.com/tmpbeing) made their first contribution in [https://github.com/pydantic/pydantic/pull/11375](https://github.com/pydantic/pydantic/pull/11375) - [@petyosi](https://github.com/petyosi) made their first contribution in [https://github.com/pydantic/pydantic/pull/11405](https://github.com/pydantic/pydantic/pull/11405) - [@austinyu](https://github.com/austinyu) made their first contribution in [https://github.com/pydantic/pydantic/pull/11392](https://github.com/pydantic/pydantic/pull/11392) - [@mikeedjones](https://github.com/mikeedjones) made their first contribution in [https://github.com/pydantic/pydantic/pull/11402](https://github.com/pydantic/pydantic/pull/11402) - [@astei](https://github.com/astei) made their first contribution in [https://github.com/pydantic/pydantic/pull/11436](https://github.com/pydantic/pydantic/pull/11436) - [@dsayling](https://github.com/dsayling) made their first contribution in [https://github.com/pydantic/pydantic/pull/11522](https://github.com/pydantic/pydantic/pull/11522) - [@sobolevn](https://github.com/sobolevn) made their first contribution in [https://github.com/pydantic/pydantic-core/pull/1645](https://github.com/pydantic/pydantic-core/pull/1645) ## v2.11.0a2 (2025-02-10) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0a2) ### What's Changed Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). This is another early alpha release, meant to collect early feedback from users having issues with core schema builds. #### Performance - Create a single dictionary when creating a `CoreConfig` instance by [@sydney-runkle](https://github.com/sydney-runkle) in [#11384](https://github.com/pydantic/pydantic/pull/11384) #### Fixes - Use the correct JSON Schema mode when handling function schemas by [@Viicos](https://github.com/Viicos) in [#11367](https://github.com/pydantic/pydantic/pull/11367) - Fix JSON Schema reference logic with `examples` keys by [@Viicos](https://github.com/Viicos) in [#11366](https://github.com/pydantic/pydantic/pull/11366) - Improve exception message when encountering recursion errors during type evaluation by [@Viicos](https://github.com/Viicos) in [#11356](https://github.com/pydantic/pydantic/pull/11356) - Always include `additionalProperties: True` for arbitrary dictionary schemas by [@austinyu](https://github.com/austinyu) in [#11392](https://github.com/pydantic/pydantic/pull/11392) - Expose `fallback` parameter in serialization methods by [@Viicos](https://github.com/Viicos) in [#11398](https://github.com/pydantic/pydantic/pull/11398) - Fix path serialization behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [#11416](https://github.com/pydantic/pydantic/pull/11416) #### Packaging - Bump `ruff` from 0.9.2 to 0.9.5 by [@Viicos](https://github.com/Viicos) in [#11407](https://github.com/pydantic/pydantic/pull/11407) - Bump `pydantic-core` to v2.29.0 by [@mikeedjones](https://github.com/mikeedjones) in [#11402](https://github.com/pydantic/pydantic/pull/11402) - Use locally-built rust with symbols & pgo by [@davidhewitt](https://github.com/davidhewitt) in [#11403](https://github.com/pydantic/pydantic/pull/11403) ### New Contributors - [@kauabh](https://github.com/kauabh) made their first contribution in [#11369](https://github.com/pydantic/pydantic/pull/11369) - [@jaceklaskowski](https://github.com/jaceklaskowski) made their first contribution in [#11353](https://github.com/pydantic/pydantic/pull/11353) - [@tmpbeing](https://github.com/tmpbeing) made their first contribution in [#11375](https://github.com/pydantic/pydantic/pull/11375) - [@petyosi](https://github.com/petyosi) made their first contribution in [#11405](https://github.com/pydantic/pydantic/pull/11405) - [@austinyu](https://github.com/austinyu) made their first contribution in [#11392](https://github.com/pydantic/pydantic/pull/11392) - [@mikeedjones](https://github.com/mikeedjones) made their first contribution in [#11402](https://github.com/pydantic/pydantic/pull/11402) ## v2.11.0a1 (2025-01-30) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.11.0a1) ### What's Changed Pydantic v2.11 is a version strongly focused on build time performance of Pydantic models (and core schema generation in general). This is an early alpha release, meant to collect early feedback from users having issues with core schema builds. #### New Features - Support unsubstituted type variables with both a default and a bound or constraints by [@FyZzyss](https://github.com/FyZzyss) in [#10789](https://github.com/pydantic/pydantic/pull/10789) - Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11034](https://github.com/pydantic/pydantic/pull/11034) - Raise a better error when a generic alias is used inside `type[]` by [@Viicos](https://github.com/Viicos) in [#11088](https://github.com/pydantic/pydantic/pull/11088) - Properly support PEP 695 generics syntax by [@Viicos](https://github.com/Viicos) in [#11189](https://github.com/pydantic/pydantic/pull/11189) - Properly support type variable defaults by [@Viicos](https://github.com/Viicos) in [#11332](https://github.com/pydantic/pydantic/pull/11332) #### Changes - Rework `create_model` field definitions format by [@Viicos](https://github.com/Viicos) in [#11032](https://github.com/pydantic/pydantic/pull/11032) - Raise a deprecation warning when a field is annotated as final with a default value by [@Viicos](https://github.com/Viicos) in [#11168](https://github.com/pydantic/pydantic/pull/11168) - Deprecate accessing `model_fields` and `model_computed_fields` on instances by [@Viicos](https://github.com/Viicos) in [#11169](https://github.com/pydantic/pydantic/pull/11169) - Move core schema generation logic for path types inside the `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in [#10846](https://github.com/pydantic/pydantic/pull/10846) - Move `deque` schema gen to `GenerateSchema` class by [@sydney-runkle](https://github.com/sydney-runkle) in [#11239](https://github.com/pydantic/pydantic/pull/11239) - Move `Mapping` schema gen to `GenerateSchema` to complete removal of `prepare_annotations_for_known_type` workaround by [@sydney-runkle](https://github.com/sydney-runkle) in [#11247](https://github.com/pydantic/pydantic/pull/11247) - Remove Python 3.8 Support by [@sydney-runkle](https://github.com/sydney-runkle) in [#11258](https://github.com/pydantic/pydantic/pull/11258) - Disable `pydantic-core` core schema validation by [@sydney-runkle](https://github.com/sydney-runkle) in [#11271](https://github.com/pydantic/pydantic/pull/11271) #### Performance - Only evaluate `FieldInfo` annotations if required during schema building by [@Viicos](https://github.com/Viicos) in [#10769](https://github.com/pydantic/pydantic/pull/10769) - Optimize calls to `get_type_ref` by [@Viicos](https://github.com/Viicos) in [#10863](https://github.com/pydantic/pydantic/pull/10863) - Improve `__setattr__` performance of Pydantic models by caching setter functions by [@MarkusSintonen](https://github.com/MarkusSintonen) in [#10868](https://github.com/pydantic/pydantic/pull/10868) - Improve annotation application performance by [@Viicos](https://github.com/Viicos) in [#11186](https://github.com/pydantic/pydantic/pull/11186) - Improve performance of `_typing_extra` module by [@Viicos](https://github.com/Viicos) in [#11255](https://github.com/pydantic/pydantic/pull/11255) - Refactor and optimize schema cleaning logic by [@Viicos](https://github.com/Viicos) and [@MarkusSintonen](https://github.com/MarkusSintonen) in [#11244](https://github.com/pydantic/pydantic/pull/11244) #### Fixes - Add validation tests for `_internal/_validators.py` by [@tkasuz](https://github.com/tkasuz) in [#10763](https://github.com/pydantic/pydantic/pull/10763) - Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in [#10872](https://github.com/pydantic/pydantic/pull/10872) - Revert "ci: use locally built pydantic-core with debug symbols by [@sydney-runkle](https://github.com/sydney-runkle) in [#10942](https://github.com/pydantic/pydantic/pull/10942) - Re-enable all FastAPI tests by [@tamird](https://github.com/tamird) in [#10948](https://github.com/pydantic/pydantic/pull/10948) - Fix typo in HISTORY.md. by [@felixxm](https://github.com/felixxm) in [#11077](https://github.com/pydantic/pydantic/pull/11077) - Infer final fields with a default value as class variables in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11121](https://github.com/pydantic/pydantic/pull/11121) - Recursively unpack `Literal` values if using PEP 695 type aliases by [@Viicos](https://github.com/Viicos) in [#11114](https://github.com/pydantic/pydantic/pull/11114) - Override `__subclasscheck__` on `ModelMetaclass` to avoid memory leak and performance issues by [@Viicos](https://github.com/Viicos) in [#11116](https://github.com/pydantic/pydantic/pull/11116) - Remove unused `_extract_get_pydantic_json_schema()` parameter by [@Viicos](https://github.com/Viicos) in [#11155](https://github.com/pydantic/pydantic/pull/11155) - Add FastAPI and SQLModel to third-party tests by [@sydney-runkle](https://github.com/sydney-runkle) in [#11044](https://github.com/pydantic/pydantic/pull/11044) - Fix conditional expressions syntax for third-party tests by [@Viicos](https://github.com/Viicos) in [#11162](https://github.com/pydantic/pydantic/pull/11162) - Move FastAPI tests to third-party workflow by [@Viicos](https://github.com/Viicos) in [#11164](https://github.com/pydantic/pydantic/pull/11164) - Improve discriminated union error message for invalid union variants by [@Viicos](https://github.com/Viicos) in [#11161](https://github.com/pydantic/pydantic/pull/11161) - Unpack PEP 695 type aliases if using the `Annotated` form by [@Viicos](https://github.com/Viicos) in [#11109](https://github.com/pydantic/pydantic/pull/11109) - Include `openapi-python-client` check in issue creation for third-party failures, use `main` branch by [@sydney-runkle](https://github.com/sydney-runkle) in [#11182](https://github.com/pydantic/pydantic/pull/11182) - Add pandera third-party tests by [@Viicos](https://github.com/Viicos) in [#11193](https://github.com/pydantic/pydantic/pull/11193) - Add ODMantic third-party tests by [@sydney-runkle](https://github.com/sydney-runkle) in [#11197](https://github.com/pydantic/pydantic/pull/11197) - Add missing stacklevel in `deprecated_instance_property` warning by [@Viicos](https://github.com/Viicos) in [#11200](https://github.com/pydantic/pydantic/pull/11200) - Copy `WithJsonSchema` schema to avoid sharing mutated data by [@thejcannon](https://github.com/thejcannon) in [#11014](https://github.com/pydantic/pydantic/pull/11014) - Do not cache parametrized models when in the process of parametrizing another model by [@Viicos](https://github.com/Viicos) in [#10704](https://github.com/pydantic/pydantic/pull/10704) - Re-enable Beanie third-party tests by [@Viicos](https://github.com/Viicos) in [#11214](https://github.com/pydantic/pydantic/pull/11214) - Add discriminated union related metadata entries to the `CoreMetadata` definition by [@Viicos](https://github.com/Viicos) in [#11216](https://github.com/pydantic/pydantic/pull/11216) - Consolidate schema definitions logic in the `_Definitions` class by [@Viicos](https://github.com/Viicos) in [#11208](https://github.com/pydantic/pydantic/pull/11208) - Support initializing root model fields with values of the `root` type in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11212](https://github.com/pydantic/pydantic/pull/11212) - Fix various issues with dataclasses and `use_attribute_docstrings` by [@Viicos](https://github.com/Viicos) in [#11246](https://github.com/pydantic/pydantic/pull/11246) - Only compute normalized decimal places if necessary in `decimal_places_validator` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#11281](https://github.com/pydantic/pydantic/pull/11281) - Fix two misplaced sentences in validation errors documentation by [@ananiavito](https://github.com/ananiavito) in [#11302](https://github.com/pydantic/pydantic/pull/11302) - Fix mkdocstrings inventory example in documentation by [@pawamoy](https://github.com/pawamoy) in [#11311](https://github.com/pydantic/pydantic/pull/11311) - Add support for `validation_alias` in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11295](https://github.com/pydantic/pydantic/pull/11295) - Do not transform model serializer functions as class methods in the mypy plugin by [@Viicos](https://github.com/Viicos) in [#11298](https://github.com/pydantic/pydantic/pull/11298) - Simplify `GenerateJsonSchema.literal_schema()` implementation by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#11321](https://github.com/pydantic/pydantic/pull/11321) - Add additional allowed schemes for `ClickHouseDsn` by [@Maze21127](https://github.com/Maze21127) in [#11319](https://github.com/pydantic/pydantic/pull/11319) - Coerce decimal constraints to `Decimal` instances by [@Viicos](https://github.com/Viicos) in [#11350](https://github.com/pydantic/pydantic/pull/11350) - Fix `ValueError` on year zero by [@davidhewitt](https://github.com/davidhewitt) in [pydantic-core#1583](https://github.com/pydantic/pydantic-core/pull/1583) #### Packaging - Bump dawidd6/action-download-artifact from 6 to 7 by [@dependabot](https://github.com/dependabot) in [#11018](https://github.com/pydantic/pydantic/pull/11018) - Re-enable memray related tests on Python 3.12+ by [@Viicos](https://github.com/Viicos) in [#11191](https://github.com/pydantic/pydantic/pull/11191) - Bump astral-sh/setup-uv to 5 by [@dependabot](https://github.com/dependabot) in [#11205](https://github.com/pydantic/pydantic/pull/11205) - Bump `ruff` to v0.9.0 by [@sydney-runkle](https://github.com/sydney-runkle) in [#11254](https://github.com/pydantic/pydantic/pull/11254) - Regular `uv.lock` deps update by [@sydney-runkle](https://github.com/sydney-runkle) in [#11333](https://github.com/pydantic/pydantic/pull/11333) - Add a `check_pydantic_core_version()` function by [@Viicos](https://github.com/Viicos) in [#11324](https://github.com/pydantic/pydantic/pull/11324) - Remove `greenlet` development dependency by [@Viicos](https://github.com/Viicos) in [#11351](https://github.com/pydantic/pydantic/pull/11351) - Bump `pydantic-core` to v2.28.0 by [@Viicos](https://github.com/Viicos) in [#11364](https://github.com/pydantic/pydantic/pull/11364) ### New Contributors - [@FyZzyss](https://github.com/FyZzyss) made their first contribution in [#10789](https://github.com/pydantic/pydantic/pull/10789) - [@tamird](https://github.com/tamird) made their first contribution in [#10948](https://github.com/pydantic/pydantic/pull/10948) - [@felixxm](https://github.com/felixxm) made their first contribution in [#11077](https://github.com/pydantic/pydantic/pull/11077) - [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in [#11082](https://github.com/pydantic/pydantic/pull/11082) - [@Kharianne](https://github.com/Kharianne) made their first contribution in [#11111](https://github.com/pydantic/pydantic/pull/11111) - [@mdaffad](https://github.com/mdaffad) made their first contribution in [#11177](https://github.com/pydantic/pydantic/pull/11177) - [@thejcannon](https://github.com/thejcannon) made their first contribution in [#11014](https://github.com/pydantic/pydantic/pull/11014) - [@thomasfrimannkoren](https://github.com/thomasfrimannkoren) made their first contribution in [#11251](https://github.com/pydantic/pydantic/pull/11251) - [@usernameMAI](https://github.com/usernameMAI) made their first contribution in [#11275](https://github.com/pydantic/pydantic/pull/11275) - [@ananiavito](https://github.com/ananiavito) made their first contribution in [#11302](https://github.com/pydantic/pydantic/pull/11302) - [@pawamoy](https://github.com/pawamoy) made their first contribution in [#11311](https://github.com/pydantic/pydantic/pull/11311) - [@Maze21127](https://github.com/Maze21127) made their first contribution in [#11319](https://github.com/pydantic/pydantic/pull/11319) ## v2.10.6 (2025-01-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.6) ### What's Changed #### Fixes - Fix JSON Schema reference collection with `'examples'` keys by [@Viicos](https://github.com/Viicos) in [#11325](https://github.com/pydantic/pydantic/pull/11325) - Fix url python serialization by [@sydney-runkle](https://github.com/sydney-runkle) in [#11331](https://github.com/pydantic/pydantic/pull/11331) ## v2.10.5 (2025-01-08) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.5) ### What's Changed #### Fixes - Remove custom MRO implementation of Pydantic models by [@Viicos](https://github.com/Viicos) in [#11184](https://github.com/pydantic/pydantic/pull/11184) - Fix URL serialization for unions by [@sydney-runkle](https://github.com/sydney-runkle) in [#11233](https://github.com/pydantic/pydantic/pull/11233) ## v2.10.4 (2024-12-18) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.4) ### What's Changed #### Fixes - Fix for comparison of `AnyUrl` objects by [@alexprabhat99](https://github.com/alexprabhat99) in [#11082](https://github.com/pydantic/pydantic/pull/11082) - Properly fetch PEP 695 type params for functions, do not fetch annotations from signature by [@Viicos](https://github.com/Viicos) in [#11093](https://github.com/pydantic/pydantic/pull/11093) - Include JSON Schema input core schema in function schemas by [@Viicos](https://github.com/Viicos) in [#11085](https://github.com/pydantic/pydantic/pull/11085) - Add `len` to `_BaseUrl` to avoid TypeError by [@Kharianne](https://github.com/Kharianne) in [#11111](https://github.com/pydantic/pydantic/pull/11111) - Make sure the type reference is removed from the seen references by [@Viicos](https://github.com/Viicos) in [#11143](https://github.com/pydantic/pydantic/pull/11143) ### New Contributors - [@FyZzyss](https://github.com/FyZzyss) made their first contribution in [#10789](https://github.com/pydantic/pydantic/pull/10789) - [@tamird](https://github.com/tamird) made their first contribution in [#10948](https://github.com/pydantic/pydantic/pull/10948) - [@felixxm](https://github.com/felixxm) made their first contribution in [#11077](https://github.com/pydantic/pydantic/pull/11077) - [@alexprabhat99](https://github.com/alexprabhat99) made their first contribution in [#11082](https://github.com/pydantic/pydantic/pull/11082) - [@Kharianne](https://github.com/Kharianne) made their first contribution in [#11111](https://github.com/pydantic/pydantic/pull/11111) #### Packaging - Bump `pydantic-core` to v2.27.2 by [@davidhewitt](https://github.com/davidhewitt) in [#11138](https://github.com/pydantic/pydantic/pull/11138) ## v2.10.3 (2024-12-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.3) ### What's Changed #### Fixes - Set fields when `defer_build` is set on Pydantic dataclasses by [@Viicos](https://github.com/Viicos) in [#10984](https://github.com/pydantic/pydantic/pull/10984) - Do not resolve the JSON Schema reference for `dict` core schema keys by [@Viicos](https://github.com/Viicos) in [#10989](https://github.com/pydantic/pydantic/pull/10989) - Use the globals of the function when evaluating the return type for `PlainSerializer` and `WrapSerializer` functions by [@Viicos](https://github.com/Viicos) in [#11008](https://github.com/pydantic/pydantic/pull/11008) - Fix host required enforcement for urls to be compatible with v2.9 behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [#11027](https://github.com/pydantic/pydantic/pull/11027) - Add a `default_factory_takes_validated_data` property to `FieldInfo` by [@Viicos](https://github.com/Viicos) in [#11034](https://github.com/pydantic/pydantic/pull/11034) - Fix url json schema in `serialization` mode by [@sydney-runkle](https://github.com/sydney-runkle) in [#11035](https://github.com/pydantic/pydantic/pull/11035) ## v2.10.2 (2024-11-25) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.2) ### What's Changed #### Fixes - Only evaluate FieldInfo annotations if required during schema building by [@Viicos](https://github.com/Viicos) in [#10769](https://github.com/pydantic/pydantic/pull/10769) - Do not evaluate annotations for private fields by [@Viicos](https://github.com/Viicos) in [#10962](https://github.com/pydantic/pydantic/pull/10962) - Support serialization as any for `Secret` types and `Url` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10947](https://github.com/pydantic/pydantic/pull/10947) - Fix type hint of `Field.default` to be compatible with Python 3.8 and 3.9 by [@Viicos](https://github.com/Viicos) in [#10972](https://github.com/pydantic/pydantic/pull/10972) - Add hashing support for URL types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10975](https://github.com/pydantic/pydantic/pull/10975) - Hide `BaseModel.__replace__` definition from type checkers by [@Viicos](https://github.com/Viicos) in [#10979](https://github.com/pydantic/pydantic/pull/10979) ## v2.10.1 (2024-11-21) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.1) ### What's Changed #### Fixes - Use the correct frame when instantiating a parametrized `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [#10893](https://github.com/pydantic/pydantic/pull/10893) - Relax check for validated data in `default_factory` utils by [@sydney-runkle](https://github.com/sydney-runkle) in [#10909](https://github.com/pydantic/pydantic/pull/10909) - Fix type checking issue with `model_fields` and `model_computed_fields` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10911](https://github.com/pydantic/pydantic/pull/10911) - Use the parent configuration during schema generation for stdlib `dataclass`es by [@sydney-runkle](https://github.com/sydney-runkle) in [#10928](https://github.com/pydantic/pydantic/pull/10928) - Use the `globals` of the function when evaluating the return type of serializers and `computed_field`s by [@Viicos](https://github.com/Viicos) in [#10929](https://github.com/pydantic/pydantic/pull/10929) - Fix URL constraint application by [@sydney-runkle](https://github.com/sydney-runkle) in [#10922](https://github.com/pydantic/pydantic/pull/10922) - Fix URL equality with different validation methods by [@sydney-runkle](https://github.com/sydney-runkle) in [#10934](https://github.com/pydantic/pydantic/pull/10934) - Fix JSON schema title when specified as `''` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10936](https://github.com/pydantic/pydantic/pull/10936) - Fix `python` mode serialization for `complex` inference by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic-core#1549](https://github.com/pydantic/pydantic-core/pull/1549) #### Packaging - Bump `pydantic-core` version to `v2.27.1` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10938](https://github.com/pydantic/pydantic/pull/10938) ### New Contributors ## v2.10.0 (2024-11-20) The code released in v2.10.0 is practically identical to that of v2.10.0b2. [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0) See the [v2.10 release blog post](https://pydantic.dev/articles/pydantic-v2-10-release) for the highlights! ### What's Changed #### New Features - Support `fractions.Fraction` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10318](https://github.com/pydantic/pydantic/pull/10318) - Support `Hashable` for json validation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10324](https://github.com/pydantic/pydantic/pull/10324) - Add a `SocketPath` type for `linux` systems by [@theunkn0wn1](https://github.com/theunkn0wn1) in [#10378](https://github.com/pydantic/pydantic/pull/10378) - Allow arbitrary refs in JSON schema `examples` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10417](https://github.com/pydantic/pydantic/pull/10417) - Support `defer_build` for Pydantic dataclasses by [@Viicos](https://github.com/Viicos) in [#10313](https://github.com/pydantic/pydantic/pull/10313) - Adding v1 / v2 incompatibility warning for nested v1 model by [@sydney-runkle](https://github.com/sydney-runkle) in [#10431](https://github.com/pydantic/pydantic/pull/10431) - Add support for unpacked `TypedDict` to type hint variadic keyword arguments with `@validate_call` by [@Viicos](https://github.com/Viicos) in [#10416](https://github.com/pydantic/pydantic/pull/10416) - Support compiled patterns in `protected_namespaces` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10522](https://github.com/pydantic/pydantic/pull/10522) - Add support for `propertyNames` in JSON schema by [@FlorianSW](https://github.com/FlorianSW) in [#10478](https://github.com/pydantic/pydantic/pull/10478) - Adding `__replace__` protocol for Python 3.13+ support by [@sydney-runkle](https://github.com/sydney-runkle) in [#10596](https://github.com/pydantic/pydantic/pull/10596) - Expose public `sort` method for JSON schema generation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10595](https://github.com/pydantic/pydantic/pull/10595) - Add runtime validation of `@validate_call` callable argument by [@kc0506](https://github.com/kc0506) in [#10627](https://github.com/pydantic/pydantic/pull/10627) - Add `experimental_allow_partial` support by [@samuelcolvin](https://github.com/samuelcolvin) in [#10748](https://github.com/pydantic/pydantic/pull/10748) - Support default factories taking validated data as an argument by [@Viicos](https://github.com/Viicos) in [#10678](https://github.com/pydantic/pydantic/pull/10678) - Allow subclassing `ValidationError` and `PydanticCustomError` by [@Youssefares](https://github.com/Youssefares) in [pydantic/pydantic-core#1413](https://github.com/pydantic/pydantic-core/pull/1413) - Add `trailing-strings` support to `experimental_allow_partial` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10825](https://github.com/pydantic/pydantic/pull/10825) - Add `rebuild()` method for `TypeAdapter` and simplify `defer_build` patterns by [@sydney-runkle](https://github.com/sydney-runkle) in [#10537](https://github.com/pydantic/pydantic/pull/10537) - Improve `TypeAdapter` instance repr by [@sydney-runkle](https://github.com/sydney-runkle) in [#10872](https://github.com/pydantic/pydantic/pull/10872) #### Changes - Don't allow customization of `SchemaGenerator` until interface is more stable by [@sydney-runkle](https://github.com/sydney-runkle) in [#10303](https://github.com/pydantic/pydantic/pull/10303) - Cleanly `defer_build` on `TypeAdapters`, removing experimental flag by [@sydney-runkle](https://github.com/sydney-runkle) in [#10329](https://github.com/pydantic/pydantic/pull/10329) - Fix `mro` of generic subclass by [@kc0506](https://github.com/kc0506) in [#10100](https://github.com/pydantic/pydantic/pull/10100) - Strip whitespaces on JSON Schema title generation by [@sydney-runkle](https://github.com/sydney-runkle) in [#10404](https://github.com/pydantic/pydantic/pull/10404) - Use `b64decode` and `b64encode` for `Base64Bytes` type by [@sydney-runkle](https://github.com/sydney-runkle) in [#10486](https://github.com/pydantic/pydantic/pull/10486) - Relax protected namespace config default by [@sydney-runkle](https://github.com/sydney-runkle) in [#10441](https://github.com/pydantic/pydantic/pull/10441) - Revalidate parametrized generics if instance's origin is subclass of OG class by [@sydney-runkle](https://github.com/sydney-runkle) in [#10666](https://github.com/pydantic/pydantic/pull/10666) - Warn if configuration is specified on the `@dataclass` decorator and with the `__pydantic_config__` attribute by [@sydney-runkle](https://github.com/sydney-runkle) in [#10406](https://github.com/pydantic/pydantic/pull/10406) - Recommend against using `Ellipsis` (...) with `Field` by [@Viicos](https://github.com/Viicos) in [#10661](https://github.com/pydantic/pydantic/pull/10661) - Migrate to subclassing instead of annotated approach for pydantic url types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10662](https://github.com/pydantic/pydantic/pull/10662) - Change JSON schema generation of `Literal`s and `Enums` by [@Viicos](https://github.com/Viicos) in [#10692](https://github.com/pydantic/pydantic/pull/10692) - Simplify unions involving `Any` or `Never` when replacing type variables by [@Viicos](https://github.com/Viicos) in [#10338](https://github.com/pydantic/pydantic/pull/10338) - Do not require padding when decoding `base64` bytes by [@bschoenmaeckers](https://github.com/bschoenmaeckers) in [pydantic/pydantic-core#1448](https://github.com/pydantic/pydantic-core/pull/1448) - Support dates all the way to 1BC by [@changhc](https://github.com/changhc) in [pydantic/speedate#77](https://github.com/pydantic/speedate/pull/77) #### Performance - Schema cleaning: skip unnecessary copies during schema walking by [@Viicos](https://github.com/Viicos) in [#10286](https://github.com/pydantic/pydantic/pull/10286) - Refactor namespace logic for annotations evaluation by [@Viicos](https://github.com/Viicos) in [#10530](https://github.com/pydantic/pydantic/pull/10530) - Improve email regexp on edge cases by [@AlekseyLobanov](https://github.com/AlekseyLobanov) in [#10601](https://github.com/pydantic/pydantic/pull/10601) - `CoreMetadata` refactor with an emphasis on documentation, schema build time performance, and reducing complexity by [@sydney-runkle](https://github.com/sydney-runkle) in [#10675](https://github.com/pydantic/pydantic/pull/10675) #### Packaging - Bump `pydantic-core` to `v2.27.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10825](https://github.com/pydantic/pydantic/pull/10825) - Replaced pdm with uv by [@frfahim](https://github.com/frfahim) in [#10727](https://github.com/pydantic/pydantic/pull/10727) #### Fixes - Remove guarding check on `computed_field` with `field_serializer` by [@nix010](https://github.com/nix010) in [#10390](https://github.com/pydantic/pydantic/pull/10390) - Fix `Predicate` issue in `v2.9.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10321](https://github.com/pydantic/pydantic/pull/10321) - Fixing `annotated-types` bound by [@sydney-runkle](https://github.com/sydney-runkle) in [#10327](https://github.com/pydantic/pydantic/pull/10327) - Turn `tzdata` install requirement into optional `timezone` dependency by [@jakob-keller](https://github.com/jakob-keller) in [#10331](https://github.com/pydantic/pydantic/pull/10331) - Use correct types namespace when building `namedtuple` core schemas by [@Viicos](https://github.com/Viicos) in [#10337](https://github.com/pydantic/pydantic/pull/10337) - Fix evaluation of stringified annotations during namespace inspection by [@Viicos](https://github.com/Viicos) in [#10347](https://github.com/pydantic/pydantic/pull/10347) - Fix `IncEx` type alias definition by [@Viicos](https://github.com/Viicos) in [#10339](https://github.com/pydantic/pydantic/pull/10339) - Do not error when trying to evaluate annotations of private attributes by [@Viicos](https://github.com/Viicos) in [#10358](https://github.com/pydantic/pydantic/pull/10358) - Fix nested type statement by [@kc0506](https://github.com/kc0506) in [#10369](https://github.com/pydantic/pydantic/pull/10369) - Improve typing of `ModelMetaclass.mro` by [@Viicos](https://github.com/Viicos) in [#10372](https://github.com/pydantic/pydantic/pull/10372) - Fix class access of deprecated `computed_field`s by [@Viicos](https://github.com/Viicos) in [#10391](https://github.com/pydantic/pydantic/pull/10391) - Make sure `inspect.iscoroutinefunction` works on coroutines decorated with `@validate_call` by [@MovisLi](https://github.com/MovisLi) in [#10374](https://github.com/pydantic/pydantic/pull/10374) - Fix `NameError` when using `validate_call` with PEP 695 on a class by [@kc0506](https://github.com/kc0506) in [#10380](https://github.com/pydantic/pydantic/pull/10380) - Fix `ZoneInfo` with various invalid types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10408](https://github.com/pydantic/pydantic/pull/10408) - Fix `PydanticUserError` on empty `model_config` with annotations by [@cdwilson](https://github.com/cdwilson) in [#10412](https://github.com/pydantic/pydantic/pull/10412) - Fix variance issue in `_IncEx` type alias, only allow `True` by [@Viicos](https://github.com/Viicos) in [#10414](https://github.com/pydantic/pydantic/pull/10414) - Fix serialization schema generation when using `PlainValidator` by [@Viicos](https://github.com/Viicos) in [#10427](https://github.com/pydantic/pydantic/pull/10427) - Fix schema generation error when serialization schema holds references by [@Viicos](https://github.com/Viicos) in [#10444](https://github.com/pydantic/pydantic/pull/10444) - Inline references if possible when generating schema for `json_schema_input_type` by [@Viicos](https://github.com/Viicos) in [#10439](https://github.com/pydantic/pydantic/pull/10439) - Fix recursive arguments in `Representation` by [@Viicos](https://github.com/Viicos) in [#10480](https://github.com/pydantic/pydantic/pull/10480) - Fix representation for builtin function types by [@kschwab](https://github.com/kschwab) in [#10479](https://github.com/pydantic/pydantic/pull/10479) - Add python validators for decimal constraints (`max_digits` and `decimal_places`) by [@sydney-runkle](https://github.com/sydney-runkle) in [#10506](https://github.com/pydantic/pydantic/pull/10506) - Only fetch `__pydantic_core_schema__` from the current class during schema generation by [@Viicos](https://github.com/Viicos) in [#10518](https://github.com/pydantic/pydantic/pull/10518) - Fix `stacklevel` on deprecation warnings for `BaseModel` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10520](https://github.com/pydantic/pydantic/pull/10520) - Fix warning `stacklevel` in `BaseModel.__init__` by [@Viicos](https://github.com/Viicos) in [#10526](https://github.com/pydantic/pydantic/pull/10526) - Improve error handling for in-evaluable refs for discriminator application by [@sydney-runkle](https://github.com/sydney-runkle) in [#10440](https://github.com/pydantic/pydantic/pull/10440) - Change the signature of `ConfigWrapper.core_config` to take the title directly by [@Viicos](https://github.com/Viicos) in [#10562](https://github.com/pydantic/pydantic/pull/10562) - Do not use the previous config from the stack for dataclasses without config by [@Viicos](https://github.com/Viicos) in [#10576](https://github.com/pydantic/pydantic/pull/10576) - Fix serialization for IP types with `mode='python'` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10594](https://github.com/pydantic/pydantic/pull/10594) - Support constraint application for `Base64Etc` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10584](https://github.com/pydantic/pydantic/pull/10584) - Fix `validate_call` ignoring `Field` in `Annotated` by [@kc0506](https://github.com/kc0506) in [#10610](https://github.com/pydantic/pydantic/pull/10610) - Raise an error when `Self` is invalid by [@kc0506](https://github.com/kc0506) in [#10609](https://github.com/pydantic/pydantic/pull/10609) - Using `core_schema.InvalidSchema` instead of metadata injection + checks by [@sydney-runkle](https://github.com/sydney-runkle) in [#10523](https://github.com/pydantic/pydantic/pull/10523) - Tweak type alias logic by [@kc0506](https://github.com/kc0506) in [#10643](https://github.com/pydantic/pydantic/pull/10643) - Support usage of `type` with `typing.Self` and type aliases by [@kc0506](https://github.com/kc0506) in [#10621](https://github.com/pydantic/pydantic/pull/10621) - Use overloads for `Field` and `PrivateAttr` functions by [@Viicos](https://github.com/Viicos) in [#10651](https://github.com/pydantic/pydantic/pull/10651) - Clean up the `mypy` plugin implementation by [@Viicos](https://github.com/Viicos) in [#10669](https://github.com/pydantic/pydantic/pull/10669) - Properly check for `typing_extensions` variant of `TypeAliasType` by [@Daraan](https://github.com/Daraan) in [#10713](https://github.com/pydantic/pydantic/pull/10713) - Allow any mapping in `BaseModel.model_copy()` by [@Viicos](https://github.com/Viicos) in [#10751](https://github.com/pydantic/pydantic/pull/10751) - Fix `isinstance` behavior for urls by [@sydney-runkle](https://github.com/sydney-runkle) in [#10766](https://github.com/pydantic/pydantic/pull/10766) - Ensure `cached_property` can be set on Pydantic models by [@Viicos](https://github.com/Viicos) in [#10774](https://github.com/pydantic/pydantic/pull/10774) - Fix equality checks for primitives in literals by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1459](https://github.com/pydantic/pydantic-core/pull/1459) - Properly enforce `host_required` for URLs by [@Viicos](https://github.com/Viicos) in [pydantic/pydantic-core#1488](https://github.com/pydantic/pydantic-core/pull/1488) - Fix when `coerce_numbers_to_str` enabled and string has invalid Unicode character by [@andrey-berenda](https://github.com/andrey-berenda) in [pydantic/pydantic-core#1515](https://github.com/pydantic/pydantic-core/pull/1515) - Fix serializing `complex` values in `Enum`s by [@changhc](https://github.com/changhc) in [pydantic/pydantic-core#1524](https://github.com/pydantic/pydantic-core/pull/1524) - Refactor `_typing_extra` module by [@Viicos](https://github.com/Viicos) in [#10725](https://github.com/pydantic/pydantic/pull/10725) - Support intuitive equality for urls by [@sydney-runkle](https://github.com/sydney-runkle) in [#10798](https://github.com/pydantic/pydantic/pull/10798) - Add `bytearray` to `TypeAdapter.validate_json` signature by [@samuelcolvin](https://github.com/samuelcolvin) in [#10802](https://github.com/pydantic/pydantic/pull/10802) - Ensure class access of method descriptors is performed when used as a default with `Field` by [@Viicos](https://github.com/Viicos) in [#10816](https://github.com/pydantic/pydantic/pull/10816) - Fix circular import with `validate_call` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10807](https://github.com/pydantic/pydantic/pull/10807) - Fix error when using type aliases referencing other type aliases by [@Viicos](https://github.com/Viicos) in [#10809](https://github.com/pydantic/pydantic/pull/10809) - Fix `IncEx` type alias to be compatible with mypy by [@Viicos](https://github.com/Viicos) in [#10813](https://github.com/pydantic/pydantic/pull/10813) - Make `__signature__` a lazy property, do not deepcopy defaults by [@Viicos](https://github.com/Viicos) in [#10818](https://github.com/pydantic/pydantic/pull/10818) - Make `__signature__` lazy for dataclasses, too by [@sydney-runkle](https://github.com/sydney-runkle) in [#10832](https://github.com/pydantic/pydantic/pull/10832) - Subclass all single host url classes from `AnyUrl` to preserve behavior from v2.9 by [@sydney-runkle](https://github.com/sydney-runkle) in [#10856](https://github.com/pydantic/pydantic/pull/10856) ### New Contributors - [@jakob-keller](https://github.com/jakob-keller) made their first contribution in [#10331](https://github.com/pydantic/pydantic/pull/10331) - [@MovisLi](https://github.com/MovisLi) made their first contribution in [#10374](https://github.com/pydantic/pydantic/pull/10374) - [@joaopalmeiro](https://github.com/joaopalmeiro) made their first contribution in [#10405](https://github.com/pydantic/pydantic/pull/10405) - [@theunkn0wn1](https://github.com/theunkn0wn1) made their first contribution in [#10378](https://github.com/pydantic/pydantic/pull/10378) - [@cdwilson](https://github.com/cdwilson) made their first contribution in [#10412](https://github.com/pydantic/pydantic/pull/10412) - [@dlax](https://github.com/dlax) made their first contribution in [#10421](https://github.com/pydantic/pydantic/pull/10421) - [@kschwab](https://github.com/kschwab) made their first contribution in [#10479](https://github.com/pydantic/pydantic/pull/10479) - [@santibreo](https://github.com/santibreo) made their first contribution in [#10453](https://github.com/pydantic/pydantic/pull/10453) - [@FlorianSW](https://github.com/FlorianSW) made their first contribution in [#10478](https://github.com/pydantic/pydantic/pull/10478) - [@tkasuz](https://github.com/tkasuz) made their first contribution in [#10555](https://github.com/pydantic/pydantic/pull/10555) - [@AlekseyLobanov](https://github.com/AlekseyLobanov) made their first contribution in [#10601](https://github.com/pydantic/pydantic/pull/10601) - [@NiclasvanEyk](https://github.com/NiclasvanEyk) made their first contribution in [#10667](https://github.com/pydantic/pydantic/pull/10667) - [@mschoettle](https://github.com/mschoettle) made their first contribution in [#10677](https://github.com/pydantic/pydantic/pull/10677) - [@Daraan](https://github.com/Daraan) made their first contribution in [#10713](https://github.com/pydantic/pydantic/pull/10713) - [@k4nar](https://github.com/k4nar) made their first contribution in [#10736](https://github.com/pydantic/pydantic/pull/10736) - [@UriyaHarpeness](https://github.com/UriyaHarpeness) made their first contribution in [#10740](https://github.com/pydantic/pydantic/pull/10740) - [@frfahim](https://github.com/frfahim) made their first contribution in [#10727](https://github.com/pydantic/pydantic/pull/10727) ## v2.10.0b2 (2024-11-13) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0b2) for details. ## v2.10.0b1 (2024-11-06) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.10.0b1) for details. ## v2.9.2 (2024-09-17) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.9.2) ### What's Changed #### Fixes - Do not error when trying to evaluate annotations of private attributes by [@Viicos](https://github.com/Viicos) in [#10358](https://github.com/pydantic/pydantic/pull/10358) - Adding notes on designing sound `Callable` discriminators by [@sydney-runkle](https://github.com/sydney-runkle) in [#10400](https://github.com/pydantic/pydantic/pull/10400) - Fix serialization schema generation when using `PlainValidator` by [@Viicos](https://github.com/Viicos) in [#10427](https://github.com/pydantic/pydantic/pull/10427) - Fix `Union` serialization warnings by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1449](https://github.com/pydantic/pydantic-core/pull/1449) - Fix variance issue in `_IncEx` type alias, only allow `True` by [@Viicos](https://github.com/Viicos) in [#10414](https://github.com/pydantic/pydantic/pull/10414) - Fix `ZoneInfo` validation with various invalid types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10408](https://github.com/pydantic/pydantic/pull/10408) ## v2.9.1 (2024-09-09) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.9.1) ### What's Changed #### Fixes - Fix Predicate issue in v2.9.0 by [@sydney-runkle](https://github.com/sydney-runkle) in [#10321](https://github.com/pydantic/pydantic/pull/10321) - Fixing `annotated-types` bound to `>=0.6.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10327](https://github.com/pydantic/pydantic/pull/10327) - Turn `tzdata` install requirement into optional `timezone` dependency by [@jakob-keller](https://github.com/jakob-keller) in [#10331](https://github.com/pydantic/pydantic/pull/10331) - Fix `IncExc` type alias definition by [@Viicos](https://github.com/Viicos) in [#10339](https://github.com/pydantic/pydantic/pull/10339) - Use correct types namespace when building namedtuple core schemas by [@Viicos](https://github.com/Viicos) in [#10337](https://github.com/pydantic/pydantic/pull/10337) - Fix evaluation of stringified annotations during namespace inspection by [@Viicos](https://github.com/Viicos) in [#10347](https://github.com/pydantic/pydantic/pull/10347) - Fix tagged union serialization with alias generators by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1442](https://github.com/pydantic/pydantic-core/pull/1442) ## v2.9.0 (2024-09-05) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.9.0) The code released in v2.9.0 is practically identical to that of v2.9.0b2. ### What's Changed #### New Features - Add support for `ZoneInfo` by [@Youssefares](https://github.com/Youssefares) in [#9896](https://github.com/pydantic/pydantic/pull/9896) - Add `Config.val_json_bytes` by [@josh-newman](https://github.com/josh-newman) in [#9770](https://github.com/pydantic/pydantic/pull/9770) - Add DSN for Snowflake by [@aditkumar72](https://github.com/aditkumar72) in [#10128](https://github.com/pydantic/pydantic/pull/10128) - Support `complex` number by [@changhc](https://github.com/changhc) in [#9654](https://github.com/pydantic/pydantic/pull/9654) - Add support for `annotated_types.Not` by [@aditkumar72](https://github.com/aditkumar72) in [#10210](https://github.com/pydantic/pydantic/pull/10210) - Allow `WithJsonSchema` to inject `$ref`s w/ `http` or `https` links by [@dAIsySHEng1](https://github.com/dAIsySHEng1) in [#9863](https://github.com/pydantic/pydantic/pull/9863) - Allow validators to customize validation JSON schema by [@Viicos](https://github.com/Viicos) in [#10094](https://github.com/pydantic/pydantic/pull/10094) - Support parametrized `PathLike` types by [@nix010](https://github.com/nix010) in [#9764](https://github.com/pydantic/pydantic/pull/9764) - Add tagged union serializer that attempts to use `str` or `callable` discriminators to select the correct serializer by [@sydney-runkle](https://github.com/sydney-runkle) in in [pydantic/pydantic-core#1397](https://github.com/pydantic/pydantic-core/pull/1397) #### Changes - Breaking Change: Merge `dict` type `json_schema_extra` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9792](https://github.com/pydantic/pydantic/pull/9792) - For more info (how to replicate old behavior) on this change, see [here](https://docs.pydantic.dev/dev/concepts/json_schema/#merging-json_schema_extra) - Refactor annotation injection for known (often generic) types by [@sydney-runkle](https://github.com/sydney-runkle) in [#9979](https://github.com/pydantic/pydantic/pull/9979) - Move annotation compatibility errors to validation phase by [@sydney-runkle](https://github.com/sydney-runkle) in [#9999](https://github.com/pydantic/pydantic/pull/9999) - Improve runtime errors for string constraints like `pattern` for incompatible types by [@sydney-runkle](https://github.com/sydney-runkle) in [#10158](https://github.com/pydantic/pydantic/pull/10158) - Remove `'allOf'` JSON schema workarounds by [@dpeachey](https://github.com/dpeachey) in [#10029](https://github.com/pydantic/pydantic/pull/10029) - Remove `typed_dict_cls` data from `CoreMetadata` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10180](https://github.com/pydantic/pydantic/pull/10180) - Deprecate passing a dict to the `Examples` class by [@Viicos](https://github.com/Viicos) in [#10181](https://github.com/pydantic/pydantic/pull/10181) - Remove `initial_metadata` from internal metadata construct by [@sydney-runkle](https://github.com/sydney-runkle) in [#10194](https://github.com/pydantic/pydantic/pull/10194) - Use `re.Pattern.search` instead of `re.Pattern.match` for consistency with `rust` behavior by [@tinez](https://github.com/tinez) in [pydantic/pydantic-core#1368](https://github.com/pydantic/pydantic-core/pull/1368) - Show value of wrongly typed data in `pydantic-core` serialization warning by [@BoxyUwU](https://github.com/BoxyUwU) in [pydantic/pydantic-core#1377](https://github.com/pydantic/pydantic-core/pull/1377) - Breaking Change: in `pydantic-core`, change `metadata` type hint in core schemas from `Any` -> `Dict[str, Any] | None` by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1411](https://github.com/pydantic/pydantic-core/pull/1411) - Raise helpful warning when `self` isn't returned from model validator by [@sydney-runkle](https://github.com/sydney-runkle) in [#10255](https://github.com/pydantic/pydantic/pull/10255) #### Performance - Initial start at improving import times for modules, using caching primarily by [@sydney-runkle](https://github.com/sydney-runkle) in [#10009](https://github.com/pydantic/pydantic/pull/10009) - Using cached internal import for `BaseModel` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10013](https://github.com/pydantic/pydantic/pull/10013) - Simplify internal generics logic - remove generator overhead by [@sydney-runkle](https://github.com/sydney-runkle) in [#10059](https://github.com/pydantic/pydantic/pull/10059) - Remove default module globals from types namespace by [@sydney-runkle](https://github.com/sydney-runkle) in [#10123](https://github.com/pydantic/pydantic/pull/10123) - Performance boost: skip caching parent namespaces in most cases by [@sydney-runkle](https://github.com/sydney-runkle) in [#10113](https://github.com/pydantic/pydantic/pull/10113) - Update ns stack with already copied ns by [@sydney-runkle](https://github.com/sydney-runkle) in [#10267](https://github.com/pydantic/pydantic/pull/10267) ##### Minor Internal Improvements - ⚡️ Speed up `multiple_of_validator()` by 31% in `pydantic/_internal/_validators.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9839](https://github.com/pydantic/pydantic/pull/9839) - ⚡️ Speed up `ModelPrivateAttr.__set_name__()` by 18% in `pydantic/fields.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9841](https://github.com/pydantic/pydantic/pull/9841) - ⚡️ Speed up `dataclass()` by 7% in `pydantic/dataclasses.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9843](https://github.com/pydantic/pydantic/pull/9843) - ⚡️ Speed up function `_field_name_for_signature` by 37% in `pydantic/_internal/_signature.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9951](https://github.com/pydantic/pydantic/pull/9951) - ⚡️ Speed up method `GenerateSchema._unpack_refs_defs` by 26% in `pydantic/_internal/_generate_schema.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9949](https://github.com/pydantic/pydantic/pull/9949) - ⚡️ Speed up function `apply_each_item_validators` by 100% in `pydantic/_internal/_generate_schema.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9950](https://github.com/pydantic/pydantic/pull/9950) - ⚡️ Speed up method `ConfigWrapper.core_config` by 28% in `pydantic/_internal/_config.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9953](https://github.com/pydantic/pydantic/pull/9953) #### Fixes - Respect `use_enum_values` on `Literal` types by [@kwint](https://github.com/kwint) in [#9787](https://github.com/pydantic/pydantic/pull/9787) - Prevent type error for exotic `BaseModel/RootModel` inheritance by [@dmontagu](https://github.com/dmontagu) in [#9913](https://github.com/pydantic/pydantic/pull/9913) - Fix typing issue with field\_validator-decorated methods by [@dmontagu](https://github.com/dmontagu) in [#9914](https://github.com/pydantic/pydantic/pull/9914) - Replace `str` type annotation with `Any` in validator factories in documentation on validators by [@maximilianfellhuber](https://github.com/maximilianfellhuber) in [#9885](https://github.com/pydantic/pydantic/pull/9885) - Fix `ComputedFieldInfo.wrapped_property` pointer when a property setter is assigned by [@tlambert03](https://github.com/tlambert03) in [#9892](https://github.com/pydantic/pydantic/pull/9892) - Fix recursive typing of `main.IncEnx` by [@tlambert03](https://github.com/tlambert03) in [#9924](https://github.com/pydantic/pydantic/pull/9924) - Allow usage of `type[Annotated[...]]` by [@Viicos](https://github.com/Viicos) in [#9932](https://github.com/pydantic/pydantic/pull/9932) - `mypy` plugin: handle frozen fields on a per-field basis by [@dmontagu](https://github.com/dmontagu) in [#9935](https://github.com/pydantic/pydantic/pull/9935) - Fix typo in `invalid-annotated-type` error code by [@sydney-runkle](https://github.com/sydney-runkle) in [#9948](https://github.com/pydantic/pydantic/pull/9948) - Simplify schema generation for `uuid`, `url`, and `ip` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#9975](https://github.com/pydantic/pydantic/pull/9975) - Move `date` schemas to `_generate_schema.py` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9976](https://github.com/pydantic/pydantic/pull/9976) - Move `decimal.Decimal` validation to `_generate_schema.py` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9977](https://github.com/pydantic/pydantic/pull/9977) - Simplify IP address schema in `_std_types_schema.py` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9959](https://github.com/pydantic/pydantic/pull/9959) - Fix type annotations for some potentially generic `GenerateSchema.match_type` options by [@sydney-runkle](https://github.com/sydney-runkle) in [#9961](https://github.com/pydantic/pydantic/pull/9961) - Add class name to "has conflict" warnings by [@msabramo](https://github.com/msabramo) in [#9964](https://github.com/pydantic/pydantic/pull/9964) - Fix `dataclass` ignoring `default_factory` passed in Annotated by [@kc0506](https://github.com/kc0506) in [#9971](https://github.com/pydantic/pydantic/pull/9971) - Fix `Sequence` ignoring `discriminator` by [@kc0506](https://github.com/kc0506) in [#9980](https://github.com/pydantic/pydantic/pull/9980) - Fix typing for `IPvAnyAddress` and `IPvAnyInterface` by [@haoyun](https://github.com/haoyun) in [#9990](https://github.com/pydantic/pydantic/pull/9990) - Fix false positives on v1 models in `mypy` plugin for `from_orm` check requiring from\_attributes=True config by [@radekwlsk](https://github.com/radekwlsk) in [#9938](https://github.com/pydantic/pydantic/pull/9938) - Apply `strict=True` to `__init__` in `mypy` plugin by [@kc0506](https://github.com/kc0506) in [#9998](https://github.com/pydantic/pydantic/pull/9998) - Refactor application of `deque` annotations by [@sydney-runkle](https://github.com/sydney-runkle) in [#10018](https://github.com/pydantic/pydantic/pull/10018) - Raise a better user error when failing to evaluate a forward reference by [@Viicos](https://github.com/Viicos) in [#10030](https://github.com/pydantic/pydantic/pull/10030) - Fix evaluation of `__pydantic_extra__` annotation in specific circumstances by [@Viicos](https://github.com/Viicos) in [#10070](https://github.com/pydantic/pydantic/pull/10070) - Fix `frozen` enforcement for `dataclasses` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10066](https://github.com/pydantic/pydantic/pull/10066) - Remove logic to handle unused `__get_pydantic_core_schema__` signature by [@Viicos](https://github.com/Viicos) in [#10075](https://github.com/pydantic/pydantic/pull/10075) - Use `is_annotated` consistently by [@Viicos](https://github.com/Viicos) in [#10095](https://github.com/pydantic/pydantic/pull/10095) - Fix `PydanticDeprecatedSince26` typo by [@kc0506](https://github.com/kc0506) in [#10101](https://github.com/pydantic/pydantic/pull/10101) - Improve `pyright` tests, refactor model decorators signatures by [@Viicos](https://github.com/Viicos) in [#10092](https://github.com/pydantic/pydantic/pull/10092) - Fix `ip` serialization logic by [@sydney-runkle](https://github.com/sydney-runkle) in [#10112](https://github.com/pydantic/pydantic/pull/10112) - Warn when frozen defined twice for `dataclasses` by [@mochi22](https://github.com/mochi22) in [#10082](https://github.com/pydantic/pydantic/pull/10082) - Do not compute JSON Schema default when plain serializers are used with `when_used` set to `'json-unless-none'` and the default value is `None` by [@Viicos](https://github.com/Viicos) in [#10121](https://github.com/pydantic/pydantic/pull/10121) - Fix `ImportString` special cases by [@sydney-runkle](https://github.com/sydney-runkle) in [#10137](https://github.com/pydantic/pydantic/pull/10137) - Blacklist default globals to support exotic user code with `__` prefixed annotations by [@sydney-runkle](https://github.com/sydney-runkle) in [#10136](https://github.com/pydantic/pydantic/pull/10136) - Handle `nullable` schemas with `serialization` schema available during JSON Schema generation by [@Viicos](https://github.com/Viicos) in [#10132](https://github.com/pydantic/pydantic/pull/10132) - Reorganize `BaseModel` annotations by [@kc0506](https://github.com/kc0506) in [#10110](https://github.com/pydantic/pydantic/pull/10110) - Fix core schema simplification when serialization schemas are involved in specific scenarios by [@Viicos](https://github.com/Viicos) in [#10155](https://github.com/pydantic/pydantic/pull/10155) - Add support for stringified annotations when using `PrivateAttr` with `Annotated` by [@Viicos](https://github.com/Viicos) in [#10157](https://github.com/pydantic/pydantic/pull/10157) - Fix JSON Schema `number` type for literal and enum schemas by [@Viicos](https://github.com/Viicos) in [#10172](https://github.com/pydantic/pydantic/pull/10172) - Fix JSON Schema generation of fields with plain validators in serialization mode by [@Viicos](https://github.com/Viicos) in [#10167](https://github.com/pydantic/pydantic/pull/10167) - Fix invalid JSON Schemas being generated for functions in certain scenarios by [@Viicos](https://github.com/Viicos) in [#10188](https://github.com/pydantic/pydantic/pull/10188) - Make sure generated JSON Schemas are valid in tests by [@Viicos](https://github.com/Viicos) in [#10182](https://github.com/pydantic/pydantic/pull/10182) - Fix key error with custom serializer by [@sydney-runkle](https://github.com/sydney-runkle) in [#10200](https://github.com/pydantic/pydantic/pull/10200) - Add 'wss' for allowed schemes in NatsDsn by [@swelborn](https://github.com/swelborn) in [#10224](https://github.com/pydantic/pydantic/pull/10224) - Fix `Mapping` and `MutableMapping` annotations to use mapping schema instead of dict schema by [@sydney-runkle](https://github.com/sydney-runkle) in [#10020](https://github.com/pydantic/pydantic/pull/10020) - Fix JSON Schema generation for constrained dates by [@Viicos](https://github.com/Viicos) in [#10185](https://github.com/pydantic/pydantic/pull/10185) - Fix discriminated union bug regression when using enums by [@kfreezen](https://github.com/kfreezen) in [pydantic/pydantic-core#1286](https://github.com/pydantic/pydantic-core/pull/1286) - Fix `field_serializer` with computed field when using `*` by [@nix010](https://github.com/nix010) in [pydantic/pydantic-core#1349](https://github.com/pydantic/pydantic-core/pull/1349) - Try each option in `Union` serializer before inference by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1398](https://github.com/pydantic/pydantic-core/pull/1398) - Fix `float` serialization behavior in `strict` mode by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1400](https://github.com/pydantic/pydantic-core/pull/1400) - Introduce `exactness` into Decimal validation logic to improve union validation behavior by [@sydney-runkle](https://github.com/sydney-runkle) in in [pydantic/pydantic-core#1405](https://github.com/pydantic/pydantic-core/pull/1405) - Fix new warnings assertions to use `pytest.warns()` by [@mgorny](https://github.com/mgorny) in [#10241](https://github.com/pydantic/pydantic/pull/10241) - Fix a crash when cleaning the namespace in `ModelMetaclass` by [@Viicos](https://github.com/Viicos) in [#10242](https://github.com/pydantic/pydantic/pull/10242) - Fix parent namespace issue with model rebuilds by [@sydney-runkle](https://github.com/sydney-runkle) in [#10257](https://github.com/pydantic/pydantic/pull/10257) - Remove defaults filter for namespace by [@sydney-runkle](https://github.com/sydney-runkle) in [#10261](https://github.com/pydantic/pydantic/pull/10261) - Use identity instead of equality after validating model in `__init__` by [@Viicos](https://github.com/Viicos) in [#10264](https://github.com/pydantic/pydantic/pull/10264) - Support `BigInt` serialization for `int` subclasses by [@kxx317](https://github.com/kxx317) in [pydantic/pydantic-core#1417](https://github.com/pydantic/pydantic-core/pull/1417) - Support signature for wrap validators without `info` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10277](https://github.com/pydantic/pydantic/pull/10277) - Ensure `__pydantic_complete__` is set when rebuilding `dataclasses` by [@Viicos](https://github.com/Viicos) in [#10291](https://github.com/pydantic/pydantic/pull/10291) - Respect `schema_generator` config value in `TypeAdapter` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10300](https://github.com/pydantic/pydantic/pull/10300) #### Packaging - Bump `ruff` to `v0.5.0` and `pyright` to `v1.1.369` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9801](https://github.com/pydantic/pydantic/pull/9801) - Bump `pydantic-extra-types` to `v2.9.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9832](https://github.com/pydantic/pydantic/pull/9832) - Support compatibility with `pdm v2.18.1` by [@Viicos](https://github.com/Viicos) in [#10138](https://github.com/pydantic/pydantic/pull/10138) - Bump `v1` version stub to `v1.10.18` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10214](https://github.com/pydantic/pydantic/pull/10214) - Bump `pydantic-core` to `v2.23.2` by [@sydney-runkle](https://github.com/sydney-runkle) in [#10311](https://github.com/pydantic/pydantic/pull/10311) ### New Contributors #### `pydantic` - [@kwint](https://github.com/kwint) made their first contribution in [#9787](https://github.com/pydantic/pydantic/pull/9787) - [@seekinginfiniteloop](https://github.com/seekinginfiniteloop) made their first contribution in [#9822](https://github.com/pydantic/pydantic/pull/9822) - [@a-alexander](https://github.com/a-alexander) made their first contribution in [#9848](https://github.com/pydantic/pydantic/pull/9848) - [@maximilianfellhuber](https://github.com/maximilianfellhuber) made their first contribution in [#9885](https://github.com/pydantic/pydantic/pull/9885) - [@karmaBonfire](https://github.com/karmaBonfire) made their first contribution in [#9945](https://github.com/pydantic/pydantic/pull/9945) - [@s-rigaud](https://github.com/s-rigaud) made their first contribution in [#9958](https://github.com/pydantic/pydantic/pull/9958) - [@msabramo](https://github.com/msabramo) made their first contribution in [#9964](https://github.com/pydantic/pydantic/pull/9964) - [@DimaCybr](https://github.com/DimaCybr) made their first contribution in [#9972](https://github.com/pydantic/pydantic/pull/9972) - [@kc0506](https://github.com/kc0506) made their first contribution in [#9971](https://github.com/pydantic/pydantic/pull/9971) - [@haoyun](https://github.com/haoyun) made their first contribution in [#9990](https://github.com/pydantic/pydantic/pull/9990) - [@radekwlsk](https://github.com/radekwlsk) made their first contribution in [#9938](https://github.com/pydantic/pydantic/pull/9938) - [@dpeachey](https://github.com/dpeachey) made their first contribution in [#10029](https://github.com/pydantic/pydantic/pull/10029) - [@BoxyUwU](https://github.com/BoxyUwU) made their first contribution in [#10085](https://github.com/pydantic/pydantic/pull/10085) - [@mochi22](https://github.com/mochi22) made their first contribution in [#10082](https://github.com/pydantic/pydantic/pull/10082) - [@aditkumar72](https://github.com/aditkumar72) made their first contribution in [#10128](https://github.com/pydantic/pydantic/pull/10128) - [@changhc](https://github.com/changhc) made their first contribution in [#9654](https://github.com/pydantic/pydantic/pull/9654) - [@insumanth](https://github.com/insumanth) made their first contribution in [#10229](https://github.com/pydantic/pydantic/pull/10229) - [@AdolfoVillalobos](https://github.com/AdolfoVillalobos) made their first contribution in [#10240](https://github.com/pydantic/pydantic/pull/10240) - [@bllchmbrs](https://github.com/bllchmbrs) made their first contribution in [#10270](https://github.com/pydantic/pydantic/pull/10270) #### `pydantic-core` - [@kfreezen](https://github.com/kfreezen) made their first contribution in [pydantic/pydantic-core#1286](https://github.com/pydantic/pydantic-core/pull/1286) - [@tinez](https://github.com/tinez) made their first contribution in [pydantic/pydantic-core#1368](https://github.com/pydantic/pydantic-core/pull/1368) - [@fft001](https://github.com/fft001) made their first contribution in [pydantic/pydantic-core#1362](https://github.com/pydantic/pydantic-core/pull/1362) - [@nix010](https://github.com/nix010) made their first contribution in [pydantic/pydantic-core#1349](https://github.com/pydantic/pydantic-core/pull/1349) - [@BoxyUwU](https://github.com/BoxyUwU) made their first contribution in [pydantic/pydantic-core#1379](https://github.com/pydantic/pydantic-core/pull/1379) - [@candleindark](https://github.com/candleindark) made their first contribution in [pydantic/pydantic-core#1404](https://github.com/pydantic/pydantic-core/pull/1404) - [@changhc](https://github.com/changhc) made their first contribution in [pydantic/pydantic-core#1331](https://github.com/pydantic/pydantic-core/pull/1331) ## v2.9.0b2 (2024-08-30) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.9.0b2) for details. ## v2.9.0b1 (2024-08-26) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.9.0b1) for details. ## v2.8.2 (2024-07-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.8.2) ### What's Changed #### Fixes - Fix issue with assertion caused by pluggable schema validator by [@dmontagu](https://github.com/dmontagu) in [#9838](https://github.com/pydantic/pydantic/pull/9838) ## v2.8.1 (2024-07-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.8.1) ### What's Changed #### Packaging - Bump `ruff` to `v0.5.0` and `pyright` to `v1.1.369` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9801](https://github.com/pydantic/pydantic/pull/9801) - Bump `pydantic-core` to `v2.20.1`, `pydantic-extra-types` to `v2.9.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9832](https://github.com/pydantic/pydantic/pull/9832) #### Fixes - Fix breaking change in `to_snake` from v2.7 -> v2.8 by [@sydney-runkle](https://github.com/sydney-runkle) in [#9812](https://github.com/pydantic/pydantic/pull/9812) - Fix list constraint json schema application by [@sydney-runkle](https://github.com/sydney-runkle) in [#9818](https://github.com/pydantic/pydantic/pull/9818) - Support time duration more than 23 by [@nix010](https://github.com/nix010) in [pydantic/speedate#64](https://github.com/pydantic/speedate/pull/64) - Fix millisecond fraction being handled with the wrong scale by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/speedate#65](https://github.com/pydantic/speedate/pull/65) - Handle negative fractional durations correctly by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/speedate#71](https://github.com/pydantic/speedate/pull/71) ## v2.8.0 (2024-07-01) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.8.0) The code released in v2.8.0 is functionally identical to that of v2.8.0b1. ### What's Changed #### Packaging - Update citation version automatically with new releases by [@sydney-runkle](https://github.com/sydney-runkle) in [#9673](https://github.com/pydantic/pydantic/pull/9673) - Bump pyright to `v1.1.367` and add type checking tests for pipeline API by [@adriangb](https://github.com/adriangb) in [#9674](https://github.com/pydantic/pydantic/pull/9674) - Update `pydantic.v1` stub to `v1.10.17` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9707](https://github.com/pydantic/pydantic/pull/9707) - General package updates to prep for `v2.8.0b1` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9741](https://github.com/pydantic/pydantic/pull/9741) - Bump `pydantic-core` to `v2.20.0` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9745](https://github.com/pydantic/pydantic/pull/9745) - Add support for Python 3.13 by [@sydney-runkle](https://github.com/sydney-runkle) in [#9743](https://github.com/pydantic/pydantic/pull/9743) - Update `pdm` version used for `pdm.lock` to v2.16.1 by [@sydney-runkle](https://github.com/sydney-runkle) in [#9761](https://github.com/pydantic/pydantic/pull/9761) - Update to `ruff` `v0.4.8` by [@Viicos](https://github.com/Viicos) in [#9585](https://github.com/pydantic/pydantic/pull/9585) #### New Features - Experimental: support `defer_build` for `TypeAdapter` by [@MarkusSintonen](https://github.com/MarkusSintonen) in [#8939](https://github.com/pydantic/pydantic/pull/8939) - Implement `deprecated` field in json schema by [@NeevCohen](https://github.com/NeevCohen) in [#9298](https://github.com/pydantic/pydantic/pull/9298) - Experimental: Add pipeline API by [@adriangb](https://github.com/adriangb) in [#9459](https://github.com/pydantic/pydantic/pull/9459) - Add support for programmatic title generation by [@NeevCohen](https://github.com/NeevCohen) in [#9183](https://github.com/pydantic/pydantic/pull/9183) - Implement `fail_fast` feature by [@uriyyo](https://github.com/uriyyo) in [#9708](https://github.com/pydantic/pydantic/pull/9708) - Add `ser_json_inf_nan='strings'` mode to produce valid JSON by [@josh-newman](https://github.com/josh-newman) in [pydantic/pydantic-core#1307](https://github.com/pydantic/pydantic-core/pull/1307) #### Changes - Add warning when "alias" is set in ignored `Annotated` field by [@nix010](https://github.com/nix010) in [#9170](https://github.com/pydantic/pydantic/pull/9170) - Support serialization of some serializable defaults in JSON schema by [@sydney-runkle](https://github.com/sydney-runkle) in [#9624](https://github.com/pydantic/pydantic/pull/9624) - Relax type specification for `__validators__` values in `create_model` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9697](https://github.com/pydantic/pydantic/pull/9697) - **Breaking Change:** Improve `smart` union matching logic by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1322](https://github.com/pydantic/pydantic-core/pull/1322) You can read more about our `smart` union matching logic [here](https://docs.pydantic.dev/dev/concepts/unions/#smart-mode). In some cases, if the old behavior is desired, you can switch to `left-to-right` mode and change the order of your `Union` members. #### Performance ##### Internal Improvements - ⚡️ Speed up `_display_error_loc()` by 25% in `pydantic/v1/error_wrappers.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9653](https://github.com/pydantic/pydantic/pull/9653) - ⚡️ Speed up `_get_all_json_refs()` by 34% in `pydantic/json_schema.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9650](https://github.com/pydantic/pydantic/pull/9650) - ⚡️ Speed up `is_pydantic_dataclass()` by 41% in `pydantic/dataclasses.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9652](https://github.com/pydantic/pydantic/pull/9652) - ⚡️ Speed up `to_snake()` by 27% in `pydantic/alias_generators.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9747](https://github.com/pydantic/pydantic/pull/9747) - ⚡️ Speed up `unwrap_wrapped_function()` by 93% in `pydantic/_internal/_decorators.py` by [@misrasaurabh1](https://github.com/misrasaurabh1) in [#9727](https://github.com/pydantic/pydantic/pull/9727) #### Fixes - Replace `__spec__.parent` with `__package__` by [@hramezani](https://github.com/hramezani) in [#9331](https://github.com/pydantic/pydantic/pull/9331) - Fix Outputted Model JSON Schema for `Sequence` type by [@anesmemisevic](https://github.com/anesmemisevic) in [#9303](https://github.com/pydantic/pydantic/pull/9303) - Fix typing of `_frame_depth` by [@Viicos](https://github.com/Viicos) in [#9353](https://github.com/pydantic/pydantic/pull/9353) - Make `ImportString` json schema compatible by [@amitschang](https://github.com/amitschang) in [#9344](https://github.com/pydantic/pydantic/pull/9344) - Hide private attributes (`PrivateAttr`) from `__init__` signature in type checkers by [@idan22moral](https://github.com/idan22moral) in [#9293](https://github.com/pydantic/pydantic/pull/9293) - Make detection of `TypeVar` defaults robust to the CPython `PEP-696` implementation by [@AlexWaygood](https://github.com/AlexWaygood) in [#9426](https://github.com/pydantic/pydantic/pull/9426) - Fix usage of `PlainSerializer` with builtin types by [@Viicos](https://github.com/Viicos) in [#9450](https://github.com/pydantic/pydantic/pull/9450) - Add more robust custom validation examples by [@ChrisPappalardo](https://github.com/ChrisPappalardo) in [#9468](https://github.com/pydantic/pydantic/pull/9468) - Fix ignored `strict` specification for `StringConstraint(strict=False)` by [@vbmendes](https://github.com/vbmendes) in [#9476](https://github.com/pydantic/pydantic/pull/9476) - **Breaking Change:** Use PEP 570 syntax by [@Viicos](https://github.com/Viicos) in [#9479](https://github.com/pydantic/pydantic/pull/9479) - Use `Self` where possible by [@Viicos](https://github.com/Viicos) in [#9479](https://github.com/pydantic/pydantic/pull/9479) - Do not alter `RootModel.model_construct` signature in the `mypy` plugin by [@Viicos](https://github.com/Viicos) in [#9480](https://github.com/pydantic/pydantic/pull/9480) - Fixed type hint of `validation_context` by [@OhioDschungel6](https://github.com/OhioDschungel6) in [#9508](https://github.com/pydantic/pydantic/pull/9508) - Support context being passed to TypeAdapter's `dump_json`/`dump_python` by [@alexcouper](https://github.com/alexcouper) in [#9495](https://github.com/pydantic/pydantic/pull/9495) - Updates type signature for `Field()` constructor by [@bjmc](https://github.com/bjmc) in [#9484](https://github.com/pydantic/pydantic/pull/9484) - Improve builtin alias generators by [@sydney-runkle](https://github.com/sydney-runkle) in [#9561](https://github.com/pydantic/pydantic/pull/9561) - Fix typing of `TypeAdapter` by [@Viicos](https://github.com/Viicos) in [#9570](https://github.com/pydantic/pydantic/pull/9570) - Add fallback default value for private fields in `__setstate__` of BaseModel by [@anhpham1509](https://github.com/anhpham1509) in [#9584](https://github.com/pydantic/pydantic/pull/9584) - Support `PEP 746` by [@adriangb](https://github.com/adriangb) in [#9587](https://github.com/pydantic/pydantic/pull/9587) - Allow validator and serializer functions to have default values by [@Viicos](https://github.com/Viicos) in [#9478](https://github.com/pydantic/pydantic/pull/9478) - Fix bug with mypy plugin's handling of covariant `TypeVar` fields by [@dmontagu](https://github.com/dmontagu) in [#9606](https://github.com/pydantic/pydantic/pull/9606) - Fix multiple annotation / constraint application logic by [@sydney-runkle](https://github.com/sydney-runkle) in [#9623](https://github.com/pydantic/pydantic/pull/9623) - Respect `regex` flags in validation and json schema by [@sydney-runkle](https://github.com/sydney-runkle) in [#9591](https://github.com/pydantic/pydantic/pull/9591) - Fix type hint on `IpvAnyAddress` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9640](https://github.com/pydantic/pydantic/pull/9640) - Allow a field specifier on `__pydantic_extra__` by [@dmontagu](https://github.com/dmontagu) in [#9659](https://github.com/pydantic/pydantic/pull/9659) - Use normalized case for file path comparison by [@sydney-runkle](https://github.com/sydney-runkle) in [#9737](https://github.com/pydantic/pydantic/pull/9737) - Modify constraint application logic to allow field constraints on `Optional[Decimal]` by [@lazyhope](https://github.com/lazyhope) in [#9754](https://github.com/pydantic/pydantic/pull/9754) - `validate_call` type params fix by [@sydney-runkle](https://github.com/sydney-runkle) in [#9760](https://github.com/pydantic/pydantic/pull/9760) - Check all warnings returned by pytest.warns() by [@s-t-e-v-e-n-k](https://github.com/s-t-e-v-e-n-k) in [#9702](https://github.com/pydantic/pydantic/pull/9702) - Reuse `re.Pattern` object in regex patterns to allow for regex flags by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1318](https://github.com/pydantic/pydantic-core/pull/1318) ### New Contributors - [@idan22moral](https://github.com/idan22moral) made their first contribution in [#9294](https://github.com/pydantic/pydantic/pull/9294) - [@anesmemisevic](https://github.com/anesmemisevic) made their first contribution in [#9303](https://github.com/pydantic/pydantic/pull/9303) - [@max-muoto](https://github.com/max-muoto) made their first contribution in [#9338](https://github.com/pydantic/pydantic/pull/9338) - [@amitschang](https://github.com/amitschang) made their first contribution in [#9344](https://github.com/pydantic/pydantic/pull/9344) - [@paulmartin91](https://github.com/paulmartin91) made their first contribution in [#9410](https://github.com/pydantic/pydantic/pull/9410) - [@OhioDschungel6](https://github.com/OhioDschungel6) made their first contribution in [#9405](https://github.com/pydantic/pydantic/pull/9405) - [@AlexWaygood](https://github.com/AlexWaygood) made their first contribution in [#9426](https://github.com/pydantic/pydantic/pull/9426) - [@kinuax](https://github.com/kinuax) made their first contribution in [#9433](https://github.com/pydantic/pydantic/pull/9433) - [@antoni-jamiolkowski](https://github.com/antoni-jamiolkowski) made their first contribution in [#9431](https://github.com/pydantic/pydantic/pull/9431) - [@candleindark](https://github.com/candleindark) made their first contribution in [#9448](https://github.com/pydantic/pydantic/pull/9448) - [@nix010](https://github.com/nix010) made their first contribution in [#9170](https://github.com/pydantic/pydantic/pull/9170) - [@tomy0000000](https://github.com/tomy0000000) made their first contribution in [#9457](https://github.com/pydantic/pydantic/pull/9457) - [@vbmendes](https://github.com/vbmendes) made their first contribution in [#9470](https://github.com/pydantic/pydantic/pull/9470) - [@micheleAlberto](https://github.com/micheleAlberto) made their first contribution in [#9471](https://github.com/pydantic/pydantic/pull/9471) - [@ChrisPappalardo](https://github.com/ChrisPappalardo) made their first contribution in [#9468](https://github.com/pydantic/pydantic/pull/9468) - [@blueTurtz](https://github.com/blueTurtz) made their first contribution in [#9475](https://github.com/pydantic/pydantic/pull/9475) - [@WinterBlue16](https://github.com/WinterBlue16) made their first contribution in [#9477](https://github.com/pydantic/pydantic/pull/9477) - [@bittner](https://github.com/bittner) made their first contribution in [#9500](https://github.com/pydantic/pydantic/pull/9500) - [@alexcouper](https://github.com/alexcouper) made their first contribution in [#9495](https://github.com/pydantic/pydantic/pull/9495) - [@bjmc](https://github.com/bjmc) made their first contribution in [#9484](https://github.com/pydantic/pydantic/pull/9484) - [@pjvv](https://github.com/pjvv) made their first contribution in [#9529](https://github.com/pydantic/pydantic/pull/9529) - [@nedbat](https://github.com/nedbat) made their first contribution in [#9530](https://github.com/pydantic/pydantic/pull/9530) - [@gunnellEvan](https://github.com/gunnellEvan) made their first contribution in [#9469](https://github.com/pydantic/pydantic/pull/9469) - [@jaymbans](https://github.com/jaymbans) made their first contribution in [#9531](https://github.com/pydantic/pydantic/pull/9531) - [@MarcBresson](https://github.com/MarcBresson) made their first contribution in [#9534](https://github.com/pydantic/pydantic/pull/9534) - [@anhpham1509](https://github.com/anhpham1509) made their first contribution in [#9584](https://github.com/pydantic/pydantic/pull/9584) - [@K-dash](https://github.com/K-dash) made their first contribution in [#9595](https://github.com/pydantic/pydantic/pull/9595) - [@s-t-e-v-e-n-k](https://github.com/s-t-e-v-e-n-k) made their first contribution in [#9527](https://github.com/pydantic/pydantic/pull/9527) - [@airwoodix](https://github.com/airwoodix) made their first contribution in [#9506](https://github.com/pydantic/pydantic/pull/9506) - [@misrasaurabh1](https://github.com/misrasaurabh1) made their first contribution in [#9653](https://github.com/pydantic/pydantic/pull/9653) - [@AlessandroMiola](https://github.com/AlessandroMiola) made their first contribution in [#9740](https://github.com/pydantic/pydantic/pull/9740) - [@mylapallilavanyaa](https://github.com/mylapallilavanyaa) made their first contribution in [#9746](https://github.com/pydantic/pydantic/pull/9746) - [@lazyhope](https://github.com/lazyhope) made their first contribution in [#9754](https://github.com/pydantic/pydantic/pull/9754) - [@YassinNouh21](https://github.com/YassinNouh21) made their first contribution in [#9759](https://github.com/pydantic/pydantic/pull/9759) ## v2.8.0b1 (2024-06-27) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.8.0b1) for details. ## v2.7.4 (2024-06-12) [Github release](https://github.com/pydantic/pydantic/releases/tag/v2.7.4) ### What's Changed #### Packaging - Bump `pydantic.v1` to `v1.10.16` reference by [@sydney-runkle](https://github.com/sydney-runkle) in [#9639](https://github.com/pydantic/pydantic/pull/9639) #### Fixes - Specify `recursive_guard` as kwarg in `FutureRef._evaluate` by [@vfazio](https://github.com/vfazio) in [#9612](https://github.com/pydantic/pydantic/pull/9612) ## v2.7.3 (2024-06-03) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.7.3) ### What's Changed #### Packaging - Bump `pydantic-core` to `v2.18.4` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9550](https://github.com/pydantic/pydantic/pull/9550) #### Fixes - Fix u style unicode strings in python [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/jiter#110](https://github.com/pydantic/jiter/pull/110) ## v2.7.2 (2024-05-28) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.7.2) ### What's Changed #### Packaging - Bump `pydantic-core` to `v2.18.3` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9515](https://github.com/pydantic/pydantic/pull/9515) #### Fixes - Replace `__spec__.parent` with `__package__` by [@hramezani](https://github.com/hramezani) in [#9331](https://github.com/pydantic/pydantic/pull/9331) - Fix validation of `int`s with leading unary minus by [@RajatRajdeep](https://github.com/RajatRajdeep) in [pydantic/pydantic-core#1291](https://github.com/pydantic/pydantic-core/pull/1291) - Fix `str` subclass validation for enums by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1273](https://github.com/pydantic/pydantic-core/pull/1273) - Support `BigInt`s in `Literal`s and `Enum`s by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1297](https://github.com/pydantic/pydantic-core/pull/1297) - Fix: uuid - allow `str` subclass as input by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1296](https://github.com/pydantic/pydantic-core/pull/1296) ## v2.7.1 (2024-04-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.7.1) ### What's Changed #### Packaging - Bump `pydantic-core` to `v2.18.2` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9307](https://github.com/pydantic/pydantic/pull/9307) #### New Features - Ftp and Websocket connection strings support by [@CherrySuryp](https://github.com/CherrySuryp) in [#9205](https://github.com/pydantic/pydantic/pull/9205) #### Changes - Use field description for RootModel schema description when there is `...` by [@LouisGobert](https://github.com/LouisGobert) in [#9214](https://github.com/pydantic/pydantic/pull/9214) #### Fixes - Fix `validation_alias` behavior with `model_construct` for `AliasChoices` and `AliasPath` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9223](https://github.com/pydantic/pydantic/pull/9223) - Revert `typing.Literal` and import it outside the TYPE\_CHECKING block by [@frost-nzcr4](https://github.com/frost-nzcr4) in [#9232](https://github.com/pydantic/pydantic/pull/9232) - Fix `Secret` serialization schema, applicable for unions by [@sydney-runkle](https://github.com/sydney-runkle) in [#9240](https://github.com/pydantic/pydantic/pull/9240) - Fix `strict` application to `function-after` with `use_enum_values` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9279](https://github.com/pydantic/pydantic/pull/9279) - Address case where `model_construct` on a class which defines `model_post_init` fails with `AttributeError` by [@babygrimes](https://github.com/babygrimes) in [#9168](https://github.com/pydantic/pydantic/pull/9168) - Fix `model_json_schema` with config types by [@NeevCohen](https://github.com/NeevCohen) in [#9287](https://github.com/pydantic/pydantic/pull/9287) - Support multiple zeros as an `int` by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1269](https://github.com/pydantic/pydantic-core/pull/1269) - Fix validation of `int`s with leading unary plus by [@cknv](https://github.com/cknv) in [pydantic/pydantic-core#1272](https://github.com/pydantic/pydantic-core/pull/1272) - Fix interaction between `extra != 'ignore'` and `from_attributes=True` by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1276](https://github.com/pydantic/pydantic-core/pull/1276) - Handle error from `Enum`'s `missing` function as `ValidationError` by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1274](https://github.com/pydantic/pydantic-core/pull/1754) - Fix memory leak with `Iterable` validation by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1271](https://github.com/pydantic/pydantic-core/pull/1751) ### New Contributors - [@zzstoatzz](https://github.com/zzstoatzz) made their first contribution in [#9219](https://github.com/pydantic/pydantic/pull/9219) - [@frost-nzcr4](https://github.com/frost-nzcr4) made their first contribution in [#9232](https://github.com/pydantic/pydantic/pull/9232) - [@CherrySuryp](https://github.com/CherrySuryp) made their first contribution in [#9205](https://github.com/pydantic/pydantic/pull/9205) - [@vagenas](https://github.com/vagenas) made their first contribution in [#9268](https://github.com/pydantic/pydantic/pull/9268) - [@ollz272](https://github.com/ollz272) made their first contribution in [#9262](https://github.com/pydantic/pydantic/pull/9262) - [@babygrimes](https://github.com/babygrimes) made their first contribution in [#9168](https://github.com/pydantic/pydantic/pull/9168) - [@swelborn](https://github.com/swelborn) made their first contribution in [#9296](https://github.com/pydantic/pydantic/pull/9296) - [@kf-novi](https://github.com/kf-novi) made their first contribution in [#9236](https://github.com/pydantic/pydantic/pull/9236) - [@lgeiger](https://github.com/lgeiger) made their first contribution in [#9288](https://github.com/pydantic/pydantic/pull/9288) ## v2.7.0 (2024-04-11) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.7.0) The code released in v2.7.0 is practically identical to that of v2.7.0b1. ### What's Changed #### Packaging - Reorganize `pyproject.toml` sections by [@Viicos](https://github.com/Viicos) in [#8899](https://github.com/pydantic/pydantic/pull/8899) - Bump `pydantic-core` to `v2.18.1` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9211](https://github.com/pydantic/pydantic/pull/9211) - Adopt `jiter` `v0.2.0` by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1250](https://github.com/pydantic/pydantic-core/pull/1250) #### New Features - Extract attribute docstrings from `FieldInfo.description` by [@Viicos](https://github.com/Viicos) in [#6563](https://github.com/pydantic/pydantic/pull/6563) - Add a `with_config` decorator to comply with typing spec by [@Viicos](https://github.com/Viicos) in [#8611](https://github.com/pydantic/pydantic/pull/8611) - Allow an optional separator splitting the value and unit of the result of `ByteSize.human_readable` by [@jks15satoshi](https://github.com/jks15satoshi) in [#8706](https://github.com/pydantic/pydantic/pull/8706) - Add generic `Secret` base type by [@conradogarciaberrotaran](https://github.com/conradogarciaberrotaran) in [#8519](https://github.com/pydantic/pydantic/pull/8519) - Make use of `Sphinx` inventories for cross references in docs by [@Viicos](https://github.com/Viicos) in [#8682](https://github.com/pydantic/pydantic/pull/8682) - Add environment variable to disable plugins by [@geospackle](https://github.com/geospackle) in [#8767](https://github.com/pydantic/pydantic/pull/8767) - Add support for `deprecated` fields by [@Viicos](https://github.com/Viicos) in [#8237](https://github.com/pydantic/pydantic/pull/8237) - Allow `field_serializer('*')` by [@ornariece](https://github.com/ornariece) in [#9001](https://github.com/pydantic/pydantic/pull/9001) - Handle a case when `model_config` is defined as a model property by [@alexeyt101](https://github.com/alexeyt101) in [#9004](https://github.com/pydantic/pydantic/pull/9004) - Update `create_model()` to support `typing.Annotated` as input by [@wannieman98](https://github.com/wannieman98) in [#8947](https://github.com/pydantic/pydantic/pull/8947) - Add `ClickhouseDsn` support by [@solidguy7](https://github.com/solidguy7) in [#9062](https://github.com/pydantic/pydantic/pull/9062) - Add support for `re.Pattern[str]` to `pattern` field by [@jag-k](https://github.com/jag-k) in [#9053](https://github.com/pydantic/pydantic/pull/9053) - Support for `serialize_as_any` runtime setting by [@sydney-runkle](https://github.com/sydney-runkle) in [#8830](https://github.com/pydantic/pydantic/pull/8830) - Add support for `typing.Self` by [@Youssefares](https://github.com/Youssefares) in [#9023](https://github.com/pydantic/pydantic/pull/9023) - Ability to pass `context` to serialization by [@ornariece](https://github.com/ornariece) in [#8965](https://github.com/pydantic/pydantic/pull/8965) - Add feedback widget to docs with flarelytics integration by [@sydney-runkle](https://github.com/sydney-runkle) in [#9129](https://github.com/pydantic/pydantic/pull/9129) - Support for parsing partial JSON strings in Python by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/jiter#66](https://github.com/pydantic/jiter/pull/66) **Finalized in v2.7.0, rather than v2.7.0b1:** - Add support for field level number to str coercion option by [@NeevCohen](https://github.com/NeevCohen) in [#9137](https://github.com/pydantic/pydantic/pull/9137) - Update `warnings` parameter for serialization utilities to allow raising a warning by [@Lance-Drane](https://github.com/Lance-Drane) in [#9166](https://github.com/pydantic/pydantic/pull/9166) #### Changes - Correct docs, logic for `model_construct` behavior with `extra` by [@sydney-runkle](https://github.com/sydney-runkle) in [#8807](https://github.com/pydantic/pydantic/pull/8807) - Improve error message for improper `RootModel` subclasses by [@sydney-runkle](https://github.com/sydney-runkle) in [#8857](https://github.com/pydantic/pydantic/pull/8857) - **Breaking Change:** Use `PEP570` syntax by [@Viicos](https://github.com/Viicos) in [#8940](https://github.com/pydantic/pydantic/pull/8940) - Add `enum` and `type` to the JSON schema for single item literals by [@dmontagu](https://github.com/dmontagu) in [#8944](https://github.com/pydantic/pydantic/pull/8944) - Deprecate `update_json_schema` internal function by [@sydney-runkle](https://github.com/sydney-runkle) in [#9125](https://github.com/pydantic/pydantic/pull/9125) - Serialize duration to hour minute second, instead of just seconds by [@kakilangit](https://github.com/kakilangit) in [pydantic/speedate#50](https://github.com/pydantic/speedate/pull/50) - Trimming str before parsing to int and float by [@hungtsetse](https://github.com/hungtsetse) in [pydantic/pydantic-core#1203](https://github.com/pydantic/pydantic-core/pull/1203) #### Performance - `enum` validator improvements by [@samuelcolvin](https://github.com/samuelcolvin) in [#9045](https://github.com/pydantic/pydantic/pull/9045) - Move `enum` validation and serialization to Rust by [@samuelcolvin](https://github.com/samuelcolvin) in [#9064](https://github.com/pydantic/pydantic/pull/9064) - Improve schema generation for nested dataclasses by [@sydney-runkle](https://github.com/sydney-runkle) in [#9114](https://github.com/pydantic/pydantic/pull/9114) - Fast path for ASCII python string creation in JSON by [@samuelcolvin](https://github.com/samuelcolvin) in in [pydantic/jiter#72](https://github.com/pydantic/jiter/pull/72) - SIMD integer and string JSON parsing on `aarch64`(**Note:** SIMD on x86 will be implemented in a future release) by [@samuelcolvin](https://github.com/samuelcolvin) in in [pydantic/jiter#65](https://github.com/pydantic/jiter/pull/65) - Support JSON `Cow` from `jiter` by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1231](https://github.com/pydantic/pydantic-core/pull/1231) - MAJOR performance improvement: update to PyO3 0.21 final by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1248](https://github.com/pydantic/pydantic-core/pull/1248) - cache Python strings by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1240](https://github.com/pydantic/pydantic-core/pull/1240) #### Fixes - Fix strict parsing for some `Sequence`s by [@sydney-runkle](https://github.com/sydney-runkle) in [#8614](https://github.com/pydantic/pydantic/pull/8614) - Add a check on the existence of `__qualname__` by [@anci3ntr0ck](https://github.com/anci3ntr0ck) in [#8642](https://github.com/pydantic/pydantic/pull/8642) - Handle `__pydantic_extra__` annotation being a string or inherited by [@alexmojaki](https://github.com/alexmojaki) in [#8659](https://github.com/pydantic/pydantic/pull/8659) - Fix json validation for `NameEmail` by [@Holi0317](https://github.com/Holi0317) in [#8650](https://github.com/pydantic/pydantic/pull/8650) - Fix type-safety of attribute access in `BaseModel` by [@bluenote10](https://github.com/bluenote10) in [#8651](https://github.com/pydantic/pydantic/pull/8651) - Fix bug with `mypy` plugin and `no_strict_optional = True` by [@dmontagu](https://github.com/dmontagu) in [#8666](https://github.com/pydantic/pydantic/pull/8666) - Fix `ByteSize` error `type` change by [@sydney-runkle](https://github.com/sydney-runkle) in [#8681](https://github.com/pydantic/pydantic/pull/8681) - Fix inheriting annotations in dataclasses by [@sydney-runkle](https://github.com/sydney-runkle) in [#8679](https://github.com/pydantic/pydantic/pull/8679) - Fix regression in core schema generation for indirect definition references by [@dmontagu](https://github.com/dmontagu) in [#8702](https://github.com/pydantic/pydantic/pull/8702) - Fix unsupported types bug with plain validator by [@sydney-runkle](https://github.com/sydney-runkle) in [#8710](https://github.com/pydantic/pydantic/pull/8710) - Reverting problematic fix from 2.6 release, fixing schema building bug by [@sydney-runkle](https://github.com/sydney-runkle) in [#8718](https://github.com/pydantic/pydantic/pull/8718) - fixes `__pydantic_config__` ignored for TypeDict by [@13sin](https://github.com/13sin) in [#8734](https://github.com/pydantic/pydantic/pull/8734) - Fix test failures with `pytest v8.0.0` due to `pytest.warns()` starting to work inside `pytest.raises()` by [@mgorny](https://github.com/mgorny) in [#8678](https://github.com/pydantic/pydantic/pull/8678) - Use `is_valid_field` from 1.x for `mypy` plugin by [@DanielNoord](https://github.com/DanielNoord) in [#8738](https://github.com/pydantic/pydantic/pull/8738) - Better-support `mypy` strict equality flag by [@dmontagu](https://github.com/dmontagu) in [#8799](https://github.com/pydantic/pydantic/pull/8799) - model\_json\_schema export with Annotated types misses 'required' parameters by [@LouisGobert](https://github.com/LouisGobert) in [#8793](https://github.com/pydantic/pydantic/pull/8793) - Fix default inclusion in `FieldInfo.__repr_args__` by [@sydney-runkle](https://github.com/sydney-runkle) in [#8801](https://github.com/pydantic/pydantic/pull/8801) - Fix resolution of forward refs in dataclass base classes that are not present in the subclass module namespace by [@matsjoyce-refeyn](https://github.com/matsjoyce-refeyn) in [#8751](https://github.com/pydantic/pydantic/pull/8751) - Fix `BaseModel` type annotations to be resolvable by `typing.get_type_hints` by [@devmonkey22](https://github.com/devmonkey22) in [#7680](https://github.com/pydantic/pydantic/pull/7680) - Fix: allow empty string aliases with `AliasGenerator` by [@sydney-runkle](https://github.com/sydney-runkle) in [#8810](https://github.com/pydantic/pydantic/pull/8810) - Fix test along with `date` -> `datetime` timezone assumption fix by [@sydney-runkle](https://github.com/sydney-runkle) in [#8823](https://github.com/pydantic/pydantic/pull/8823) - Fix deprecation warning with usage of `ast.Str` by [@Viicos](https://github.com/Viicos) in [#8837](https://github.com/pydantic/pydantic/pull/8837) - Add missing `deprecated` decorators by [@Viicos](https://github.com/Viicos) in [#8877](https://github.com/pydantic/pydantic/pull/8877) - Fix serialization of `NameEmail` if name includes an email address by [@NeevCohen](https://github.com/NeevCohen) in [#8860](https://github.com/pydantic/pydantic/pull/8860) - Add information about class in error message of schema generation by [@Czaki](https://github.com/Czaki) in [#8917](https://github.com/pydantic/pydantic/pull/8917) - Make `TypeAdapter`'s typing compatible with special forms by [@adriangb](https://github.com/adriangb) in [#8923](https://github.com/pydantic/pydantic/pull/8923) - Fix issue with config behavior being baked into the ref schema for `enum`s by [@dmontagu](https://github.com/dmontagu) in [#8920](https://github.com/pydantic/pydantic/pull/8920) - More helpful error re wrong `model_json_schema` usage by [@sydney-runkle](https://github.com/sydney-runkle) in [#8928](https://github.com/pydantic/pydantic/pull/8928) - Fix nested discriminated union schema gen, pt 2 by [@sydney-runkle](https://github.com/sydney-runkle) in [#8932](https://github.com/pydantic/pydantic/pull/8932) - Fix schema build for nested dataclasses / TypedDicts with discriminators by [@sydney-runkle](https://github.com/sydney-runkle) in [#8950](https://github.com/pydantic/pydantic/pull/8950) - Remove unnecessary logic for definitions schema gen with discriminated unions by [@sydney-runkle](https://github.com/sydney-runkle) in [#8951](https://github.com/pydantic/pydantic/pull/8951) - Fix handling of optionals in `mypy` plugin by [@dmontagu](https://github.com/dmontagu) in [#9008](https://github.com/pydantic/pydantic/pull/9008) - Fix `PlainSerializer` usage with std type constructor by [@sydney-runkle](https://github.com/sydney-runkle) in [#9031](https://github.com/pydantic/pydantic/pull/9031) - Remove unnecessary warning for config in plugin by [@dmontagu](https://github.com/dmontagu) in [#9039](https://github.com/pydantic/pydantic/pull/9039) - Fix default value serializing by [@NeevCohen](https://github.com/NeevCohen) in [#9066](https://github.com/pydantic/pydantic/pull/9066) - Fix extra fields check in `Model.__getattr__()` by [@NeevCohen](https://github.com/NeevCohen) in [#9082](https://github.com/pydantic/pydantic/pull/9082) - Fix `ClassVar` forward ref inherited from parent class by [@alexmojaki](https://github.com/alexmojaki) in [#9097](https://github.com/pydantic/pydantic/pull/9097) - fix sequence like validator with strict `True` by [@andresliszt](https://github.com/andresliszt) in [#8977](https://github.com/pydantic/pydantic/pull/8977) - Improve warning message when a field name shadows a field in a parent model by [@chan-vince](https://github.com/chan-vince) in [#9105](https://github.com/pydantic/pydantic/pull/9105) - Do not warn about shadowed fields if they are not redefined in a child class by [@chan-vince](https://github.com/chan-vince) in [#9111](https://github.com/pydantic/pydantic/pull/9111) - Fix discriminated union bug with unsubstituted type var by [@sydney-runkle](https://github.com/sydney-runkle) in [#9124](https://github.com/pydantic/pydantic/pull/9124) - Support serialization of `deque` when passed to `Sequence[blah blah blah]` by [@sydney-runkle](https://github.com/sydney-runkle) in [#9128](https://github.com/pydantic/pydantic/pull/9128) - Init private attributes from super-types in `model_post_init` by [@Viicos](https://github.com/Viicos) in [#9134](https://github.com/pydantic/pydantic/pull/9134) - fix `model_construct` with `validation_alias` by [@ornariece](https://github.com/ornariece) in [#9144](https://github.com/pydantic/pydantic/pull/9144) - Ensure json-schema generator handles `Literal` `null` types by [@bruno-f-cruz](https://github.com/bruno-f-cruz) in [#9135](https://github.com/pydantic/pydantic/pull/9135) - **Fixed in v2.7.0**: Fix allow extra generic by [@dmontagu](https://github.com/dmontagu) in [#9193](https://github.com/pydantic/pydantic/pull/9193) ### New Contributors - [@hungtsetse](https://github.com/hungtsetse) made their first contribution in [#8546](https://github.com/pydantic/pydantic/pull/8546) - [@StrawHatDrag0n](https://github.com/StrawHatDrag0n) made their first contribution in [#8583](https://github.com/pydantic/pydantic/pull/8583) - [@anci3ntr0ck](https://github.com/anci3ntr0ck) made their first contribution in [#8642](https://github.com/pydantic/pydantic/pull/8642) - [@Holi0317](https://github.com/Holi0317) made their first contribution in [#8650](https://github.com/pydantic/pydantic/pull/8650) - [@bluenote10](https://github.com/bluenote10) made their first contribution in [#8651](https://github.com/pydantic/pydantic/pull/8651) - [@ADSteele916](https://github.com/ADSteele916) made their first contribution in [#8703](https://github.com/pydantic/pydantic/pull/8703) - [@musicinmybrain](https://github.com/musicinmybrain) made their first contribution in [#8731](https://github.com/pydantic/pydantic/pull/8731) - [@jks15satoshi](https://github.com/jks15satoshi) made their first contribution in [#8706](https://github.com/pydantic/pydantic/pull/8706) - [@13sin](https://github.com/13sin) made their first contribution in [#8734](https://github.com/pydantic/pydantic/pull/8734) - [@DanielNoord](https://github.com/DanielNoord) made their first contribution in [#8738](https://github.com/pydantic/pydantic/pull/8738) - [@conradogarciaberrotaran](https://github.com/conradogarciaberrotaran) made their first contribution in [#8519](https://github.com/pydantic/pydantic/pull/8519) - [@chris-griffin](https://github.com/chris-griffin) made their first contribution in [#8775](https://github.com/pydantic/pydantic/pull/8775) - [@LouisGobert](https://github.com/LouisGobert) made their first contribution in [#8793](https://github.com/pydantic/pydantic/pull/8793) - [@matsjoyce-refeyn](https://github.com/matsjoyce-refeyn) made their first contribution in [#8751](https://github.com/pydantic/pydantic/pull/8751) - [@devmonkey22](https://github.com/devmonkey22) made their first contribution in [#7680](https://github.com/pydantic/pydantic/pull/7680) - [@adamency](https://github.com/adamency) made their first contribution in [#8847](https://github.com/pydantic/pydantic/pull/8847) - [@MamfTheKramf](https://github.com/MamfTheKramf) made their first contribution in [#8851](https://github.com/pydantic/pydantic/pull/8851) - [@ornariece](https://github.com/ornariece) made their first contribution in [#9001](https://github.com/pydantic/pydantic/pull/9001) - [@alexeyt101](https://github.com/alexeyt101) made their first contribution in [#9004](https://github.com/pydantic/pydantic/pull/9004) - [@wannieman98](https://github.com/wannieman98) made their first contribution in [#8947](https://github.com/pydantic/pydantic/pull/8947) - [@solidguy7](https://github.com/solidguy7) made their first contribution in [#9062](https://github.com/pydantic/pydantic/pull/9062) - [@kloczek](https://github.com/kloczek) made their first contribution in [#9047](https://github.com/pydantic/pydantic/pull/9047) - [@jag-k](https://github.com/jag-k) made their first contribution in [#9053](https://github.com/pydantic/pydantic/pull/9053) - [@priya-gitTest](https://github.com/priya-gitTest) made their first contribution in [#9088](https://github.com/pydantic/pydantic/pull/9088) - [@Youssefares](https://github.com/Youssefares) made their first contribution in [#9023](https://github.com/pydantic/pydantic/pull/9023) - [@chan-vince](https://github.com/chan-vince) made their first contribution in [#9105](https://github.com/pydantic/pydantic/pull/9105) - [@bruno-f-cruz](https://github.com/bruno-f-cruz) made their first contribution in [#9135](https://github.com/pydantic/pydantic/pull/9135) - [@Lance-Drane](https://github.com/Lance-Drane) made their first contribution in [#9166](https://github.com/pydantic/pydantic/pull/9166) ## v2.7.0b1 (2024-04-03) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.7.0b1) for details. ## v2.6.4 (2024-03-12) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.4) ### What's Changed #### Fixes - Fix usage of `AliasGenerator` with `computed_field` decorator by [@sydney-runkle](https://github.com/sydney-runkle) in [#8806](https://github.com/pydantic/pydantic/pull/8806) - Fix nested discriminated union schema gen, pt 2 by [@sydney-runkle](https://github.com/sydney-runkle) in [#8932](https://github.com/pydantic/pydantic/pull/8932) - Fix bug with no\_strict\_optional=True caused by API deferral by [@dmontagu](https://github.com/dmontagu) in [#8826](https://github.com/pydantic/pydantic/pull/8826) ## v2.6.3 (2024-02-27) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.3) ### What's Changed #### Packaging - Update `pydantic-settings` version in the docs by [@hramezani](https://github.com/hramezani) in [#8906](https://github.com/pydantic/pydantic/pull/8906) #### Fixes - Fix discriminated union schema gen bug by [@sydney-runkle](https://github.com/sydney-runkle) in [#8904](https://github.com/pydantic/pydantic/pull/8904) ## v2.6.2 (2024-02-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.2) ### What's Changed #### Packaging - Upgrade to `pydantic-core` 2.16.3 by [@sydney-runkle](https://github.com/sydney-runkle) in [#8879](https://github.com/pydantic/pydantic/pull/8879) #### Fixes - 'YYYY-MM-DD' date string coerced to datetime shouldn't infer timezone by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1193](https://github.com/pydantic/pydantic-core/pull/1193) ## v2.6.1 (2024-02-05) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.1) ### What's Changed #### Packaging - Upgrade to `pydantic-core` 2.16.2 by [@sydney-runkle](https://github.com/sydney-runkle) in [#8717](https://github.com/pydantic/pydantic/pull/8717) #### Fixes - Fix bug with `mypy` plugin and `no_strict_optional = True` by [@dmontagu](https://github.com/dmontagu) in [#8666](https://github.com/pydantic/pydantic/pull/8666) - Fix `ByteSize` error `type` change by [@sydney-runkle](https://github.com/sydney-runkle) in [#8681](https://github.com/pydantic/pydantic/pull/8681) - Fix inheriting `Field` annotations in dataclasses by [@sydney-runkle](https://github.com/sydney-runkle) in [#8679](https://github.com/pydantic/pydantic/pull/8679) - Fix regression in core schema generation for indirect definition references by [@dmontagu](https://github.com/dmontagu) in [#8702](https://github.com/pydantic/pydantic/pull/8702) - Fix unsupported types bug with `PlainValidator` by [@sydney-runkle](https://github.com/sydney-runkle) in [#8710](https://github.com/pydantic/pydantic/pull/8710) - Reverting problematic fix from 2.6 release, fixing schema building bug by [@sydney-runkle](https://github.com/sydney-runkle) in [#8718](https://github.com/pydantic/pydantic/pull/8718) - Fix warning for tuple of wrong size in `Union` by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1174](https://github.com/pydantic/pydantic-core/pull/1174) - Fix `computed_field` JSON serializer `exclude_none` behavior by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1187](https://github.com/pydantic/pydantic-core/pull/1187) ## v2.6.0 (2024-01-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.0) The code released in v2.6.0 is practically identical to that of v2.6.0b1. ### What's Changed #### Packaging - Check for `email-validator` version >= 2.0 by [@commonism](https://github.com/commonism) in [#6033](https://github.com/pydantic/pydantic/pull/6033) - Upgrade \`ruff" target version to Python 3.8 by [@Elkiwa](https://github.com/Elkiwa) in [#8341](https://github.com/pydantic/pydantic/pull/8341) - Update to `pydantic-extra-types==2.4.1` by [@yezz123](https://github.com/yezz123) in [#8478](https://github.com/pydantic/pydantic/pull/8478) - Update to `pyright==1.1.345` by [@Viicos](https://github.com/Viicos) in [#8453](https://github.com/pydantic/pydantic/pull/8453) - Update pydantic-core from 2.14.6 to 2.16.1, significant changes from these updates are described below, full changelog [here](https://github.com/pydantic/pydantic-core/compare/v2.14.6...v2.16.1) #### New Features - Add `NatsDsn` by [@ekeew](https://github.com/ekeew) in [#6874](https://github.com/pydantic/pydantic/pull/6874) - Add `ConfigDict.ser_json_inf_nan` by [@davidhewitt](https://github.com/davidhewitt) in [#8159](https://github.com/pydantic/pydantic/pull/8159) - Add `types.OnErrorOmit` by [@adriangb](https://github.com/adriangb) in [#8222](https://github.com/pydantic/pydantic/pull/8222) - Support `AliasGenerator` usage by [@sydney-runkle](https://github.com/sydney-runkle) in [#8282](https://github.com/pydantic/pydantic/pull/8282) - Add Pydantic People Page to docs by [@sydney-runkle](https://github.com/sydney-runkle) in [#8345](https://github.com/pydantic/pydantic/pull/8345) - Support `yyyy-MM-DD` datetime parsing by [@sydney-runkle](https://github.com/sydney-runkle) in [#8404](https://github.com/pydantic/pydantic/pull/8404) - Added bits conversions to the `ByteSize` class #8415 by [@luca-matei](https://github.com/luca-matei) in [#8507](https://github.com/pydantic/pydantic/pull/8507) - Enable json schema creation with type `ByteSize` by [@geospackle](https://github.com/geospackle) in [#8537](https://github.com/pydantic/pydantic/pull/8537) - Add `eval_type_backport` to handle union operator and builtin generic subscripting in older Pythons by [@alexmojaki](https://github.com/alexmojaki) in [#8209](https://github.com/pydantic/pydantic/pull/8209) - Add support for `dataclass` fields `init` by [@dmontagu](https://github.com/dmontagu) in [#8552](https://github.com/pydantic/pydantic/pull/8552) - Implement pickling for `ValidationError` by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1119](https://github.com/pydantic/pydantic-core/pull/1119) - Add unified tuple validator that can handle "variadic" tuples via PEP-646 by [@dmontagu](https://github.com/dmontagu) in [pydantic/pydantic-core#865](https://github.com/pydantic/pydantic-core/pull/865) #### Changes - Drop Python3.7 support by [@hramezani](https://github.com/hramezani) in [#7188](https://github.com/pydantic/pydantic/pull/7188) - Drop Python 3.7, and PyPy 3.7 and 3.8 by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1129](https://github.com/pydantic/pydantic-core/pull/1129) - Use positional-only `self` in `BaseModel` constructor, so no field name can ever conflict with it by [@ariebovenberg](https://github.com/ariebovenberg) in [#8072](https://github.com/pydantic/pydantic/pull/8072) - Make `@validate_call` return a function instead of a custom descriptor - fixes binding issue with inheritance and adds `self/cls` argument to validation errors by [@alexmojaki](https://github.com/alexmojaki) in [#8268](https://github.com/pydantic/pydantic/pull/8268) - Exclude `BaseModel` docstring from JSON schema description by [@sydney-runkle](https://github.com/sydney-runkle) in [#8352](https://github.com/pydantic/pydantic/pull/8352) - Introducing `classproperty` decorator for `model_computed_fields` by [@Jocelyn-Gas](https://github.com/Jocelyn-Gas) in [#8437](https://github.com/pydantic/pydantic/pull/8437) - Explicitly raise an error if field names clashes with types by [@Viicos](https://github.com/Viicos) in [#8243](https://github.com/pydantic/pydantic/pull/8243) - Use stricter serializer for unions of simple types by [@alexdrydew](https://github.com/alexdrydew) [pydantic/pydantic-core#1132](https://github.com/pydantic/pydantic-core/pull/1132) #### Performance - Add Codspeed profiling Actions workflow by [@lambertsbennett](https://github.com/lambertsbennett) in [#8054](https://github.com/pydantic/pydantic/pull/8054) - Improve `int` extraction by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1155](https://github.com/pydantic/pydantic-core/pull/1155) - Improve performance of recursion guard by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1156](https://github.com/pydantic/pydantic-core/pull/1156) - `dataclass` serialization speedups by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1162](https://github.com/pydantic/pydantic-core/pull/1162) - Avoid `HashMap` creation when looking up small JSON objects in `LazyIndexMaps` by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/jiter#55](https://github.com/pydantic/jiter/pull/55) - use hashbrown to speedup python string caching by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/jiter#51](https://github.com/pydantic/jiter/pull/51) - Replace `Peak` with more efficient `Peek` by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/jiter#48](https://github.com/pydantic/jiter/pull/48) #### Fixes - Move `getattr` warning in deprecated `BaseConfig` by [@tlambert03](https://github.com/tlambert03) in [#7183](https://github.com/pydantic/pydantic/pull/7183) - Only hash `model_fields`, not whole `__dict__` by [@alexmojaki](https://github.com/alexmojaki) in [#7786](https://github.com/pydantic/pydantic/pull/7786) - Fix mishandling of unions while freezing types in the `mypy` plugin by [@dmontagu](https://github.com/dmontagu) in [#7411](https://github.com/pydantic/pydantic/pull/7411) - Fix `mypy` error on untyped `ClassVar` by [@vincent-hachin-wmx](https://github.com/vincent-hachin-wmx) in [#8138](https://github.com/pydantic/pydantic/pull/8138) - Only compare pydantic fields in `BaseModel.__eq__` instead of whole `__dict__` by [@QuentinSoubeyranAqemia](https://github.com/QuentinSoubeyranAqemia) in [#7825](https://github.com/pydantic/pydantic/pull/7825) - Update `strict` docstring in `model_validate` method. by [@LukeTonin](https://github.com/LukeTonin) in [#8223](https://github.com/pydantic/pydantic/pull/8223) - Fix overload position of `computed_field` by [@Viicos](https://github.com/Viicos) in [#8227](https://github.com/pydantic/pydantic/pull/8227) - Fix custom type type casting used in multiple attributes by [@ianhfc](https://github.com/ianhfc) in [#8066](https://github.com/pydantic/pydantic/pull/8066) - Fix issue not allowing `validate_call` decorator to be dynamically assigned to a class method by [@jusexton](https://github.com/jusexton) in [#8249](https://github.com/pydantic/pydantic/pull/8249) - Fix issue `unittest.mock` deprecation warnings by [@ibleedicare](https://github.com/ibleedicare) in [#8262](https://github.com/pydantic/pydantic/pull/8262) - Added tests for the case `JsonValue` contains subclassed primitive values by [@jusexton](https://github.com/jusexton) in [#8286](https://github.com/pydantic/pydantic/pull/8286) - Fix `mypy` error on free before validator (classmethod) by [@sydney-runkle](https://github.com/sydney-runkle) in [#8285](https://github.com/pydantic/pydantic/pull/8285) - Fix `to_snake` conversion by [@jevins09](https://github.com/jevins09) in [#8316](https://github.com/pydantic/pydantic/pull/8316) - Fix type annotation of `ModelMetaclass.__prepare__` by [@slanzmich](https://github.com/slanzmich) in [#8305](https://github.com/pydantic/pydantic/pull/8305) - Disallow `config` specification when initializing a `TypeAdapter` when the annotated type has config already by [@sydney-runkle](https://github.com/sydney-runkle) in [#8365](https://github.com/pydantic/pydantic/pull/8365) - Fix a naming issue with JSON schema for generics parametrized by recursive type aliases by [@dmontagu](https://github.com/dmontagu) in [#8389](https://github.com/pydantic/pydantic/pull/8389) - Fix type annotation in pydantic people script by [@shenxiangzhuang](https://github.com/shenxiangzhuang) in [#8402](https://github.com/pydantic/pydantic/pull/8402) - Add support for field `alias` in `dataclass` signature by [@NeevCohen](https://github.com/NeevCohen) in [#8387](https://github.com/pydantic/pydantic/pull/8387) - Fix bug with schema generation with `Field(...)` in a forward ref by [@dmontagu](https://github.com/dmontagu) in [#8494](https://github.com/pydantic/pydantic/pull/8494) - Fix ordering of keys in `__dict__` with `model_construct` call by [@sydney-runkle](https://github.com/sydney-runkle) in [#8500](https://github.com/pydantic/pydantic/pull/8500) - Fix module `path_type` creation when globals does not contain `__name__` by [@hramezani](https://github.com/hramezani) in [#8470](https://github.com/pydantic/pydantic/pull/8470) - Fix for namespace issue with dataclasses with `from __future__ import annotations` by [@sydney-runkle](https://github.com/sydney-runkle) in [#8513](https://github.com/pydantic/pydantic/pull/8513) - Fix: make function validator types positional-only by [@pmmmwh](https://github.com/pmmmwh) in [#8479](https://github.com/pydantic/pydantic/pull/8479) - Fix usage of `@deprecated` by [@Viicos](https://github.com/Viicos) in [#8294](https://github.com/pydantic/pydantic/pull/8294) - Add more support for private attributes in `model_construct` call by [@sydney-runkle](https://github.com/sydney-runkle) in [#8525](https://github.com/pydantic/pydantic/pull/8525) - Use a stack for the types namespace by [@dmontagu](https://github.com/dmontagu) in [#8378](https://github.com/pydantic/pydantic/pull/8378) - Fix schema-building bug with `TypeAliasType` for types with refs by [@dmontagu](https://github.com/dmontagu) in [#8526](https://github.com/pydantic/pydantic/pull/8526) - Support `pydantic.Field(repr=False)` in dataclasses by [@tigeryy2](https://github.com/tigeryy2) in [#8511](https://github.com/pydantic/pydantic/pull/8511) - Override `dataclass_transform` behavior for `RootModel` by [@Viicos](https://github.com/Viicos) in [#8163](https://github.com/pydantic/pydantic/pull/8163) - Refactor signature generation for simplicity by [@sydney-runkle](https://github.com/sydney-runkle) in [#8572](https://github.com/pydantic/pydantic/pull/8572) - Fix ordering bug of PlainValidator annotation by [@Anvil](https://github.com/Anvil) in [#8567](https://github.com/pydantic/pydantic/pull/8567) - Fix `exclude_none` for json serialization of `computed_field`s by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1098](https://github.com/pydantic/pydantic-core/pull/1098) - Support yyyy-MM-DD string for datetimes by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1124](https://github.com/pydantic/pydantic-core/pull/1124) - Tweak ordering of definitions in generated schemas by [@StrawHatDrag0n](https://github.com/StrawHatDrag0n) in [#8583](https://github.com/pydantic/pydantic/pull/8583) ### New Contributors #### `pydantic` - [@ekeew](https://github.com/ekeew) made their first contribution in [#6874](https://github.com/pydantic/pydantic/pull/6874) - [@lambertsbennett](https://github.com/lambertsbennett) made their first contribution in [#8054](https://github.com/pydantic/pydantic/pull/8054) - [@vincent-hachin-wmx](https://github.com/vincent-hachin-wmx) made their first contribution in [#8138](https://github.com/pydantic/pydantic/pull/8138) - [@QuentinSoubeyranAqemia](https://github.com/QuentinSoubeyranAqemia) made their first contribution in [#7825](https://github.com/pydantic/pydantic/pull/7825) - [@ariebovenberg](https://github.com/ariebovenberg) made their first contribution in [#8072](https://github.com/pydantic/pydantic/pull/8072) - [@LukeTonin](https://github.com/LukeTonin) made their first contribution in [#8223](https://github.com/pydantic/pydantic/pull/8223) - [@denisart](https://github.com/denisart) made their first contribution in [#8231](https://github.com/pydantic/pydantic/pull/8231) - [@ianhfc](https://github.com/ianhfc) made their first contribution in [#8066](https://github.com/pydantic/pydantic/pull/8066) - [@eonu](https://github.com/eonu) made their first contribution in [#8255](https://github.com/pydantic/pydantic/pull/8255) - [@amandahla](https://github.com/amandahla) made their first contribution in [#8263](https://github.com/pydantic/pydantic/pull/8263) - [@ibleedicare](https://github.com/ibleedicare) made their first contribution in [#8262](https://github.com/pydantic/pydantic/pull/8262) - [@jevins09](https://github.com/jevins09) made their first contribution in [#8316](https://github.com/pydantic/pydantic/pull/8316) - [@cuu508](https://github.com/cuu508) made their first contribution in [#8322](https://github.com/pydantic/pydantic/pull/8322) - [@slanzmich](https://github.com/slanzmich) made their first contribution in [#8305](https://github.com/pydantic/pydantic/pull/8305) - [@jensenbox](https://github.com/jensenbox) made their first contribution in [#8331](https://github.com/pydantic/pydantic/pull/8331) - [@szepeviktor](https://github.com/szepeviktor) made their first contribution in [#8356](https://github.com/pydantic/pydantic/pull/8356) - [@Elkiwa](https://github.com/Elkiwa) made their first contribution in [#8341](https://github.com/pydantic/pydantic/pull/8341) - [@parhamfh](https://github.com/parhamfh) made their first contribution in [#8395](https://github.com/pydantic/pydantic/pull/8395) - [@shenxiangzhuang](https://github.com/shenxiangzhuang) made their first contribution in [#8402](https://github.com/pydantic/pydantic/pull/8402) - [@NeevCohen](https://github.com/NeevCohen) made their first contribution in [#8387](https://github.com/pydantic/pydantic/pull/8387) - [@zby](https://github.com/zby) made their first contribution in [#8497](https://github.com/pydantic/pydantic/pull/8497) - [@patelnets](https://github.com/patelnets) made their first contribution in [#8491](https://github.com/pydantic/pydantic/pull/8491) - [@edwardwli](https://github.com/edwardwli) made their first contribution in [#8503](https://github.com/pydantic/pydantic/pull/8503) - [@luca-matei](https://github.com/luca-matei) made their first contribution in [#8507](https://github.com/pydantic/pydantic/pull/8507) - [@Jocelyn-Gas](https://github.com/Jocelyn-Gas) made their first contribution in [#8437](https://github.com/pydantic/pydantic/pull/8437) - [@bL34cHig0](https://github.com/bL34cHig0) made their first contribution in [#8501](https://github.com/pydantic/pydantic/pull/8501) - [@tigeryy2](https://github.com/tigeryy2) made their first contribution in [#8511](https://github.com/pydantic/pydantic/pull/8511) - [@geospackle](https://github.com/geospackle) made their first contribution in [#8537](https://github.com/pydantic/pydantic/pull/8537) - [@Anvil](https://github.com/Anvil) made their first contribution in [#8567](https://github.com/pydantic/pydantic/pull/8567) - [@hungtsetse](https://github.com/hungtsetse) made their first contribution in [#8546](https://github.com/pydantic/pydantic/pull/8546) - [@StrawHatDrag0n](https://github.com/StrawHatDrag0n) made their first contribution in [#8583](https://github.com/pydantic/pydantic/pull/8583) #### `pydantic-core` - [@mariuswinger](https://github.com/mariuswinger) made their first contribution in [pydantic/pydantic-core#1087](https://github.com/pydantic/pydantic-core/pull/1087) - [@adamchainz](https://github.com/adamchainz) made their first contribution in [pydantic/pydantic-core#1090](https://github.com/pydantic/pydantic-core/pull/1090) - [@akx](https://github.com/akx) made their first contribution in [pydantic/pydantic-core#1123](https://github.com/pydantic/pydantic-core/pull/1123) ## v2.6.0b1 (2024-01-19) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.6.0b1) for details. ## v2.5.3 (2023-12-22) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.5.3) ### What's Changed #### Packaging - uprev `pydantic-core` to 2.14.6 #### Fixes - Fix memory leak with recursive definitions creating reference cycles by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1125](https://github.com/pydantic/pydantic-core/pull/1125) ## v2.5.2 (2023-11-22) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.5.2) ### What's Changed #### Packaging - uprev `pydantic-core` to 2.14.5 #### New Features - Add `ConfigDict.ser_json_inf_nan` by [@davidhewitt](https://github.com/davidhewitt) in [#8159](https://github.com/pydantic/pydantic/pull/8159) #### Fixes - Fix validation of `Literal` from JSON keys when used as `dict` key by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1075](https://github.com/pydantic/pydantic-core/pull/1075) - Fix bug re `custom_init` on members of `Union` by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1076](https://github.com/pydantic/pydantic-core/pull/1076) - Fix `JsonValue` `bool` serialization by [@sydney-runkle](https://github.com/sydney-runkle) in [#8190](https://github.com/pydantic/pydantic/pull/8159) - Fix handling of unhashable inputs with `Literal` in `Union`s by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1089](https://github.com/pydantic/pydantic-core/pull/1089) ## v2.5.1 (2023-11-15) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.5.1) ### What's Changed #### Packaging - uprev pydantic-core to 2.14.3 by [@samuelcolvin](https://github.com/samuelcolvin) in [#8120](https://github.com/pydantic/pydantic/pull/8120) #### Fixes - Fix package description limit by [@dmontagu](https://github.com/dmontagu) in [#8097](https://github.com/pydantic/pydantic/pull/8097) - Fix `ValidateCallWrapper` error when creating a model which has a [@validate\_call](https://github.com/validate_call) wrapped field annotation by [@sydney-runkle](https://github.com/sydney-runkle) in [#8110](https://github.com/pydantic/pydantic/pull/8110) ## v2.5.0 (2023-11-13) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.5.0) The code released in v2.5.0 is functionally identical to that of v2.5.0b1. ### What's Changed #### Packaging - Update pydantic-core from 2.10.1 to 2.14.1, significant changes from these updates are described below, full changelog [here](https://github.com/pydantic/pydantic-core/compare/v2.10.1...v2.14.1) - Update to `pyright==1.1.335` by [@Viicos](https://github.com/Viicos) in [#8075](https://github.com/pydantic/pydantic/pull/8075) #### New Features - Allow plugins to catch non `ValidationError` errors by [@adriangb](https://github.com/adriangb) in [#7806](https://github.com/pydantic/pydantic/pull/7806) - Support `__doc__` argument in `create_model()` by [@chris-spann](https://github.com/chris-spann) in [#7863](https://github.com/pydantic/pydantic/pull/7863) - Expose `regex_engine` flag - meaning you can use with the Rust or Python regex libraries in constraints by [@utkini](https://github.com/utkini) in [#7768](https://github.com/pydantic/pydantic/pull/7768) - Save return type generated from type annotation in `ComputedFieldInfo` by [@alexmojaki](https://github.com/alexmojaki) in [#7889](https://github.com/pydantic/pydantic/pull/7889) - Adopting `ruff` formatter by [@Luca-Blight](https://github.com/Luca-Blight) in [#7930](https://github.com/pydantic/pydantic/pull/7930) - Added `validation_error_cause` to config by [@zakstucke](https://github.com/zakstucke) in [#7626](https://github.com/pydantic/pydantic/pull/7626) - Make path of the item to validate available in plugin by [@hramezani](https://github.com/hramezani) in [#7861](https://github.com/pydantic/pydantic/pull/7861) - Add `CallableDiscriminator` and `Tag` by [@dmontagu](https://github.com/dmontagu) in [#7983](https://github.com/pydantic/pydantic/pull/7983) - `CallableDiscriminator` renamed to `Discriminator` by [@dmontagu](https://github.com/dmontagu) in [#8047](https://github.com/pydantic/pydantic/pull/8047) - Make union case tags affect union error messages by [@dmontagu](https://github.com/dmontagu) in [#8001](https://github.com/pydantic/pydantic/pull/8001) - Add `examples` and `json_schema_extra` to `@computed_field` by [@alexmojaki](https://github.com/alexmojaki) in [#8013](https://github.com/pydantic/pydantic/pull/8013) - Add `JsonValue` type by [@dmontagu](https://github.com/dmontagu) in [#7998](https://github.com/pydantic/pydantic/pull/7998) - Allow `str` as argument to `Discriminator` by [@dmontagu](https://github.com/dmontagu) in [#8047](https://github.com/pydantic/pydantic/pull/8047) - Add `SchemaSerializer.__reduce__` method to enable pickle serialization by [@edoakes](https://github.com/edoakes) in [pydantic/pydantic-core#1006](https://github.com/pydantic/pydantic-core/pull/1006) #### Changes - **Significant Change:** replace `ultra_strict` with new smart union implementation, the way unions are validated has changed significantly to improve performance and correctness, we have worked hard to absolutely minimise the number of cases where behaviour has changed, see the PR for details - by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#867](https://github.com/pydantic/pydantic-core/pull/867) - Add support for instance method reassignment when `extra='allow'` by [@sydney-runkle](https://github.com/sydney-runkle) in [#7683](https://github.com/pydantic/pydantic/pull/7683) - Support JSON schema generation for `Enum` types with no cases by [@sydney-runkle](https://github.com/sydney-runkle) in [#7927](https://github.com/pydantic/pydantic/pull/7927) - Warn if a class inherits from `Generic` before `BaseModel` by [@alexmojaki](https://github.com/alexmojaki) in [#7891](https://github.com/pydantic/pydantic/pull/7891) #### Performance - New custom JSON parser, `jiter` by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#974](https://github.com/pydantic/pydantic-core/pull/974) - PGO build for MacOS M1 by [@samuelcolvin](https://github.com/samuelcolvin) in [pydantic/pydantic-core#1063](https://github.com/pydantic/pydantic-core/pull/1063) - Use `__getattr__` for all package imports, improve import time by [@samuelcolvin](https://github.com/samuelcolvin) in [#7947](https://github.com/pydantic/pydantic/pull/7947) #### Fixes - Fix `mypy` issue with subclasses of `RootModel` by [@sydney-runkle](https://github.com/sydney-runkle) in [#7677](https://github.com/pydantic/pydantic/pull/7677) - Properly rebuild the `FieldInfo` when a forward ref gets evaluated by [@dmontagu](https://github.com/dmontagu) in [#7698](https://github.com/pydantic/pydantic/pull/7698) - Fix failure to load `SecretStr` from JSON (regression in v2.4) by [@sydney-runkle](https://github.com/sydney-runkle) in [#7729](https://github.com/pydantic/pydantic/pull/7729) - Fix `defer_build` behavior with `TypeAdapter` by [@sydney-runkle](https://github.com/sydney-runkle) in [#7736](https://github.com/pydantic/pydantic/pull/7736) - Improve compatibility with legacy `mypy` versions by [@dmontagu](https://github.com/dmontagu) in [#7742](https://github.com/pydantic/pydantic/pull/7742) - Fix: update `TypeVar` handling when default is not set by [@pmmmwh](https://github.com/pmmmwh) in [#7719](https://github.com/pydantic/pydantic/pull/7719) - Support specification of `strict` on `Enum` type fields by [@sydney-runkle](https://github.com/sydney-runkle) in [#7761](https://github.com/pydantic/pydantic/pull/7761) - Wrap `weakref.ref` instead of subclassing to fix `cloudpickle` serialization by [@edoakes](https://github.com/edoakes) in [#7780](https://github.com/pydantic/pydantic/pull/7780) - Keep values of private attributes set within `model_post_init` in subclasses by [@alexmojaki](https://github.com/alexmojaki) in [#7775](https://github.com/pydantic/pydantic/pull/7775) - Add more specific type for non-callable `json_schema_extra` by [@alexmojaki](https://github.com/alexmojaki) in [#7803](https://github.com/pydantic/pydantic/pull/7803) - Raise an error when deleting frozen (model) fields by [@alexmojaki](https://github.com/alexmojaki) in [#7800](https://github.com/pydantic/pydantic/pull/7800) - Fix schema sorting bug with default values by [@sydney-runkle](https://github.com/sydney-runkle) in [#7817](https://github.com/pydantic/pydantic/pull/7817) - Use generated alias for aliases that are not specified otherwise by [@alexmojaki](https://github.com/alexmojaki) in [#7802](https://github.com/pydantic/pydantic/pull/7802) - Support `strict` specification for `UUID` types by [@sydney-runkle](https://github.com/sydney-runkle) in [#7865](https://github.com/pydantic/pydantic/pull/7865) - JSON schema: fix extra parameter handling by [@me-and](https://github.com/me-and) in [#7810](https://github.com/pydantic/pydantic/pull/7810) - Fix: support `pydantic.Field(kw_only=True)` with inherited dataclasses by [@PrettyWood](https://github.com/PrettyWood) in [#7827](https://github.com/pydantic/pydantic/pull/7827) - Support `validate_call` decorator for methods in classes with `__slots__` by [@sydney-runkle](https://github.com/sydney-runkle) in [#7883](https://github.com/pydantic/pydantic/pull/7883) - Fix pydantic dataclass problem with `dataclasses.field` default by [@hramezani](https://github.com/hramezani) in [#7898](https://github.com/pydantic/pydantic/pull/7898) - Fix schema generation for generics with union type bounds by [@sydney-runkle](https://github.com/sydney-runkle) in [#7899](https://github.com/pydantic/pydantic/pull/7899) - Fix version for `importlib_metadata` on python 3.7 by [@sydney-runkle](https://github.com/sydney-runkle) in [#7904](https://github.com/pydantic/pydantic/pull/7904) - Support `|` operator (Union) in PydanticRecursiveRef by [@alexmojaki](https://github.com/alexmojaki) in [#7892](https://github.com/pydantic/pydantic/pull/7892) - Fix `display_as_type` for `TypeAliasType` in python 3.12 by [@dmontagu](https://github.com/dmontagu) in [#7929](https://github.com/pydantic/pydantic/pull/7929) - Add support for `NotRequired` generics in `TypedDict` by [@sydney-runkle](https://github.com/sydney-runkle) in [#7932](https://github.com/pydantic/pydantic/pull/7932) - Make generic `TypeAliasType` specifications produce different schema definitions by [@alexdrydew](https://github.com/alexdrydew) in [#7893](https://github.com/pydantic/pydantic/pull/7893) - Added fix for signature of inherited dataclass by [@howsunjow](https://github.com/howsunjow) in [#7925](https://github.com/pydantic/pydantic/pull/7925) - Make the model name generation more robust in JSON schema by [@joakimnordling](https://github.com/joakimnordling) in [#7881](https://github.com/pydantic/pydantic/pull/7881) - Fix plurals in validation error messages (in tests) by [@Iipin](https://github.com/Iipin) in [#7972](https://github.com/pydantic/pydantic/pull/7972) - `PrivateAttr` is passed from `Annotated` default position by [@tabassco](https://github.com/tabassco) in [#8004](https://github.com/pydantic/pydantic/pull/8004) - Don't decode bytes (which may not be UTF8) when displaying SecretBytes by [@alexmojaki](https://github.com/alexmojaki) in [#8012](https://github.com/pydantic/pydantic/pull/8012) - Use `classmethod` instead of `classmethod[Any, Any, Any]` by [@Mr-Pepe](https://github.com/Mr-Pepe) in [#7979](https://github.com/pydantic/pydantic/pull/7979) - Clearer error on invalid Plugin by [@samuelcolvin](https://github.com/samuelcolvin) in [#8023](https://github.com/pydantic/pydantic/pull/8023) - Correct pydantic dataclasses import by [@samuelcolvin](https://github.com/samuelcolvin) in [#8027](https://github.com/pydantic/pydantic/pull/8027) - Fix misbehavior for models referencing redefined type aliases by [@dmontagu](https://github.com/dmontagu) in [#8050](https://github.com/pydantic/pydantic/pull/8050) - Fix `Optional` field with `validate_default` only performing one field validation by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1002](https://github.com/pydantic/pydantic-core/pull/1002) - Fix `definition-ref` bug with `Dict` keys by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1014](https://github.com/pydantic/pydantic-core/pull/1014) - Fix bug allowing validation of `bool` types with `coerce_numbers_to_str=True` by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1017](https://github.com/pydantic/pydantic-core/pull/1017) - Don't accept `NaN` in float and decimal constraints by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1037](https://github.com/pydantic/pydantic-core/pull/1037) - Add `lax_str` and `lax_int` support for enum values not inherited from str/int by [@michaelhly](https://github.com/michaelhly) in [pydantic/pydantic-core#1015](https://github.com/pydantic/pydantic-core/pull/1015) - Support subclasses in lists in `Union` of `List` types by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1039](https://github.com/pydantic/pydantic-core/pull/1039) - Allow validation against `max_digits` and `decimals` to pass if normalized or non-normalized input is valid by [@sydney-runkle](https://github.com/sydney-runkle) in [pydantic/pydantic-core#1049](https://github.com/pydantic/pydantic-core/pull/1049) - Fix: proper pluralization in `ValidationError` messages by [@Iipin](https://github.com/Iipin) in [pydantic/pydantic-core#1050](https://github.com/pydantic/pydantic-core/pull/1050) - Disallow the string `'-'` as `datetime` input by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/speedate#52](https://github.com/pydantic/speedate/pull/52) & [pydantic/pydantic-core#1060](https://github.com/pydantic/pydantic-core/pull/1060) - Fix: NaN and Inf float serialization by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1062](https://github.com/pydantic/pydantic-core/pull/1062) - Restore manylinux-compatible PGO builds by [@davidhewitt](https://github.com/davidhewitt) in [pydantic/pydantic-core#1068](https://github.com/pydantic/pydantic-core/pull/1068) ### New Contributors #### `pydantic` - [@schneebuzz](https://github.com/schneebuzz) made their first contribution in [#7699](https://github.com/pydantic/pydantic/pull/7699) - [@edoakes](https://github.com/edoakes) made their first contribution in [#7780](https://github.com/pydantic/pydantic/pull/7780) - [@alexmojaki](https://github.com/alexmojaki) made their first contribution in [#7775](https://github.com/pydantic/pydantic/pull/7775) - [@NickG123](https://github.com/NickG123) made their first contribution in [#7751](https://github.com/pydantic/pydantic/pull/7751) - [@gowthamgts](https://github.com/gowthamgts) made their first contribution in [#7830](https://github.com/pydantic/pydantic/pull/7830) - [@jamesbraza](https://github.com/jamesbraza) made their first contribution in [#7848](https://github.com/pydantic/pydantic/pull/7848) - [@laundmo](https://github.com/laundmo) made their first contribution in [#7850](https://github.com/pydantic/pydantic/pull/7850) - [@rahmatnazali](https://github.com/rahmatnazali) made their first contribution in [#7870](https://github.com/pydantic/pydantic/pull/7870) - [@waterfountain1996](https://github.com/waterfountain1996) made their first contribution in [#7878](https://github.com/pydantic/pydantic/pull/7878) - [@chris-spann](https://github.com/chris-spann) made their first contribution in [#7863](https://github.com/pydantic/pydantic/pull/7863) - [@me-and](https://github.com/me-and) made their first contribution in [#7810](https://github.com/pydantic/pydantic/pull/7810) - [@utkini](https://github.com/utkini) made their first contribution in [#7768](https://github.com/pydantic/pydantic/pull/7768) - [@bn-l](https://github.com/bn-l) made their first contribution in [#7744](https://github.com/pydantic/pydantic/pull/7744) - [@alexdrydew](https://github.com/alexdrydew) made their first contribution in [#7893](https://github.com/pydantic/pydantic/pull/7893) - [@Luca-Blight](https://github.com/Luca-Blight) made their first contribution in [#7930](https://github.com/pydantic/pydantic/pull/7930) - [@howsunjow](https://github.com/howsunjow) made their first contribution in [#7925](https://github.com/pydantic/pydantic/pull/7925) - [@joakimnordling](https://github.com/joakimnordling) made their first contribution in [#7881](https://github.com/pydantic/pydantic/pull/7881) - [@icfly2](https://github.com/icfly2) made their first contribution in [#7976](https://github.com/pydantic/pydantic/pull/7976) - [@Yummy-Yums](https://github.com/Yummy-Yums) made their first contribution in [#8003](https://github.com/pydantic/pydantic/pull/8003) - [@Iipin](https://github.com/Iipin) made their first contribution in [#7972](https://github.com/pydantic/pydantic/pull/7972) - [@tabassco](https://github.com/tabassco) made their first contribution in [#8004](https://github.com/pydantic/pydantic/pull/8004) - [@Mr-Pepe](https://github.com/Mr-Pepe) made their first contribution in [#7979](https://github.com/pydantic/pydantic/pull/7979) - [@0x00cl](https://github.com/0x00cl) made their first contribution in [#8010](https://github.com/pydantic/pydantic/pull/8010) - [@barraponto](https://github.com/barraponto) made their first contribution in [#8032](https://github.com/pydantic/pydantic/pull/8032) #### `pydantic-core` - [@sisp](https://github.com/sisp) made their first contribution in [pydantic/pydantic-core#995](https://github.com/pydantic/pydantic-core/pull/995) - [@michaelhly](https://github.com/michaelhly) made their first contribution in [pydantic/pydantic-core#1015](https://github.com/pydantic/pydantic-core/pull/1015) ## v2.5.0b1 (2023-11-09) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.5.0b1) for details. ## v2.4.2 (2023-09-27) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.4.2) ### What's Changed #### Fixes - Fix bug with JSON schema for sequence of discriminated union by [@dmontagu](https://github.com/dmontagu) in [#7647](https://github.com/pydantic/pydantic/pull/7647) - Fix schema references in discriminated unions by [@adriangb](https://github.com/adriangb) in [#7646](https://github.com/pydantic/pydantic/pull/7646) - Fix json schema generation for recursive models by [@adriangb](https://github.com/adriangb) in [#7653](https://github.com/pydantic/pydantic/pull/7653) - Fix `models_json_schema` for generic models by [@adriangb](https://github.com/adriangb) in [#7654](https://github.com/pydantic/pydantic/pull/7654) - Fix xfailed test for generic model signatures by [@adriangb](https://github.com/adriangb) in [#7658](https://github.com/pydantic/pydantic/pull/7658) ### New Contributors - [@austinorr](https://github.com/austinorr) made their first contribution in [#7657](https://github.com/pydantic/pydantic/pull/7657) - [@peterHoburg](https://github.com/peterHoburg) made their first contribution in [#7670](https://github.com/pydantic/pydantic/pull/7670) ## v2.4.1 (2023-09-26) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.4.1) ### What's Changed #### Packaging - Update pydantic-core to 2.10.1 by [@davidhewitt](https://github.com/davidhewitt) in [#7633](https://github.com/pydantic/pydantic/pull/7633) #### Fixes - Serialize unsubstituted type vars as `Any` by [@adriangb](https://github.com/adriangb) in [#7606](https://github.com/pydantic/pydantic/pull/7606) - Remove schema building caches by [@adriangb](https://github.com/adriangb) in [#7624](https://github.com/pydantic/pydantic/pull/7624) - Fix an issue where JSON schema extras weren't JSON encoded by [@dmontagu](https://github.com/dmontagu) in [#7625](https://github.com/pydantic/pydantic/pull/7625) ## v2.4.0 (2023-09-22) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.4.0) ### What's Changed #### Packaging - Update pydantic-core to 2.10.0 by [@samuelcolvin](https://github.com/samuelcolvin) in [#7542](https://github.com/pydantic/pydantic/pull/7542) #### New Features - Add `Base64Url` types by [@dmontagu](https://github.com/dmontagu) in [#7286](https://github.com/pydantic/pydantic/pull/7286) - Implement optional `number` to `str` coercion by [@lig](https://github.com/lig) in [#7508](https://github.com/pydantic/pydantic/pull/7508) - Allow access to `field_name` and `data` in all validators if there is data and a field name by [@samuelcolvin](https://github.com/samuelcolvin) in [#7542](https://github.com/pydantic/pydantic/pull/7542) - Add `BaseModel.model_validate_strings` and `TypeAdapter.validate_strings` by [@hramezani](https://github.com/hramezani) in [#7552](https://github.com/pydantic/pydantic/pull/7552) - Add Pydantic `plugins` experimental implementation by [@lig](https://github.com/lig) [@samuelcolvin](https://github.com/samuelcolvin) and [@Kludex](https://github.com/Kludex) in [#6820](https://github.com/pydantic/pydantic/pull/6820) #### Changes - Do not override `model_post_init` in subclass with private attrs by [@Viicos](https://github.com/Viicos) in [#7302](https://github.com/pydantic/pydantic/pull/7302) - Make fields with defaults not required in the serialization schema by default by [@dmontagu](https://github.com/dmontagu) in [#7275](https://github.com/pydantic/pydantic/pull/7275) - Mark `Extra` as deprecated by [@disrupted](https://github.com/disrupted) in [#7299](https://github.com/pydantic/pydantic/pull/7299) - Make `EncodedStr` a dataclass by [@Kludex](https://github.com/Kludex) in [#7396](https://github.com/pydantic/pydantic/pull/7396) - Move `annotated_handlers` to be public by [@samuelcolvin](https://github.com/samuelcolvin) in [#7569](https://github.com/pydantic/pydantic/pull/7569) #### Performance - Simplify flattening and inlining of `CoreSchema` by [@adriangb](https://github.com/adriangb) in [#7523](https://github.com/pydantic/pydantic/pull/7523) - Remove unused copies in `CoreSchema` walking by [@adriangb](https://github.com/adriangb) in [#7528](https://github.com/pydantic/pydantic/pull/7528) - Add caches for collecting definitions and invalid schemas from a CoreSchema by [@adriangb](https://github.com/adriangb) in [#7527](https://github.com/pydantic/pydantic/pull/7527) - Eagerly resolve discriminated unions and cache cases where we can't by [@adriangb](https://github.com/adriangb) in [#7529](https://github.com/pydantic/pydantic/pull/7529) - Replace `dict.get` and `dict.setdefault` with more verbose versions in `CoreSchema` building hot paths by [@adriangb](https://github.com/adriangb) in [#7536](https://github.com/pydantic/pydantic/pull/7536) - Cache invalid `CoreSchema` discovery by [@adriangb](https://github.com/adriangb) in [#7535](https://github.com/pydantic/pydantic/pull/7535) - Allow disabling `CoreSchema` validation for faster startup times by [@adriangb](https://github.com/adriangb) in [#7565](https://github.com/pydantic/pydantic/pull/7565) #### Fixes - Fix config detection for `TypedDict` from grandparent classes by [@dmontagu](https://github.com/dmontagu) in [#7272](https://github.com/pydantic/pydantic/pull/7272) - Fix hash function generation for frozen models with unusual MRO by [@dmontagu](https://github.com/dmontagu) in [#7274](https://github.com/pydantic/pydantic/pull/7274) - Make `strict` config overridable in field for Path by [@hramezani](https://github.com/hramezani) in [#7281](https://github.com/pydantic/pydantic/pull/7281) - Use `ser_json_` on default in `GenerateJsonSchema` by [@Kludex](https://github.com/Kludex) in [#7269](https://github.com/pydantic/pydantic/pull/7269) - Adding a check that alias is validated as an identifier for Python by [@andree0](https://github.com/andree0) in [#7319](https://github.com/pydantic/pydantic/pull/7319) - Raise an error when computed field overrides field by [@sydney-runkle](https://github.com/sydney-runkle) in [#7346](https://github.com/pydantic/pydantic/pull/7346) - Fix applying `SkipValidation` to referenced schemas by [@adriangb](https://github.com/adriangb) in [#7381](https://github.com/pydantic/pydantic/pull/7381) - Enforce behavior of private attributes having double leading underscore by [@lig](https://github.com/lig) in [#7265](https://github.com/pydantic/pydantic/pull/7265) - Standardize `__get_pydantic_core_schema__` signature by [@hramezani](https://github.com/hramezani) in [#7415](https://github.com/pydantic/pydantic/pull/7415) - Fix generic dataclass fields mutation bug (when using `TypeAdapter`) by [@sydney-runkle](https://github.com/sydney-runkle) in [#7435](https://github.com/pydantic/pydantic/pull/7435) - Fix `TypeError` on `model_validator` in `wrap` mode by [@pmmmwh](https://github.com/pmmmwh) in [#7496](https://github.com/pydantic/pydantic/pull/7496) - Improve enum error message by [@hramezani](https://github.com/hramezani) in [#7506](https://github.com/pydantic/pydantic/pull/7506) - Make `repr` work for instances that failed initialization when handling `ValidationError`s by [@dmontagu](https://github.com/dmontagu) in [#7439](https://github.com/pydantic/pydantic/pull/7439) - Fixed a regular expression denial of service issue by limiting whitespaces by [@prodigysml](https://github.com/prodigysml) in [#7360](https://github.com/pydantic/pydantic/pull/7360) - Fix handling of `UUID` values having `UUID.version=None` by [@lig](https://github.com/lig) in [#7566](https://github.com/pydantic/pydantic/pull/7566) - Fix `__iter__` returning private `cached_property` info by [@sydney-runkle](https://github.com/sydney-runkle) in [#7570](https://github.com/pydantic/pydantic/pull/7570) - Improvements to version info message by [@samuelcolvin](https://github.com/samuelcolvin) in [#7594](https://github.com/pydantic/pydantic/pull/7594) ### New Contributors - [@15498th](https://github.com/15498th) made their first contribution in [#7238](https://github.com/pydantic/pydantic/pull/7238) - [@GabrielCappelli](https://github.com/GabrielCappelli) made their first contribution in [#7213](https://github.com/pydantic/pydantic/pull/7213) - [@tobni](https://github.com/tobni) made their first contribution in [#7184](https://github.com/pydantic/pydantic/pull/7184) - [@redruin1](https://github.com/redruin1) made their first contribution in [#7282](https://github.com/pydantic/pydantic/pull/7282) - [@FacerAin](https://github.com/FacerAin) made their first contribution in [#7288](https://github.com/pydantic/pydantic/pull/7288) - [@acdha](https://github.com/acdha) made their first contribution in [#7297](https://github.com/pydantic/pydantic/pull/7297) - [@andree0](https://github.com/andree0) made their first contribution in [#7319](https://github.com/pydantic/pydantic/pull/7319) - [@gordonhart](https://github.com/gordonhart) made their first contribution in [#7375](https://github.com/pydantic/pydantic/pull/7375) - [@pmmmwh](https://github.com/pmmmwh) made their first contribution in [#7496](https://github.com/pydantic/pydantic/pull/7496) - [@disrupted](https://github.com/disrupted) made their first contribution in [#7299](https://github.com/pydantic/pydantic/pull/7299) - [@prodigysml](https://github.com/prodigysml) made their first contribution in [#7360](https://github.com/pydantic/pydantic/pull/7360) ## v2.3.0 (2023-08-23) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.3.0) - 🔥 Remove orphaned changes file from repo by [@lig](https://github.com/lig) in [#7168](https://github.com/pydantic/pydantic/pull/7168) - Add copy button on documentation by [@Kludex](https://github.com/Kludex) in [#7190](https://github.com/pydantic/pydantic/pull/7190) - Fix docs on JSON type by [@Kludex](https://github.com/Kludex) in [#7189](https://github.com/pydantic/pydantic/pull/7189) - Update mypy 1.5.0 to 1.5.1 in CI by [@hramezani](https://github.com/hramezani) in [#7191](https://github.com/pydantic/pydantic/pull/7191) - fix download links badge by [@samuelcolvin](https://github.com/samuelcolvin) in [#7200](https://github.com/pydantic/pydantic/pull/7200) - add 2.2.1 to changelog by [@samuelcolvin](https://github.com/samuelcolvin) in [#7212](https://github.com/pydantic/pydantic/pull/7212) - Make ModelWrapValidator protocols generic by [@dmontagu](https://github.com/dmontagu) in [#7154](https://github.com/pydantic/pydantic/pull/7154) - Correct `Field(..., exclude: bool)` docs by [@samuelcolvin](https://github.com/samuelcolvin) in [#7214](https://github.com/pydantic/pydantic/pull/7214) - Make shadowing attributes a warning instead of an error by [@adriangb](https://github.com/adriangb) in [#7193](https://github.com/pydantic/pydantic/pull/7193) - Document `Base64Str` and `Base64Bytes` by [@Kludex](https://github.com/Kludex) in [#7192](https://github.com/pydantic/pydantic/pull/7192) - Fix `config.defer_build` for serialization first cases by [@samuelcolvin](https://github.com/samuelcolvin) in [#7024](https://github.com/pydantic/pydantic/pull/7024) - clean Model docstrings in JSON Schema by [@samuelcolvin](https://github.com/samuelcolvin) in [#7210](https://github.com/pydantic/pydantic/pull/7210) - fix [#7228](https://github.com/pydantic/pydantic/pull/7228) (typo): docs in `validators.md` to correct `validate_default` kwarg by [@lmmx](https://github.com/lmmx) in [#7229](https://github.com/pydantic/pydantic/pull/7229) - ✅ Implement `tzinfo.fromutc` method for `TzInfo` in `pydantic-core` by [@lig](https://github.com/lig) in [#7019](https://github.com/pydantic/pydantic/pull/7019) - Support `__get_validators__` by [@hramezani](https://github.com/hramezani) in [#7197](https://github.com/pydantic/pydantic/pull/7197) ## v2.2.1 (2023-08-18) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.2.1) - Make `xfail`ing test for root model extra stop `xfail`ing by [@dmontagu](https://github.com/dmontagu) in [#6937](https://github.com/pydantic/pydantic/pull/6937) - Optimize recursion detection by stopping on the second visit for the same object by [@mciucu](https://github.com/mciucu) in [#7160](https://github.com/pydantic/pydantic/pull/7160) - fix link in docs by [@tlambert03](https://github.com/tlambert03) in [#7166](https://github.com/pydantic/pydantic/pull/7166) - Replace MiMalloc w/ default allocator by [@adriangb](https://github.com/adriangb) in [pydantic/pydantic-core#900](https://github.com/pydantic/pydantic-core/pull/900) - Bump pydantic-core to 2.6.1 and prepare 2.2.1 release by [@adriangb](https://github.com/adriangb) in [#7176](https://github.com/pydantic/pydantic/pull/7176) ## v2.2.0 (2023-08-17) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.2.0) - Split "pipx install" setup command into two commands on the documentation site by [@nomadmtb](https://github.com/nomadmtb) in [#6869](https://github.com/pydantic/pydantic/pull/6869) - Deprecate `Field.include` by [@hramezani](https://github.com/hramezani) in [#6852](https://github.com/pydantic/pydantic/pull/6852) - Fix typo in default factory error msg by [@hramezani](https://github.com/hramezani) in [#6880](https://github.com/pydantic/pydantic/pull/6880) - Simplify handling of typing.Annotated in GenerateSchema by [@dmontagu](https://github.com/dmontagu) in [#6887](https://github.com/pydantic/pydantic/pull/6887) - Re-enable fastapi tests in CI by [@dmontagu](https://github.com/dmontagu) in [#6883](https://github.com/pydantic/pydantic/pull/6883) - Make it harder to hit collisions with json schema defrefs by [@dmontagu](https://github.com/dmontagu) in [#6566](https://github.com/pydantic/pydantic/pull/6566) - Cleaner error for invalid input to `Path` fields by [@samuelcolvin](https://github.com/samuelcolvin) in [#6903](https://github.com/pydantic/pydantic/pull/6903) - 📝 support Coordinate Type by [@yezz123](https://github.com/yezz123) in [#6906](https://github.com/pydantic/pydantic/pull/6906) - Fix `ForwardRef` wrapper for py 3.10.0 (shim until bpo-45166) by [@randomir](https://github.com/randomir) in [#6919](https://github.com/pydantic/pydantic/pull/6919) - Fix misbehavior related to copying of RootModel by [@dmontagu](https://github.com/dmontagu) in [#6918](https://github.com/pydantic/pydantic/pull/6918) - Fix issue with recursion error caused by ParamSpec by [@dmontagu](https://github.com/dmontagu) in [#6923](https://github.com/pydantic/pydantic/pull/6923) - Add section about Constrained classes to the Migration Guide by [@Kludex](https://github.com/Kludex) in [#6924](https://github.com/pydantic/pydantic/pull/6924) - Use `main` branch for badge links by [@Viicos](https://github.com/Viicos) in [#6925](https://github.com/pydantic/pydantic/pull/6925) - Add test for v1/v2 Annotated discrepancy by [@carlbordum](https://github.com/carlbordum) in [#6926](https://github.com/pydantic/pydantic/pull/6926) - Make the v1 mypy plugin work with both v1 and v2 by [@dmontagu](https://github.com/dmontagu) in [#6921](https://github.com/pydantic/pydantic/pull/6921) - Fix issue where generic models couldn't be parametrized with BaseModel by [@dmontagu](https://github.com/dmontagu) in [#6933](https://github.com/pydantic/pydantic/pull/6933) - Remove xfail for discriminated union with alias by [@dmontagu](https://github.com/dmontagu) in [#6938](https://github.com/pydantic/pydantic/pull/6938) - add field\_serializer to computed\_field by [@andresliszt](https://github.com/andresliszt) in [#6965](https://github.com/pydantic/pydantic/pull/6965) - Use union\_schema with Type\[Union\[...\]\] by [@JeanArhancet](https://github.com/JeanArhancet) in [#6952](https://github.com/pydantic/pydantic/pull/6952) - Fix inherited typeddict attributes / config by [@adriangb](https://github.com/adriangb) in [#6981](https://github.com/pydantic/pydantic/pull/6981) - fix dataclass annotated before validator called twice by [@davidhewitt](https://github.com/davidhewitt) in [#6998](https://github.com/pydantic/pydantic/pull/6998) - Update test-fastapi deselected tests by [@hramezani](https://github.com/hramezani) in [#7014](https://github.com/pydantic/pydantic/pull/7014) - Fix validator doc format by [@hramezani](https://github.com/hramezani) in [#7015](https://github.com/pydantic/pydantic/pull/7015) - Fix typo in docstring of model\_json\_schema by [@AdamVinch-Federated](https://github.com/AdamVinch-Federated) in [#7032](https://github.com/pydantic/pydantic/pull/7032) - remove unused "type ignores" with pyright by [@samuelcolvin](https://github.com/samuelcolvin) in [#7026](https://github.com/pydantic/pydantic/pull/7026) - Add benchmark representing FastAPI startup time by [@adriangb](https://github.com/adriangb) in [#7030](https://github.com/pydantic/pydantic/pull/7030) - Fix json\_encoders for Enum subclasses by [@adriangb](https://github.com/adriangb) in [#7029](https://github.com/pydantic/pydantic/pull/7029) - Update docstring of `ser_json_bytes` regarding base64 encoding by [@Viicos](https://github.com/Viicos) in [#7052](https://github.com/pydantic/pydantic/pull/7052) - Allow `@validate_call` to work on async methods by [@adriangb](https://github.com/adriangb) in [#7046](https://github.com/pydantic/pydantic/pull/7046) - Fix: mypy error with `Settings` and `SettingsConfigDict` by [@JeanArhancet](https://github.com/JeanArhancet) in [#7002](https://github.com/pydantic/pydantic/pull/7002) - Fix some typos (repeated words and it's/its) by [@eumiro](https://github.com/eumiro) in [#7063](https://github.com/pydantic/pydantic/pull/7063) - Fix the typo in docstring by [@harunyasar](https://github.com/harunyasar) in [#7062](https://github.com/pydantic/pydantic/pull/7062) - Docs: Fix broken URL in the pydantic-settings package recommendation by [@swetjen](https://github.com/swetjen) in [#6995](https://github.com/pydantic/pydantic/pull/6995) - Handle constraints being applied to schemas that don't accept it by [@adriangb](https://github.com/adriangb) in [#6951](https://github.com/pydantic/pydantic/pull/6951) - Replace almost\_equal\_floats with math.isclose by [@eumiro](https://github.com/eumiro) in [#7082](https://github.com/pydantic/pydantic/pull/7082) - bump pydantic-core to 2.5.0 by [@davidhewitt](https://github.com/davidhewitt) in [#7077](https://github.com/pydantic/pydantic/pull/7077) - Add `short_version` and use it in links by [@hramezani](https://github.com/hramezani) in [#7115](https://github.com/pydantic/pydantic/pull/7115) - 📝 Add usage link to `RootModel` by [@Kludex](https://github.com/Kludex) in [#7113](https://github.com/pydantic/pydantic/pull/7113) - Revert "Fix default port for mongosrv DSNs (#6827)" by [@Kludex](https://github.com/Kludex) in [#7116](https://github.com/pydantic/pydantic/pull/7116) - Clarify validate\_default and \_Unset handling in usage docs and migration guide by [@benbenbang](https://github.com/benbenbang) in [#6950](https://github.com/pydantic/pydantic/pull/6950) - Tweak documentation of `Field.exclude` by [@Viicos](https://github.com/Viicos) in [#7086](https://github.com/pydantic/pydantic/pull/7086) - Do not require `validate_assignment` to use `Field.frozen` by [@Viicos](https://github.com/Viicos) in [#7103](https://github.com/pydantic/pydantic/pull/7103) - tweaks to `_core_utils` by [@samuelcolvin](https://github.com/samuelcolvin) in [#7040](https://github.com/pydantic/pydantic/pull/7040) - Make DefaultDict working with set by [@hramezani](https://github.com/hramezani) in [#7126](https://github.com/pydantic/pydantic/pull/7126) - Don't always require typing.Generic as a base for partially parametrized models by [@dmontagu](https://github.com/dmontagu) in [#7119](https://github.com/pydantic/pydantic/pull/7119) - Fix issue with JSON schema incorrectly using parent class core schema by [@dmontagu](https://github.com/dmontagu) in [#7020](https://github.com/pydantic/pydantic/pull/7020) - Fix xfailed test related to TypedDict and alias\_generator by [@dmontagu](https://github.com/dmontagu) in [#6940](https://github.com/pydantic/pydantic/pull/6940) - Improve error message for NameEmail by [@dmontagu](https://github.com/dmontagu) in [#6939](https://github.com/pydantic/pydantic/pull/6939) - Fix generic computed fields by [@dmontagu](https://github.com/dmontagu) in [#6988](https://github.com/pydantic/pydantic/pull/6988) - Reflect namedtuple default values during validation by [@dmontagu](https://github.com/dmontagu) in [#7144](https://github.com/pydantic/pydantic/pull/7144) - Update dependencies, fix pydantic-core usage, fix CI issues by [@dmontagu](https://github.com/dmontagu) in [#7150](https://github.com/pydantic/pydantic/pull/7150) - Add mypy 1.5.0 by [@hramezani](https://github.com/hramezani) in [#7118](https://github.com/pydantic/pydantic/pull/7118) - Handle non-json native enum values by [@adriangb](https://github.com/adriangb) in [#7056](https://github.com/pydantic/pydantic/pull/7056) - document `round_trip` in Json type documentation by [@jc-louis](https://github.com/jc-louis) in [#7137](https://github.com/pydantic/pydantic/pull/7137) - Relax signature checks to better support builtins and C extension functions as validators by [@adriangb](https://github.com/adriangb) in [#7101](https://github.com/pydantic/pydantic/pull/7101) - add union\_mode='left\_to\_right' by [@davidhewitt](https://github.com/davidhewitt) in [#7151](https://github.com/pydantic/pydantic/pull/7151) - Include an error message hint for inherited ordering by [@yvalencia91](https://github.com/yvalencia91) in [#7124](https://github.com/pydantic/pydantic/pull/7124) - Fix one docs link and resolve some warnings for two others by [@dmontagu](https://github.com/dmontagu) in [#7153](https://github.com/pydantic/pydantic/pull/7153) - Include Field extra keys name in warning by [@hramezani](https://github.com/hramezani) in [#7136](https://github.com/pydantic/pydantic/pull/7136) ## v2.1.1 (2023-07-25) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.1.1) - Skip FieldInfo merging when unnecessary by [@dmontagu](https://github.com/dmontagu) in [#6862](https://github.com/pydantic/pydantic/pull/6862) ## v2.1.0 (2023-07-25) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.1.0) - Add `StringConstraints` for use as Annotated metadata by [@adriangb](https://github.com/adriangb) in [#6605](https://github.com/pydantic/pydantic/pull/6605) - Try to fix intermittently failing CI by [@adriangb](https://github.com/adriangb) in [#6683](https://github.com/pydantic/pydantic/pull/6683) - Remove redundant example of optional vs default. by [@ehiggs-deliverect](https://github.com/ehiggs-deliverect) in [#6676](https://github.com/pydantic/pydantic/pull/6676) - Docs update by [@samuelcolvin](https://github.com/samuelcolvin) in [#6692](https://github.com/pydantic/pydantic/pull/6692) - Remove the Validate always section in validator docs by [@adriangb](https://github.com/adriangb) in [#6679](https://github.com/pydantic/pydantic/pull/6679) - Fix recursion error in json schema generation by [@adriangb](https://github.com/adriangb) in [#6720](https://github.com/pydantic/pydantic/pull/6720) - Fix incorrect subclass check for secretstr by [@AlexVndnblcke](https://github.com/AlexVndnblcke) in [#6730](https://github.com/pydantic/pydantic/pull/6730) - update pdm / pdm lockfile to 2.8.0 by [@davidhewitt](https://github.com/davidhewitt) in [#6714](https://github.com/pydantic/pydantic/pull/6714) - unpin pdm on more CI jobs by [@davidhewitt](https://github.com/davidhewitt) in [#6755](https://github.com/pydantic/pydantic/pull/6755) - improve source locations for auxiliary packages in docs by [@davidhewitt](https://github.com/davidhewitt) in [#6749](https://github.com/pydantic/pydantic/pull/6749) - Assume builtins don't accept an info argument by [@adriangb](https://github.com/adriangb) in [#6754](https://github.com/pydantic/pydantic/pull/6754) - Fix bug where calling `help(BaseModelSubclass)` raises errors by [@hramezani](https://github.com/hramezani) in [#6758](https://github.com/pydantic/pydantic/pull/6758) - Fix mypy plugin handling of `@model_validator(mode="after")` by [@ljodal](https://github.com/ljodal) in [#6753](https://github.com/pydantic/pydantic/pull/6753) - update pydantic-core to 2.3.1 by [@davidhewitt](https://github.com/davidhewitt) in [#6756](https://github.com/pydantic/pydantic/pull/6756) - Mypy plugin for settings by [@hramezani](https://github.com/hramezani) in [#6760](https://github.com/pydantic/pydantic/pull/6760) - Use `contentSchema` keyword for JSON schema by [@dmontagu](https://github.com/dmontagu) in [#6715](https://github.com/pydantic/pydantic/pull/6715) - fast-path checking finite decimals by [@davidhewitt](https://github.com/davidhewitt) in [#6769](https://github.com/pydantic/pydantic/pull/6769) - Docs update by [@samuelcolvin](https://github.com/samuelcolvin) in [#6771](https://github.com/pydantic/pydantic/pull/6771) - Improve json schema doc by [@hramezani](https://github.com/hramezani) in [#6772](https://github.com/pydantic/pydantic/pull/6772) - Update validator docs by [@adriangb](https://github.com/adriangb) in [#6695](https://github.com/pydantic/pydantic/pull/6695) - Fix typehint for wrap validator by [@dmontagu](https://github.com/dmontagu) in [#6788](https://github.com/pydantic/pydantic/pull/6788) - 🐛 Fix validation warning for unions of Literal and other type by [@lig](https://github.com/lig) in [#6628](https://github.com/pydantic/pydantic/pull/6628) - Update documentation for generics support in V2 by [@tpdorsey](https://github.com/tpdorsey) in [#6685](https://github.com/pydantic/pydantic/pull/6685) - add pydantic-core build info to `version_info()` by [@samuelcolvin](https://github.com/samuelcolvin) in [#6785](https://github.com/pydantic/pydantic/pull/6785) - Fix pydantic dataclasses that use slots with default values by [@dmontagu](https://github.com/dmontagu) in [#6796](https://github.com/pydantic/pydantic/pull/6796) - Fix inheritance of hash function for frozen models by [@dmontagu](https://github.com/dmontagu) in [#6789](https://github.com/pydantic/pydantic/pull/6789) - ✨ Add `SkipJsonSchema` annotation by [@Kludex](https://github.com/Kludex) in [#6653](https://github.com/pydantic/pydantic/pull/6653) - Error if an invalid field name is used with Field by [@dmontagu](https://github.com/dmontagu) in [#6797](https://github.com/pydantic/pydantic/pull/6797) - Add `GenericModel` to `MOVED_IN_V2` by [@adriangb](https://github.com/adriangb) in [#6776](https://github.com/pydantic/pydantic/pull/6776) - Remove unused code from `docs/usage/types/custom.md` by [@hramezani](https://github.com/hramezani) in [#6803](https://github.com/pydantic/pydantic/pull/6803) - Fix `float` -> `Decimal` coercion precision loss by [@adriangb](https://github.com/adriangb) in [#6810](https://github.com/pydantic/pydantic/pull/6810) - remove email validation from the north star benchmark by [@davidhewitt](https://github.com/davidhewitt) in [#6816](https://github.com/pydantic/pydantic/pull/6816) - Fix link to mypy by [@progsmile](https://github.com/progsmile) in [#6824](https://github.com/pydantic/pydantic/pull/6824) - Improve initialization hooks example by [@hramezani](https://github.com/hramezani) in [#6822](https://github.com/pydantic/pydantic/pull/6822) - Fix default port for mongosrv DSNs by [@dmontagu](https://github.com/dmontagu) in [#6827](https://github.com/pydantic/pydantic/pull/6827) - Improve API documentation, in particular more links between usage and API docs by [@samuelcolvin](https://github.com/samuelcolvin) in [#6780](https://github.com/pydantic/pydantic/pull/6780) - update pydantic-core to 2.4.0 by [@davidhewitt](https://github.com/davidhewitt) in [#6831](https://github.com/pydantic/pydantic/pull/6831) - Fix `annotated_types.MaxLen` validator for custom sequence types by [@ImogenBits](https://github.com/ImogenBits) in [#6809](https://github.com/pydantic/pydantic/pull/6809) - Update V1 by [@hramezani](https://github.com/hramezani) in [#6833](https://github.com/pydantic/pydantic/pull/6833) - Make it so callable JSON schema extra works by [@dmontagu](https://github.com/dmontagu) in [#6798](https://github.com/pydantic/pydantic/pull/6798) - Fix serialization issue with `InstanceOf` by [@dmontagu](https://github.com/dmontagu) in [#6829](https://github.com/pydantic/pydantic/pull/6829) - Add back support for `json_encoders` by [@adriangb](https://github.com/adriangb) in [#6811](https://github.com/pydantic/pydantic/pull/6811) - Update field annotations when building the schema by [@dmontagu](https://github.com/dmontagu) in [#6838](https://github.com/pydantic/pydantic/pull/6838) - Use `WeakValueDictionary` to fix generic memory leak by [@dmontagu](https://github.com/dmontagu) in [#6681](https://github.com/pydantic/pydantic/pull/6681) - Add `config.defer_build` to optionally make model building lazy by [@samuelcolvin](https://github.com/samuelcolvin) in [#6823](https://github.com/pydantic/pydantic/pull/6823) - delegate `UUID` serialization to pydantic-core by [@davidhewitt](https://github.com/davidhewitt) in [#6850](https://github.com/pydantic/pydantic/pull/6850) - Update `json_encoders` docs by [@adriangb](https://github.com/adriangb) in [#6848](https://github.com/pydantic/pydantic/pull/6848) - Fix error message for `staticmethod`/`classmethod` order with validate\_call by [@dmontagu](https://github.com/dmontagu) in [#6686](https://github.com/pydantic/pydantic/pull/6686) - Improve documentation for `Config` by [@samuelcolvin](https://github.com/samuelcolvin) in [#6847](https://github.com/pydantic/pydantic/pull/6847) - Update serialization doc to mention `Field.exclude` takes priority over call-time `include/exclude` by [@hramezani](https://github.com/hramezani) in [#6851](https://github.com/pydantic/pydantic/pull/6851) - Allow customizing core schema generation by making `GenerateSchema` public by [@adriangb](https://github.com/adriangb) in [#6737](https://github.com/pydantic/pydantic/pull/6737) ## v2.0.3 (2023-07-05) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.0.3) - Mention PyObject (v1) moving to ImportString (v2) in migration doc by [@slafs](https://github.com/slafs) in [#6456](https://github.com/pydantic/pydantic/pull/6456) - Fix release-tweet CI by [@Kludex](https://github.com/Kludex) in [#6461](https://github.com/pydantic/pydantic/pull/6461) - Revise the section on required / optional / nullable fields. by [@ybressler](https://github.com/ybressler) in [#6468](https://github.com/pydantic/pydantic/pull/6468) - Warn if a type hint is not in fact a type by [@adriangb](https://github.com/adriangb) in [#6479](https://github.com/pydantic/pydantic/pull/6479) - Replace TransformSchema with GetPydanticSchema by [@dmontagu](https://github.com/dmontagu) in [#6484](https://github.com/pydantic/pydantic/pull/6484) - Fix the un-hashability of various annotation types, for use in caching generic containers by [@dmontagu](https://github.com/dmontagu) in [#6480](https://github.com/pydantic/pydantic/pull/6480) - PYD-164: Rework custom types docs by [@adriangb](https://github.com/adriangb) in [#6490](https://github.com/pydantic/pydantic/pull/6490) - Fix ci by [@adriangb](https://github.com/adriangb) in [#6507](https://github.com/pydantic/pydantic/pull/6507) - Fix forward ref in generic by [@adriangb](https://github.com/adriangb) in [#6511](https://github.com/pydantic/pydantic/pull/6511) - Fix generation of serialization JSON schemas for core\_schema.ChainSchema by [@dmontagu](https://github.com/dmontagu) in [#6515](https://github.com/pydantic/pydantic/pull/6515) - Document the change in `Field.alias` behavior in Pydantic V2 by [@hramezani](https://github.com/hramezani) in [#6508](https://github.com/pydantic/pydantic/pull/6508) - Give better error message attempting to compute the json schema of a model with undefined fields by [@dmontagu](https://github.com/dmontagu) in [#6519](https://github.com/pydantic/pydantic/pull/6519) - Document `alias_priority` by [@tpdorsey](https://github.com/tpdorsey) in [#6520](https://github.com/pydantic/pydantic/pull/6520) - Add redirect for types documentation by [@tpdorsey](https://github.com/tpdorsey) in [#6513](https://github.com/pydantic/pydantic/pull/6513) - Allow updating docs without release by [@samuelcolvin](https://github.com/samuelcolvin) in [#6551](https://github.com/pydantic/pydantic/pull/6551) - Ensure docs tests always run in the right folder by [@dmontagu](https://github.com/dmontagu) in [#6487](https://github.com/pydantic/pydantic/pull/6487) - Defer evaluation of return type hints for serializer functions by [@dmontagu](https://github.com/dmontagu) in [#6516](https://github.com/pydantic/pydantic/pull/6516) - Disable E501 from Ruff and rely on just Black by [@adriangb](https://github.com/adriangb) in [#6552](https://github.com/pydantic/pydantic/pull/6552) - Update JSON Schema documentation for V2 by [@tpdorsey](https://github.com/tpdorsey) in [#6492](https://github.com/pydantic/pydantic/pull/6492) - Add documentation of cyclic reference handling by [@dmontagu](https://github.com/dmontagu) in [#6493](https://github.com/pydantic/pydantic/pull/6493) - Remove the need for change files by [@samuelcolvin](https://github.com/samuelcolvin) in [#6556](https://github.com/pydantic/pydantic/pull/6556) - add "north star" benchmark by [@davidhewitt](https://github.com/davidhewitt) in [#6547](https://github.com/pydantic/pydantic/pull/6547) - Update Dataclasses docs by [@tpdorsey](https://github.com/tpdorsey) in [#6470](https://github.com/pydantic/pydantic/pull/6470) - ♻️ Use different error message on v1 redirects by [@Kludex](https://github.com/Kludex) in [#6595](https://github.com/pydantic/pydantic/pull/6595) - ⬆ Upgrade `pydantic-core` to v2.2.0 by [@lig](https://github.com/lig) in [#6589](https://github.com/pydantic/pydantic/pull/6589) - Fix serialization for IPvAny by [@dmontagu](https://github.com/dmontagu) in [#6572](https://github.com/pydantic/pydantic/pull/6572) - Improve CI by using PDM instead of pip to install typing-extensions by [@adriangb](https://github.com/adriangb) in [#6602](https://github.com/pydantic/pydantic/pull/6602) - Add `enum` error type docs by [@lig](https://github.com/lig) in [#6603](https://github.com/pydantic/pydantic/pull/6603) - 🐛 Fix `max_length` for unicode strings by [@lig](https://github.com/lig) in [#6559](https://github.com/pydantic/pydantic/pull/6559) - Add documentation for accessing features via `pydantic.v1` by [@tpdorsey](https://github.com/tpdorsey) in [#6604](https://github.com/pydantic/pydantic/pull/6604) - Include extra when iterating over a model by [@adriangb](https://github.com/adriangb) in [#6562](https://github.com/pydantic/pydantic/pull/6562) - Fix typing of model\_validator by [@adriangb](https://github.com/adriangb) in [#6514](https://github.com/pydantic/pydantic/pull/6514) - Touch up Decimal validator by [@adriangb](https://github.com/adriangb) in [#6327](https://github.com/pydantic/pydantic/pull/6327) - Fix various docstrings using fixed pytest-examples by [@dmontagu](https://github.com/dmontagu) in [#6607](https://github.com/pydantic/pydantic/pull/6607) - Handle function validators in a discriminated union by [@dmontagu](https://github.com/dmontagu) in [#6570](https://github.com/pydantic/pydantic/pull/6570) - Review json\_schema.md by [@tpdorsey](https://github.com/tpdorsey) in [#6608](https://github.com/pydantic/pydantic/pull/6608) - Make validate\_call work on basemodel methods by [@dmontagu](https://github.com/dmontagu) in [#6569](https://github.com/pydantic/pydantic/pull/6569) - add test for big int json serde by [@davidhewitt](https://github.com/davidhewitt) in [#6614](https://github.com/pydantic/pydantic/pull/6614) - Fix pydantic dataclass problem with dataclasses.field default\_factory by [@hramezani](https://github.com/hramezani) in [#6616](https://github.com/pydantic/pydantic/pull/6616) - Fixed mypy type inference for TypeAdapter by [@zakstucke](https://github.com/zakstucke) in [#6617](https://github.com/pydantic/pydantic/pull/6617) - Make it work to use None as a generic parameter by [@dmontagu](https://github.com/dmontagu) in [#6609](https://github.com/pydantic/pydantic/pull/6609) - Make it work to use `$ref` as an alias by [@dmontagu](https://github.com/dmontagu) in [#6568](https://github.com/pydantic/pydantic/pull/6568) - add note to migration guide about changes to `AnyUrl` etc by [@davidhewitt](https://github.com/davidhewitt) in [#6618](https://github.com/pydantic/pydantic/pull/6618) - 🐛 Support defining `json_schema_extra` on `RootModel` using `Field` by [@lig](https://github.com/lig) in [#6622](https://github.com/pydantic/pydantic/pull/6622) - Update pre-commit to prevent commits to main branch on accident by [@dmontagu](https://github.com/dmontagu) in [#6636](https://github.com/pydantic/pydantic/pull/6636) - Fix PDM CI for python 3.7 on MacOS/windows by [@dmontagu](https://github.com/dmontagu) in [#6627](https://github.com/pydantic/pydantic/pull/6627) - Produce more accurate signatures for pydantic dataclasses by [@dmontagu](https://github.com/dmontagu) in [#6633](https://github.com/pydantic/pydantic/pull/6633) - Updates to Url types for Pydantic V2 by [@tpdorsey](https://github.com/tpdorsey) in [#6638](https://github.com/pydantic/pydantic/pull/6638) - Fix list markdown in `transform` docstring by [@StefanBRas](https://github.com/StefanBRas) in [#6649](https://github.com/pydantic/pydantic/pull/6649) - simplify slots\_dataclass construction to appease mypy by [@davidhewitt](https://github.com/davidhewitt) in [#6639](https://github.com/pydantic/pydantic/pull/6639) - Update TypedDict schema generation docstring by [@adriangb](https://github.com/adriangb) in [#6651](https://github.com/pydantic/pydantic/pull/6651) - Detect and lint-error for prints by [@dmontagu](https://github.com/dmontagu) in [#6655](https://github.com/pydantic/pydantic/pull/6655) - Add xfailing test for pydantic-core PR 766 by [@dmontagu](https://github.com/dmontagu) in [#6641](https://github.com/pydantic/pydantic/pull/6641) - Ignore unrecognized fields from dataclasses metadata by [@dmontagu](https://github.com/dmontagu) in [#6634](https://github.com/pydantic/pydantic/pull/6634) - Make non-existent class getattr a mypy error by [@dmontagu](https://github.com/dmontagu) in [#6658](https://github.com/pydantic/pydantic/pull/6658) - Update pydantic-core to 2.3.0 by [@hramezani](https://github.com/hramezani) in [#6648](https://github.com/pydantic/pydantic/pull/6648) - Use OrderedDict from typing\_extensions by [@dmontagu](https://github.com/dmontagu) in [#6664](https://github.com/pydantic/pydantic/pull/6664) - Fix typehint for JSON schema extra callable by [@dmontagu](https://github.com/dmontagu) in [#6659](https://github.com/pydantic/pydantic/pull/6659) ## v2.0.2 (2023-07-05) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.0.2) - Fix bug where round-trip pickling/unpickling a `RootModel` would change the value of `__dict__`, [#6457](https://github.com/pydantic/pydantic/pull/6457) by [@dmontagu](https://github.com/dmontagu) - Allow single-item discriminated unions, [#6405](https://github.com/pydantic/pydantic/pull/6405) by [@dmontagu](https://github.com/dmontagu) - Fix issue with union parsing of enums, [#6440](https://github.com/pydantic/pydantic/pull/6440) by [@dmontagu](https://github.com/dmontagu) - Docs: Fixed `constr` documentation, renamed old `regex` to new `pattern`, [#6452](https://github.com/pydantic/pydantic/pull/6452) by [@miili](https://github.com/miili) - Change `GenerateJsonSchema.generate_definitions` signature, [#6436](https://github.com/pydantic/pydantic/pull/6436) by [@dmontagu](https://github.com/dmontagu) See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0.2) ## v2.0.1 (2023-07-04) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.0.1) First patch release of Pydantic V2 - Extra fields added via `setattr` (i.e. `m.some_extra_field = 'extra_value'`) are added to `.model_extra` if `model_config` `extra='allowed'`. Fixed [#6333](https://github.com/pydantic/pydantic/pull/6333), [#6365](https://github.com/pydantic/pydantic/pull/6365) by [@aaraney](https://github.com/aaraney) - Automatically unpack JSON schema '$ref' for custom types, [#6343](https://github.com/pydantic/pydantic/pull/6343) by [@adriangb](https://github.com/adriangb) - Fix tagged unions multiple processing in submodels, [#6340](https://github.com/pydantic/pydantic/pull/6340) by [@suharnikov](https://github.com/suharnikov) See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0.1) ## v2.0 (2023-06-30) [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.0) Pydantic V2 is here! 🎉 See [this post](https://docs.pydantic.dev/2.0/blog/pydantic-v2-final/) for more details. ## v2.0b3 (2023-06-16) Third beta pre-release of Pydantic V2 See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b3) ## v2.0b2 (2023-06-03) Add `from_attributes` runtime flag to `TypeAdapter.validate_python` and `BaseModel.model_validate`. See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b2) ## v2.0b1 (2023-06-01) First beta pre-release of Pydantic V2 See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0b1) ## v2.0a4 (2023-05-05) Fourth pre-release of Pydantic V2 See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a4) ## v2.0a3 (2023-04-20) Third pre-release of Pydantic V2 See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a3) ## v2.0a2 (2023-04-12) Second pre-release of Pydantic V2 See the full changelog [here](https://github.com/pydantic/pydantic/releases/tag/v2.0a2) ## v2.0a1 (2023-04-03) First pre-release of Pydantic V2! See [this post](https://docs.pydantic.dev/blog/pydantic-v2-alpha/) for more details. ## v1.10.24 (2025-09-25) - Add user warning when using Python 3.14 by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/12263](https://github.com/pydantic/pydantic/pull/12263) Pydantic V1 will _not_ work with Python 3.14 and greater. A warning is now raised as no actual error show up when using it, but the core behavior will silently get broken at runtime. - Fix mypy plugin issue for mypy v1.18 by [@cdce8p](https://github.com/cdce8p) in [https://github.com/pydantic/pydantic/pull/12254](https://github.com/pydantic/pydantic/pull/12254) This fixes another mypy issue that was discovered after the previous v1.10.23 release. ## v1.10.23 (2025-09-13) - Fix mypy plugin for mypy 1.18 by [@cdce8p](https://github.com/cdce8p) in [https://github.com/pydantic/pydantic/pull/12207](https://github.com/pydantic/pydantic/pull/12207) ## v1.10.22 (2025-04-17) - Fix compatibility with `typing-extensions` by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/11764](https://github.com/pydantic/pydantic/pull/11764) ## v1.10.21 (2025-01-10) - Fix compatibility with ForwardRef.\_evaluate and Python < 3.12.4 by [@griels](https://github.com/griels) in [https://github.com/pydantic/pydantic/pull/11232](https://github.com/pydantic/pydantic/pull/11232) ## v1.10.20 (2025-01-07) This release provides proper support for Python 3.13, with (Cythonized) wheels published for this version. As a consequence, Cython was updated from `0.29.x` to `3.0.x`. - General maintenance of CI and build ecosystem by [@Viicos](https://github.com/Viicos) in [https://github.com/pydantic/pydantic/pull/10847](https://github.com/pydantic/pydantic/pull/10847) - Update Cython to `3.0.x`. - Properly address Python 3.13 deprecation warnings. - Migrate packaging to `pyproject.toml`, make use of PEP 517 build options. - Use [`build`](https://pypi.org/project/build/) instead of direct `setup.py` invocations. - Update various Github Actions versions. - Replace outdated stpmex link in documentation by [@jaredenorris](https://github.com/jaredenorris) in [https://github.com/pydantic/pydantic/pull/10997](https://github.com/pydantic/pydantic/pull/10997) ## v1.10.19 (2024-11-06) - Add warning when v2 model is nested in v1 model by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/10432](https://github.com/pydantic/pydantic/pull/10432) - Fix deprecation warning in V1 `isinstance` check by [@alicederyn](https://github.com/alicederyn) in [https://github.com/pydantic/pydantic/pull/10645](https://github.com/pydantic/pydantic/pull/10645) ## v1.10.18 (2024-08-22) - Eval type fix in V1 by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/9751](https://github.com/pydantic/pydantic/pull/9751) - Add `to_lower_camel` to `__all__` in `utils.py` by [@sydney-runkle](https://github.com/sydney-runkle) (direct commit) - Fix `mypy` v1 plugin for mypy 1.11 release by [@flaeppe](https://github.com/flaeppe) in [https://github.com/pydantic/pydantic/pull/10139](https://github.com/pydantic/pydantic/pull/10139) - Fix discriminator key used when discriminator has alias and `.schema(by_alias=False)` by [@exs-dwoodward](https://github.com/exs-dwoodward) in [https://github.com/pydantic/pydantic/pull/10146](https://github.com/pydantic/pydantic/pull/10146) ## v1.10.17 (2024-06-20) - Advertise Python 3.12 for 1.10.x! Part Deux by [@vfazio](https://github.com/vfazio) in [https://github.com/pydantic/pydantic/pull/9644](https://github.com/pydantic/pydantic/pull/9644) - Mirrored modules in `v1` namespace to fix typing and object resolution in python>3.11 by [@exs-dwoodward](https://github.com/exs-dwoodward) in [https://github.com/pydantic/pydantic/pull/9660](https://github.com/pydantic/pydantic/pull/9660) - setup: remove upper bound from python\_requires by [@vfazio](https://github.com/vfazio) in [https://github.com/pydantic/pydantic/pull/9685](https://github.com/pydantic/pydantic/pull/9685) ## v1.10.16 (2024-06-11) - Specify recursive\_guard as kwarg in FutureRef.\_evaluate by [@vfazio](https://github.com/vfazio) in [https://github.com/pydantic/pydantic/pull/9612](https://github.com/pydantic/pydantic/pull/9612) - Fix mypy v1 plugin for upcoming mypy release by @ cdce8p in [https://github.com/pydantic/pydantic/pull/9586](https://github.com/pydantic/pydantic/pull/9586) - Import modules/objects directly from v1 namespace by [@exs-dwoodward](https://github.com/exs-dwoodward) in [https://github.com/pydantic/pydantic/pull/9162](https://github.com/pydantic/pydantic/pull/9162) ## v1.10.15 (2024-04-03) - Add pydantic.v1 namespace to Pydantic v1 by [@exs-dmiketa](https://github.com/exs-dmiketa) in [https://github.com/pydantic/pydantic/pull/9042](https://github.com/pydantic/pydantic/pull/9042) - Relax version of typing-extensions for V1 by [@SonOfLilit](https://github.com/SonOfLilit) in [https://github.com/pydantic/pydantic/pull/8819](https://github.com/pydantic/pydantic/pull/8819) - patch fix for mypy by [@sydney-runkle](https://github.com/sydney-runkle) in [https://github.com/pydantic/pydantic/pull/8765](https://github.com/pydantic/pydantic/pull/8765) ## v1.10.14 (2024-01-19) - Update install.md by [@dmontagu](https://github.com/dmontagu) in #7690 - Fix ci to only deploy docs on release by [@sydney-runkle](https://github.com/sydney-runkle) in #7740 - Ubuntu fixes for V1 by [@sydney-runkle](https://github.com/sydney-runkle) in #8540 and #8587 - Fix cached\_property handling in dataclasses when copied by [@rdbisme](https://github.com/rdbisme) in #8407 ## v1.10.13 (2023-09-27) - Fix: Add max length check to `pydantic.validate_email`, #7673 by [@hramezani](https://github.com/hramezani) - Docs: Fix pip commands to install v1, #6930 by [@chbndrhnns](https://github.com/chbndrhnns) ## v1.10.12 (2023-07-24) - Fixes the `maxlen` property being dropped on `deque` validation. Happened only if the deque item has been typed. Changes the `_validate_sequence_like` func, [#6581](https://github.com/pydantic/pydantic/pull/6581) by [@maciekglowka](https://github.com/maciekglowka) ## v1.10.11 (2023-07-04) - Importing create\_model in tools.py through relative path instead of absolute path - so that it doesn't import V2 code when copied over to V2 branch, [#6361](https://github.com/pydantic/pydantic/pull/6361) by [@SharathHuddar](https://github.com/SharathHuddar) ## v1.10.10 (2023-06-30) - Add Pydantic `Json` field support to settings management, [#6250](https://github.com/pydantic/pydantic/pull/6250) by [@hramezani](https://github.com/hramezani) - Fixed literal validator errors for unhashable values, [#6188](https://github.com/pydantic/pydantic/pull/6188) by [@markus1978](https://github.com/markus1978) - Fixed bug with generics receiving forward refs, [#6130](https://github.com/pydantic/pydantic/pull/6130) by [@mark-todd](https://github.com/mark-todd) - Update install method of FastAPI for internal tests in CI, [#6117](https://github.com/pydantic/pydantic/pull/6117) by [@Kludex](https://github.com/Kludex) ## v1.10.9 (2023-06-07) - Fix trailing zeros not ignored in Decimal validation, [#5968](https://github.com/pydantic/pydantic/pull/5968) by [@hramezani](https://github.com/hramezani) - Fix mypy plugin for v1.4.0, [#5928](https://github.com/pydantic/pydantic/pull/5928) by [@cdce8p](https://github.com/cdce8p) - Add future and past date hypothesis strategies, [#5850](https://github.com/pydantic/pydantic/pull/5850) by [@bschoenmaeckers](https://github.com/bschoenmaeckers) - Discourage usage of Cython 3 with Pydantic 1.x, [#5845](https://github.com/pydantic/pydantic/pull/5845) by [@lig](https://github.com/lig) ## v1.10.8 (2023-05-23) - Fix a bug in `Literal` usage with `typing-extension==4.6.0`, [#5826](https://github.com/pydantic/pydantic/pull/5826) by [@hramezani](https://github.com/hramezani) - This solves the (closed) issue [#3849](https://github.com/pydantic/pydantic/pull/3849) where aliased fields that use discriminated union fail to validate when the data contains the non-aliased field name, [#5736](https://github.com/pydantic/pydantic/pull/5736) by [@benwah](https://github.com/benwah) - Update email-validator dependency to >=2.0.0post2, [#5627](https://github.com/pydantic/pydantic/pull/5627) by [@adriangb](https://github.com/adriangb) - update `AnyClassMethod` for changes in [python/typeshed#9771](https://github.com/python/typeshed/issues/9771), [#5505](https://github.com/pydantic/pydantic/pull/5505) by [@ITProKyle](https://github.com/ITProKyle) ## v1.10.7 (2023-03-22) - Fix creating schema from model using `ConstrainedStr` with `regex` as dict key, [#5223](https://github.com/pydantic/pydantic/pull/5223) by [@matejetz](https://github.com/matejetz) - Address bug in mypy plugin caused by explicit\_package\_bases=True, [#5191](https://github.com/pydantic/pydantic/pull/5191) by [@dmontagu](https://github.com/dmontagu) - Add implicit defaults in the mypy plugin for Field with no default argument, [#5190](https://github.com/pydantic/pydantic/pull/5190) by [@dmontagu](https://github.com/dmontagu) - Fix schema generated for Enum values used as Literals in discriminated unions, [#5188](https://github.com/pydantic/pydantic/pull/5188) by [@javibookline](https://github.com/javibookline) - Fix mypy failures caused by the pydantic mypy plugin when users define `from_orm` in their own classes, [#5187](https://github.com/pydantic/pydantic/pull/5187) by [@dmontagu](https://github.com/dmontagu) - Fix `InitVar` usage with pydantic dataclasses, mypy version `1.1.1` and the custom mypy plugin, [#5162](https://github.com/pydantic/pydantic/pull/5162) by [@cdce8p](https://github.com/cdce8p) ## v1.10.6 (2023-03-08) - Implement logic to support creating validators from non standard callables by using defaults to identify them and unwrapping `functools.partial` and `functools.partialmethod` when checking the signature, [#5126](https://github.com/pydantic/pydantic/pull/5126) by [@JensHeinrich](https://github.com/JensHeinrich) - Fix mypy plugin for v1.1.1, and fix `dataclass_transform` decorator for pydantic dataclasses, [#5111](https://github.com/pydantic/pydantic/pull/5111) by [@cdce8p](https://github.com/cdce8p) - Raise `ValidationError`, not `ConfigError`, when a discriminator value is unhashable, [#4773](https://github.com/pydantic/pydantic/pull/4773) by [@kurtmckee](https://github.com/kurtmckee) ## v1.10.5 (2023-02-15) - Fix broken parametrized bases handling with `GenericModel`s with complex sets of models, [#5052](https://github.com/pydantic/pydantic/pull/5052) by [@MarkusSintonen](https://github.com/MarkusSintonen) - Invalidate mypy cache if plugin config changes, [#5007](https://github.com/pydantic/pydantic/pull/5007) by [@cdce8p](https://github.com/cdce8p) - Fix `RecursionError` when deep-copying dataclass types wrapped by pydantic, [#4949](https://github.com/pydantic/pydantic/pull/4949) by [@mbillingr](https://github.com/mbillingr) - Fix `X | Y` union syntax breaking `GenericModel`, [#4146](https://github.com/pydantic/pydantic/pull/4146) by [@thenx](https://github.com/thenx) - Switch coverage badge to show coverage for this branch/release, [#5060](https://github.com/pydantic/pydantic/pull/5060) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.10.4 (2022-12-30) - Change dependency to `typing-extensions>=4.2.0`, [#4885](https://github.com/pydantic/pydantic/pull/4885) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.10.3 (2022-12-29) **NOTE: v1.10.3 was ["yanked"](https://pypi.org/help/#yanked) from PyPI due to [#4885](https://github.com/pydantic/pydantic/pull/4885) which is fixed in v1.10.4** - fix parsing of custom root models, [#4883](https://github.com/pydantic/pydantic/pull/4883) by [@gou177](https://github.com/gou177) - fix: use dataclass proxy for frozen or empty dataclasses, [#4878](https://github.com/pydantic/pydantic/pull/4878) by [@PrettyWood](https://github.com/PrettyWood) - Fix `schema` and `schema_json` on models where a model instance is a one of default values, [#4781](https://github.com/pydantic/pydantic/pull/4781) by [@Bobronium](https://github.com/Bobronium) - Add Jina AI to sponsors on docs index page, [#4767](https://github.com/pydantic/pydantic/pull/4767) by [@samuelcolvin](https://github.com/samuelcolvin) - fix: support assignment on `DataclassProxy`, [#4695](https://github.com/pydantic/pydantic/pull/4695) by [@PrettyWood](https://github.com/PrettyWood) - Add `postgresql+psycopg` as allowed scheme for `PostgreDsn` to make it usable with SQLAlchemy 2, [#4689](https://github.com/pydantic/pydantic/pull/4689) by [@morian](https://github.com/morian) - Allow dict schemas to have both `patternProperties` and `additionalProperties`, [#4641](https://github.com/pydantic/pydantic/pull/4641) by [@jparise](https://github.com/jparise) - Fixes error passing None for optional lists with `unique_items`, [#4568](https://github.com/pydantic/pydantic/pull/4568) by [@mfulgo](https://github.com/mfulgo) - Fix `GenericModel` with `Callable` param raising a `TypeError`, [#4551](https://github.com/pydantic/pydantic/pull/4551) by [@mfulgo](https://github.com/mfulgo) - Fix field regex with `StrictStr` type annotation, [#4538](https://github.com/pydantic/pydantic/pull/4538) by [@sisp](https://github.com/sisp) - Correct `dataclass_transform` keyword argument name from `field_descriptors` to `field_specifiers`, [#4500](https://github.com/pydantic/pydantic/pull/4500) by [@samuelcolvin](https://github.com/samuelcolvin) - fix: avoid multiple calls of `__post_init__` when dataclasses are inherited, [#4487](https://github.com/pydantic/pydantic/pull/4487) by [@PrettyWood](https://github.com/PrettyWood) - Reduce the size of binary wheels, [#2276](https://github.com/pydantic/pydantic/pull/2276) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.10.2 (2022-09-05) - **Revert Change:** Revert percent encoding of URL parts which was originally added in [#4224](https://github.com/pydantic/pydantic/pull/4224), [#4470](https://github.com/pydantic/pydantic/pull/4470) by [@samuelcolvin](https://github.com/samuelcolvin) - Prevent long (length > `4_300`) strings/bytes as input to int fields, see [python/cpython#95778](https://github.com/python/cpython/issues/95778) and [CVE-2020-10735](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-10735), [#1477](https://github.com/pydantic/pydantic/pull/1477) by [@samuelcolvin](https://github.com/samuelcolvin) - fix: dataclass wrapper was not always called, [#4477](https://github.com/pydantic/pydantic/pull/4477) by [@PrettyWood](https://github.com/PrettyWood) - Use `tomllib` on Python 3.11 when parsing `mypy` configuration, [#4476](https://github.com/pydantic/pydantic/pull/4476) by [@hauntsaninja](https://github.com/hauntsaninja) - Basic fix of `GenericModel` cache to detect order of arguments in `Union` models, [#4474](https://github.com/pydantic/pydantic/pull/4474) by [@sveinugu](https://github.com/sveinugu) - Fix mypy plugin when using bare types like `list` and `dict` as `default_factory`, [#4457](https://github.com/pydantic/pydantic/pull/4457) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.10.1 (2022-08-31) - Add `__hash__` method to `pydantic.color.Color` class, [#4454](https://github.com/pydantic/pydantic/pull/4454) by [@czaki](https://github.com/czaki) ## v1.10.0 (2022-08-30) - Refactor the whole _pydantic_ `dataclass` decorator to really act like its standard lib equivalent. It hence keeps `__eq__`, `__hash__`, ... and makes comparison with its non-validated version possible. It also fixes usage of `frozen` dataclasses in fields and usage of `default_factory` in nested dataclasses. The support of `Config.extra` has been added. Finally, config customization directly via a `dict` is now possible, [#2557](https://github.com/pydantic/pydantic/pull/2557) by [@PrettyWood](https://github.com/PrettyWood) **BREAKING CHANGES:** - The `compiled` boolean (whether _pydantic_ is compiled with cython) has been moved from `main.py` to `version.py` - Now that `Config.extra` is supported, `dataclass` ignores by default extra arguments (like `BaseModel`) - Fix PEP487 `__set_name__` protocol in `BaseModel` for PrivateAttrs, [#4407](https://github.com/pydantic/pydantic/pull/4407) by [@tlambert03](https://github.com/tlambert03) - Allow for custom parsing of environment variables via `parse_env_var` in `Config`, [#4406](https://github.com/pydantic/pydantic/pull/4406) by [@acmiyaguchi](https://github.com/acmiyaguchi) - Rename `master` to `main`, [#4405](https://github.com/pydantic/pydantic/pull/4405) by [@hramezani](https://github.com/hramezani) - Fix `StrictStr` does not raise `ValidationError` when `max_length` is present in `Field`, [#4388](https://github.com/pydantic/pydantic/pull/4388) by [@hramezani](https://github.com/hramezani) - Make `SecretStr` and `SecretBytes` hashable, [#4387](https://github.com/pydantic/pydantic/pull/4387) by [@chbndrhnns](https://github.com/chbndrhnns) - Fix `StrictBytes` does not raise `ValidationError` when `max_length` is present in `Field`, [#4380](https://github.com/pydantic/pydantic/pull/4380) by [@JeanArhancet](https://github.com/JeanArhancet) - Add support for bare `type`, [#4375](https://github.com/pydantic/pydantic/pull/4375) by [@hramezani](https://github.com/hramezani) - Support Python 3.11, including binaries for 3.11 in PyPI, [#4374](https://github.com/pydantic/pydantic/pull/4374) by [@samuelcolvin](https://github.com/samuelcolvin) - Add support for `re.Pattern`, [#4366](https://github.com/pydantic/pydantic/pull/4366) by [@hramezani](https://github.com/hramezani) - Fix `__post_init_post_parse__` is incorrectly passed keyword arguments when no `__post_init__` is defined, [#4361](https://github.com/pydantic/pydantic/pull/4361) by [@hramezani](https://github.com/hramezani) - Fix implicitly importing `ForwardRef` and `Callable` from `pydantic.typing` instead of `typing` and also expose `MappingIntStrAny`, [#4358](https://github.com/pydantic/pydantic/pull/4358) by [@aminalaee](https://github.com/aminalaee) - remove `Any` types from the `dataclass` decorator so it can be used with the `disallow_any_expr` mypy option, [#4356](https://github.com/pydantic/pydantic/pull/4356) by [@DetachHead](https://github.com/DetachHead) - moved repo to `pydantic/pydantic`, [#4348](https://github.com/pydantic/pydantic/pull/4348) by [@yezz123](https://github.com/yezz123) - fix "extra fields not permitted" error when dataclass with `Extra.forbid` is validated multiple times, [#4343](https://github.com/pydantic/pydantic/pull/4343) by [@detachhead](https://github.com/detachhead) - Add Python 3.9 and 3.10 examples to docs, [#4339](https://github.com/pydantic/pydantic/pull/4339) by [@Bobronium](https://github.com/Bobronium) - Discriminated union models now use `oneOf` instead of `anyOf` when generating OpenAPI schema definitions, [#4335](https://github.com/pydantic/pydantic/pull/4335) by [@MaxwellPayne](https://github.com/MaxwellPayne) - Allow type checkers to infer inner type of `Json` type. `Json[list[str]]` will be now inferred as `list[str]`, `Json[Any]` should be used instead of plain `Json`. Runtime behaviour is not changed, [#4332](https://github.com/pydantic/pydantic/pull/4332) by [@Bobronium](https://github.com/Bobronium) - Allow empty string aliases by using a `alias is not None` check, rather than `bool(alias)`, [#4253](https://github.com/pydantic/pydantic/pull/4253) by [@sergeytsaplin](https://github.com/sergeytsaplin) - Update `ForwardRef`s in `Field.outer_type_`, [#4249](https://github.com/pydantic/pydantic/pull/4249) by [@JacobHayes](https://github.com/JacobHayes) - The use of `__dataclass_transform__` has been replaced by `typing_extensions.dataclass_transform`, which is the preferred way to mark pydantic models as a dataclass under [PEP 681](https://peps.python.org/pep-0681/), [#4241](https://github.com/pydantic/pydantic/pull/4241) by [@multimeric](https://github.com/multimeric) - Use parent model's `Config` when validating nested `NamedTuple` fields, [#4219](https://github.com/pydantic/pydantic/pull/4219) by [@synek](https://github.com/synek) - Update `BaseModel.construct` to work with aliased Fields, [#4192](https://github.com/pydantic/pydantic/pull/4192) by [@kylebamos](https://github.com/kylebamos) - Catch certain raised errors in `smart_deepcopy` and revert to `deepcopy` if so, [#4184](https://github.com/pydantic/pydantic/pull/4184) by [@coneybeare](https://github.com/coneybeare) - Add `Config.anystr_upper` and `to_upper` kwarg to constr and conbytes, [#4165](https://github.com/pydantic/pydantic/pull/4165) by [@satheler](https://github.com/satheler) - Fix JSON schema for `set` and `frozenset` when they include default values, [#4155](https://github.com/pydantic/pydantic/pull/4155) by [@aminalaee](https://github.com/aminalaee) - Teach the mypy plugin that methods decorated by `@validator` are classmethods, [#4102](https://github.com/pydantic/pydantic/pull/4102) by [@DMRobertson](https://github.com/DMRobertson) - Improve mypy plugin's ability to detect required fields, [#4086](https://github.com/pydantic/pydantic/pull/4086) by [@richardxia](https://github.com/richardxia) - Support fields of type `Type[]` in schema, [#4051](https://github.com/pydantic/pydantic/pull/4051) by [@aminalaee](https://github.com/aminalaee) - Add `default` value in JSON Schema when `const=True`, [#4031](https://github.com/pydantic/pydantic/pull/4031) by [@aminalaee](https://github.com/aminalaee) - Adds reserved word check to signature generation logic, [#4011](https://github.com/pydantic/pydantic/pull/4011) by [@strue36](https://github.com/strue36) - Fix Json strategy failure for the complex nested field, [#4005](https://github.com/pydantic/pydantic/pull/4005) by [@sergiosim](https://github.com/sergiosim) - Add JSON-compatible float constraint `allow_inf_nan`, [#3994](https://github.com/pydantic/pydantic/pull/3994) by [@tiangolo](https://github.com/tiangolo) - Remove undefined behaviour when `env_prefix` had characters in common with `env_nested_delimiter`, [#3975](https://github.com/pydantic/pydantic/pull/3975) by [@arsenron](https://github.com/arsenron) - Support generics model with `create_model`, [#3945](https://github.com/pydantic/pydantic/pull/3945) by [@hot123s](https://github.com/hot123s) - allow submodels to overwrite extra field info, [#3934](https://github.com/pydantic/pydantic/pull/3934) by [@PrettyWood](https://github.com/PrettyWood) - Document and test structural pattern matching ([PEP 636](https://peps.python.org/pep-0636/)) on `BaseModel`, [#3920](https://github.com/pydantic/pydantic/pull/3920) by [@irgolic](https://github.com/irgolic) - Fix incorrect deserialization of python timedelta object to ISO 8601 for negative time deltas. Minus was serialized in incorrect place ("P-1DT23H59M59.888735S" instead of correct "-P1DT23H59M59.888735S"), [#3899](https://github.com/pydantic/pydantic/pull/3899) by [@07pepa](https://github.com/07pepa) - Fix validation of discriminated union fields with an alias when passing a model instance, [#3846](https://github.com/pydantic/pydantic/pull/3846) by [@chornsby](https://github.com/chornsby) - Add a CockroachDsn type to validate CockroachDB connection strings. The type supports the following schemes: `cockroachdb`, `cockroachdb+psycopg2` and `cockroachdb+asyncpg`, [#3839](https://github.com/pydantic/pydantic/pull/3839) by [@blubber](https://github.com/blubber) - Fix MyPy plugin to not override pre-existing `__init__` method in models, [#3824](https://github.com/pydantic/pydantic/pull/3824) by [@patrick91](https://github.com/patrick91) - Fix mypy version checking, [#3783](https://github.com/pydantic/pydantic/pull/3783) by [@KotlinIsland](https://github.com/KotlinIsland) - support overwriting dunder attributes of `BaseModel` instances, [#3777](https://github.com/pydantic/pydantic/pull/3777) by [@PrettyWood](https://github.com/PrettyWood) - Added `ConstrainedDate` and `condate`, [#3740](https://github.com/pydantic/pydantic/pull/3740) by [@hottwaj](https://github.com/hottwaj) - Support `kw_only` in dataclasses, [#3670](https://github.com/pydantic/pydantic/pull/3670) by [@detachhead](https://github.com/detachhead) - Add comparison method for `Color` class, [#3646](https://github.com/pydantic/pydantic/pull/3646) by [@aminalaee](https://github.com/aminalaee) - Drop support for python3.6, associated cleanup, [#3605](https://github.com/pydantic/pydantic/pull/3605) by [@samuelcolvin](https://github.com/samuelcolvin) - created new function `to_lower_camel()` for "non pascal case" camel case, [#3463](https://github.com/pydantic/pydantic/pull/3463) by [@schlerp](https://github.com/schlerp) - Add checks to `default` and `default_factory` arguments in Mypy plugin, [#3430](https://github.com/pydantic/pydantic/pull/3430) by [@klaa97](https://github.com/klaa97) - fix mangling of `inspect.signature` for `BaseModel`, [#3413](https://github.com/pydantic/pydantic/pull/3413) by [@fix-inspect-signature](https://github.com/fix-inspect-signature) - Adds the `SecretField` abstract class so that all the current and future secret fields like `SecretStr` and `SecretBytes` will derive from it, [#3409](https://github.com/pydantic/pydantic/pull/3409) by [@expobrain](https://github.com/expobrain) - Support multi hosts validation in `PostgresDsn`, [#3337](https://github.com/pydantic/pydantic/pull/3337) by [@rglsk](https://github.com/rglsk) - Fix parsing of very small numeric timedelta values, [#3315](https://github.com/pydantic/pydantic/pull/3315) by [@samuelcolvin](https://github.com/samuelcolvin) - Update `SecretsSettingsSource` to respect `config.case_sensitive`, [#3273](https://github.com/pydantic/pydantic/pull/3273) by [@JeanArhancet](https://github.com/JeanArhancet) - Add MongoDB network data source name (DSN) schema, [#3229](https://github.com/pydantic/pydantic/pull/3229) by [@snosratiershad](https://github.com/snosratiershad) - Add support for multiple dotenv files, [#3222](https://github.com/pydantic/pydantic/pull/3222) by [@rekyungmin](https://github.com/rekyungmin) - Raise an explicit `ConfigError` when multiple fields are incorrectly set for a single validator, [#3215](https://github.com/pydantic/pydantic/pull/3215) by [@SunsetOrange](https://github.com/SunsetOrange) - Allow ellipsis on `Field`s inside `Annotated` for `TypedDicts` required, [#3133](https://github.com/pydantic/pydantic/pull/3133) by [@ezegomez](https://github.com/ezegomez) - Catch overflow errors in `int_validator`, [#3112](https://github.com/pydantic/pydantic/pull/3112) by [@ojii](https://github.com/ojii) - Adds a `__rich_repr__` method to `Representation` class which enables pretty printing with [Rich](https://github.com/willmcgugan/rich), [#3099](https://github.com/pydantic/pydantic/pull/3099) by [@willmcgugan](https://github.com/willmcgugan) - Add percent encoding in `AnyUrl` and descendent types, [#3061](https://github.com/pydantic/pydantic/pull/3061) by [@FaresAhmedb](https://github.com/FaresAhmedb) - `validate_arguments` decorator now supports `alias`, [#3019](https://github.com/pydantic/pydantic/pull/3019) by [@MAD-py](https://github.com/MAD-py) - Avoid `__dict__` and `__weakref__` attributes in `AnyUrl` and IP address fields, [#2890](https://github.com/pydantic/pydantic/pull/2890) by [@nuno-andre](https://github.com/nuno-andre) - Add ability to use `Final` in a field type annotation, [#2766](https://github.com/pydantic/pydantic/pull/2766) by [@uriyyo](https://github.com/uriyyo) - Update requirement to `typing_extensions>=4.1.0` to guarantee `dataclass_transform` is available, [#4424](https://github.com/pydantic/pydantic/pull/4424) by [@commonism](https://github.com/commonism) - Add Explosion and AWS to main sponsors, [#4413](https://github.com/pydantic/pydantic/pull/4413) by [@samuelcolvin](https://github.com/samuelcolvin) - Update documentation for `copy_on_model_validation` to reflect recent changes, [#4369](https://github.com/pydantic/pydantic/pull/4369) by [@samuelcolvin](https://github.com/samuelcolvin) - Runtime warning if `__slots__` is passed to `create_model`, `__slots__` is then ignored, [#4432](https://github.com/pydantic/pydantic/pull/4432) by [@samuelcolvin](https://github.com/samuelcolvin) - Add type hints to `BaseSettings.Config` to avoid mypy errors, also correct mypy version compatibility notice in docs, [#4450](https://github.com/pydantic/pydantic/pull/4450) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.10.0b1 (2022-08-24) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0b1) for details. ## v1.10.0a2 (2022-08-24) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a2) for details. ## v1.10.0a1 (2022-08-22) Pre-release, see [the GitHub release](https://github.com/pydantic/pydantic/releases/tag/v1.10.0a1) for details. ## v1.9.2 (2022-08-11) **Revert Breaking Change**: _v1.9.1_ introduced a breaking change where model fields were deep copied by default, this release reverts the default behaviour to match _v1.9.0_ and before, while also allow deep-copy behaviour via `copy_on_model_validation = 'deep'`. See [#4092](https://github.com/pydantic/pydantic/pull/4092) for more information. - Allow for shallow copies of model fields, `Config.copy_on_model_validation` is now a str which must be `'none'`, `'deep'`, or `'shallow'` corresponding to not copying, deep copy & shallow copy; default `'shallow'`, [#4093](https://github.com/pydantic/pydantic/pull/4093) by [@timkpaine](https://github.com/timkpaine) ## v1.9.1 (2022-05-19) Thank you to pydantic's sponsors: [@tiangolo](https://github.com/tiangolo), [@stellargraph](https://github.com/stellargraph), [@JonasKs](https://github.com/JonasKs), [@grillazz](https://github.com/grillazz), [@Mazyod](https://github.com/Mazyod), [@kevinalh](https://github.com/kevinalh), [@chdsbd](https://github.com/chdsbd), [@povilasb](https://github.com/povilasb), [@povilasb](https://github.com/povilasb), [@jina-ai](https://github.com/jina-ai), [@mainframeindustries](https://github.com/mainframeindustries), [@robusta-dev](https://github.com/robusta-dev), [@SendCloud](https://github.com/SendCloud), [@rszamszur](https://github.com/rszamszur), [@jodal](https://github.com/jodal), [@hardbyte](https://github.com/hardbyte), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), [@Rehket](https://github.com/Rehket), [@jokull](https://github.com/jokull), [@reillysiemens](https://github.com/reillysiemens), [@westonsteimel](https://github.com/westonsteimel), [@primer-io](https://github.com/primer-io), [@koxudaxi](https://github.com/koxudaxi), [@browniebroke](https://github.com/browniebroke), [@stradivari96](https://github.com/stradivari96), [@adriangb](https://github.com/adriangb), [@kamalgill](https://github.com/kamalgill), [@jqueguiner](https://github.com/jqueguiner), [@dev-zero](https://github.com/dev-zero), [@datarootsio](https://github.com/datarootsio), [@RedCarpetUp](https://github.com/RedCarpetUp) for their kind support. - Limit the size of `generics._generic_types_cache` and `generics._assigned_parameters` to avoid unlimited increase in memory usage, [#4083](https://github.com/pydantic/pydantic/pull/4083) by [@samuelcolvin](https://github.com/samuelcolvin) - Add Jupyverse and FPS as Jupyter projects using pydantic, [#4082](https://github.com/pydantic/pydantic/pull/4082) by [@davidbrochart](https://github.com/davidbrochart) - Speedup `__isinstancecheck__` on pydantic models when the type is not a model, may also avoid memory "leaks", [#4081](https://github.com/pydantic/pydantic/pull/4081) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix in-place modification of `FieldInfo` that caused problems with PEP 593 type aliases, [#4067](https://github.com/pydantic/pydantic/pull/4067) by [@adriangb](https://github.com/adriangb) - Add support for autocomplete in VS Code via `__dataclass_transform__` when using `pydantic.dataclasses.dataclass`, [#4006](https://github.com/pydantic/pydantic/pull/4006) by [@giuliano-oliveira](https://github.com/giuliano-oliveira) - Remove benchmarks from codebase and docs, [#3973](https://github.com/pydantic/pydantic/pull/3973) by [@samuelcolvin](https://github.com/samuelcolvin) - Typing checking with pyright in CI, improve docs on vscode/pylance/pyright, [#3972](https://github.com/pydantic/pydantic/pull/3972) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix nested Python dataclass schema regression, [#3819](https://github.com/pydantic/pydantic/pull/3819) by [@himbeles](https://github.com/himbeles) - Update documentation about lazy evaluation of sources for Settings, [#3806](https://github.com/pydantic/pydantic/pull/3806) by [@garyd203](https://github.com/garyd203) - Prevent subclasses of bytes being converted to bytes, [#3706](https://github.com/pydantic/pydantic/pull/3706) by [@samuelcolvin](https://github.com/samuelcolvin) - Fixed "error checking inheritance of" when using PEP585 and PEP604 type hints, [#3681](https://github.com/pydantic/pydantic/pull/3681) by [@aleksul](https://github.com/aleksul) - Allow self referencing `ClassVar`s in models, [#3679](https://github.com/pydantic/pydantic/pull/3679) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change, see [#4106](https://github.com/pydantic/pydantic/pull/4106)**: Fix issue with self-referencing dataclass, [#3675](https://github.com/pydantic/pydantic/pull/3675) by [@uriyyo](https://github.com/uriyyo) - Include non-standard port numbers in rendered URLs, [#3652](https://github.com/pydantic/pydantic/pull/3652) by [@dolfinus](https://github.com/dolfinus) - `Config.copy_on_model_validation` does a deep copy and not a shallow one, [#3641](https://github.com/pydantic/pydantic/pull/3641) by [@PrettyWood](https://github.com/PrettyWood) - fix: clarify that discriminated unions do not support singletons, [#3636](https://github.com/pydantic/pydantic/pull/3636) by [@tommilligan](https://github.com/tommilligan) - Add `read_text(encoding='utf-8')` for `setup.py`, [#3625](https://github.com/pydantic/pydantic/pull/3625) by [@hswong3i](https://github.com/hswong3i) - Fix JSON Schema generation for Discriminated Unions within lists, [#3608](https://github.com/pydantic/pydantic/pull/3608) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.9.0 (2021-12-31) Thank you to pydantic's sponsors: [@sthagen](https://github.com/sthagen), [@timdrijvers](https://github.com/timdrijvers), [@toinbis](https://github.com/toinbis), [@koxudaxi](https://github.com/koxudaxi), [@ginomempin](https://github.com/ginomempin), [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@westonsteimel](https://github.com/westonsteimel), [@reillysiemens](https://github.com/reillysiemens), [@es3n1n](https://github.com/es3n1n), [@jokull](https://github.com/jokull), [@JonasKs](https://github.com/JonasKs), [@Rehket](https://github.com/Rehket), [@corleyma](https://github.com/corleyma), [@daddycocoaman](https://github.com/daddycocoaman), [@hardbyte](https://github.com/hardbyte), [@datarootsio](https://github.com/datarootsio), [@jodal](https://github.com/jodal), [@aminalaee](https://github.com/aminalaee), [@rafsaf](https://github.com/rafsaf), [@jqueguiner](https://github.com/jqueguiner), [@chdsbd](https://github.com/chdsbd), [@kevinalh](https://github.com/kevinalh), [@Mazyod](https://github.com/Mazyod), [@grillazz](https://github.com/grillazz), [@JonasKs](https://github.com/JonasKs), [@simw](https://github.com/simw), [@leynier](https://github.com/leynier), [@xfenix](https://github.com/xfenix) for their kind support. ### Highlights - add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/pull/2885) by [@PrettyWood](https://github.com/PrettyWood) - [Discriminated unions](https://docs.pydantic.dev/usage/types/#discriminated-unions-aka-tagged-unions), [#619](https://github.com/pydantic/pydantic/pull/619) by [@PrettyWood](https://github.com/PrettyWood) - [`Config.smart_union` for better union logic](https://docs.pydantic.dev/usage/model_config/#smart-union), [#2092](https://github.com/pydantic/pydantic/pull/2092) by [@PrettyWood](https://github.com/PrettyWood) - Binaries for Macos M1 CPUs, [#3498](https://github.com/pydantic/pydantic/pull/3498) by [@samuelcolvin](https://github.com/samuelcolvin) - Complex types can be set via [nested environment variables](https://docs.pydantic.dev/usage/settings/#parsing-environment-variable-values), e.g. `foo___bar`, [#3159](https://github.com/pydantic/pydantic/pull/3159) by [@Air-Mark](https://github.com/Air-Mark) - add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/pull/2913) by [@gbdlin](https://github.com/gbdlin) - Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/pull/2721) by [@tiangolo](https://github.com/tiangolo) - Add "exclude" as a field parameter so that it can be configured using model config, [#660](https://github.com/pydantic/pydantic/pull/660) by [@daviskirk](https://github.com/daviskirk) ### v1.9.0 (2021-12-31) Changes - Apply `update_forward_refs` to `Config.json_encodes` prevent name clashes in types defined via strings, [#3583](https://github.com/pydantic/pydantic/pull/3583) by [@samuelcolvin](https://github.com/samuelcolvin) - Extend pydantic's mypy plugin to support mypy versions `0.910`, `0.920`, `0.921` & `0.930`, [#3573](https://github.com/pydantic/pydantic/pull/3573) & [#3594](https://github.com/pydantic/pydantic/pull/3594) by [@PrettyWood](https://github.com/PrettyWood), [@christianbundy](https://github.com/christianbundy), [@samuelcolvin](https://github.com/samuelcolvin) ### v1.9.0a2 (2021-12-24) Changes - support generic models with discriminated union, [#3551](https://github.com/pydantic/pydantic/pull/3551) by [@PrettyWood](https://github.com/PrettyWood) - keep old behaviour of `json()` by default, [#3542](https://github.com/pydantic/pydantic/pull/3542) by [@PrettyWood](https://github.com/PrettyWood) - Removed typing-only `__root__` attribute from `BaseModel`, [#3540](https://github.com/pydantic/pydantic/pull/3540) by [@layday](https://github.com/layday) - Build Python 3.10 wheels, [#3539](https://github.com/pydantic/pydantic/pull/3539) by [@mbachry](https://github.com/mbachry) - Fix display of `extra` fields with model `__repr__`, [#3234](https://github.com/pydantic/pydantic/pull/3234) by [@cocolman](https://github.com/cocolman) - models copied via `Config.copy_on_model_validation` always have all fields, [#3201](https://github.com/pydantic/pydantic/pull/3201) by [@PrettyWood](https://github.com/PrettyWood) - nested ORM from nested dictionaries, [#3182](https://github.com/pydantic/pydantic/pull/3182) by [@PrettyWood](https://github.com/PrettyWood) - fix link to discriminated union section by [@PrettyWood](https://github.com/PrettyWood) ### v1.9.0a1 (2021-12-18) Changes - Add support for `Decimal`\-specific validation configurations in `Field()`, additionally to using `condecimal()`, to allow better support from editors and tooling, [#3507](https://github.com/pydantic/pydantic/pull/3507) by [@tiangolo](https://github.com/tiangolo) - Add `arm64` binaries suitable for MacOS with an M1 CPU to PyPI, [#3498](https://github.com/pydantic/pydantic/pull/3498) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix issue where `None` was considered invalid when using a `Union` type containing `Any` or `object`, [#3444](https://github.com/pydantic/pydantic/pull/3444) by [@tharradine](https://github.com/tharradine) - When generating field schema, pass optional `field` argument (of type `pydantic.fields.ModelField`) to `__modify_schema__()` if present, [#3434](https://github.com/pydantic/pydantic/pull/3434) by [@jasujm](https://github.com/jasujm) - Fix issue when pydantic fail to parse `typing.ClassVar` string type annotation, [#3401](https://github.com/pydantic/pydantic/pull/3401) by [@uriyyo](https://github.com/uriyyo) - Mention Python >= 3.9.2 as an alternative to `typing_extensions.TypedDict`, [#3374](https://github.com/pydantic/pydantic/pull/3374) by [@BvB93](https://github.com/BvB93) - Changed the validator method name in the [Custom Errors example](https://docs.pydantic.dev/usage/models/#custom-errors) to more accurately describe what the validator is doing; changed from `name_must_contain_space` to `value_must_equal_bar`, [#3327](https://github.com/pydantic/pydantic/pull/3327) by [@michaelrios28](https://github.com/michaelrios28) - Add `AmqpDsn` class, [#3254](https://github.com/pydantic/pydantic/pull/3254) by [@kludex](https://github.com/kludex) - Always use `Enum` value as default in generated JSON schema, [#3190](https://github.com/pydantic/pydantic/pull/3190) by [@joaommartins](https://github.com/joaommartins) - Add support for Mypy 0.920, [#3175](https://github.com/pydantic/pydantic/pull/3175) by [@christianbundy](https://github.com/christianbundy) - `validate_arguments` now supports `extra` customization (used to always be `Extra.forbid`), [#3161](https://github.com/pydantic/pydantic/pull/3161) by [@PrettyWood](https://github.com/PrettyWood) - Complex types can be set by nested environment variables, [#3159](https://github.com/pydantic/pydantic/pull/3159) by [@Air-Mark](https://github.com/Air-Mark) - Fix mypy plugin to collect fields based on `pydantic.utils.is_valid_field` so that it ignores untyped private variables, [#3146](https://github.com/pydantic/pydantic/pull/3146) by [@hi-ogawa](https://github.com/hi-ogawa) - fix `validate_arguments` issue with `Config.validate_all`, [#3135](https://github.com/pydantic/pydantic/pull/3135) by [@PrettyWood](https://github.com/PrettyWood) - avoid dict coercion when using dict subclasses as field type, [#3122](https://github.com/pydantic/pydantic/pull/3122) by [@PrettyWood](https://github.com/PrettyWood) - add support for `object` type, [#3062](https://github.com/pydantic/pydantic/pull/3062) by [@PrettyWood](https://github.com/PrettyWood) - Updates pydantic dataclasses to keep `_special` properties on parent classes, [#3043](https://github.com/pydantic/pydantic/pull/3043) by [@zulrang](https://github.com/zulrang) - Add a `TypedDict` class for error objects, [#3038](https://github.com/pydantic/pydantic/pull/3038) by [@matthewhughes934](https://github.com/matthewhughes934) - Fix support for using a subclass of an annotation as a default, [#3018](https://github.com/pydantic/pydantic/pull/3018) by [@JacobHayes](https://github.com/JacobHayes) - make `create_model_from_typeddict` mypy compliant, [#3008](https://github.com/pydantic/pydantic/pull/3008) by [@PrettyWood](https://github.com/PrettyWood) - Make multiple inheritance work when using `PrivateAttr`, [#2989](https://github.com/pydantic/pydantic/pull/2989) by [@hmvp](https://github.com/hmvp) - Parse environment variables as JSON, if they have a `Union` type with a complex subfield, [#2936](https://github.com/pydantic/pydantic/pull/2936) by [@cbartz](https://github.com/cbartz) - Prevent `StrictStr` permitting `Enum` values where the enum inherits from `str`, [#2929](https://github.com/pydantic/pydantic/pull/2929) by [@samuelcolvin](https://github.com/samuelcolvin) - Make `SecretsSettingsSource` parse values being assigned to fields of complex types when sourced from a secrets file, just as when sourced from environment variables, [#2917](https://github.com/pydantic/pydantic/pull/2917) by [@davidmreed](https://github.com/davidmreed) - add a dark mode to _pydantic_ documentation, [#2913](https://github.com/pydantic/pydantic/pull/2913) by [@gbdlin](https://github.com/gbdlin) - Make `pydantic-mypy` plugin compatible with `pyproject.toml` configuration, consistent with `mypy` changes. See the [doc](https://docs.pydantic.dev/mypy_plugin/#configuring-the-plugin) for more information, [#2908](https://github.com/pydantic/pydantic/pull/2908) by [@jrwalk](https://github.com/jrwalk) - add Python 3.10 support, [#2885](https://github.com/pydantic/pydantic/pull/2885) by [@PrettyWood](https://github.com/PrettyWood) - Correctly parse generic models with `Json[T]`, [#2860](https://github.com/pydantic/pydantic/pull/2860) by [@geekingfrog](https://github.com/geekingfrog) - Update contrib docs re: Python version to use for building docs, [#2856](https://github.com/pydantic/pydantic/pull/2856) by [@paxcodes](https://github.com/paxcodes) - Clarify documentation about _pydantic_'s support for custom validation and strict type checking, despite _pydantic_ being primarily a parsing library, [#2855](https://github.com/pydantic/pydantic/pull/2855) by [@paxcodes](https://github.com/paxcodes) - Fix schema generation for `Deque` fields, [#2810](https://github.com/pydantic/pydantic/pull/2810) by [@sergejkozin](https://github.com/sergejkozin) - fix an edge case when mixing constraints and `Literal`, [#2794](https://github.com/pydantic/pydantic/pull/2794) by [@PrettyWood](https://github.com/PrettyWood) - Fix postponed annotation resolution for `NamedTuple` and `TypedDict` when they're used directly as the type of fields within Pydantic models, [#2760](https://github.com/pydantic/pydantic/pull/2760) by [@jameysharp](https://github.com/jameysharp) - Fix bug when `mypy` plugin fails on `construct` method call for `BaseSettings` derived classes, [#2753](https://github.com/pydantic/pydantic/pull/2753) by [@uriyyo](https://github.com/uriyyo) - Add function overloading for a `pydantic.create_model` function, [#2748](https://github.com/pydantic/pydantic/pull/2748) by [@uriyyo](https://github.com/uriyyo) - Fix mypy plugin issue with self field declaration, [#2743](https://github.com/pydantic/pydantic/pull/2743) by [@uriyyo](https://github.com/uriyyo) - The colon at the end of the line "The fields which were supplied when user was initialised:" suggests that the code following it is related. Changed it to a period, [#2733](https://github.com/pydantic/pydantic/pull/2733) by [@krisaoe](https://github.com/krisaoe) - Renamed variable `schema` to `schema_` to avoid shadowing of global variable name, [#2724](https://github.com/pydantic/pydantic/pull/2724) by [@shahriyarr](https://github.com/shahriyarr) - Add support for autocomplete in VS Code via `__dataclass_transform__`, [#2721](https://github.com/pydantic/pydantic/pull/2721) by [@tiangolo](https://github.com/tiangolo) - add missing type annotations in `BaseConfig` and handle `max_length = 0`, [#2719](https://github.com/pydantic/pydantic/pull/2719) by [@PrettyWood](https://github.com/PrettyWood) - Change `orm_mode` checking to allow recursive ORM mode parsing with dicts, [#2718](https://github.com/pydantic/pydantic/pull/2718) by [@nuno-andre](https://github.com/nuno-andre) - Add episode 313 of the _Talk Python To Me_ podcast, where Michael Kennedy and Samuel Colvin discuss Pydantic, to the docs, [#2712](https://github.com/pydantic/pydantic/pull/2712) by [@RatulMaharaj](https://github.com/RatulMaharaj) - fix JSON schema generation when a field is of type `NamedTuple` and has a default value, [#2707](https://github.com/pydantic/pydantic/pull/2707) by [@PrettyWood](https://github.com/PrettyWood) - `Enum` fields now properly support extra kwargs in schema generation, [#2697](https://github.com/pydantic/pydantic/pull/2697) by [@sammchardy](https://github.com/sammchardy) - **Breaking Change, see [#3780](https://github.com/pydantic/pydantic/pull/3780)**: Make serialization of referenced pydantic models possible, [#2650](https://github.com/pydantic/pydantic/pull/2650) by [@PrettyWood](https://github.com/PrettyWood) - Add `uniqueItems` option to `ConstrainedList`, [#2618](https://github.com/pydantic/pydantic/pull/2618) by [@nuno-andre](https://github.com/nuno-andre) - Try to evaluate forward refs automatically at model creation, [#2588](https://github.com/pydantic/pydantic/pull/2588) by [@uriyyo](https://github.com/uriyyo) - Switch docs preview and coverage display to use [smokeshow](https://smokeshow.helpmanual.io/), [#2580](https://github.com/pydantic/pydantic/pull/2580) by [@samuelcolvin](https://github.com/samuelcolvin) - Add `__version__` attribute to pydantic module, [#2572](https://github.com/pydantic/pydantic/pull/2572) by [@paxcodes](https://github.com/paxcodes) - Add `postgresql+asyncpg`, `postgresql+pg8000`, `postgresql+psycopg2`, `postgresql+psycopg2cffi`, `postgresql+py-postgresql` and `postgresql+pygresql` schemes for `PostgresDsn`, [#2567](https://github.com/pydantic/pydantic/pull/2567) by [@postgres-asyncpg](https://github.com/postgres-asyncpg) - Enable the Hypothesis plugin to generate a constrained decimal when the `decimal_places` argument is specified, [#2524](https://github.com/pydantic/pydantic/pull/2524) by [@cwe5590](https://github.com/cwe5590) - Allow `collections.abc.Callable` to be used as type in Python 3.9, [#2519](https://github.com/pydantic/pydantic/pull/2519) by [@daviskirk](https://github.com/daviskirk) - Documentation update how to custom compile pydantic when using pip install, small change in `setup.py` to allow for custom CFLAGS when compiling, [#2517](https://github.com/pydantic/pydantic/pull/2517) by [@peterroelants](https://github.com/peterroelants) - remove side effect of `default_factory` to run it only once even if `Config.validate_all` is set, [#2515](https://github.com/pydantic/pydantic/pull/2515) by [@PrettyWood](https://github.com/PrettyWood) - Add lookahead to ip regexes for `AnyUrl` hosts. This allows urls with DNS labels looking like IPs to validate as they are perfectly valid host names, [#2512](https://github.com/pydantic/pydantic/pull/2512) by [@sbv-csis](https://github.com/sbv-csis) - Set `minItems` and `maxItems` in generated JSON schema for fixed-length tuples, [#2497](https://github.com/pydantic/pydantic/pull/2497) by [@PrettyWood](https://github.com/PrettyWood) - Add `strict` argument to `conbytes`, [#2489](https://github.com/pydantic/pydantic/pull/2489) by [@koxudaxi](https://github.com/koxudaxi) - Support user defined generic field types in generic models, [#2465](https://github.com/pydantic/pydantic/pull/2465) by [@daviskirk](https://github.com/daviskirk) - Add an example and a short explanation of subclassing `GetterDict` to docs, [#2463](https://github.com/pydantic/pydantic/pull/2463) by [@nuno-andre](https://github.com/nuno-andre) - add `KafkaDsn` type, `HttpUrl` now has default port 80 for http and 443 for https, [#2447](https://github.com/pydantic/pydantic/pull/2447) by [@MihanixA](https://github.com/MihanixA) - Add `PastDate` and `FutureDate` types, [#2425](https://github.com/pydantic/pydantic/pull/2425) by [@Kludex](https://github.com/Kludex) - Support generating schema for `Generic` fields with subtypes, [#2375](https://github.com/pydantic/pydantic/pull/2375) by [@maximberg](https://github.com/maximberg) - fix(encoder): serialize `NameEmail` to str, [#2341](https://github.com/pydantic/pydantic/pull/2341) by [@alecgerona](https://github.com/alecgerona) - add `Config.smart_union` to prevent coercion in `Union` if possible, see [the doc](https://docs.pydantic.dev/usage/model_config/#smart-union) for more information, [#2092](https://github.com/pydantic/pydantic/pull/2092) by [@PrettyWood](https://github.com/PrettyWood) - Add ability to use `typing.Counter` as a model field type, [#2060](https://github.com/pydantic/pydantic/pull/2060) by [@uriyyo](https://github.com/uriyyo) - Add parameterised subclasses to `__bases__` when constructing new parameterised classes, so that `A <: B => A[int] <: B[int]`, [#2007](https://github.com/pydantic/pydantic/pull/2007) by [@diabolo-dan](https://github.com/diabolo-dan) - Create `FileUrl` type that allows URLs that conform to [RFC 8089](https://tools.ietf.org/html/rfc8089#section-2). Add `host_required` parameter, which is `True` by default (`AnyUrl` and subclasses), `False` in `RedisDsn`, `FileUrl`, [#1983](https://github.com/pydantic/pydantic/pull/1983) by [@vgerak](https://github.com/vgerak) - add `confrozenset()`, analogous to `conset()` and `conlist()`, [#1897](https://github.com/pydantic/pydantic/pull/1897) by [@PrettyWood](https://github.com/PrettyWood) - stop calling parent class `root_validator` if overridden, [#1895](https://github.com/pydantic/pydantic/pull/1895) by [@PrettyWood](https://github.com/PrettyWood) - Add `repr` (defaults to `True`) parameter to `Field`, to hide it from the default representation of the `BaseModel`, [#1831](https://github.com/pydantic/pydantic/pull/1831) by [@fnep](https://github.com/fnep) - Accept empty query/fragment URL parts, [#1807](https://github.com/pydantic/pydantic/pull/1807) by [@xavier](https://github.com/xavier) ## v1.8.2 (2021-05-11) Caution A security vulnerability, level "moderate" is fixed in v1.8.2. Please upgrade **ASAP**. See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) - **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` (or their negative values) does not cause an infinite loop, see security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) - fix schema generation with Enum by generating a valid name, [#2575](https://github.com/pydantic/pydantic/pull/2575) by [@PrettyWood](https://github.com/PrettyWood) - fix JSON schema generation with a `Literal` of an enum member, [#2536](https://github.com/pydantic/pydantic/pull/2536) by [@PrettyWood](https://github.com/PrettyWood) - Fix bug with configurations declarations that are passed as keyword arguments during class creation, [#2532](https://github.com/pydantic/pydantic/pull/2532) by [@uriyyo](https://github.com/uriyyo) - Allow passing `json_encoders` in class kwargs, [#2521](https://github.com/pydantic/pydantic/pull/2521) by [@layday](https://github.com/layday) - support arbitrary types with custom `__eq__`, [#2483](https://github.com/pydantic/pydantic/pull/2483) by [@PrettyWood](https://github.com/PrettyWood) - support `Annotated` in `validate_arguments` and in generic models with Python 3.9, [#2483](https://github.com/pydantic/pydantic/pull/2483) by [@PrettyWood](https://github.com/PrettyWood) ## v1.8.1 (2021-03-03) Bug fixes for regressions and new features from `v1.8` - allow elements of `Config.field` to update elements of a `Field`, [#2461](https://github.com/pydantic/pydantic/pull/2461) by [@samuelcolvin](https://github.com/samuelcolvin) - fix validation with a `BaseModel` field and a custom root type, [#2449](https://github.com/pydantic/pydantic/pull/2449) by [@PrettyWood](https://github.com/PrettyWood) - expose `Pattern` encoder to `fastapi`, [#2444](https://github.com/pydantic/pydantic/pull/2444) by [@PrettyWood](https://github.com/PrettyWood) - enable the Hypothesis plugin to generate a constrained float when the `multiple_of` argument is specified, [#2442](https://github.com/pydantic/pydantic/pull/2442) by [@tobi-lipede-oodle](https://github.com/tobi-lipede-oodle) - Avoid `RecursionError` when using some types like `Enum` or `Literal` with generic models, [#2436](https://github.com/pydantic/pydantic/pull/2436) by [@PrettyWood](https://github.com/PrettyWood) - do not overwrite declared `__hash__` in subclasses of a model, [#2422](https://github.com/pydantic/pydantic/pull/2422) by [@PrettyWood](https://github.com/PrettyWood) - fix `mypy` complaints on `Path` and `UUID` related custom types, [#2418](https://github.com/pydantic/pydantic/pull/2418) by [@PrettyWood](https://github.com/PrettyWood) - Support properly variable length tuples of compound types, [#2416](https://github.com/pydantic/pydantic/pull/2416) by [@PrettyWood](https://github.com/PrettyWood) ## v1.8 (2021-02-26) Thank you to pydantic's sponsors: [@jorgecarleitao](https://github.com/jorgecarleitao), [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@koxudaxi](https://github.com/koxudaxi), [@timdrijvers](https://github.com/timdrijvers), [@mkeen](https://github.com/mkeen), [@meadsteve](https://github.com/meadsteve), [@ginomempin](https://github.com/ginomempin), [@primer-io](https://github.com/primer-io), [@and-semakin](https://github.com/and-semakin), [@tomthorogood](https://github.com/tomthorogood), [@AjitZK](https://github.com/AjitZK), [@westonsteimel](https://github.com/westonsteimel), [@Mazyod](https://github.com/Mazyod), [@christippett](https://github.com/christippett), [@CarlosDomingues](https://github.com/CarlosDomingues), [@Kludex](https://github.com/Kludex), [@r-m-n](https://github.com/r-m-n) for their kind support. ### Highlights - [Hypothesis plugin](https://docs.pydantic.dev/hypothesis_plugin/) for testing, [#2097](https://github.com/pydantic/pydantic/pull/2097) by [@Zac-HD](https://github.com/Zac-HD) - support for [`NamedTuple` and `TypedDict`](https://docs.pydantic.dev/usage/types/#annotated-types), [#2216](https://github.com/pydantic/pydantic/pull/2216) by [@PrettyWood](https://github.com/PrettyWood) - Support [`Annotated` hints on model fields](https://docs.pydantic.dev/usage/schema/#typingannotated-fields), [#2147](https://github.com/pydantic/pydantic/pull/2147) by [@JacobHayes](https://github.com/JacobHayes) - [`frozen` parameter on `Config`](https://docs.pydantic.dev/usage/model_config/) to allow models to be hashed, [#1880](https://github.com/pydantic/pydantic/pull/1880) by [@rhuille](https://github.com/rhuille) ### Changes - **Breaking Change**, remove old deprecation aliases from v1, [#2415](https://github.com/pydantic/pydantic/pull/2415) by [@samuelcolvin](https://github.com/samuelcolvin): - remove notes on migrating to v1 in docs - remove `Schema` which was replaced by `Field` - remove `Config.case_insensitive` which was replaced by `Config.case_sensitive` (default `False`) - remove `Config.allow_population_by_alias` which was replaced by `Config.allow_population_by_field_name` - remove `model.fields` which was replaced by `model.__fields__` - remove `model.to_string()` which was replaced by `str(model)` - remove `model.__values__` which was replaced by `model.__dict__` - **Breaking Change:** always validate only first sublevel items with `each_item`. There were indeed some edge cases with some compound types where the validated items were the last sublevel ones, [#1933](https://github.com/pydantic/pydantic/pull/1933) by [@PrettyWood](https://github.com/PrettyWood) - Update docs extensions to fix local syntax highlighting, [#2400](https://github.com/pydantic/pydantic/pull/2400) by [@daviskirk](https://github.com/daviskirk) - fix: allow `utils.lenient_issubclass` to handle `typing.GenericAlias` objects like `list[str]` in Python >= 3.9, [#2399](https://github.com/pydantic/pydantic/pull/2399) by [@daviskirk](https://github.com/daviskirk) - Improve field declaration for _pydantic_ `dataclass` by allowing the usage of _pydantic_ `Field` or `'metadata'` kwarg of `dataclasses.field`, [#2384](https://github.com/pydantic/pydantic/pull/2384) by [@PrettyWood](https://github.com/PrettyWood) - Making `typing-extensions` a required dependency, [#2368](https://github.com/pydantic/pydantic/pull/2368) by [@samuelcolvin](https://github.com/samuelcolvin) - Make `resolve_annotations` more lenient, allowing for missing modules, [#2363](https://github.com/pydantic/pydantic/pull/2363) by [@samuelcolvin](https://github.com/samuelcolvin) - Allow configuring models through class kwargs, [#2356](https://github.com/pydantic/pydantic/pull/2356) by [@Bobronium](https://github.com/Bobronium) - Prevent `Mapping` subclasses from always being coerced to `dict`, [#2325](https://github.com/pydantic/pydantic/pull/2325) by [@ofek](https://github.com/ofek) - fix: allow `None` for type `Optional[conset / conlist]`, [#2320](https://github.com/pydantic/pydantic/pull/2320) by [@PrettyWood](https://github.com/PrettyWood) - Support empty tuple type, [#2318](https://github.com/pydantic/pydantic/pull/2318) by [@PrettyWood](https://github.com/PrettyWood) - fix: `python_requires` metadata to require >=3.6.1, [#2306](https://github.com/pydantic/pydantic/pull/2306) by [@hukkinj1](https://github.com/hukkinj1) - Properly encode `Decimal` with, or without any decimal places, [#2293](https://github.com/pydantic/pydantic/pull/2293) by [@hultner](https://github.com/hultner) - fix: update `__fields_set__` in `BaseModel.copy(update=...)`, [#2290](https://github.com/pydantic/pydantic/pull/2290) by [@PrettyWood](https://github.com/PrettyWood) - fix: keep order of fields with `BaseModel.construct()`, [#2281](https://github.com/pydantic/pydantic/pull/2281) by [@PrettyWood](https://github.com/PrettyWood) - Support generating schema for Generic fields, [#2262](https://github.com/pydantic/pydantic/pull/2262) by [@maximberg](https://github.com/maximberg) - Fix `validate_decorator` so `**kwargs` doesn't exclude values when the keyword has the same name as the `*args` or `**kwargs` names, [#2251](https://github.com/pydantic/pydantic/pull/2251) by [@cybojenix](https://github.com/cybojenix) - Prevent overriding positional arguments with keyword arguments in `validate_arguments`, as per behaviour with native functions, [#2249](https://github.com/pydantic/pydantic/pull/2249) by [@cybojenix](https://github.com/cybojenix) - add documentation for `con*` type functions, [#2242](https://github.com/pydantic/pydantic/pull/2242) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) - Support custom root type (aka `__root__`) when using `parse_obj()` with nested models, [#2238](https://github.com/pydantic/pydantic/pull/2238) by [@PrettyWood](https://github.com/PrettyWood) - Support custom root type (aka `__root__`) with `from_orm()`, [#2237](https://github.com/pydantic/pydantic/pull/2237) by [@PrettyWood](https://github.com/PrettyWood) - ensure cythonized functions are left untouched when creating models, based on [#1944](https://github.com/pydantic/pydantic/pull/1944) by [@kollmats](https://github.com/kollmats), [#2228](https://github.com/pydantic/pydantic/pull/2228) by [@samuelcolvin](https://github.com/samuelcolvin) - Resolve forward refs for stdlib dataclasses converted into _pydantic_ ones, [#2220](https://github.com/pydantic/pydantic/pull/2220) by [@PrettyWood](https://github.com/PrettyWood) - Add support for `NamedTuple` and `TypedDict` types. Those two types are now handled and validated when used inside `BaseModel` or _pydantic_ `dataclass`. Two utils are also added `create_model_from_namedtuple` and `create_model_from_typeddict`, [#2216](https://github.com/pydantic/pydantic/pull/2216) by [@PrettyWood](https://github.com/PrettyWood) - Do not ignore annotated fields when type is `Union[Type[...], ...]`, [#2213](https://github.com/pydantic/pydantic/pull/2213) by [@PrettyWood](https://github.com/PrettyWood) - Raise a user-friendly `TypeError` when a `root_validator` does not return a `dict` (e.g. `None`), [#2209](https://github.com/pydantic/pydantic/pull/2209) by [@masalim2](https://github.com/masalim2) - Add a `FrozenSet[str]` type annotation to the `allowed_schemes` argument on the `strict_url` field type, [#2198](https://github.com/pydantic/pydantic/pull/2198) by [@Midnighter](https://github.com/Midnighter) - add `allow_mutation` constraint to `Field`, [#2195](https://github.com/pydantic/pydantic/pull/2195) by [@sblack-usu](https://github.com/sblack-usu) - Allow `Field` with a `default_factory` to be used as an argument to a function decorated with `validate_arguments`, [#2176](https://github.com/pydantic/pydantic/pull/2176) by [@thomascobb](https://github.com/thomascobb) - Allow non-existent secrets directory by only issuing a warning, [#2175](https://github.com/pydantic/pydantic/pull/2175) by [@davidolrik](https://github.com/davidolrik) - fix URL regex to parse fragment without query string, [#2168](https://github.com/pydantic/pydantic/pull/2168) by [@andrewmwhite](https://github.com/andrewmwhite) - fix: ensure to always return one of the values in `Literal` field type, [#2166](https://github.com/pydantic/pydantic/pull/2166) by [@PrettyWood](https://github.com/PrettyWood) - Support `typing.Annotated` hints on model fields. A `Field` may now be set in the type hint with `Annotated[..., Field(...)`; all other annotations are ignored but still visible with `get_type_hints(..., include_extras=True)`, [#2147](https://github.com/pydantic/pydantic/pull/2147) by [@JacobHayes](https://github.com/JacobHayes) - Added `StrictBytes` type as well as `strict=False` option to `ConstrainedBytes`, [#2136](https://github.com/pydantic/pydantic/pull/2136) by [@rlizzo](https://github.com/rlizzo) - added `Config.anystr_lower` and `to_lower` kwarg to `constr` and `conbytes`, [#2134](https://github.com/pydantic/pydantic/pull/2134) by [@tayoogunbiyi](https://github.com/tayoogunbiyi) - Support plain `typing.Tuple` type, [#2132](https://github.com/pydantic/pydantic/pull/2132) by [@PrettyWood](https://github.com/PrettyWood) - Add a bound method `validate` to functions decorated with `validate_arguments` to validate parameters without actually calling the function, [#2127](https://github.com/pydantic/pydantic/pull/2127) by [@PrettyWood](https://github.com/PrettyWood) - Add the ability to customize settings sources (add / disable / change priority order), [#2107](https://github.com/pydantic/pydantic/pull/2107) by [@kozlek](https://github.com/kozlek) - Fix mypy complaints about most custom _pydantic_ types, [#2098](https://github.com/pydantic/pydantic/pull/2098) by [@PrettyWood](https://github.com/PrettyWood) - Add a [Hypothesis](https://hypothesis.readthedocs.io/) plugin for easier [property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/) with Pydantic's custom types - [usage details here](https://docs.pydantic.dev/hypothesis_plugin/), [#2097](https://github.com/pydantic/pydantic/pull/2097) by [@Zac-HD](https://github.com/Zac-HD) - add validator for `None`, `NoneType` or `Literal[None]`, [#2095](https://github.com/pydantic/pydantic/pull/2095) by [@PrettyWood](https://github.com/PrettyWood) - Handle properly fields of type `Callable` with a default value, [#2094](https://github.com/pydantic/pydantic/pull/2094) by [@PrettyWood](https://github.com/PrettyWood) - Updated `create_model` return type annotation to return type which inherits from `__base__` argument, [#2071](https://github.com/pydantic/pydantic/pull/2071) by [@uriyyo](https://github.com/uriyyo) - Add merged `json_encoders` inheritance, [#2064](https://github.com/pydantic/pydantic/pull/2064) by [@art049](https://github.com/art049) - allow overwriting `ClassVar`s in sub-models without having to re-annotate them, [#2061](https://github.com/pydantic/pydantic/pull/2061) by [@layday](https://github.com/layday) - add default encoder for `Pattern` type, [#2045](https://github.com/pydantic/pydantic/pull/2045) by [@PrettyWood](https://github.com/PrettyWood) - Add `NonNegativeInt`, `NonPositiveInt`, `NonNegativeFloat`, `NonPositiveFloat`, [#1975](https://github.com/pydantic/pydantic/pull/1975) by [@mdavis-xyz](https://github.com/mdavis-xyz) - Use % for percentage in string format of colors, [#1960](https://github.com/pydantic/pydantic/pull/1960) by [@EdwardBetts](https://github.com/EdwardBetts) - Fixed issue causing `KeyError` to be raised when building schema from multiple `BaseModel` with the same names declared in separate classes, [#1912](https://github.com/pydantic/pydantic/pull/1912) by [@JSextonn](https://github.com/JSextonn) - Add `rediss` (Redis over SSL) protocol to `RedisDsn` Allow URLs without `user` part (e.g., `rediss://:pass@localhost`), [#1911](https://github.com/pydantic/pydantic/pull/1911) by [@TrDex](https://github.com/TrDex) - Add a new `frozen` boolean parameter to `Config` (default: `False`). Setting `frozen=True` does everything that `allow_mutation=False` does, and also generates a `__hash__()` method for the model. This makes instances of the model potentially hashable if all the attributes are hashable, [#1880](https://github.com/pydantic/pydantic/pull/1880) by [@rhuille](https://github.com/rhuille) - fix schema generation with multiple Enums having the same name, [#1857](https://github.com/pydantic/pydantic/pull/1857) by [@PrettyWood](https://github.com/PrettyWood) - Added support for 13/19 digits VISA credit cards in `PaymentCardNumber` type, [#1416](https://github.com/pydantic/pydantic/pull/1416) by [@AlexanderSov](https://github.com/AlexanderSov) - fix: prevent `RecursionError` while using recursive `GenericModel`s, [#1370](https://github.com/pydantic/pydantic/pull/1370) by [@xppt](https://github.com/xppt) - use `enum` for `typing.Literal` in JSON schema, [#1350](https://github.com/pydantic/pydantic/pull/1350) by [@PrettyWood](https://github.com/PrettyWood) - Fix: some recursive models did not require `update_forward_refs` and silently behaved incorrectly, [#1201](https://github.com/pydantic/pydantic/pull/1201) by [@PrettyWood](https://github.com/PrettyWood) - Fix bug where generic models with fields where the typevar is nested in another type `a: List[T]` are considered to be concrete. This allows these models to be subclassed and composed as expected, [#947](https://github.com/pydantic/pydantic/pull/947) by [@daviskirk](https://github.com/daviskirk) - Add `Config.copy_on_model_validation` flag. When set to `False`, _pydantic_ will keep models used as fields untouched on validation instead of reconstructing (copying) them, [#265](https://github.com/pydantic/pydantic/pull/265) by [@PrettyWood](https://github.com/PrettyWood) ## v1.7.4 (2021-05-11) - **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` (or their negative values) does not cause an infinite loop, See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) ## v1.7.3 (2020-11-30) Thank you to pydantic's sponsors: [@timdrijvers](https://github.com/timdrijvers), [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), [@mkeen](https://github.com/mkeen), [@meadsteve](https://github.com/meadsteve) for their kind support. - fix: set right default value for required (optional) fields, [#2142](https://github.com/pydantic/pydantic/pull/2142) by [@PrettyWood](https://github.com/PrettyWood) - fix: support `underscore_attrs_are_private` with generic models, [#2138](https://github.com/pydantic/pydantic/pull/2138) by [@PrettyWood](https://github.com/PrettyWood) - fix: update all modified field values in `root_validator` when `validate_assignment` is on, [#2116](https://github.com/pydantic/pydantic/pull/2116) by [@PrettyWood](https://github.com/PrettyWood) - Allow pickling of `pydantic.dataclasses.dataclass` dynamically created from a built-in `dataclasses.dataclass`, [#2111](https://github.com/pydantic/pydantic/pull/2111) by [@aimestereo](https://github.com/aimestereo) - Fix a regression where Enum fields would not propagate keyword arguments to the schema, [#2109](https://github.com/pydantic/pydantic/pull/2109) by [@bm424](https://github.com/bm424) - Ignore `__doc__` as private attribute when `Config.underscore_attrs_are_private` is set, [#2090](https://github.com/pydantic/pydantic/pull/2090) by [@PrettyWood](https://github.com/PrettyWood) ## v1.7.2 (2020-11-01) - fix slow `GenericModel` concrete model creation, allow `GenericModel` concrete name reusing in module, [#2078](https://github.com/pydantic/pydantic/pull/2078) by [@Bobronium](https://github.com/Bobronium) - keep the order of the fields when `validate_assignment` is set, [#2073](https://github.com/pydantic/pydantic/pull/2073) by [@PrettyWood](https://github.com/PrettyWood) - forward all the params of the stdlib `dataclass` when converted into _pydantic_ `dataclass`, [#2065](https://github.com/pydantic/pydantic/pull/2065) by [@PrettyWood](https://github.com/PrettyWood) ## v1.7.1 (2020-10-28) Thank you to pydantic's sponsors: [@timdrijvers](https://github.com/timdrijvers), [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api), [@mkeen](https://github.com/mkeen) for their kind support. - fix annotation of `validate_arguments` when passing configuration as argument, [#2055](https://github.com/pydantic/pydantic/pull/2055) by [@layday](https://github.com/layday) - Fix mypy assignment error when using `PrivateAttr`, [#2048](https://github.com/pydantic/pydantic/pull/2048) by [@aphedges](https://github.com/aphedges) - fix `underscore_attrs_are_private` causing `TypeError` when overriding `__init__`, [#2047](https://github.com/pydantic/pydantic/pull/2047) by [@samuelcolvin](https://github.com/samuelcolvin) - Fixed regression introduced in v1.7 involving exception handling in field validators when `validate_assignment=True`, [#2044](https://github.com/pydantic/pydantic/pull/2044) by [@johnsabath](https://github.com/johnsabath) - fix: _pydantic_ `dataclass` can inherit from stdlib `dataclass` and `Config.arbitrary_types_allowed` is supported, [#2042](https://github.com/pydantic/pydantic/pull/2042) by [@PrettyWood](https://github.com/PrettyWood) ## v1.7 (2020-10-26) Thank you to pydantic's sponsors: [@timdrijvers](https://github.com/timdrijvers), [@BCarley](https://github.com/BCarley), [@chdsbd](https://github.com/chdsbd), [@tiangolo](https://github.com/tiangolo), [@matin](https://github.com/matin), [@linusg](https://github.com/linusg), [@kevinalh](https://github.com/kevinalh), [@jorgecarleitao](https://github.com/jorgecarleitao), [@koxudaxi](https://github.com/koxudaxi), [@primer-api](https://github.com/primer-api) for their kind support. ### Highlights - Python 3.9 support, thanks [@PrettyWood](https://github.com/PrettyWood) - [Private model attributes](https://docs.pydantic.dev/usage/models/#private-model-attributes), thanks [@Bobronium](https://github.com/Bobronium) - ["secrets files" support in `BaseSettings`](https://docs.pydantic.dev/usage/settings/#secret-support), thanks [@mdgilene](https://github.com/mdgilene) - [convert stdlib dataclasses to pydantic dataclasses and use stdlib dataclasses in models](https://docs.pydantic.dev/usage/dataclasses/#stdlib-dataclasses-and-pydantic-dataclasses), thanks [@PrettyWood](https://github.com/PrettyWood) ### Changes - **Breaking Change:** remove `__field_defaults__`, add `default_factory` support with `BaseModel.construct`. Use `.get_default()` method on fields in `__fields__` attribute instead, [#1732](https://github.com/pydantic/pydantic/pull/1732) by [@PrettyWood](https://github.com/PrettyWood) - Rearrange CI to run linting as a separate job, split install recipes for different tasks, [#2020](https://github.com/pydantic/pydantic/pull/2020) by [@samuelcolvin](https://github.com/samuelcolvin) - Allows subclasses of generic models to make some, or all, of the superclass's type parameters concrete, while also defining new type parameters in the subclass, [#2005](https://github.com/pydantic/pydantic/pull/2005) by [@choogeboom](https://github.com/choogeboom) - Call validator with the correct `values` parameter type in `BaseModel.__setattr__`, when `validate_assignment = True` in model config, [#1999](https://github.com/pydantic/pydantic/pull/1999) by [@me-ransh](https://github.com/me-ransh) - Force `fields.Undefined` to be a singleton object, fixing inherited generic model schemas, [#1981](https://github.com/pydantic/pydantic/pull/1981) by [@daviskirk](https://github.com/daviskirk) - Include tests in source distributions, [#1976](https://github.com/pydantic/pydantic/pull/1976) by [@sbraz](https://github.com/sbraz) - Add ability to use `min_length/max_length` constraints with secret types, [#1974](https://github.com/pydantic/pydantic/pull/1974) by [@uriyyo](https://github.com/uriyyo) - Also check `root_validators` when `validate_assignment` is on, [#1971](https://github.com/pydantic/pydantic/pull/1971) by [@PrettyWood](https://github.com/PrettyWood) - Fix const validators not running when custom validators are present, [#1957](https://github.com/pydantic/pydantic/pull/1957) by [@hmvp](https://github.com/hmvp) - add `deque` to field types, [#1935](https://github.com/pydantic/pydantic/pull/1935) by [@wozniakty](https://github.com/wozniakty) - add basic support for Python 3.9, [#1832](https://github.com/pydantic/pydantic/pull/1832) by [@PrettyWood](https://github.com/PrettyWood) - Fix typo in the anchor of exporting\_models.md#modelcopy and incorrect description, [#1821](https://github.com/pydantic/pydantic/pull/1821) by [@KimMachineGun](https://github.com/KimMachineGun) - Added ability for `BaseSettings` to read "secret files", [#1820](https://github.com/pydantic/pydantic/pull/1820) by [@mdgilene](https://github.com/mdgilene) - add `parse_raw_as` utility function, [#1812](https://github.com/pydantic/pydantic/pull/1812) by [@PrettyWood](https://github.com/PrettyWood) - Support home directory relative paths for `dotenv` files (e.g. `~/.env`), [#1803](https://github.com/pydantic/pydantic/pull/1803) by [@PrettyWood](https://github.com/PrettyWood) - Clarify documentation for `parse_file` to show that the argument should be a file _path_ not a file-like object, [#1794](https://github.com/pydantic/pydantic/pull/1794) by [@mdavis-xyz](https://github.com/mdavis-xyz) - Fix false positive from mypy plugin when a class nested within a `BaseModel` is named `Model`, [#1770](https://github.com/pydantic/pydantic/pull/1770) by [@selimb](https://github.com/selimb) - add basic support of Pattern type in schema generation, [#1767](https://github.com/pydantic/pydantic/pull/1767) by [@PrettyWood](https://github.com/PrettyWood) - Support custom title, description and default in schema of enums, [#1748](https://github.com/pydantic/pydantic/pull/1748) by [@PrettyWood](https://github.com/PrettyWood) - Properly represent `Literal` Enums when `use_enum_values` is True, [#1747](https://github.com/pydantic/pydantic/pull/1747) by [@noelevans](https://github.com/noelevans) - Allows timezone information to be added to strings to be formatted as time objects. Permitted formats are `Z` for UTC or an offset for absolute positive or negative time shifts. Or the timezone data can be omitted, [#1744](https://github.com/pydantic/pydantic/pull/1744) by [@noelevans](https://github.com/noelevans) - Add stub `__init__` with Python 3.6 signature for `ForwardRef`, [#1738](https://github.com/pydantic/pydantic/pull/1738) by [@sirtelemak](https://github.com/sirtelemak) - Fix behaviour with forward refs and optional fields in nested models, [#1736](https://github.com/pydantic/pydantic/pull/1736) by [@PrettyWood](https://github.com/PrettyWood) - add `Enum` and `IntEnum` as valid types for fields, [#1735](https://github.com/pydantic/pydantic/pull/1735) by [@PrettyWood](https://github.com/PrettyWood) - Change default value of `__module__` argument of `create_model` from `None` to `'pydantic.main'`. Set reference of created concrete model to it's module to allow pickling (not applied to models created in functions), [#1686](https://github.com/pydantic/pydantic/pull/1686) by [@Bobronium](https://github.com/Bobronium) - Add private attributes support, [#1679](https://github.com/pydantic/pydantic/pull/1679) by [@Bobronium](https://github.com/Bobronium) - add `config` to `@validate_arguments`, [#1663](https://github.com/pydantic/pydantic/pull/1663) by [@samuelcolvin](https://github.com/samuelcolvin) - Allow descendant Settings models to override env variable names for the fields defined in parent Settings models with `env` in their `Config`. Previously only `env_prefix` configuration option was applicable, [#1561](https://github.com/pydantic/pydantic/pull/1561) by [@ojomio](https://github.com/ojomio) - Support `ref_template` when creating schema `$ref`s, [#1479](https://github.com/pydantic/pydantic/pull/1479) by [@kilo59](https://github.com/kilo59) - Add a `__call__` stub to `PyObject` so that mypy will know that it is callable, [#1352](https://github.com/pydantic/pydantic/pull/1352) by [@brianmaissy](https://github.com/brianmaissy) - `pydantic.dataclasses.dataclass` decorator now supports built-in `dataclasses.dataclass`. It is hence possible to convert an existing `dataclass` easily to add Pydantic validation. Moreover nested dataclasses are also supported, [#744](https://github.com/pydantic/pydantic/pull/744) by [@PrettyWood](https://github.com/PrettyWood) ## v1.6.2 (2021-05-11) - **Security fix:** Fix `date` and `datetime` parsing so passing either `'infinity'` or `float('inf')` (or their negative values) does not cause an infinite loop, See security advisory [CVE-2021-29510](https://github.com/pydantic/pydantic/security/advisories/GHSA-5jqp-qgf6-3pvh) ## v1.6.1 (2020-07-15) - fix validation and parsing of nested models with `default_factory`, [#1710](https://github.com/pydantic/pydantic/pull/1710) by [@PrettyWood](https://github.com/PrettyWood) ## v1.6 (2020-07-11) Thank you to pydantic's sponsors: [@matin](https://github.com/matin), [@tiangolo](https://github.com/tiangolo), [@chdsbd](https://github.com/chdsbd), [@jorgecarleitao](https://github.com/jorgecarleitao), and 1 anonymous sponsor for their kind support. - Modify validators for `conlist` and `conset` to not have `always=True`, [#1682](https://github.com/pydantic/pydantic/pull/1682) by [@samuelcolvin](https://github.com/samuelcolvin) - add port check to `AnyUrl` (can't exceed 65536) ports are 16 unsigned bits: `0 <= port <= 2**16-1` src: [rfc793 header format](https://tools.ietf.org/html/rfc793#section-3.1), [#1654](https://github.com/pydantic/pydantic/pull/1654) by [@flapili](https://github.com/flapili) - Document default `regex` anchoring semantics, [#1648](https://github.com/pydantic/pydantic/pull/1648) by [@yurikhan](https://github.com/yurikhan) - Use `chain.from_iterable` in class\_validators.py. This is a faster and more idiomatic way of using `itertools.chain`. Instead of computing all the items in the iterable and storing them in memory, they are computed one-by-one and never stored as a huge list. This can save on both runtime and memory space, [#1642](https://github.com/pydantic/pydantic/pull/1642) by [@cool-RR](https://github.com/cool-RR) - Add `conset()`, analogous to `conlist()`, [#1623](https://github.com/pydantic/pydantic/pull/1623) by [@patrickkwang](https://github.com/patrickkwang) - make Pydantic errors (un)pickable, [#1616](https://github.com/pydantic/pydantic/pull/1616) by [@PrettyWood](https://github.com/PrettyWood) - Allow custom encoding for `dotenv` files, [#1615](https://github.com/pydantic/pydantic/pull/1615) by [@PrettyWood](https://github.com/PrettyWood) - Ensure `SchemaExtraCallable` is always defined to get type hints on BaseConfig, [#1614](https://github.com/pydantic/pydantic/pull/1614) by [@PrettyWood](https://github.com/PrettyWood) - Update datetime parser to support negative timestamps, [#1600](https://github.com/pydantic/pydantic/pull/1600) by [@mlbiche](https://github.com/mlbiche) - Update mypy, remove `AnyType` alias for `Type[Any]`, [#1598](https://github.com/pydantic/pydantic/pull/1598) by [@samuelcolvin](https://github.com/samuelcolvin) - Adjust handling of root validators so that errors are aggregated from _all_ failing root validators, instead of reporting on only the first root validator to fail, [#1586](https://github.com/pydantic/pydantic/pull/1586) by [@beezee](https://github.com/beezee) - Make `__modify_schema__` on Enums apply to the enum schema rather than fields that use the enum, [#1581](https://github.com/pydantic/pydantic/pull/1581) by [@therefromhere](https://github.com/therefromhere) - Fix behavior of `__all__` key when used in conjunction with index keys in advanced include/exclude of fields that are sequences, [#1579](https://github.com/pydantic/pydantic/pull/1579) by [@xspirus](https://github.com/xspirus) - Subclass validators do not run when referencing a `List` field defined in a parent class when `each_item=True`. Added an example to the docs illustrating this, [#1566](https://github.com/pydantic/pydantic/pull/1566) by [@samueldeklund](https://github.com/samueldeklund) - change `schema.field_class_to_schema` to support `frozenset` in schema, [#1557](https://github.com/pydantic/pydantic/pull/1557) by [@wangpeibao](https://github.com/wangpeibao) - Call `__modify_schema__` only for the field schema, [#1552](https://github.com/pydantic/pydantic/pull/1552) by [@PrettyWood](https://github.com/PrettyWood) - Move the assignment of `field.validate_always` in `fields.py` so the `always` parameter of validators work on inheritance, [#1545](https://github.com/pydantic/pydantic/pull/1545) by [@dcHHH](https://github.com/dcHHH) - Added support for UUID instantiation through 16 byte strings such as `b'\x12\x34\x56\x78' * 4`. This was done to support `BINARY(16)` columns in sqlalchemy, [#1541](https://github.com/pydantic/pydantic/pull/1541) by [@shawnwall](https://github.com/shawnwall) - Add a test assertion that `default_factory` can return a singleton, [#1523](https://github.com/pydantic/pydantic/pull/1523) by [@therefromhere](https://github.com/therefromhere) - Add `NameEmail.__eq__` so duplicate `NameEmail` instances are evaluated as equal, [#1514](https://github.com/pydantic/pydantic/pull/1514) by [@stephen-bunn](https://github.com/stephen-bunn) - Add datamodel-code-generator link in pydantic document site, [#1500](https://github.com/pydantic/pydantic/pull/1500) by [@koxudaxi](https://github.com/koxudaxi) - Added a "Discussion of Pydantic" section to the documentation, with a link to "Pydantic Introduction" video by Alexander Hultnér, [#1499](https://github.com/pydantic/pydantic/pull/1499) by [@hultner](https://github.com/hultner) - Avoid some side effects of `default_factory` by calling it only once if possible and by not setting a default value in the schema, [#1491](https://github.com/pydantic/pydantic/pull/1491) by [@PrettyWood](https://github.com/PrettyWood) - Added docs about dumping dataclasses to JSON, [#1487](https://github.com/pydantic/pydantic/pull/1487) by [@mikegrima](https://github.com/mikegrima) - Make `BaseModel.__signature__` class-only, so getting `__signature__` from model instance will raise `AttributeError`, [#1466](https://github.com/pydantic/pydantic/pull/1466) by [@Bobronium](https://github.com/Bobronium) - include `'format': 'password'` in the schema for secret types, [#1424](https://github.com/pydantic/pydantic/pull/1424) by [@atheuz](https://github.com/atheuz) - Modify schema constraints on `ConstrainedFloat` so that `exclusiveMinimum` and minimum are not included in the schema if they are equal to `-math.inf` and `exclusiveMaximum` and `maximum` are not included if they are equal to `math.inf`, [#1417](https://github.com/pydantic/pydantic/pull/1417) by [@vdwees](https://github.com/vdwees) - Squash internal `__root__` dicts in `.dict()` (and, by extension, in `.json()`), [#1414](https://github.com/pydantic/pydantic/pull/1414) by [@patrickkwang](https://github.com/patrickkwang) - Move `const` validator to post-validators so it validates the parsed value, [#1410](https://github.com/pydantic/pydantic/pull/1410) by [@selimb](https://github.com/selimb) - Fix model validation to handle nested literals, e.g. `Literal['foo', Literal['bar']]`, [#1364](https://github.com/pydantic/pydantic/pull/1364) by [@DBCerigo](https://github.com/DBCerigo) - Remove `user_required = True` from `RedisDsn`, neither user nor password are required, [#1275](https://github.com/pydantic/pydantic/pull/1275) by [@samuelcolvin](https://github.com/samuelcolvin) - Remove extra `allOf` from schema for fields with `Union` and custom `Field`, [#1209](https://github.com/pydantic/pydantic/pull/1209) by [@mostaphaRoudsari](https://github.com/mostaphaRoudsari) - Updates OpenAPI schema generation to output all enums as separate models. Instead of inlining the enum values in the model schema, models now use a `$ref` property to point to the enum definition, [#1173](https://github.com/pydantic/pydantic/pull/1173) by [@calvinwyoung](https://github.com/calvinwyoung) ## v1.5.1 (2020-04-23) - Signature generation with `extra: allow` never uses a field name, [#1418](https://github.com/pydantic/pydantic/pull/1418) by [@prettywood](https://github.com/prettywood) - Avoid mutating `Field` default value, [#1412](https://github.com/pydantic/pydantic/pull/1412) by [@prettywood](https://github.com/prettywood) ## v1.5 (2020-04-18) - Make includes/excludes arguments for `.dict()`, `._iter()`, ..., immutable, [#1404](https://github.com/pydantic/pydantic/pull/1404) by [@AlexECX](https://github.com/AlexECX) - Always use a field's real name with includes/excludes in `model._iter()`, regardless of `by_alias`, [#1397](https://github.com/pydantic/pydantic/pull/1397) by [@AlexECX](https://github.com/AlexECX) - Update constr regex example to include start and end lines, [#1396](https://github.com/pydantic/pydantic/pull/1396) by [@lmcnearney](https://github.com/lmcnearney) - Confirm that shallow `model.copy()` does make a shallow copy of attributes, [#1383](https://github.com/pydantic/pydantic/pull/1383) by [@samuelcolvin](https://github.com/samuelcolvin) - Renaming `model_name` argument of `main.create_model()` to `__model_name` to allow using `model_name` as a field name, [#1367](https://github.com/pydantic/pydantic/pull/1367) by [@kittipatv](https://github.com/kittipatv) - Replace raising of exception to silent passing for non-Var attributes in mypy plugin, [#1345](https://github.com/pydantic/pydantic/pull/1345) by [@b0g3r](https://github.com/b0g3r) - Remove `typing_extensions` dependency for Python 3.8, [#1342](https://github.com/pydantic/pydantic/pull/1342) by [@prettywood](https://github.com/prettywood) - Make `SecretStr` and `SecretBytes` initialization idempotent, [#1330](https://github.com/pydantic/pydantic/pull/1330) by [@atheuz](https://github.com/atheuz) - document making secret types dumpable using the json method, [#1328](https://github.com/pydantic/pydantic/pull/1328) by [@atheuz](https://github.com/atheuz) - Move all testing and build to github actions, add windows and macos binaries, thank you [@StephenBrown2](https://github.com/StephenBrown2) for much help, [#1326](https://github.com/pydantic/pydantic/pull/1326) by [@samuelcolvin](https://github.com/samuelcolvin) - fix card number length check in `PaymentCardNumber`, `PaymentCardBrand` now inherits from `str`, [#1317](https://github.com/pydantic/pydantic/pull/1317) by [@samuelcolvin](https://github.com/samuelcolvin) - Have `BaseModel` inherit from `Representation` to make mypy happy when overriding `__str__`, [#1310](https://github.com/pydantic/pydantic/pull/1310) by [@FuegoFro](https://github.com/FuegoFro) - Allow `None` as input to all optional list fields, [#1307](https://github.com/pydantic/pydantic/pull/1307) by [@prettywood](https://github.com/prettywood) - Add `datetime` field to `default_factory` example, [#1301](https://github.com/pydantic/pydantic/pull/1301) by [@StephenBrown2](https://github.com/StephenBrown2) - Allow subclasses of known types to be encoded with superclass encoder, [#1291](https://github.com/pydantic/pydantic/pull/1291) by [@StephenBrown2](https://github.com/StephenBrown2) - Exclude exported fields from all elements of a list/tuple of submodels/dicts with `'__all__'`, [#1286](https://github.com/pydantic/pydantic/pull/1286) by [@masalim2](https://github.com/masalim2) - Add pydantic.color.Color objects as available input for Color fields, [#1258](https://github.com/pydantic/pydantic/pull/1258) by [@leosussan](https://github.com/leosussan) - In examples, type nullable fields as `Optional`, so that these are valid mypy annotations, [#1248](https://github.com/pydantic/pydantic/pull/1248) by [@kokes](https://github.com/kokes) - Make `pattern_validator()` accept pre-compiled `Pattern` objects. Fix `str_validator()` return type to `str`, [#1237](https://github.com/pydantic/pydantic/pull/1237) by [@adamgreg](https://github.com/adamgreg) - Document how to manage Generics and inheritance, [#1229](https://github.com/pydantic/pydantic/pull/1229) by [@esadruhn](https://github.com/esadruhn) - `update_forward_refs()` method of BaseModel now copies `__dict__` of class module instead of modifying it, [#1228](https://github.com/pydantic/pydantic/pull/1228) by [@paul-ilyin](https://github.com/paul-ilyin) - Support instance methods and class methods with `@validate_arguments`, [#1222](https://github.com/pydantic/pydantic/pull/1222) by [@samuelcolvin](https://github.com/samuelcolvin) - Add `default_factory` argument to `Field` to create a dynamic default value by passing a zero-argument callable, [#1210](https://github.com/pydantic/pydantic/pull/1210) by [@prettywood](https://github.com/prettywood) - add support for `NewType` of `List`, `Optional`, etc, [#1207](https://github.com/pydantic/pydantic/pull/1207) by [@Kazy](https://github.com/Kazy) - fix mypy signature for `root_validator`, [#1192](https://github.com/pydantic/pydantic/pull/1192) by [@samuelcolvin](https://github.com/samuelcolvin) - Fixed parsing of nested 'custom root type' models, [#1190](https://github.com/pydantic/pydantic/pull/1190) by [@Shados](https://github.com/Shados) - Add `validate_arguments` function decorator which checks the arguments to a function matches type annotations, [#1179](https://github.com/pydantic/pydantic/pull/1179) by [@samuelcolvin](https://github.com/samuelcolvin) - Add `__signature__` to models, [#1034](https://github.com/pydantic/pydantic/pull/1034) by [@Bobronium](https://github.com/Bobronium) - Refactor `._iter()` method, 10x speed boost for `dict(model)`, [#1017](https://github.com/pydantic/pydantic/pull/1017) by [@Bobronium](https://github.com/Bobronium) ## v1.4 (2020-01-24) - **Breaking Change:** alias precedence logic changed so aliases on a field always take priority over an alias from `alias_generator` to avoid buggy/unexpected behaviour, see [here](https://docs.pydantic.dev/usage/model_config/#alias-precedence) for details, [#1178](https://github.com/pydantic/pydantic/pull/1178) by [@samuelcolvin](https://github.com/samuelcolvin) - Add support for unicode and punycode in TLDs, [#1182](https://github.com/pydantic/pydantic/pull/1182) by [@jamescurtin](https://github.com/jamescurtin) - Fix `cls` argument in validators during assignment, [#1172](https://github.com/pydantic/pydantic/pull/1172) by [@samuelcolvin](https://github.com/samuelcolvin) - completing Luhn algorithm for `PaymentCardNumber`, [#1166](https://github.com/pydantic/pydantic/pull/1166) by [@cuencandres](https://github.com/cuencandres) - add support for generics that implement `__get_validators__` like a custom data type, [#1159](https://github.com/pydantic/pydantic/pull/1159) by [@tiangolo](https://github.com/tiangolo) - add support for infinite generators with `Iterable`, [#1152](https://github.com/pydantic/pydantic/pull/1152) by [@tiangolo](https://github.com/tiangolo) - fix `url_regex` to accept schemas with `+`, `-` and `.` after the first character, [#1142](https://github.com/pydantic/pydantic/pull/1142) by [@samuelcolvin](https://github.com/samuelcolvin) - move `version_info()` to `version.py`, suggest its use in issues, [#1138](https://github.com/pydantic/pydantic/pull/1138) by [@samuelcolvin](https://github.com/samuelcolvin) - Improve pydantic import time by roughly 50% by deferring some module loading and regex compilation, [#1127](https://github.com/pydantic/pydantic/pull/1127) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix `EmailStr` and `NameEmail` to accept instances of themselves in cython, [#1126](https://github.com/pydantic/pydantic/pull/1126) by [@koxudaxi](https://github.com/koxudaxi) - Pass model class to the `Config.schema_extra` callable, [#1125](https://github.com/pydantic/pydantic/pull/1125) by [@therefromhere](https://github.com/therefromhere) - Fix regex for username and password in URLs, [#1115](https://github.com/pydantic/pydantic/pull/1115) by [@samuelcolvin](https://github.com/samuelcolvin) - Add support for nested generic models, [#1104](https://github.com/pydantic/pydantic/pull/1104) by [@dmontagu](https://github.com/dmontagu) - add `__all__` to `__init__.py` to prevent "implicit reexport" errors from mypy, [#1072](https://github.com/pydantic/pydantic/pull/1072) by [@samuelcolvin](https://github.com/samuelcolvin) - Add support for using "dotenv" files with `BaseSettings`, [#1011](https://github.com/pydantic/pydantic/pull/1011) by [@acnebs](https://github.com/acnebs) ## v1.3 (2019-12-21) - Change `schema` and `schema_model` to handle dataclasses by using their `__pydantic_model__` feature, [#792](https://github.com/pydantic/pydantic/pull/792) by [@aviramha](https://github.com/aviramha) - Added option for `root_validator` to be skipped if values validation fails using keyword `skip_on_failure=True`, [#1049](https://github.com/pydantic/pydantic/pull/1049) by [@aviramha](https://github.com/aviramha) - Allow `Config.schema_extra` to be a callable so that the generated schema can be post-processed, [#1054](https://github.com/pydantic/pydantic/pull/1054) by [@selimb](https://github.com/selimb) - Update mypy to version 0.750, [#1057](https://github.com/pydantic/pydantic/pull/1057) by [@dmontagu](https://github.com/dmontagu) - Trick Cython into allowing str subclassing, [#1061](https://github.com/pydantic/pydantic/pull/1061) by [@skewty](https://github.com/skewty) - Prevent type attributes being added to schema unless the attribute `__schema_attributes__` is `True`, [#1064](https://github.com/pydantic/pydantic/pull/1064) by [@samuelcolvin](https://github.com/samuelcolvin) - Change `BaseModel.parse_file` to use `Config.json_loads`, [#1067](https://github.com/pydantic/pydantic/pull/1067) by [@kierandarcy](https://github.com/kierandarcy) - Fix for optional `Json` fields, [#1073](https://github.com/pydantic/pydantic/pull/1073) by [@volker48](https://github.com/volker48) - Change the default number of threads used when compiling with cython to one, allow override via the `CYTHON_NTHREADS` environment variable, [#1074](https://github.com/pydantic/pydantic/pull/1074) by [@samuelcolvin](https://github.com/samuelcolvin) - Run FastAPI tests during Pydantic's CI tests, [#1075](https://github.com/pydantic/pydantic/pull/1075) by [@tiangolo](https://github.com/tiangolo) - My mypy strictness constraints, and associated tweaks to type annotations, [#1077](https://github.com/pydantic/pydantic/pull/1077) by [@samuelcolvin](https://github.com/samuelcolvin) - Add `__eq__` to SecretStr and SecretBytes to allow "value equals", [#1079](https://github.com/pydantic/pydantic/pull/1079) by [@sbv-trueenergy](https://github.com/sbv-trueenergy) - Fix schema generation for nested None case, [#1088](https://github.com/pydantic/pydantic/pull/1088) by [@lutostag](https://github.com/lutostag) - Consistent checks for sequence like objects, [#1090](https://github.com/pydantic/pydantic/pull/1090) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix `Config` inheritance on `BaseSettings` when used with `env_prefix`, [#1091](https://github.com/pydantic/pydantic/pull/1091) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix for `__modify_schema__` when it conflicted with `field_class_to_schema*`, [#1102](https://github.com/pydantic/pydantic/pull/1102) by [@samuelcolvin](https://github.com/samuelcolvin) - docs: Fix explanation of case sensitive environment variable names when populating `BaseSettings` subclass attributes, [#1105](https://github.com/pydantic/pydantic/pull/1105) by [@tribals](https://github.com/tribals) - Rename django-rest-framework benchmark in documentation, [#1119](https://github.com/pydantic/pydantic/pull/1119) by [@frankie567](https://github.com/frankie567) ## v1.2 (2019-11-28) - **Possible Breaking Change:** Add support for required `Optional` with `name: Optional[AnyType] = Field(...)` and refactor `ModelField` creation to preserve `required` parameter value, [#1031](https://github.com/pydantic/pydantic/pull/1031) by [@tiangolo](https://github.com/tiangolo); see [here](https://docs.pydantic.dev/usage/models/#required-optional-fields) for details - Add benchmarks for `cattrs`, [#513](https://github.com/pydantic/pydantic/pull/513) by [@sebastianmika](https://github.com/sebastianmika) - Add `exclude_none` option to `dict()` and friends, [#587](https://github.com/pydantic/pydantic/pull/587) by [@niknetniko](https://github.com/niknetniko) - Add benchmarks for `valideer`, [#670](https://github.com/pydantic/pydantic/pull/670) by [@gsakkis](https://github.com/gsakkis) - Add `parse_obj_as` and `parse_file_as` functions for ad-hoc parsing of data into arbitrary pydantic-compatible types, [#934](https://github.com/pydantic/pydantic/pull/934) by [@dmontagu](https://github.com/dmontagu) - Add `allow_reuse` argument to validators, thus allowing validator reuse, [#940](https://github.com/pydantic/pydantic/pull/940) by [@dmontagu](https://github.com/dmontagu) - Add support for mapping types for custom root models, [#958](https://github.com/pydantic/pydantic/pull/958) by [@dmontagu](https://github.com/dmontagu) - Mypy plugin support for dataclasses, [#966](https://github.com/pydantic/pydantic/pull/966) by [@koxudaxi](https://github.com/koxudaxi) - Add support for dataclasses default factory, [#968](https://github.com/pydantic/pydantic/pull/968) by [@ahirner](https://github.com/ahirner) - Add a `ByteSize` type for converting byte string (`1GB`) to plain bytes, [#977](https://github.com/pydantic/pydantic/pull/977) by [@dgasmith](https://github.com/dgasmith) - Fix mypy complaint about `@root_validator(pre=True)`, [#984](https://github.com/pydantic/pydantic/pull/984) by [@samuelcolvin](https://github.com/samuelcolvin) - Add manylinux binaries for Python 3.8 to pypi, also support manylinux2010, [#994](https://github.com/pydantic/pydantic/pull/994) by [@samuelcolvin](https://github.com/samuelcolvin) - Adds ByteSize conversion to another unit, [#995](https://github.com/pydantic/pydantic/pull/995) by [@dgasmith](https://github.com/dgasmith) - Fix `__str__` and `__repr__` inheritance for models, [#1022](https://github.com/pydantic/pydantic/pull/1022) by [@samuelcolvin](https://github.com/samuelcolvin) - add testimonials section to docs, [#1025](https://github.com/pydantic/pydantic/pull/1025) by [@sullivancolin](https://github.com/sullivancolin) - Add support for `typing.Literal` for Python 3.8, [#1026](https://github.com/pydantic/pydantic/pull/1026) by [@dmontagu](https://github.com/dmontagu) ## v1.1.1 (2019-11-20) - Fix bug where use of complex fields on sub-models could cause fields to be incorrectly configured, [#1015](https://github.com/pydantic/pydantic/pull/1015) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.1 (2019-11-07) - Add a mypy plugin for type checking `BaseModel.__init__` and more, [#722](https://github.com/pydantic/pydantic/pull/722) by [@dmontagu](https://github.com/dmontagu) - Change return type typehint for `GenericModel.__class_getitem__` to prevent PyCharm warnings, [#936](https://github.com/pydantic/pydantic/pull/936) by [@dmontagu](https://github.com/dmontagu) - Fix usage of `Any` to allow `None`, also support `TypeVar` thus allowing use of un-parameterised collection types e.g. `Dict` and `List`, [#962](https://github.com/pydantic/pydantic/pull/962) by [@samuelcolvin](https://github.com/samuelcolvin) - Set `FieldInfo` on subfields to fix schema generation for complex nested types, [#965](https://github.com/pydantic/pydantic/pull/965) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.0 (2019-10-23) - **Breaking Change:** deprecate the `Model.fields` property, use `Model.__fields__` instead, [#883](https://github.com/pydantic/pydantic/pull/883) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change:** Change the precedence of aliases so child model aliases override parent aliases, including using `alias_generator`, [#904](https://github.com/pydantic/pydantic/pull/904) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking change:** Rename `skip_defaults` to `exclude_unset`, and add ability to exclude actual defaults, [#915](https://github.com/pydantic/pydantic/pull/915) by [@dmontagu](https://github.com/dmontagu) - Add `**kwargs` to `pydantic.main.ModelMetaclass.__new__` so `__init_subclass__` can take custom parameters on extended `BaseModel` classes, [#867](https://github.com/pydantic/pydantic/pull/867) by [@retnikt](https://github.com/retnikt) - Fix field of a type that has a default value, [#880](https://github.com/pydantic/pydantic/pull/880) by [@koxudaxi](https://github.com/koxudaxi) - Use `FutureWarning` instead of `DeprecationWarning` when `alias` instead of `env` is used for settings models, [#881](https://github.com/pydantic/pydantic/pull/881) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix issue with `BaseSettings` inheritance and `alias` getting set to `None`, [#882](https://github.com/pydantic/pydantic/pull/882) by [@samuelcolvin](https://github.com/samuelcolvin) - Modify `__repr__` and `__str__` methods to be consistent across all public classes, add `__pretty__` to support python-devtools, [#884](https://github.com/pydantic/pydantic/pull/884) by [@samuelcolvin](https://github.com/samuelcolvin) - deprecation warning for `case_insensitive` on `BaseSettings` config, [#885](https://github.com/pydantic/pydantic/pull/885) by [@samuelcolvin](https://github.com/samuelcolvin) - For `BaseSettings` merge environment variables and in-code values recursively, as long as they create a valid object when merged together, to allow splitting init arguments, [#888](https://github.com/pydantic/pydantic/pull/888) by [@idmitrievsky](https://github.com/idmitrievsky) - change secret types example, [#890](https://github.com/pydantic/pydantic/pull/890) by [@ashears](https://github.com/ashears) - Change the signature of `Model.construct()` to be more user-friendly, document `construct()` usage, [#898](https://github.com/pydantic/pydantic/pull/898) by [@samuelcolvin](https://github.com/samuelcolvin) - Add example for the `construct()` method, [#907](https://github.com/pydantic/pydantic/pull/907) by [@ashears](https://github.com/ashears) - Improve use of `Field` constraints on complex types, raise an error if constraints are not enforceable, also support tuples with an ellipsis `Tuple[X, ...]`, `Sequence` and `FrozenSet` in schema, [#909](https://github.com/pydantic/pydantic/pull/909) by [@samuelcolvin](https://github.com/samuelcolvin) - update docs for bool missing valid value, [#911](https://github.com/pydantic/pydantic/pull/911) by [@trim21](https://github.com/trim21) - Better `str`/`repr` logic for `ModelField`, [#912](https://github.com/pydantic/pydantic/pull/912) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix `ConstrainedList`, update schema generation to reflect `min_items` and `max_items` `Field()` arguments, [#917](https://github.com/pydantic/pydantic/pull/917) by [@samuelcolvin](https://github.com/samuelcolvin) - Allow abstracts sets (eg. dict keys) in the `include` and `exclude` arguments of `dict()`, [#921](https://github.com/pydantic/pydantic/pull/921) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix JSON serialization errors on `ValidationError.json()` by using `pydantic_encoder`, [#922](https://github.com/pydantic/pydantic/pull/922) by [@samuelcolvin](https://github.com/samuelcolvin) - Clarify usage of `remove_untouched`, improve error message for types with no validators, [#926](https://github.com/pydantic/pydantic/pull/926) by [@retnikt](https://github.com/retnikt) ## v1.0b2 (2019-10-07) - Mark `StrictBool` typecheck as `bool` to allow for default values without mypy errors, [#690](https://github.com/pydantic/pydantic/pull/690) by [@dmontagu](https://github.com/dmontagu) - Transfer the documentation build from sphinx to mkdocs, re-write much of the documentation, [#856](https://github.com/pydantic/pydantic/pull/856) by [@samuelcolvin](https://github.com/samuelcolvin) - Add support for custom naming schemes for `GenericModel` subclasses, [#859](https://github.com/pydantic/pydantic/pull/859) by [@dmontagu](https://github.com/dmontagu) - Add `if TYPE_CHECKING:` to the excluded lines for test coverage, [#874](https://github.com/pydantic/pydantic/pull/874) by [@dmontagu](https://github.com/dmontagu) - Rename `allow_population_by_alias` to `allow_population_by_field_name`, remove unnecessary warning about it, [#875](https://github.com/pydantic/pydantic/pull/875) by [@samuelcolvin](https://github.com/samuelcolvin) ## v1.0b1 (2019-10-01) - **Breaking Change:** rename `Schema` to `Field`, make it a function to placate mypy, [#577](https://github.com/pydantic/pydantic/pull/577) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change:** modify parsing behavior for `bool`, [#617](https://github.com/pydantic/pydantic/pull/617) by [@dmontagu](https://github.com/dmontagu) - **Breaking Change:** `get_validators` is no longer recognised, use `__get_validators__`. `Config.ignore_extra` and `Config.allow_extra` are no longer recognised, use `Config.extra`, [#720](https://github.com/pydantic/pydantic/pull/720) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change:** modify default config settings for `BaseSettings`; `case_insensitive` renamed to `case_sensitive`, default changed to `case_sensitive = False`, `env_prefix` default changed to `''` - e.g. no prefix, [#721](https://github.com/pydantic/pydantic/pull/721) by [@dmontagu](https://github.com/dmontagu) - **Breaking change:** Implement `root_validator` and rename root errors from `__obj__` to `__root__`, [#729](https://github.com/pydantic/pydantic/pull/729) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change:** alter the behaviour of `dict(model)` so that sub-models are no longer converted to dictionaries, [#733](https://github.com/pydantic/pydantic/pull/733) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking change:** Added `initvars` support to `post_init_post_parse`, [#748](https://github.com/pydantic/pydantic/pull/748) by [@Raphael-C-Almeida](https://github.com/Raphael-C-Almeida) - **Breaking Change:** Make `BaseModel.json()` only serialize the `__root__` key for models with custom root, [#752](https://github.com/pydantic/pydantic/pull/752) by [@dmontagu](https://github.com/dmontagu) - **Breaking Change:** complete rewrite of `URL` parsing logic, [#755](https://github.com/pydantic/pydantic/pull/755) by [@samuelcolvin](https://github.com/samuelcolvin) - **Breaking Change:** preserve superclass annotations for field-determination when not provided in subclass, [#757](https://github.com/pydantic/pydantic/pull/757) by [@dmontagu](https://github.com/dmontagu) - **Breaking Change:** `BaseSettings` now uses the special `env` settings to define which environment variables to read, not aliases, [#847](https://github.com/pydantic/pydantic/pull/847) by [@samuelcolvin](https://github.com/samuelcolvin) - add support for `assert` statements inside validators, [#653](https://github.com/pydantic/pydantic/pull/653) by [@abdusco](https://github.com/abdusco) - Update documentation to specify the use of `pydantic.dataclasses.dataclass` and subclassing `pydantic.BaseModel`, [#710](https://github.com/pydantic/pydantic/pull/710) by [@maddosaurus](https://github.com/maddosaurus) - Allow custom JSON decoding and encoding via `json_loads` and `json_dumps` `Config` properties, [#714](https://github.com/pydantic/pydantic/pull/714) by [@samuelcolvin](https://github.com/samuelcolvin) - make all annotated fields occur in the order declared, [#715](https://github.com/pydantic/pydantic/pull/715) by [@dmontagu](https://github.com/dmontagu) - use pytest to test `mypy` integration, [#735](https://github.com/pydantic/pydantic/pull/735) by [@dmontagu](https://github.com/dmontagu) - add `__repr__` method to `ErrorWrapper`, [#738](https://github.com/pydantic/pydantic/pull/738) by [@samuelcolvin](https://github.com/samuelcolvin) - Added support for `FrozenSet` members in dataclasses, and a better error when attempting to use types from the `typing` module that are not supported by Pydantic, [#745](https://github.com/pydantic/pydantic/pull/745) by [@djpetti](https://github.com/djpetti) - add documentation for Pycharm Plugin, [#750](https://github.com/pydantic/pydantic/pull/750) by [@koxudaxi](https://github.com/koxudaxi) - fix broken examples in the docs, [#753](https://github.com/pydantic/pydantic/pull/753) by [@dmontagu](https://github.com/dmontagu) - moving typing related objects into `pydantic.typing`, [#761](https://github.com/pydantic/pydantic/pull/761) by [@samuelcolvin](https://github.com/samuelcolvin) - Minor performance improvements to `ErrorWrapper`, `ValidationError` and datetime parsing, [#763](https://github.com/pydantic/pydantic/pull/763) by [@samuelcolvin](https://github.com/samuelcolvin) - Improvements to `datetime`/`date`/`time`/`timedelta` types: more descriptive errors, change errors to `value_error` not `type_error`, support bytes, [#766](https://github.com/pydantic/pydantic/pull/766) by [@samuelcolvin](https://github.com/samuelcolvin) - fix error messages for `Literal` types with multiple allowed values, [#770](https://github.com/pydantic/pydantic/pull/770) by [@dmontagu](https://github.com/dmontagu) - Improved auto-generated `title` field in JSON schema by converting underscore to space, [#772](https://github.com/pydantic/pydantic/pull/772) by [@skewty](https://github.com/skewty) - support `mypy --no-implicit-reexport` for dataclasses, also respect `--no-implicit-reexport` in pydantic itself, [#783](https://github.com/pydantic/pydantic/pull/783) by [@samuelcolvin](https://github.com/samuelcolvin) - add the `PaymentCardNumber` type, [#790](https://github.com/pydantic/pydantic/pull/790) by [@matin](https://github.com/matin) - Fix const validations for lists, [#794](https://github.com/pydantic/pydantic/pull/794) by [@hmvp](https://github.com/hmvp) - Set `additionalProperties` to false in schema for models with extra fields disallowed, [#796](https://github.com/pydantic/pydantic/pull/796) by [@Code0x58](https://github.com/Code0x58) - `EmailStr` validation method now returns local part case-sensitive per RFC 5321, [#798](https://github.com/pydantic/pydantic/pull/798) by [@henriklindgren](https://github.com/henriklindgren) - Added ability to validate strictness to `ConstrainedFloat`, `ConstrainedInt` and `ConstrainedStr` and added `StrictFloat` and `StrictInt` classes, [#799](https://github.com/pydantic/pydantic/pull/799) by [@DerRidda](https://github.com/DerRidda) - Improve handling of `None` and `Optional`, replace `whole` with `each_item` (inverse meaning, default `False`) on validators, [#803](https://github.com/pydantic/pydantic/pull/803) by [@samuelcolvin](https://github.com/samuelcolvin) - add support for `Type[T]` type hints, [#807](https://github.com/pydantic/pydantic/pull/807) by [@timonbimon](https://github.com/timonbimon) - Performance improvements from removing `change_exceptions`, change how pydantic error are constructed, [#819](https://github.com/pydantic/pydantic/pull/819) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix the error message arising when a `BaseModel`\-type model field causes a `ValidationError` during parsing, [#820](https://github.com/pydantic/pydantic/pull/820) by [@dmontagu](https://github.com/dmontagu) - allow `getter_dict` on `Config`, modify `GetterDict` to be more like a `Mapping` object and thus easier to work with, [#821](https://github.com/pydantic/pydantic/pull/821) by [@samuelcolvin](https://github.com/samuelcolvin) - Only check `TypeVar` param on base `GenericModel` class, [#842](https://github.com/pydantic/pydantic/pull/842) by [@zpencerq](https://github.com/zpencerq) - rename `Model._schema_cache` -> `Model.__schema_cache__`, `Model._json_encoder` -> `Model.__json_encoder__`, `Model._custom_root_type` -> `Model.__custom_root_type__`, [#851](https://github.com/pydantic/pydantic/pull/851) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.32.2 (2019-08-17) (Docs are available [here](https://5d584fcca7c9b70007d1c997--pydantic-docs.netlify.com)) - fix `__post_init__` usage with dataclass inheritance, fix [#739](https://github.com/pydantic/pydantic/pull/739) by [@samuelcolvin](https://github.com/samuelcolvin) - fix required fields validation on GenericModels classes, [#742](https://github.com/pydantic/pydantic/pull/742) by [@amitbl](https://github.com/amitbl) - fix defining custom `Schema` on `GenericModel` fields, [#754](https://github.com/pydantic/pydantic/pull/754) by [@amitbl](https://github.com/amitbl) ## v0.32.1 (2019-08-08) - do not validate extra fields when `validate_assignment` is on, [#724](https://github.com/pydantic/pydantic/pull/724) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) ## v0.32 (2019-08-06) - add model name to `ValidationError` error message, [#676](https://github.com/pydantic/pydantic/pull/676) by [@dmontagu](https://github.com/dmontagu) - **breaking change**: remove `__getattr__` and rename `__values__` to `__dict__` on `BaseModel`, deprecation warning on use `__values__` attr, attributes access speed increased up to 14 times, [#712](https://github.com/pydantic/pydantic/pull/712) by [@Bobronium](https://github.com/Bobronium) - support `ForwardRef` (without self-referencing annotations) in Python 3.6, [#706](https://github.com/pydantic/pydantic/pull/706) by [@koxudaxi](https://github.com/koxudaxi) - implement `schema_extra` in `Config` sub-class, [#663](https://github.com/pydantic/pydantic/pull/663) by [@tiangolo](https://github.com/tiangolo) ## v0.31.1 (2019-07-31) - fix json generation for `EnumError`, [#697](https://github.com/pydantic/pydantic/pull/697) by [@dmontagu](https://github.com/dmontagu) - update numerous dependencies ## v0.31 (2019-07-24) - better support for floating point `multiple_of` values, [#652](https://github.com/pydantic/pydantic/pull/652) by [@justindujardin](https://github.com/justindujardin) - fix schema generation for `NewType` and `Literal`, [#649](https://github.com/pydantic/pydantic/pull/649) by [@dmontagu](https://github.com/dmontagu) - fix `alias_generator` and field config conflict, [#645](https://github.com/pydantic/pydantic/pull/645) by [@gmetzker](https://github.com/gmetzker) and [#658](https://github.com/pydantic/pydantic/pull/658) by [@Bobronium](https://github.com/Bobronium) - more detailed message for `EnumError`, [#673](https://github.com/pydantic/pydantic/pull/673) by [@dmontagu](https://github.com/dmontagu) - add advanced exclude support for `dict`, `json` and `copy`, [#648](https://github.com/pydantic/pydantic/pull/648) by [@Bobronium](https://github.com/Bobronium) - fix bug in `GenericModel` for models with concrete parameterized fields, [#672](https://github.com/pydantic/pydantic/pull/672) by [@dmontagu](https://github.com/dmontagu) - add documentation for `Literal` type, [#651](https://github.com/pydantic/pydantic/pull/651) by [@dmontagu](https://github.com/dmontagu) - add `Config.keep_untouched` for custom descriptors support, [#679](https://github.com/pydantic/pydantic/pull/679) by [@Bobronium](https://github.com/Bobronium) - use `inspect.cleandoc` internally to get model description, [#657](https://github.com/pydantic/pydantic/pull/657) by [@tiangolo](https://github.com/tiangolo) - add `Color` to schema generation, by [@euri10](https://github.com/euri10) - add documentation for Literal type, [#651](https://github.com/pydantic/pydantic/pull/651) by [@dmontagu](https://github.com/dmontagu) ## v0.30.1 (2019-07-15) - fix so nested classes which inherit and change `__init__` are correctly processed while still allowing `self` as a parameter, [#644](https://github.com/pydantic/pydantic/pull/644) by [@lnaden](https://github.com/lnaden) and [@dgasmith](https://github.com/dgasmith) ## v0.30 (2019-07-07) - enforce single quotes in code, [#612](https://github.com/pydantic/pydantic/pull/612) by [@samuelcolvin](https://github.com/samuelcolvin) - fix infinite recursion with dataclass inheritance and `__post_init__`, [#606](https://github.com/pydantic/pydantic/pull/606) by [@Hanaasagi](https://github.com/Hanaasagi) - fix default values for `GenericModel`, [#610](https://github.com/pydantic/pydantic/pull/610) by [@dmontagu](https://github.com/dmontagu) - clarify that self-referencing models require Python 3.7+, [#616](https://github.com/pydantic/pydantic/pull/616) by [@vlcinsky](https://github.com/vlcinsky) - fix truncate for types, [#611](https://github.com/pydantic/pydantic/pull/611) by [@dmontagu](https://github.com/dmontagu) - add `alias_generator` support, [#622](https://github.com/pydantic/pydantic/pull/622) by [@Bobronium](https://github.com/Bobronium) - fix unparameterized generic type schema generation, [#625](https://github.com/pydantic/pydantic/pull/625) by [@dmontagu](https://github.com/dmontagu) - fix schema generation with multiple/circular references to the same model, [#621](https://github.com/pydantic/pydantic/pull/621) by [@tiangolo](https://github.com/tiangolo) and [@wongpat](https://github.com/wongpat) - support custom root types, [#628](https://github.com/pydantic/pydantic/pull/628) by [@koxudaxi](https://github.com/koxudaxi) - support `self` as a field name in `parse_obj`, [#632](https://github.com/pydantic/pydantic/pull/632) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.29 (2019-06-19) - support dataclasses.InitVar, [#592](https://github.com/pydantic/pydantic/pull/592) by [@pfrederiks](https://github.com/pfrederiks) - Updated documentation to elucidate the usage of `Union` when defining multiple types under an attribute's annotation and showcase how the type-order can affect marshalling of provided values, [#594](https://github.com/pydantic/pydantic/pull/594) by [@somada141](https://github.com/somada141) - add `conlist` type, [#583](https://github.com/pydantic/pydantic/pull/583) by [@hmvp](https://github.com/hmvp) - add support for generics, [#595](https://github.com/pydantic/pydantic/pull/595) by [@dmontagu](https://github.com/dmontagu) ## v0.28 (2019-06-06) - fix support for JSON Schema generation when using models with circular references in Python 3.7, [#572](https://github.com/pydantic/pydantic/pull/572) by [@tiangolo](https://github.com/tiangolo) - support `__post_init_post_parse__` on dataclasses, [#567](https://github.com/pydantic/pydantic/pull/567) by [@sevaho](https://github.com/sevaho) - allow dumping dataclasses to JSON, [#575](https://github.com/pydantic/pydantic/pull/575) by [@samuelcolvin](https://github.com/samuelcolvin) and [@DanielOberg](https://github.com/DanielOberg) - ORM mode, [#562](https://github.com/pydantic/pydantic/pull/562) by [@samuelcolvin](https://github.com/samuelcolvin) - fix `pydantic.compiled` on ipython, [#573](https://github.com/pydantic/pydantic/pull/573) by [@dmontagu](https://github.com/dmontagu) and [@samuelcolvin](https://github.com/samuelcolvin) - add `StrictBool` type, [#579](https://github.com/pydantic/pydantic/pull/579) by [@cazgp](https://github.com/cazgp) ## v0.27 (2019-05-30) - **breaking change** `_pydantic_post_init` to execute dataclass' original `__post_init__` before validation, [#560](https://github.com/pydantic/pydantic/pull/560) by [@HeavenVolkoff](https://github.com/HeavenVolkoff) - fix handling of generic types without specified parameters, [#550](https://github.com/pydantic/pydantic/pull/550) by [@dmontagu](https://github.com/dmontagu) - **breaking change** (maybe): this is the first release compiled with **cython**, see the docs and please submit an issue if you run into problems ## v0.27.0a1 (2019-05-26) - fix JSON Schema for `list`, `tuple`, and `set`, [#540](https://github.com/pydantic/pydantic/pull/540) by [@tiangolo](https://github.com/tiangolo) - compiling with cython, `manylinux` binaries, some other performance improvements, [#548](https://github.com/pydantic/pydantic/pull/548) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.26 (2019-05-22) - fix to schema generation for `IPvAnyAddress`, `IPvAnyInterface`, `IPvAnyNetwork` [#498](https://github.com/pydantic/pydantic/pull/498) by [@pilosus](https://github.com/pilosus) - fix variable length tuples support, [#495](https://github.com/pydantic/pydantic/pull/495) by [@pilosus](https://github.com/pilosus) - fix return type hint for `create_model`, [#526](https://github.com/pydantic/pydantic/pull/526) by [@dmontagu](https://github.com/dmontagu) - **Breaking Change:** fix `.dict(skip_keys=True)` skipping values set via alias (this involves changing `validate_model()` to always returns `Tuple[Dict[str, Any], Set[str], Optional[ValidationError]]`), [#517](https://github.com/pydantic/pydantic/pull/517) by [@sommd](https://github.com/sommd) - fix to schema generation for `IPv4Address`, `IPv6Address`, `IPv4Interface`, `IPv6Interface`, `IPv4Network`, `IPv6Network` [#532](https://github.com/pydantic/pydantic/pull/532) by [@euri10](https://github.com/euri10) - add `Color` type, [#504](https://github.com/pydantic/pydantic/pull/504) by [@pilosus](https://github.com/pilosus) and [@samuelcolvin](https://github.com/samuelcolvin) ## v0.25 (2019-05-05) - Improve documentation on self-referencing models and annotations, [#487](https://github.com/pydantic/pydantic/pull/487) by [@theenglishway](https://github.com/theenglishway) - fix `.dict()` with extra keys, [#490](https://github.com/pydantic/pydantic/pull/490) by [@JaewonKim](https://github.com/JaewonKim) - support `const` keyword in `Schema`, [#434](https://github.com/pydantic/pydantic/pull/434) by [@Sean1708](https://github.com/Sean1708) ## v0.24 (2019-04-23) - fix handling `ForwardRef` in sub-types, like `Union`, [#464](https://github.com/pydantic/pydantic/pull/464) by [@tiangolo](https://github.com/tiangolo) - fix secret serialization, [#465](https://github.com/pydantic/pydantic/pull/465) by [@atheuz](https://github.com/atheuz) - Support custom validators for dataclasses, [#454](https://github.com/pydantic/pydantic/pull/454) by [@primal100](https://github.com/primal100) - fix `parse_obj` to cope with dict-like objects, [#472](https://github.com/pydantic/pydantic/pull/472) by [@samuelcolvin](https://github.com/samuelcolvin) - fix to schema generation in nested dataclass-based models, [#474](https://github.com/pydantic/pydantic/pull/474) by [@NoAnyLove](https://github.com/NoAnyLove) - fix `json` for `Path`, `FilePath`, and `DirectoryPath` objects, [#473](https://github.com/pydantic/pydantic/pull/473) by [@mikegoodspeed](https://github.com/mikegoodspeed) ## v0.23 (2019-04-04) - improve documentation for contributing section, [#441](https://github.com/pydantic/pydantic/pull/441) by [@pilosus](https://github.com/pilosus) - improve README.rst to include essential information about the package, [#446](https://github.com/pydantic/pydantic/pull/446) by [@pilosus](https://github.com/pilosus) - `IntEnum` support, [#444](https://github.com/pydantic/pydantic/pull/444) by [@potykion](https://github.com/potykion) - fix PyObject callable value, [#409](https://github.com/pydantic/pydantic/pull/409) by [@pilosus](https://github.com/pilosus) - fix `black` deprecation warnings after update, [#451](https://github.com/pydantic/pydantic/pull/451) by [@pilosus](https://github.com/pilosus) - fix `ForwardRef` collection bug, [#450](https://github.com/pydantic/pydantic/pull/450) by [@tigerwings](https://github.com/tigerwings) - Support specialized `ClassVars`, [#455](https://github.com/pydantic/pydantic/pull/455) by [@tyrylu](https://github.com/tyrylu) - fix JSON serialization for `ipaddress` types, [#333](https://github.com/pydantic/pydantic/pull/333) by [@pilosus](https://github.com/pilosus) - add `SecretStr` and `SecretBytes` types, [#452](https://github.com/pydantic/pydantic/pull/452) by [@atheuz](https://github.com/atheuz) ## v0.22 (2019-03-29) - add `IPv{4,6,Any}Network` and `IPv{4,6,Any}Interface` types from `ipaddress` stdlib, [#333](https://github.com/pydantic/pydantic/pull/333) by [@pilosus](https://github.com/pilosus) - add docs for `datetime` types, [#386](https://github.com/pydantic/pydantic/pull/386) by [@pilosus](https://github.com/pilosus) - fix to schema generation in dataclass-based models, [#408](https://github.com/pydantic/pydantic/pull/408) by [@pilosus](https://github.com/pilosus) - fix path in nested models, [#437](https://github.com/pydantic/pydantic/pull/437) by [@kataev](https://github.com/kataev) - add `Sequence` support, [#304](https://github.com/pydantic/pydantic/pull/304) by [@pilosus](https://github.com/pilosus) ## v0.21.0 (2019-03-15) - fix typo in `NoneIsNotAllowedError` message, [#414](https://github.com/pydantic/pydantic/pull/414) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) - add `IPvAnyAddress`, `IPv4Address` and `IPv6Address` types, [#333](https://github.com/pydantic/pydantic/pull/333) by [@pilosus](https://github.com/pilosus) ## v0.20.1 (2019-02-26) - fix type hints of `parse_obj` and similar methods, [#405](https://github.com/pydantic/pydantic/pull/405) by [@erosennin](https://github.com/erosennin) - fix submodel validation, [#403](https://github.com/pydantic/pydantic/pull/403) by [@samuelcolvin](https://github.com/samuelcolvin) - correct type hints for `ValidationError.json`, [#406](https://github.com/pydantic/pydantic/pull/406) by [@layday](https://github.com/layday) ## v0.20.0 (2019-02-18) - fix tests for Python 3.8, [#396](https://github.com/pydantic/pydantic/pull/396) by [@samuelcolvin](https://github.com/samuelcolvin) - Adds fields to the `dir` method for autocompletion in interactive sessions, [#398](https://github.com/pydantic/pydantic/pull/398) by [@dgasmith](https://github.com/dgasmith) - support `ForwardRef` (and therefore `from __future__ import annotations`) with dataclasses, [#397](https://github.com/pydantic/pydantic/pull/397) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.20.0a1 (2019-02-13) - **breaking change** (maybe): more sophisticated argument parsing for validators, any subset of `values`, `config` and `field` is now permitted, eg. `(cls, value, field)`, however the variadic key word argument ("`**kwargs`") **must** be called `kwargs`, [#388](https://github.com/pydantic/pydantic/pull/388) by [@samuelcolvin](https://github.com/samuelcolvin) - **breaking change**: Adds `skip_defaults` argument to `BaseModel.dict()` to allow skipping of fields that were not explicitly set, signature of `Model.construct()` changed, [#389](https://github.com/pydantic/pydantic/pull/389) by [@dgasmith](https://github.com/dgasmith) - add `py.typed` marker file for PEP-561 support, [#391](https://github.com/pydantic/pydantic/pull/391) by [@je-l](https://github.com/je-l) - Fix `extra` behaviour for multiple inheritance/mix-ins, [#394](https://github.com/pydantic/pydantic/pull/394) by [@YaraslauZhylko](https://github.com/YaraslauZhylko) ## v0.19.0 (2019-02-04) - Support `Callable` type hint, fix [#279](https://github.com/pydantic/pydantic/pull/279) by [@proofit404](https://github.com/proofit404) - Fix schema for fields with `validator` decorator, fix [#375](https://github.com/pydantic/pydantic/pull/375) by [@tiangolo](https://github.com/tiangolo) - Add `multiple_of` constraint to `ConstrainedDecimal`, `ConstrainedFloat`, `ConstrainedInt` and their related types `condecimal`, `confloat`, and `conint` [#371](https://github.com/pydantic/pydantic/pull/371), thanks [@StephenBrown2](https://github.com/StephenBrown2) - Deprecated `ignore_extra` and `allow_extra` Config fields in favor of `extra`, [#352](https://github.com/pydantic/pydantic/pull/352) by [@liiight](https://github.com/liiight) - Add type annotations to all functions, test fully with mypy, [#373](https://github.com/pydantic/pydantic/pull/373) by [@samuelcolvin](https://github.com/samuelcolvin) - fix for 'missing' error with `validate_all` or `validate_always`, [#381](https://github.com/pydantic/pydantic/pull/381) by [@samuelcolvin](https://github.com/samuelcolvin) - Change the second/millisecond watershed for date/datetime parsing to `2e10`, [#385](https://github.com/pydantic/pydantic/pull/385) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.18.2 (2019-01-22) - Fix to schema generation with `Optional` fields, fix [#361](https://github.com/pydantic/pydantic/pull/361) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.18.1 (2019-01-17) - add `ConstrainedBytes` and `conbytes` types, [#315](https://github.com/pydantic/pydantic/pull/315) [@Gr1N](https://github.com/Gr1N) - adding `MANIFEST.in` to include license in package `.tar.gz`, [#358](https://github.com/pydantic/pydantic/pull/358) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.18.0 (2019-01-13) - **breaking change**: don't call validators on keys of dictionaries, [#254](https://github.com/pydantic/pydantic/pull/254) by [@samuelcolvin](https://github.com/samuelcolvin) - Fix validators with `always=True` when the default is `None` or the type is optional, also prevent `whole` validators being called for sub-fields, fix [#132](https://github.com/pydantic/pydantic/pull/132) by [@samuelcolvin](https://github.com/samuelcolvin) - improve documentation for settings priority and allow it to be easily changed, [#343](https://github.com/pydantic/pydantic/pull/343) by [@samuelcolvin](https://github.com/samuelcolvin) - fix `ignore_extra=False` and `allow_population_by_alias=True`, fix [#257](https://github.com/pydantic/pydantic/pull/257) by [@samuelcolvin](https://github.com/samuelcolvin) - **breaking change**: Set `BaseConfig` attributes `min_anystr_length` and `max_anystr_length` to `None` by default, fix [#349](https://github.com/pydantic/pydantic/pull/349) in [#350](https://github.com/pydantic/pydantic/pull/350) by [@tiangolo](https://github.com/tiangolo) - add support for postponed annotations, [#348](https://github.com/pydantic/pydantic/pull/348) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.17.0 (2018-12-27) - fix schema for `timedelta` as number, [#325](https://github.com/pydantic/pydantic/pull/325) by [@tiangolo](https://github.com/tiangolo) - prevent validators being called repeatedly after inheritance, [#327](https://github.com/pydantic/pydantic/pull/327) by [@samuelcolvin](https://github.com/samuelcolvin) - prevent duplicate validator check in ipython, fix [#312](https://github.com/pydantic/pydantic/pull/312) by [@samuelcolvin](https://github.com/samuelcolvin) - add "Using Pydantic" section to docs, [#323](https://github.com/pydantic/pydantic/pull/323) by [@tiangolo](https://github.com/tiangolo) & [#326](https://github.com/pydantic/pydantic/pull/326) by [@samuelcolvin](https://github.com/samuelcolvin) - fix schema generation for fields annotated as `: dict`, `: list`, `: tuple` and `: set`, [#330](https://github.com/pydantic/pydantic/pull/330) & [#335](https://github.com/pydantic/pydantic/pull/335) by [@nkonin](https://github.com/nkonin) - add support for constrained strings as dict keys in schema, [#332](https://github.com/pydantic/pydantic/pull/332) by [@tiangolo](https://github.com/tiangolo) - support for passing Config class in dataclasses decorator, [#276](https://github.com/pydantic/pydantic/pull/276) by [@jarekkar](https://github.com/jarekkar) (**breaking change**: this supersedes the `validate_assignment` argument with `config`) - support for nested dataclasses, [#334](https://github.com/pydantic/pydantic/pull/334) by [@samuelcolvin](https://github.com/samuelcolvin) - better errors when getting an `ImportError` with `PyObject`, [#309](https://github.com/pydantic/pydantic/pull/309) by [@samuelcolvin](https://github.com/samuelcolvin) - rename `get_validators` to `__get_validators__`, deprecation warning on use of old name, [#338](https://github.com/pydantic/pydantic/pull/338) by [@samuelcolvin](https://github.com/samuelcolvin) - support `ClassVar` by excluding such attributes from fields, [#184](https://github.com/pydantic/pydantic/pull/184) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.16.1 (2018-12-10) - fix `create_model` to correctly use the passed `__config__`, [#320](https://github.com/pydantic/pydantic/pull/320) by [@hugoduncan](https://github.com/hugoduncan) ## v0.16.0 (2018-12-03) - **breaking change**: refactor schema generation to be compatible with JSON Schema and OpenAPI specs, [#308](https://github.com/pydantic/pydantic/pull/308) by [@tiangolo](https://github.com/tiangolo) - add `schema` to `schema` module to generate top-level schemas from base models, [#308](https://github.com/pydantic/pydantic/pull/308) by [@tiangolo](https://github.com/tiangolo) - add additional fields to `Schema` class to declare validation for `str` and numeric values, [#311](https://github.com/pydantic/pydantic/pull/311) by [@tiangolo](https://github.com/tiangolo) - rename `_schema` to `schema` on fields, [#318](https://github.com/pydantic/pydantic/pull/318) by [@samuelcolvin](https://github.com/samuelcolvin) - add `case_insensitive` option to `BaseSettings` `Config`, [#277](https://github.com/pydantic/pydantic/pull/277) by [@jasonkuhrt](https://github.com/jasonkuhrt) ## v0.15.0 (2018-11-18) - move codebase to use black, [#287](https://github.com/pydantic/pydantic/pull/287) by [@samuelcolvin](https://github.com/samuelcolvin) - fix alias use in settings, [#286](https://github.com/pydantic/pydantic/pull/286) by [@jasonkuhrt](https://github.com/jasonkuhrt) and [@samuelcolvin](https://github.com/samuelcolvin) - fix datetime parsing in `parse_date`, [#298](https://github.com/pydantic/pydantic/pull/298) by [@samuelcolvin](https://github.com/samuelcolvin) - allow dataclass inheritance, fix [#293](https://github.com/pydantic/pydantic/pull/293) by [@samuelcolvin](https://github.com/samuelcolvin) - fix `PyObject = None`, fix [#305](https://github.com/pydantic/pydantic/pull/305) by [@samuelcolvin](https://github.com/samuelcolvin) - allow `Pattern` type, fix [#303](https://github.com/pydantic/pydantic/pull/303) by [@samuelcolvin](https://github.com/samuelcolvin) ## v0.14.0 (2018-10-02) - dataclasses decorator, [#269](https://github.com/pydantic/pydantic/pull/269) by [@Gaunt](https://github.com/Gaunt) and [@samuelcolvin](https://github.com/samuelcolvin) ## v0.13.1 (2018-09-21) - fix issue where int\_validator doesn't cast a `bool` to an `int` [#264](https://github.com/pydantic/pydantic/pull/264) by [@nphyatt](https://github.com/nphyatt) - add deep copy support for `BaseModel.copy()` [#249](https://github.com/pydantic/pydantic/pull/249), [@gangefors](https://github.com/gangefors) ## v0.13.0 (2018-08-25) - raise an exception if a field's name shadows an existing `BaseModel` attribute [#242](https://github.com/pydantic/pydantic/pull/242) - add `UrlStr` and `urlstr` types [#236](https://github.com/pydantic/pydantic/pull/236) - timedelta json encoding ISO8601 and total seconds, custom json encoders [#247](https://github.com/pydantic/pydantic/pull/247), by [@cfkanesan](https://github.com/cfkanesan) and [@samuelcolvin](https://github.com/samuelcolvin) - allow `timedelta` objects as values for properties of type `timedelta` (matches `datetime` etc. behavior) [#247](https://github.com/pydantic/pydantic/pull/247) ## v0.12.1 (2018-07-31) - fix schema generation for fields defined using `typing.Any` [#237](https://github.com/pydantic/pydantic/pull/237) ## v0.12.0 (2018-07-31) - add `by_alias` argument in `.dict()` and `.json()` model methods [#205](https://github.com/pydantic/pydantic/pull/205) - add Json type support [#214](https://github.com/pydantic/pydantic/pull/214) - support tuples [#227](https://github.com/pydantic/pydantic/pull/227) - major improvements and changes to schema [#213](https://github.com/pydantic/pydantic/pull/213) ## v0.11.2 (2018-07-05) - add `NewType` support [#115](https://github.com/pydantic/pydantic/pull/115) - fix `list`, `set` & `tuple` validation [#225](https://github.com/pydantic/pydantic/pull/225) - separate out `validate_model` method, allow errors to be returned along with valid values [#221](https://github.com/pydantic/pydantic/pull/221) ## v0.11.1 (2018-07-02) - support Python 3.7 [#216](https://github.com/pydantic/pydantic/pull/216), thanks [@layday](https://github.com/layday) - Allow arbitrary types in model [#209](https://github.com/pydantic/pydantic/pull/209), thanks [@oldPadavan](https://github.com/oldPadavan) ## v0.11.0 (2018-06-28) - make `list`, `tuple` and `set` types stricter [#86](https://github.com/pydantic/pydantic/pull/86) - **breaking change**: remove msgpack parsing [#201](https://github.com/pydantic/pydantic/pull/201) - add `FilePath` and `DirectoryPath` types [#10](https://github.com/pydantic/pydantic/pull/10) - model schema generation [#190](https://github.com/pydantic/pydantic/pull/190) - JSON serialization of models and schemas [#133](https://github.com/pydantic/pydantic/pull/133) ## v0.10.0 (2018-06-11) - add `Config.allow_population_by_alias` [#160](https://github.com/pydantic/pydantic/pull/160), thanks [@bendemaree](https://github.com/bendemaree) - **breaking change**: new errors format [#179](https://github.com/pydantic/pydantic/pull/179), thanks [@Gr1N](https://github.com/Gr1N) - **breaking change**: removed `Config.min_number_size` and `Config.max_number_size` [#183](https://github.com/pydantic/pydantic/pull/183), thanks [@Gr1N](https://github.com/Gr1N) - **breaking change**: correct behaviour of `lt` and `gt` arguments to `conint` etc. [#188](https://github.com/pydantic/pydantic/pull/188) for the old behaviour use `le` and `ge` [#194](https://github.com/pydantic/pydantic/pull/194), thanks [@jaheba](https://github.com/jaheba) - added error context and ability to redefine error message templates using `Config.error_msg_templates` [#183](https://github.com/pydantic/pydantic/pull/183), thanks [@Gr1N](https://github.com/Gr1N) - fix typo in validator exception [#150](https://github.com/pydantic/pydantic/pull/150) - copy defaults to model values, so different models don't share objects [#154](https://github.com/pydantic/pydantic/pull/154) ## v0.9.1 (2018-05-10) - allow custom `get_field_config` on config classes [#159](https://github.com/pydantic/pydantic/pull/159) - add `UUID1`, `UUID3`, `UUID4` and `UUID5` types [#167](https://github.com/pydantic/pydantic/pull/167), thanks [@Gr1N](https://github.com/Gr1N) - modify some inconsistent docstrings and annotations [#173](https://github.com/pydantic/pydantic/pull/173), thanks [@YannLuo](https://github.com/YannLuo) - fix type annotations for exotic types [#171](https://github.com/pydantic/pydantic/pull/171), thanks [@Gr1N](https://github.com/Gr1N) - Reuse type validators in exotic types [#171](https://github.com/pydantic/pydantic/pull/171) - scheduled monthly requirements updates [#168](https://github.com/pydantic/pydantic/pull/168) - add `Decimal`, `ConstrainedDecimal` and `condecimal` types [#170](https://github.com/pydantic/pydantic/pull/170), thanks [@Gr1N](https://github.com/Gr1N) ## v0.9.0 (2018-04-28) - tweak email-validator import error message [#145](https://github.com/pydantic/pydantic/pull/145) - fix parse error of `parse_date()` and `parse_datetime()` when input is 0 [#144](https://github.com/pydantic/pydantic/pull/144), thanks [@YannLuo](https://github.com/YannLuo) - add `Config.anystr_strip_whitespace` and `strip_whitespace` kwarg to `constr`, by default values is `False` [#163](https://github.com/pydantic/pydantic/pull/163), thanks [@Gr1N](https://github.com/Gr1N) - add `ConstrainedFloat`, `confloat`, `PositiveFloat` and `NegativeFloat` types [#166](https://github.com/pydantic/pydantic/pull/166), thanks [@Gr1N](https://github.com/Gr1N) ## v0.8.0 (2018-03-25) - fix type annotation for `inherit_config` [#139](https://github.com/pydantic/pydantic/pull/139) - **breaking change**: check for invalid field names in validators [#140](https://github.com/pydantic/pydantic/pull/140) - validate attributes of parent models [#141](https://github.com/pydantic/pydantic/pull/141) - **breaking change**: email validation now uses [email-validator](https://github.com/JoshData/python-email-validator) [#142](https://github.com/pydantic/pydantic/pull/142) ## v0.7.1 (2018-02-07) - fix bug with `create_model` modifying the base class ## v0.7.0 (2018-02-06) - added compatibility with abstract base classes (ABCs) [#123](https://github.com/pydantic/pydantic/pull/123) - add `create_model` method [#113](https://github.com/pydantic/pydantic/pull/113) [#125](https://github.com/pydantic/pydantic/pull/125) - **breaking change**: rename `.config` to `.__config__` on a model - **breaking change**: remove deprecated `.values()` on a model, use `.dict()` instead - remove use of `OrderedDict` and use simple dict [#126](https://github.com/pydantic/pydantic/pull/126) - add `Config.use_enum_values` [#127](https://github.com/pydantic/pydantic/pull/127) - add wildcard validators of the form `@validate('*')` [#128](https://github.com/pydantic/pydantic/pull/128) ## v0.6.4 (2018-02-01) - allow Python date and times objects [#122](https://github.com/pydantic/pydantic/pull/122) ## v0.6.3 (2017-11-26) - fix direct install without `README.rst` present ## v0.6.2 (2017-11-13) - errors for invalid validator use - safer check for complex models in `Settings` ## v0.6.1 (2017-11-08) - prevent duplicate validators, [#101](https://github.com/pydantic/pydantic/pull/101) - add `always` kwarg to validators, [#102](https://github.com/pydantic/pydantic/pull/102) ## v0.6.0 (2017-11-07) - assignment validation [#94](https://github.com/pydantic/pydantic/pull/94), thanks petroswork! - JSON in environment variables for complex types, [#96](https://github.com/pydantic/pydantic/pull/96) - add `validator` decorators for complex validation, [#97](https://github.com/pydantic/pydantic/pull/97) - depreciate `values(...)` and replace with `.dict(...)`, [#99](https://github.com/pydantic/pydantic/pull/99) ## v0.5.0 (2017-10-23) - add `UUID` validation [#89](https://github.com/pydantic/pydantic/pull/89) - remove `index` and `track` from error object (json) if they're null [#90](https://github.com/pydantic/pydantic/pull/90) - improve the error text when a list is provided rather than a dict [#90](https://github.com/pydantic/pydantic/pull/90) - add benchmarks table to docs [#91](https://github.com/pydantic/pydantic/pull/91) ## v0.4.0 (2017-07-08) - show length in string validation error - fix aliases in config during inheritance [#55](https://github.com/pydantic/pydantic/pull/55) - simplify error display - use unicode ellipsis in `truncate` - add `parse_obj`, `parse_raw` and `parse_file` helper functions [#58](https://github.com/pydantic/pydantic/pull/58) - switch annotation only fields to come first in fields list not last ## v0.3.0 (2017-06-21) - immutable models via `config.allow_mutation = False`, associated cleanup and performance improvement [#44](https://github.com/pydantic/pydantic/pull/44) - immutable helper methods `construct()` and `copy()` [#53](https://github.com/pydantic/pydantic/pull/53) - allow pickling of models [#53](https://github.com/pydantic/pydantic/pull/53) - `setattr` is removed as `__setattr__` is now intelligent [#44](https://github.com/pydantic/pydantic/pull/44) - `raise_exception` removed, Models now always raise exceptions [#44](https://github.com/pydantic/pydantic/pull/44) - instance method validators removed - django-restful-framework benchmarks added [#47](https://github.com/pydantic/pydantic/pull/47) - fix inheritance bug [#49](https://github.com/pydantic/pydantic/pull/49) - make str type stricter so list, dict etc are not coerced to strings. [#52](https://github.com/pydantic/pydantic/pull/52) - add `StrictStr` which only always strings as input [#52](https://github.com/pydantic/pydantic/pull/52) ## v0.2.1 (2017-06-07) - pypi and travis together messed up the deploy of `v0.2` this should fix it ## v0.2.0 (2017-06-07) - **breaking change**: `values()` on a model is now a method not a property, takes `include` and `exclude` arguments - allow annotation only fields to support mypy - add pretty `to_string(pretty=True)` method for models ## v0.1.0 (2017-06-03) - add docs - add history --- # [Contributing](https://pydantic.dev/docs/validation/latest/get-started/contributing/) # Contributing We'd love you to contribute to Pydantic! ## Issues Questions, feature requests and bug reports are all welcome as [discussions or issues](https://github.com/pydantic/pydantic/issues/new/choose). **However, to report a security vulnerability, please see our [security policy](https://github.com/pydantic/pydantic/security/policy).** To make it as simple as possible for us to help you, please include the output of the following call in your issue: Terminal ```bash python -c "import pydantic.version; print(pydantic.version.version_info())" ``` If you're using Pydantic prior to **v2.0** please use: Terminal ```bash python -c "import pydantic.utils; print(pydantic.utils.version_info())" ``` Please try to always include the above unless you're unable to install Pydantic or **know** it's not relevant to your question or feature request. ## Pull Requests It should be extremely simple to get started and create a Pull Request. Pydantic is released regularly so you should see your improvements release in a matter of days or weeks 🚀. Unless your change is trivial (typo, docs tweak etc.), please create an issue to discuss the change before creating a pull request. Pydantic V1 is in maintenance mode Pydantic v1 is in maintenance mode, meaning that only bug fixes and security fixes will be accepted. New features should be targeted at Pydantic v2. To submit a fix to Pydantic v1, use the `1.10.X-fixes` as a target branch. If you're looking for something to get your teeth into, check out the ["help wanted"](https://github.com/pydantic/pydantic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) label on github. To make contributing as easy and fast as possible, you'll want to run tests and linting locally. Luckily, Pydantic has few dependencies, doesn't require compiling and tests don't need access to databases, etc. Because of this, setting up and running the tests should be very simple. Tip **tl;dr**: use `make format` to fix formatting, `make` to run tests and linting and `make docs` to build the docs. ### Prerequisites You'll need the following prerequisites: - Any Python version between **Python 3.9 and 3.12** - [**uv**](https://docs.astral.sh/uv/getting-started/installation/) or other virtual environment tool - [**git**](https://git-scm.com/) - For version control - [**make**](https://www.gnu.org/software/make/) - For running development commands (or use `nmake` on Windows) - [**Rust**](https://rustup.rs/) - Rust stable (or nightly for coverage) ### Installation and setup Fork the repository on GitHub and clone your fork locally. Terminal ```bash # Clone your fork and cd into the repo directory git clone git@github.com:/pydantic.git cd pydantic # Install UV and pre-commit # We use pipx here, for other options see: # https://docs.astral.sh/uv/getting-started/installation/ # https://pre-commit.com/#install # To get pipx itself: # https://pypa.github.io/pipx/ pipx install uv pipx install pre-commit # Install pydantic, dependencies, test dependencies and doc dependencies make install ``` ### Check out a new branch and make your changes Create a new branch for your changes. Terminal ```bash # Checkout a new branch and make your changes git switch -c my-new-feature-branch # Make your changes... ``` ### Run tests and linting Run tests and linting locally to make sure everything is working as expected. Terminal ```bash # Run automated code formatting and linting make format # Pydantic uses ruff, an awesome Python linter written in rust # https://github.com/astral-sh/ruff # Run tests and linting make # There are a few sub-commands in Makefile like `test`, `testcov` and `lint` # which you might want to use, but generally just `make` should be all you need. # You can run `make help` to see more options. ``` ### Build documentation If you've made any changes to the documentation (including changes to function signatures, class definitions, or docstrings that will appear in the API documentation), make sure it builds successfully. We use `mkdocs-material[imaging]` to support social previews (see the [plugin documentation](https://squidfunk.github.io/mkdocs-material/plugins/requirements/image-processing/)). Terminal ```bash # Build documentation make docs # If you have changed the documentation, make sure it builds successfully. # You can also use `uv run mkdocs serve` to serve the documentation at localhost:8000 ``` If this isn't working due to issues with the imaging plugin, try commenting out the `social` plugin line in `mkdocs.yml` and running `make docs` again. #### Updating the documentation We push a new version of the documentation with each minor release, and we push to a `dev` path with each commit to `main`. If you're updating the documentation out of cycle with a minor release and want your changes to be reflected on `latest`, do the following: 1. Open a PR against `main` with your docs changes 2. Once the PR is merged, checkout the `docs-update` branch. This branch should be up to date with the latest patch release. For example, if the latest release is `v2.9.2`, you should make sure `docs-update` is up to date with the `v2.9.2` tag. 3. Checkout a new branch from `docs-update` and cherry-pick your changes onto this branch. 4. Push your changes and open a PR against `docs-update`. 5. Once the PR is merged, the new docs will be built and deployed. Note Maintainer shortcut - as a maintainer, you can skip the second PR and just cherry pick directly onto the `docs-update` branch. ### Commit and push your changes Commit your changes, push your branch to GitHub, and create a pull request. Please follow the pull request template and fill in as much information as possible. Link to any relevant issues and include a description of your changes. When your pull request is ready for review, add a comment with the message "please review" and we'll take a look as soon as we can. ## Documentation style Documentation is written in Markdown and built using [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/). API documentation is built from docstrings using [mkdocstrings](https://mkdocstrings.github.io/). ### Code documentation When contributing to Pydantic, please make sure that all code is well documented. The following should be documented using properly formatted docstrings: - Modules - Class definitions - Function definitions - Module-level variables Pydantic uses [Google-style docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings) formatted according to [PEP 257](https://www.python.org/dev/peps/pep-0257/) guidelines. (See [Example Google Style Python Docstrings](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) for further examples.) [pydocstyle](https://www.pydocstyle.org/en/stable/index.html) is used for linting docstrings. You can run `make format` to check your docstrings. Where this is a conflict between Google-style docstrings and pydocstyle linting, follow the pydocstyle linting hints. Class attributes and function arguments should be documented in the format "name: description." When applicable, a return type should be documented with just a description. Types are inferred from the signature. ```python class Foo: """A class docstring. Attributes: bar: A description of bar. Defaults to "bar". """ bar: str = 'bar' ``` ```python def bar(self, baz: int) -> str: """A function docstring. Args: baz: A description of `baz`. Returns: A description of the return value. """ return 'bar' ``` You may include example code in docstrings. This code should be complete, self-contained, and runnable. Docstring examples are tested, so make sure they are correct and complete. See [`BeforeValidator`](/docs/validation/latest/api/pydantic/functional_validators/#pydantic.functional_validators.AfterValidator) for an example. Class and instance attributes Class attributes should be documented in the class docstring. Instance attributes should be documented as "Args" in the `__init__` docstring. ### Documentation Style In general, documentation should be written in a friendly, approachable style. It should be easy to read and understand, and should be as concise as possible while still being complete. Code examples are encouraged, but should be kept short and simple. However, every code example should be complete, self-contained, and runnable. (If you're not sure how to do this, ask for help!) We prefer print output to naked asserts, but if you're testing something that doesn't have a useful print output, asserts are fine. Pydantic's unit test will test all code examples in the documentation, so it's important that they are correct and complete. When adding a new code example, use the following to test examples and update their formatting and output: Terminal ```bash # Run tests and update code examples pytest tests/test_docs.py --update-examples ``` ## Debugging Python and Rust If you're working with `pydantic` and `pydantic-core`, you might find it helpful to debug Python and Rust code together. Here's a quick guide on how to do that. This tutorial is done in VSCode, but you can use similar steps in other IDEs. ## Badges [![Pydantic v1](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v1.json)](https://pydantic.dev) [![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev) Pydantic has a badge that you can use to show that your project uses Pydantic. You can use this badge in your `README.md`: ### With Markdown ```md [![Pydantic v1](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v1.json)](https://pydantic.dev) [![Pydantic v2](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json)](https://pydantic.dev) ``` ### With reStructuredText ```rst .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v1.json :target: https://pydantic.dev :alt: Pydantic .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/pydantic/pydantic/main/docs/badge/v2.json :target: https://pydantic.dev :alt: Pydantic ``` ### With HTML ```html Pydantic Version 1 Pydantic Version 2 ``` ## Adding your library as part of Pydantic's third party test suite To be able to identify regressions early during development, Pydantic runs tests on various third-party projects using Pydantic. We consider adding support for testing new open source projects (that rely heavily on Pydantic) if your said project matches some of the following criteria: - The project is actively maintained. - The project makes use of Pydantic internals (e.g. relying on the [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) metaclass, typing utilities). - The project is popular enough (although small projects can still be included depending on how Pydantic is being used). - The project CI is simple enough to be ported into Pydantic's testing workflow. If your project meets some of these criteria, you can [open feature request](https://github.com/pydantic/pydantic/issues/new?assignees=&labels=feature+request&projects=&template=feature_request.yml) to discuss the inclusion of your project. --- # [Help with Pydantic](https://pydantic.dev/docs/validation/latest/get-started/help_with_pydantic/) # Help with Pydantic If you need help getting started with Pydantic or with advanced usage, the following sources may be useful. ## Usage Documentation The [usage documentation](/docs/validation/latest/concepts/models) is the most complete guide on how to use Pydantic. ## API Documentation The [API documentation](/docs/validation/latest/api/pydantic/base_model) gives reference docs for all public Pydantic APIs. ## GitHub Discussions [GitHub discussions](https://github.com/pydantic/pydantic/discussions) are useful for asking questions, your question and the answer will help everyone. ## Stack Overflow Use the [`pydantic`](https://stackoverflow.com/questions/tagged/pydantic) tag on Stack Overflow to ask questions, note this is not always monitored by the core Pydantic team. ## YouTube Youtube has lots of useful [videos on Pydantic](https://www.youtube.com/results?search_query=pydantic). In particular Marcelo Trylesinski's video ["Pydantic V1 to V2 - The Migration"](https://youtu.be/sD_xpYl4fPU) has helped people a lot when migrating from Pydantic V1 to V2. --- # [Welcome to Pydantic](https://pydantic.dev/docs/validation/latest/get-started/) # Welcome to Pydantic [![CI](https://img.shields.io/github/actions/workflow/status/pydantic/pydantic/ci.yml?branch=main&logo=github&label=CI)](https://github.com/pydantic/pydantic/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) [![Coverage](https://coverage-badge.samuelcolvin.workers.dev/pydantic/pydantic.svg)](https://github.com/pydantic/pydantic/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) [![pypi](https://img.shields.io/pypi/v/pydantic.svg)](https://pypi.python.org/pypi/pydantic) [![CondaForge](https://img.shields.io/conda/v/conda-forge/pydantic.svg)](https://anaconda.org/conda-forge/pydantic) [![downloads](https://static.pepy.tech/badge/pydantic/month)](https://pepy.tech/project/pydantic) [![license](https://img.shields.io/github/license/pydantic/pydantic.svg)](https://github.com/pydantic/pydantic/blob/main/LICENSE) [![llms.txt](https://img.shields.io/badge/llms.txt-green)](https://docs.pydantic.dev/latest/llms.txt) Documentation for version: v2.13.4. Pydantic is the most widely used data validation library for Python. Fast and extensible, Pydantic plays nicely with your linters/IDE/brain. Define how data should be in pure, canonical Python 3.9+; validate it with Pydantic. **Sign up for our newsletter, _The Pydantic Stack_, with updates & tutorials on Pydantic, Logfire, and Pydantic AI:** Subscribe ## Why use Pydantic? - **Powered by type hints** -- with Pydantic, schema validation and serialization are controlled by type annotations; less to learn, less code to write, and integration with your IDE and static analysis tools. [Learn more...](/docs/validation/latest/get-started/why#type-hints) - **Speed** -- Pydantic's core validation logic is written in Rust. As a result, Pydantic is among the fastest data validation libraries for Python. [Learn more...](/docs/validation/latest/get-started/why#performance) - **JSON Schema** -- Pydantic models can emit JSON Schema, allowing for easy integration with other tools. [Learn more...](/docs/validation/latest/get-started/why#json-schema) - **Strict** and **Lax** mode -- Pydantic can run in either strict mode (where data is not converted) or lax mode where Pydantic tries to coerce data to the correct type where appropriate. [Learn more...](/docs/validation/latest/get-started/why#strict-lax) - **Dataclasses**, **TypedDicts** and more -- Pydantic supports validation of many standard library types including `dataclass` and `TypedDict`. [Learn more...](/docs/validation/latest/get-started/why#dataclasses-typeddict-more) - **Customisation** -- Pydantic allows custom validators and serializers to alter how data is processed in many powerful ways. [Learn more...](/docs/validation/latest/get-started/why#customisation) - **Ecosystem** -- around 8,000 packages on PyPI use Pydantic, including massively popular libraries like _FastAPI_, _huggingface_, _Django Ninja_, _SQLModel_, & _LangChain_. [Learn more...](/docs/validation/latest/get-started/why#ecosystem) - **Battle tested** -- Pydantic is downloaded over 550M times/month and is used by all FAANG companies and 20 of the 25 largest companies on NASDAQ. If you're trying to do something with Pydantic, someone else has probably already done it. [Learn more...](/docs/validation/latest/get-started/why#using-pydantic) [Installing Pydantic](/docs/validation/latest/get-started/install) is as simple as: `pip install pydantic` ## Pydantic examples To see Pydantic at work, let's start with a simple example, creating a custom class that inherits from `BaseModel`: Validation Successful ```python from datetime import datetime from pydantic import BaseModel, PositiveInt class User(BaseModel): id: int # (1) name: str = 'John Doe' # (2) signup_ts: datetime | None # (3) tastes: dict[str, PositiveInt] # (4) external_data = { 'id': 123, 'signup_ts': '2019-06-01 12:22', # (5) 'tastes': { 'wine': 9, b'cheese': 7, # (6) 'cabbage': '1', # (7) }, } user = User(**external_data) # (8) print(user.id) # (9) #> 123 print(user.model_dump()) # (10) """ { 'id': 123, 'name': 'John Doe', 'signup_ts': datetime.datetime(2019, 6, 1, 12, 22), 'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1}, } """ ``` `id` is of type `int`; the annotation-only declaration tells Pydantic that this field is required. Strings, bytes, or floats will be coerced to integers if possible; otherwise an exception will be raised. `name` is a string; because it has a default, it is not required. `signup_ts` is a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) field that is required, but the value `None` may be provided; Pydantic will process either a [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time) integer (e.g. `1496498400`) or a string representing the date and time. `tastes` is a dictionary with string keys and positive integer values. The `PositiveInt` type is shorthand for `Annotated[int, annotated_types.Gt(0)]`. The input here is an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) formatted datetime, but Pydantic will convert it to a [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) object. The key here is `bytes`, but Pydantic will take care of coercing it to a string. Similarly, Pydantic will coerce the string `'1'` to the integer `1`. We create instance of `User` by passing our external data to `User` as keyword arguments. We can access fields as attributes of the model. We can convert the model to a dictionary with [`model_dump()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_dump). If validation fails, Pydantic will raise an error with a breakdown of what was wrong: Validation Error ```python # continuing the above example... from datetime import datetime from pydantic import BaseModel, PositiveInt, ValidationError class User(BaseModel): id: int name: str = 'John Doe' signup_ts: datetime | None tastes: dict[str, PositiveInt] external_data = {'id': 'not an int', 'tastes': {}} # (1) try: User(**external_data) # (2) except ValidationError as e: print(e.errors()) """ [ { 'type': 'int_parsing', 'loc': ('id',), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'not an int', 'url': 'https://errors.pydantic.dev/2/v/int_parsing', }, { 'type': 'missing', 'loc': ('signup_ts',), 'msg': 'Field required', 'input': {'id': 'not an int', 'tastes': {}}, 'url': 'https://errors.pydantic.dev/2/v/missing', }, ] """ ``` The input data is wrong here -- `id` is not a valid integer, and `signup_ts` is missing. Trying to instantiate `User` will raise a [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) with a list of errors. ## Who is using Pydantic? Hundreds of organisations and packages are using Pydantic. Some of the prominent companies and organizations around the world who are using Pydantic include: [![Adobe](/docs/validation/logos/adobe_logo.png)](why/#org-adobe "Adobe") [![Amazon and AWS](/docs/validation/logos/amazon_logo.png)](why/#org-amazon "Amazon and AWS") [![Anthropic](/docs/validation/logos/anthropic_logo.png)](why/#org-anthropic "Anthropic") [![Apple](/docs/validation/logos/apple_logo.png)](why/#org-apple "Apple") [![ASML](/docs/validation/logos/asml_logo.png)](why/#org-asml "ASML") [![AstraZeneca](/docs/validation/logos/astrazeneca_logo.png)](why/#org-astrazeneca "AstraZeneca") [![Cisco Systems](/docs/validation/logos/cisco_logo.png)](why/#org-cisco "Cisco Systems") [![Capital One](/docs/validation/logos/capital_one_logo.png)](why/#org-capital_one "Capital One") [![Comcast](/docs/validation/logos/comcast_logo.png)](why/#org-comcast "Comcast") [![Datadog](/docs/validation/logos/datadog_logo.png)](why/#org-datadog "Datadog") [![Facebook](/docs/validation/logos/facebook_logo.png)](why/#org-facebook "Facebook") [![GitHub](/docs/validation/logos/github_logo.png)](why/#org-github "GitHub") [![Google](/docs/validation/logos/google_logo.png)](why/#org-google "Google") [![HSBC](/docs/validation/logos/hsbc_logo.png)](why/#org-hsbc "HSBC") [![IBM](/docs/validation/logos/ibm_logo.png)](why/#org-ibm "IBM") [![Intel](/docs/validation/logos/intel_logo.png)](why/#org-intel "Intel") [![Intuit](/docs/validation/logos/intuit_logo.png)](why/#org-intuit "Intuit") [![Intergovernmental Panel on Climate Change](/docs/validation/logos/ipcc_logo.png)](why/#org-ipcc "Intergovernmental Panel on Climate Change") [![JPMorgan](/docs/validation/logos/jpmorgan_logo.png)](why/#org-jpmorgan "JPMorgan") [![Jupyter](/docs/validation/logos/jupyter_logo.png)](why/#org-jupyter "Jupyter") [![Microsoft](/docs/validation/logos/microsoft_logo.png)](why/#org-microsoft "Microsoft") [![Molecular Science Software Institute](/docs/validation/logos/molssi_logo.png)](why/#org-molssi "Molecular Science Software Institute") [![NASA](/docs/validation/logos/nasa_logo.png)](why/#org-nasa "NASA") [![Netflix](/docs/validation/logos/netflix_logo.png)](why/#org-netflix "Netflix") [![NSA](/docs/validation/logos/nsa_logo.png)](why/#org-nsa "NSA") [![NVIDIA](/docs/validation/logos/nvidia_logo.png)](why/#org-nvidia "NVIDIA") [![OpenAI](/docs/validation/logos/openai_logo.png)](why/#org-openai "OpenAI") [![Oracle](/docs/validation/logos/oracle_logo.png)](why/#org-oracle "Oracle") [![Palantir](/docs/validation/logos/palantir_logo.png)](why/#org-palantir "Palantir") [![Qualcomm](/docs/validation/logos/qualcomm_logo.png)](why/#org-qualcomm "Qualcomm") [![Red Hat](/docs/validation/logos/redhat_logo.png)](why/#org-redhat "Red Hat") [![Revolut](/docs/validation/logos/revolut_logo.png)](why/#org-revolut "Revolut") [![Robusta](/docs/validation/logos/robusta_logo.png)](why/#org-robusta "Robusta") [![Salesforce](/docs/validation/logos/salesforce_logo.png)](why/#org-salesforce "Salesforce") [![Starbucks](/docs/validation/logos/starbucks_logo.png)](why/#org-starbucks "Starbucks") [![Texas Instruments](/docs/validation/logos/ti_logo.png)](why/#org-ti "Texas Instruments") [![Twilio](/docs/validation/logos/twilio_logo.png)](why/#org-twilio "Twilio") [![Twitter](/docs/validation/logos/twitter_logo.png)](why/#org-twitter "Twitter") [![UK Home Office](/docs/validation/logos/ukhomeoffice_logo.png)](why/#org-ukhomeoffice "UK Home Office") For a more comprehensive list of open-source projects using Pydantic see the [list of dependents on github](https://github.com/pydantic/pydantic/network/dependents), or you can find some awesome projects using Pydantic in [awesome-pydantic](https://github.com/Kludex/awesome-pydantic). --- # [Installation](https://pydantic.dev/docs/validation/latest/get-started/install/) # Installation Installation is as simple as: - [pip](#tab-panel-608) - [uv](#tab-panel-609) Terminal ```bash pip install pydantic ``` Terminal ```bash uv add pydantic ``` Pydantic has a few dependencies: - [`pydantic-core`](https://pypi.org/project/pydantic-core/): Core validation logic for Pydantic written in Rust. - [`typing-extensions`](https://pypi.org/project/typing-extensions/): Backport of the standard library [typing](https://docs.python.org/3/library/typing.html#module-typing) module. - [`annotated-types`](https://pypi.org/project/annotated-types/): Reusable constraint types to use with [`typing.Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated). If you've got Python 3.9+ and `pip` installed, you're good to go. Pydantic is also available on [conda](https://www.anaconda.com) under the [conda-forge](https://conda-forge.org) channel: Terminal ```bash conda install pydantic -c conda-forge ``` ## Optional dependencies Pydantic has the following optional dependencies: - `email`: Email validation provided by the [email-validator](https://pypi.org/project/email-validator/) package. - `timezone`: Fallback IANA time zone database provided by the [tzdata](https://pypi.org/project/tzdata/) package. To install optional dependencies along with Pydantic: - [pip](#tab-panel-610) - [uv](#tab-panel-611) Terminal ```bash # with the `email` extra: pip install 'pydantic[email]' # or with `email` and `timezone` extras: pip install 'pydantic[email,timezone]' ``` Terminal ```bash # with the `email` extra: uv add 'pydantic[email]' # or with `email` and `timezone` extras: uv add 'pydantic[email,timezone]' ``` Of course, you can also install requirements manually with `pip install email-validator tzdata`. ## Install from repository And if you prefer to install Pydantic directly from the repository: - [pip](#tab-panel-612) - [uv](#tab-panel-613) Terminal ```bash pip install 'git+https://github.com/pydantic/pydantic@main' # or with `email` and `timezone` extras: pip install 'git+https://github.com/pydantic/pydantic@main#egg=pydantic[email,timezone]' ``` Terminal ```bash uv add 'git+https://github.com/pydantic/pydantic@main' # or with `email` and `timezone` extras: uv add 'git+https://github.com/pydantic/pydantic@main#egg=pydantic[email,timezone]' ``` --- # [Migration Guide](https://pydantic.dev/docs/validation/latest/get-started/migration/) > Migrating from Pydantic V1. # Migration Guide Pydantic V2 introduces a number of changes to the API, including some breaking changes. This page provides a guide highlighting the most important changes to help you migrate your code from Pydantic V1 to Pydantic V2. ## Install Pydantic V2 Pydantic V2 is now the current production release of Pydantic. You can install Pydantic V2 from PyPI: Terminal ```bash pip install -U pydantic ``` If you encounter any issues, please [create an issue in GitHub](https://github.com/pydantic/pydantic/issues) using the `bug V2` label. This will help us to actively monitor and track errors, and to continue to improve the library's performance. If you need to use latest Pydantic V1 for any reason, see the [Continue using Pydantic V1 features](#continue-using-pydantic-v1-features) section below for details on installation and imports from `pydantic.v1`. ## Code transformation tool We have created a tool to help you migrate your code. This tool is still in beta, but we hope it will help you to migrate your code more quickly. You can install the tool from PyPI: Terminal ```bash pip install bump-pydantic ``` The usage is simple. If your project structure is: - repo\_folder - my\_package - ... Then you'll want to do: cd /path/to/repo\_folder bump-pydantic my\_package See more about it on the [Bump Pydantic](https://github.com/pydantic/bump-pydantic) repository. ## Continue using Pydantic V1 features Pydantic V1 is still available when you need it, though we recommend migrating to Pydantic V2 for its improvements and new features. If you need to use latest Pydantic V1, you can install it with: Terminal ```bash pip install "pydantic==1.*" ``` The Pydantic V2 package also continues to provide access to the Pydantic V1 API by importing through `pydantic.v1`. For example, you can use the `BaseModel` class from Pydantic V1 instead of the Pydantic V2 `pydantic.BaseModel` class: ```python from pydantic.v1 import BaseModel ``` You can also import functions that have been removed from Pydantic V2, such as `lenient_isinstance`: ```python from pydantic.v1.utils import lenient_isinstance ``` Pydantic V1 documentation is available at [https://docs.pydantic.dev/1.10/](https://docs.pydantic.dev/1.10/). ### Using Pydantic v1 features in a v1/v2 environment As of `pydantic>=1.10.17`, the `pydantic.v1` namespace can be used within V1. This makes it easier to migrate to V2, which also supports the `pydantic.v1` namespace. In order to unpin a `pydantic<2` dependency and continue using V1 features, take the following steps: 1. Replace `pydantic<2` with `pydantic>=1.10.17` 2. Find and replace all occurrences of: ```python from pydantic. import ``` with: ```python from pydantic.v1. import ``` Here's how you can import `pydantic`'s v1 features based on your version of `pydantic`: - [pydantic>=1.10.17,<3](#tab-panel-614) - [pydantic<3](#tab-panel-615) As of `v1.10.17` the `.v1` namespace is available in V1, allowing imports as below: ```python from pydantic.v1.fields import ModelField ``` All versions of Pydantic V1 and V2 support the following import pattern, in case you don't know which version of Pydantic you are using: ```python try: from pydantic.v1.fields import ModelField except ImportError: from pydantic.fields import ModelField ``` Note When importing modules using `pydantic>=1.10.17,<2` with the `.v1` namespace these modules will _not_ be the **same** module as the same import without the `.v1` namespace, but the symbols imported _will_ be. For example `pydantic.v1.fields is not pydantic.fields` but `pydantic.v1.fields.ModelField is pydantic.fields.ModelField`. Luckily, this is not likely to be relevant in the vast majority of cases. It's just an unfortunate consequence of providing a smoother migration experience. ## Migration guide The following sections provide details on the most important changes in Pydantic V2. ### Changes to `pydantic.BaseModel` Various method names have been changed; all non-deprecated `BaseModel` methods now have names matching either the format `model_.*` or `__.*pydantic.*__`. Where possible, we have retained the deprecated methods with their old names to help ease migration, but calling them will emit `DeprecationWarning`s. Pydantic V1 Pydantic V2 `__fields__` `model_fields` `__private_attributes__` `__pydantic_private__` `__validators__` `__pydantic_validator__` `construct()` `model_construct()` `copy()` `model_copy()` `dict()` `model_dump()` `json_schema()` `model_json_schema()` `json()` `model_dump_json()` `parse_obj()` `model_validate()` `update_forward_refs()` `model_rebuild()` - Some of the built-in data-loading functionality has been slated for removal. In particular, `parse_raw` and `parse_file` are now deprecated. In Pydantic V2, `model_validate_json` works like `parse_raw`. Otherwise, you should load the data and then pass it to `model_validate`. - The `from_orm` method has been deprecated; you can now just use `model_validate` (equivalent to `parse_obj` from Pydantic V1) to achieve something similar, as long as you've set `from_attributes=True` in the model config. - The `__eq__` method has changed for models. - Models can only be equal to other `BaseModel` instances. - For two model instances to be equal, they must have the same: - Type (or, in the case of generic models, non-parametrized generic origin type) - Field values - Extra values (only relevant when `model_config['extra'] == 'allow'`) - Private attribute values; models with different values of private attributes are no longer equal. - Models are no longer equal to the dicts containing their data. - Non-generic models of different types are never equal. - Generic models with different origin types are never equal. We don't require _exact_ type equality so that, for example, instances of `MyGenericModel[Any]` could be equal to instances of `MyGenericModel[int]`. - We have replaced the use of the `__root__` field to specify a "custom root model" with a new type called [`RootModel`](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types) which is intended to replace the functionality of using a field called `__root__` in Pydantic V1. Note, `RootModel` types no longer support the `arbitrary_types_allowed` config setting. See [this issue comment](https://github.com/pydantic/pydantic/issues/6710#issuecomment-1700948167) for an explanation. - We have significantly expanded Pydantic's capabilities related to customizing serialization. In particular, we have added the [`@field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers#pydantic.functional_serializers.field_serializer), [`@model_serializer`](/docs/validation/latest/api/pydantic/functional_serializers#pydantic.functional_serializers.model_serializer), and [`@computed_field`](/docs/validation/latest/api/pydantic/fields#pydantic.fields.computed_field) decorators, which each address various shortcomings from Pydantic V1. - See [Custom serializers](/docs/validation/latest/concepts/serialization#serializers) for the usage docs of these new decorators. - Due to performance overhead and implementation complexity, we have now deprecated support for specifying `json_encoders` in the model config. This functionality was originally added for the purpose of achieving custom serialization logic, and we think the new serialization decorators are a better choice in most common scenarios. - We have changed the behavior related to serializing subclasses of models when they occur as nested fields in a parent model. In V1, we would always include all fields from the subclass instance. In V2, when we dump a model, we only include the fields that are defined on the annotated type of the field. This helps prevent some accidental security bugs. You can read more about this (including how to opt out of this behavior) in the [relevant section](/docs/validation/latest/concepts/serialization#subclasses-of-model-like-types) of the model exporting docs. - `GetterDict` has been removed as it was just an implementation detail of `orm_mode`, which has been removed. - In many cases, arguments passed to the constructor will be **copied** in order to perform validation and, where necessary, coercion (see the [documentation](/docs/validation/latest/concepts/models#attribute-copies)). This is notable in the case of passing mutable objects as arguments to a constructor. - The `.json()` method is deprecated, and attempting to use this deprecated method with arguments such as `indent` or `ensure_ascii` may lead to confusing errors. For best results, switch to V2's equivalent, `model_dump_json()`. If you'd still like to use said arguments, you can use [this workaround](https://github.com/pydantic/pydantic/issues/8825#issuecomment-1946206415). - JSON serialization of non-string key values is generally done with `str(key)`, leading to some changes in behavior such as the following: ```python from typing import Optional from pydantic import BaseModel as V2BaseModel from pydantic.v1 import BaseModel as V1BaseModel class V1Model(V1BaseModel): a: dict[Optional[str], int] class V2Model(V2BaseModel): a: dict[Optional[str], int] v1_model = V1Model(a={None: 123}) v2_model = V2Model(a={None: 123}) # V1 print(v1_model.json()) #> {"a": {"null": 123}} # V2 print(v2_model.model_dump_json()) #> {"a":{"None":123}} ``` - `model_dump_json()` results are compacted in order to save space, and don't always exactly match that of `json.dumps()` output. That being said, you can easily modify the separators used in `json.dumps()` results in order to align the two outputs: ```python import json from pydantic import BaseModel as V2BaseModel from pydantic.v1 import BaseModel as V1BaseModel class V1Model(V1BaseModel): a: list[str] class V2Model(V2BaseModel): a: list[str] v1_model = V1Model(a=['fancy', 'sushi']) v2_model = V2Model(a=['fancy', 'sushi']) # V1 print(v1_model.json()) #> {"a": ["fancy", "sushi"]} # V2 print(v2_model.model_dump_json()) #> {"a":["fancy","sushi"]} # Plain json.dumps print(json.dumps(v2_model.model_dump())) #> {"a": ["fancy", "sushi"]} # Modified json.dumps print(json.dumps(v2_model.model_dump(), separators=(',', ':'))) #> {"a":["fancy","sushi"]} ``` ### Changes to `pydantic.generics.GenericModel` The `pydantic.generics.GenericModel` class is no longer necessary, and has been removed. Instead, you can now create generic `BaseModel` subclasses by just adding `Generic` as a parent class on a `BaseModel` subclass directly. This looks like `class MyGenericModel(BaseModel, Generic[T]): ...`. Mixing of V1 and V2 models is not supported which means that type parameters of such generic `BaseModel` (V2) cannot be V1 models. While it may not raise an error, we strongly advise against using _parametrized_ generics in `isinstance` checks. - For example, you should not do `isinstance(my_model, MyGenericModel[int])`. However, it is fine to do `isinstance(my_model, MyGenericModel)`. (Note that for standard generics, it would raise an error to do a subclass check with a parameterized generic.) - If you need to perform `isinstance` checks against parametrized generics, you can do this by subclassing the parametrized generic class. This looks like `class MyIntModel(MyGenericModel[int]): ...` and `isinstance(my_model, MyIntModel)`. Find more information in the [Generic models](/docs/validation/latest/concepts/models#generic-models) documentation. ### Changes to `pydantic.Field` `Field` no longer supports arbitrary keyword arguments to be added to the JSON schema. Instead, any extra data you want to add to the JSON schema should be passed as a dictionary to the `json_schema_extra` keyword argument. In Pydantic V1, the `alias` property returns the field's name when no alias is set. In Pydantic V2, this behavior has changed to return `None` when no alias is set. The following properties have been removed from or changed in `Field`: - `const` - `min_items` (use `min_length` instead) - `max_items` (use `max_length` instead) - `unique_items` - `allow_mutation` (use `frozen` instead) - `regex` (use `pattern` instead) - `final` (use the [typing.Final](https://docs.python.org/3/library/typing.html#typing.Final) type hint instead) Field constraints are no longer automatically pushed down to the parameters of generics. For example, you can no longer validate every element of a list matches a regex by providing `my_list: list[str] = Field(pattern=".*")`. Instead, use [`typing.Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) to provide an annotation on the `str` itself: `my_list: list[Annotated[str, Field(pattern=".*")]]` ### Changes to dataclasses Pydantic [dataclasses](/docs/validation/latest/concepts/dataclasses) continue to be useful for enabling the data validation on standard dataclasses without having to subclass `BaseModel`. Pydantic V2 introduces the following changes to this dataclass behavior: - When used as fields, dataclasses (Pydantic or vanilla) no longer accept tuples as validation inputs; dicts should be used instead. - The `__post_init__` in Pydantic dataclasses will now be called _after_ validation, rather than before. - As a result, the `__post_init_post_parse__` method would have become redundant, so has been removed. - Pydantic no longer supports `extra='allow'` for Pydantic dataclasses, where extra fields passed to the initializer would be stored as extra attributes on the dataclass. `extra='ignore'` is still supported for the purpose of ignoring unexpected fields while parsing data, they just won't be stored on the instance. - Pydantic dataclasses no longer have an attribute `__pydantic_model__`, and no longer use an underlying `BaseModel` to perform validation or provide other functionality. - To perform validation, generate a JSON schema, or make use of any other functionality that may have required `__pydantic_model__` in V1, you should now wrap the dataclass with a [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) ([discussed more below](#introduction-of-typeadapter)) and make use of its methods. - In Pydantic V1, if you used a vanilla (i.e., non-Pydantic) dataclass as a field, the config of the parent type would be used as though it was the config for the dataclass itself as well. In Pydantic V2, this is no longer the case. - In Pydantic V2, to override the config (like you would with `model_config` on a `BaseModel`), you can use the `config` parameter on the `@dataclass` decorator. See [Dataclass Config](/docs/validation/latest/concepts/dataclasses#dataclass-config) for examples. ### Changes to config - In Pydantic V2, to specify config on a model, you should set a class attribute called `model_config` to be a dict with the key/value pairs you want to be used as the config. The Pydantic V1 behavior to create a class called `Config` in the namespace of the parent `BaseModel` subclass is now deprecated. - When subclassing a model, the `model_config` attribute is inherited. This is helpful in the case where you'd like to use a base class with a given configuration for many models. Note, if you inherit from multiple `BaseModel` subclasses, like `class MyModel(Model1, Model2)`, the non-default settings in the `model_config` attribute from the two models will be merged, and for any settings defined in both, those from `Model2` will override those from `Model1`. - The following config settings have been removed: - `allow_mutation` -- this has been removed. You should be able to use [frozen](/docs/validation/latest/api/pydantic/config#pydantic.config.ConfigDict) equivalently (inverse of current use). - `error_msg_templates` - `fields` -- this was the source of various bugs, so has been removed. You should be able to use `Annotated` on fields to modify them as desired. - `getter_dict` -- `orm_mode` has been removed, and this implementation detail is no longer necessary. - `smart_union` - the default `union_mode` in Pydantic V2 is `'smart'`. - `underscore_attrs_are_private` -- the Pydantic V2 behavior is now the same as if this was always set to `True` in Pydantic V1. - `json_loads` - `json_dumps` - `copy_on_model_validation` - `post_init_call` - The following config settings have been renamed: - `allow_population_by_field_name` → `populate_by_name` (or `validate_by_name` starting in v2.11) - `anystr_lower` → `str_to_lower` - `anystr_strip_whitespace` → `str_strip_whitespace` - `anystr_upper` → `str_to_upper` - `keep_untouched` → `ignored_types` - `max_anystr_length` → `str_max_length` - `min_anystr_length` → `str_min_length` - `orm_mode` → `from_attributes` - `schema_extra` → `json_schema_extra` - `validate_all` → `validate_default` See the [`ConfigDict` API reference](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict) for more details. ### Changes to validators #### `@validator` and `@root_validator` are deprecated - `@validator` has been deprecated, and should be replaced with [`@field_validator`](/docs/validation/latest/concepts/validators), which provides various new features and improvements. - The new `@field_validator` decorator does not have the `each_item` keyword argument; validators you want to apply to items within a generic container should be added by annotating the type argument. See [validators in Annotated metadata](/docs/validation/latest/concepts/types#using-the-annotated-pattern) for details. This looks like `list[Annotated[int, Field(ge=0)]]` - Even if you keep using the deprecated `@validator` decorator, you can no longer add the `field` or `config` arguments to the signature of validator functions. If you need access to these, you'll need to migrate to `@field_validator` -- see the [next section](#changes-to-validators-allowed-signatures) for more details. - If you use the `always=True` keyword argument to a validator function, note that standard validators for the annotated type will _also_ be applied even to defaults, not just the custom validators. For example, despite the fact that the validator below will never error, the following code raises a `ValidationError`: Note To avoid this, you can use the `validate_default` argument in the `Field` function. When set to `True`, it mimics the behavior of `always=True` in Pydantic v1. However, the new way of using `validate_default` is encouraged as it provides more flexibility and control. ```python from pydantic import BaseModel, validator class Model(BaseModel): x: str = 1 @validator('x', always=True) @classmethod def validate_x(cls, v): return v Model() ``` - `@root_validator` has been deprecated, and should be replaced with [`@model_validator`](/docs/validation/latest/api/pydantic/functional_validators#pydantic.functional_validators.model_validator), which also provides new features and improvements. Be aware that the allowed signatures have changed (see the [relevant documentation](/docs/validation/latest/concepts/validators#model-validators)). - Under some circumstances (such as assignment when `model_config['validate_assignment'] is True`), the `@model_validator` decorator will receive an instance of the model, not a dict of values. You may need to be careful to handle this case. - Even if you keep using the deprecated `@root_validator` decorator, due to refactors in validation logic, you can no longer run with `skip_on_failure=False` (which is the default value of this keyword argument, so must be set explicitly to `True`). #### Changes to `@validator`'s allowed signatures In Pydantic V1, functions wrapped by `@validator` could receive keyword arguments with metadata about what was being validated. Some of these arguments have been removed from `@field_validator` in Pydantic V2: - `config`: Pydantic V2's config is now a dictionary instead of a class, which means this argument is no longer backwards compatible. If you need to access the configuration you should migrate to `@field_validator` and use `info.config`. - `field`: this argument used to be a `ModelField` object, which was a quasi-internal class that no longer exists in Pydantic V2. Most of this information can still be accessed by using the field name from `info.field_name` to index into `cls.model_fields` ```python from pydantic import BaseModel, ValidationInfo, field_validator class Model(BaseModel): x: int @field_validator('x') def val_x(cls, v: int, info: ValidationInfo) -> int: assert info.config is not None print(info.config.get('title')) #> Model print(cls.model_fields[info.field_name].is_required()) #> True return v Model(x=1) ``` #### `TypeError` is no longer converted to `ValidationError` in validators Previously, when raising a `TypeError` within a validator function, that error would be wrapped into a `ValidationError` and, in some cases (such as with FastAPI), these errors might be displayed to end users. This led to a variety of undesirable behavior -- for example, calling a function with the wrong signature might produce a user-facing `ValidationError`. However, in Pydantic V2, when a `TypeError` is raised in a validator, it is no longer converted into a `ValidationError`: ```python import pytest from pydantic import BaseModel, field_validator class Model(BaseModel): x: int @field_validator('x') def val_x(cls, v: int) -> int: return str.lower(v) # raises a TypeError with pytest.raises(TypeError): Model(x=1) ``` This applies to all validation decorators. #### Validator behavior changes Pydantic V2 includes some changes to type coercion. For example: - coercing `int`, `float`, and `Decimal` values to strings is now optional and disabled by default, see [Coerce Numbers to Strings](/docs/validation/latest/api/pydantic/config/#pydantic.config.ConfigDict.coerce_numbers_to_str). - iterable of pairs is no longer coerced to a dict. See the [Conversion table](/docs/validation/latest/concepts/conversion_table) for details on Pydantic V2 type coercion defaults. #### The `allow_reuse` keyword argument is no longer necessary Previously, Pydantic tracked "reused" functions in decorators as this was a common source of mistakes. We did this by comparing the function's fully qualified name (module name + function name), which could result in false positives. The `allow_reuse` keyword argument could be used to disable this when it was intentional. Our approach to detecting repeatedly defined functions has been overhauled to only error for redefinition within a single class, reducing false positives and bringing the behavior more in line with the errors that type checkers and linters would give for defining a method with the same name multiple times in a single class definition. In nearly all cases, if you were using `allow_reuse=True`, you should be able to simply delete that keyword argument and have things keep working as expected. #### `@validate_arguments` has been renamed to `@validate_call` In Pydantic V2, the `@validate_arguments` decorator has been renamed to `@validate_call`. In Pydantic V1, the decorated function had various attributes added, such as `raw_function`, and `validate` (which could be used to validate arguments without actually calling the decorated function). Due to limited use of these attributes, and performance-oriented changes in implementation, we have not preserved this functionality in `@validate_call`. ### Input types are not preserved In Pydantic V1 we made great efforts to preserve the types of all field inputs for generic collections when they were proper subtypes of the field annotations. For example, given the annotation `Mapping[str, int]` if you passed in a `collection.Counter()` you'd get a `collection.Counter()` as the value. Supporting this behavior in V2 would have negative performance implications for the general case (we'd have to check types every time) and would add a lot of complexity to validation. Further, even in V1 this behavior was inconsistent and partially broken: it did not work for many types (`str`, `UUID`, etc.), and for generic collections it's impossible to re-build the original input correctly without a lot of special casing (consider `ChainMap`; rebuilding the input is necessary because we need to replace values after validation, e.g. if coercing strings to ints). In Pydantic V2 we no longer attempt to preserve the input type in all cases; instead, we only promise that the output type will match the type annotations. Going back to the `Mapping` example, we promise the output will be a valid `Mapping`, and in practice it will be a plain `dict`: ```python from collections.abc import Mapping from pydantic import TypeAdapter class MyDict(dict): pass ta = TypeAdapter(Mapping[str, int]) v = ta.validate_python(MyDict()) print(type(v)) #> ``` If you want the output type to be a specific type, consider annotating it as such or implementing a custom validator: ```python from collections.abc import Mapping from typing import Annotated, Any, TypeVar from pydantic import ( TypeAdapter, ValidationInfo, ValidatorFunctionWrapHandler, WrapValidator, ) def restore_input_type( value: Any, handler: ValidatorFunctionWrapHandler, _info: ValidationInfo ) -> Any: return type(value)(handler(value)) T = TypeVar('T') PreserveType = Annotated[T, WrapValidator(restore_input_type)] ta = TypeAdapter(PreserveType[Mapping[str, int]]) class MyDict(dict): pass v = ta.validate_python(MyDict()) assert type(v) is MyDict ``` While we don't promise to preserve input types everywhere, we _do_ preserve them for subclasses of `BaseModel`, and for dataclasses: ```python import pydantic.dataclasses from pydantic import BaseModel class InnerModel(BaseModel): x: int class OuterModel(BaseModel): inner: InnerModel class SubInnerModel(InnerModel): y: int m = OuterModel(inner=SubInnerModel(x=1, y=2)) print(m) #> inner=SubInnerModel(x=1, y=2) @pydantic.dataclasses.dataclass class InnerDataclass: x: int @pydantic.dataclasses.dataclass class SubInnerDataclass(InnerDataclass): y: int @pydantic.dataclasses.dataclass class OuterDataclass: inner: InnerDataclass d = OuterDataclass(inner=SubInnerDataclass(x=1, y=2)) print(d) #> OuterDataclass(inner=SubInnerDataclass(x=1, y=2)) ``` ### Changes to Handling of Standard Types #### Dicts Iterables of pairs (which include empty iterables) no longer pass validation for fields of type `dict`. #### Unions While union types will still attempt validation of each choice from left to right, they now preserve the type of the input whenever possible, even if the correct type is not the first choice for which the input would pass validation. As a demonstration, consider the following example: ```python from typing import Union from pydantic import BaseModel class Model(BaseModel): x: Union[int, str] print(Model(x='1')) #> x='1' ``` In Pydantic V1, the printed result would have been `x=1`, since the value would pass validation as an `int`. In Pydantic V2, we recognize that the value is an instance of one of the cases and short-circuit the standard union validation. To revert to the non-short-circuiting left-to-right behavior of V1, annotate the union with `Field(union_mode='left_to_right')`. See [Union Mode](/docs/validation/latest/concepts/unions#union-modes) for more details. #### Required, optional, and nullable fields Pydantic V2 changes some of the logic for specifying whether a field annotated as `Optional` is required (i.e., has no default value) or not (i.e., has a default value of `None` or any other value of the corresponding type), and now more closely matches the behavior of `dataclasses`. Similarly, fields annotated as `Any` no longer have a default value of `None`. The following table describes the behavior of field annotations in V2: State Field Definition Required, cannot be `None` `f1: str` Not required, cannot be `None`, is `'abc'` by default `f2: str = 'abc'` Required, can be `None` `f3: Optional[str]` Not required, can be `None`, is `None` by default `f4: Optional[str] = None` Not required, can be `None`, is `'abc'` by default `f5: Optional[str] = 'abc'` Required, can be any type (including `None`) `f6: Any` Not required, can be any type (including `None`) `f7: Any = None` Note A field annotated as `typing.Optional[T]` will be required, and will allow for a value of `None`. It does not mean that the field has a default value of `None`. _(This is a breaking change from V1.)_ Note Any default value if provided makes a field not required. Here is a code example demonstrating the above: ```python from typing import Optional from pydantic import BaseModel, ValidationError class Foo(BaseModel): f1: str # required, cannot be None f2: Optional[str] # required, can be None - same as str | None f3: Optional[str] = None # not required, can be None f4: str = 'Foobar' # not required, but cannot be None try: Foo(f1=None, f2=None, f4='b') except ValidationError as e: print(e) """ 1 validation error for Foo f1 Input should be a valid string [type=string_type, input_value=None, input_type=NoneType] """ ``` #### Patterns / regex on strings Pydantic V1 used Python's regex library. Pydantic V2 uses the Rust [regex crate](https://github.com/rust-lang/regex). This crate is not just a "Rust version of regular expressions", it's a completely different approach to regular expressions. In particular, it promises linear time searching of strings in exchange for dropping a couple of features (namely look arounds and backreferences). We believe this is a tradeoff worth making, in particular because Pydantic is used to validate untrusted input where ensuring things don't accidentally run in exponential time depending on the untrusted input is important. On the flipside, for anyone not using these features complex regex validation should be orders of magnitude faster because it's done in Rust and in linear time. If you still want to use Python's regex library, you can use the [`regex_engine`](/docs/validation/latest/api/pydantic/config#pydantic.config.ConfigDict.regex_engine) config setting. ### Type conversion from floats to integers In V1, whenever a field was annotated as `int`, any float value would be accepted, which could lead to a potential data loss if the float value contains a non-zero decimal part. In V2, type conversion from floats to integers is only allowed if the decimal part is zero: ```python from pydantic import BaseModel, ValidationError class Model(BaseModel): x: int print(Model(x=10.0)) #> x=10 try: Model(x=10.2) except ValidationError as err: print(err) """ 1 validation error for Model x Input should be a valid integer, got a number with a fractional part [type=int_from_float, input_value=10.2, input_type=float] """ ``` ### Introduction of `TypeAdapter` Pydantic V1 had weak support for validating or serializing non-`BaseModel` types. To work with them, you had to either create a "root" model or use the utility functions in `pydantic.tools` (namely, `parse_obj_as` and `schema_of`). In Pydantic V2 this is _a lot_ easier: the [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) class lets you create an object with methods for validating, serializing, and producing JSON schemas for arbitrary types. This serves as a complete replacement for `parse_obj_as` and `schema_of` (which are now deprecated), and also covers some of the use cases of "root" models. ([`RootModel`](/docs/validation/latest/concepts/models#rootmodel-and-custom-root-types), [discussed above](#changes-to-pydanticbasemodel), covers the others.) ```python from pydantic import TypeAdapter adapter = TypeAdapter(list[int]) assert adapter.validate_python(['1', '2', '3']) == [1, 2, 3] print(adapter.json_schema()) #> {'items': {'type': 'integer'}, 'type': 'array'} ``` Due to limitations of inferring generic types with common type checkers, to get proper typing in some scenarios, you may need to explicitly specify the generic parameter: ```python from pydantic import TypeAdapter adapter = TypeAdapter[str | int](str | int) ... ``` See [Type Adapter](/docs/validation/latest/concepts/type_adapter) for more information. ### Defining custom types We have completely overhauled the way custom types are defined in pydantic. We have exposed hooks for generating both `pydantic-core` and JSON schemas, allowing you to get all the performance benefits of Pydantic V2 even when using your own custom types. We have also introduced ways to use [`typing.Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) to add custom validation to your own types. The main changes are: - `__get_validators__` should be replaced with `__get_pydantic_core_schema__`. See [Custom Data Types](/docs/validation/latest/concepts/types#customizing_validation_with_get_pydantic_core_schema) for more information. - `__modify_schema__` becomes `__get_pydantic_json_schema__`. See [JSON Schema Customization](/docs/validation/latest/concepts/json_schema#customizing-json-schema) for more information. Additionally, you can use [`typing.Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) to modify or provide the `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__` functions of a type by annotating it, rather than modifying the type itself. This provides a powerful and flexible mechanism for integrating third-party types with Pydantic, and in some cases may help you remove hacks from Pydantic V1 introduced to work around the limitations for custom types. See [Custom Data Types](/docs/validation/latest/concepts/types#custom-types) for more information. ### Changes to JSON schema generation We received many requests over the years to make changes to the JSON schemas that pydantic generates. In Pydantic V2, we have tried to address many of the common requests: - The JSON schema for `Optional` fields now indicates that the value `null` is allowed. - The `Decimal` type is now exposed in JSON schema (and serialized) as a string. - The JSON schema no longer preserves namedtuples as namedtuples. - The JSON schema we generate by default now targets draft 2020-12 (with some OpenAPI extensions). - When they differ, you can now specify if you want the JSON schema representing the inputs to validation, or the outputs from serialization. However, there have been many reasonable requests over the years for changes which we have not chosen to implement. In Pydantic V1, even if you were willing to implement changes yourself, it was very difficult because the JSON schema generation process involved various recursive function calls; to override one, you'd have to copy and modify the whole implementation. In Pydantic V2, one of our design goals was to make it easier to customize JSON schema generation. To this end, we have introduced the class [`GenerateJsonSchema`](/docs/validation/latest/api/pydantic/json_schema#pydantic.json_schema.GenerateJsonSchema), which implements the translation of a type's pydantic-core schema into a JSON schema. By design, this class breaks the JSON schema generation process into smaller methods that can be easily overridden in subclasses to modify the "global" approach to generating JSON schema. The various methods that can be used to produce JSON schema (such as `BaseModel.model_json_schema` or `TypeAdapter.json_schema`) accept a keyword argument `schema_generator: type[GenerateJsonSchema] = GenerateJsonSchema`, and you can pass your custom subclass to these methods in order to use your own approach to generating JSON schema. Hopefully this means that if you disagree with any of the choices we've made, or if you are reliant on behaviors in Pydantic V1 that have changed in Pydantic V2, you can use a custom `schema_generator`, modifying the `GenerateJsonSchema` class as necessary for your application. ### `BaseSettings` has moved to `pydantic-settings` [`BaseSettings`](/docs/validation/latest/api/pydantic_settings#pydantic_settings.BaseSettings), the base object for Pydantic [settings management](/docs/validation/latest/concepts/pydantic_settings), has been moved to a separate package, [`pydantic-settings`](https://github.com/pydantic/pydantic-settings). Also, the `parse_env_var` classmethod has been removed. So, you need to [customise settings sources](/docs/validation/latest/concepts/pydantic_settings#customise-settings-sources) to have your own parsing function. ### Color and Payment Card Numbers moved to `pydantic-extra-types` The following special-use types have been moved to the [Pydantic Extra Types](https://github.com/pydantic/pydantic-extra-types) package, which may be installed separately if needed. - [Color Types](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_color) - [Payment Card Numbers](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_payment) ### Url and Dsn types in `pydantic.networks` no longer inherit from `str` In Pydantic V1 the [`AnyUrl`](/docs/validation/latest/api/pydantic/networks/#pydantic.networks.AnyUrl) type inherited from `str`, and all the other `Url` and `Dsn` types inherited from these. In Pydantic V2 these types are built on two new `Url` and `MultiHostUrl` classes using `Annotated`. Inheriting from `str` had upsides and downsides, and for V2 we decided it would be better to remove this. To use these types in APIs which expect `str` you'll now need to convert them (with `str(url)`). Pydantic V2 uses Rust's [Url](https://crates.io/crates/url) crate for URL validation. Some of the URL validation differs slightly from the previous behavior in V1. One notable difference is that the new `Url` types append slashes to the validated version if no path is included, even if a slash is not specified in the argument to a `Url` type constructor. See the example below for this behavior: ```python from pydantic import AnyUrl assert str(AnyUrl(url='https://google.com')) == 'https://google.com/' assert str(AnyUrl(url='https://google.com/')) == 'https://google.com/' assert str(AnyUrl(url='https://google.com/api')) == 'https://google.com/api' assert str(AnyUrl(url='https://google.com/api/')) == 'https://google.com/api/' ``` If you still want to use the old behavior without the appended slash, take a look at this [solution](https://github.com/pydantic/pydantic/issues/7186#issuecomment-1690235887). ### Constrained types The `Constrained*` classes were _removed_, and you should replace them by `Annotated[, Field(...)]`, for example: ```python from pydantic import BaseModel, ConstrainedInt class MyInt(ConstrainedInt): ge = 0 class Model(BaseModel): x: MyInt ``` ...becomes: ```python from typing import Annotated from pydantic import BaseModel, Field MyInt = Annotated[int, Field(ge=0)] class Model(BaseModel): x: MyInt ``` Read more about it in the [Composing types via `Annotated`](/docs/validation/latest/concepts/types#using-the-annotated-pattern) docs. For `ConstrainedStr` you can use [`StringConstraints`](/docs/validation/latest/api/pydantic/types/#pydantic.types.StringConstraints) instead. ### Mypy plugins Pydantic V2 contains a [mypy](https://mypy.readthedocs.io/en/stable/extending_mypy.html#configuring-mypy-to-use-plugins) plugin in `pydantic.mypy`. When using [V1 features](/docs/validation/latest/get-started/migration#continue-using-pydantic-v1-features) the `pydantic.v1.mypy` plugin might need to also be enabled. To configure the mypy plugins: - [mypy.ini](#tab-panel-616) - [pyproject.toml](#tab-panel-617) ```ini [mypy] plugins = pydantic.mypy, pydantic.v1.mypy # include `.v1.mypy` if required. ``` ```toml [tool.mypy] plugins = [ "pydantic.mypy", "pydantic.v1.mypy", # include `.v1.mypy` if required. ] ``` ## Other changes - Dropped support for [`email-validator<2.0.0`](https://github.com/JoshData/python-email-validator). Make sure to update using `pip install -U email-validator`. ## Moved in Pydantic V2 Pydantic V1 Pydantic V2 `pydantic.BaseSettings` [`pydantic_settings.BaseSettings`](#basesettings-has-moved-to-pydantic-settings) `pydantic.color` [`pydantic_extra_types.color`](/docs/validation/latest/api/pydantic-extra-types/pydantic_extra_types_color/#pydantic_extra_types.color) `pydantic.types.PaymentCardBrand` [`pydantic_extra_types.PaymentCardBrand`](#color-and-payment-card-numbers-moved-to-pydantic-extra-types) `pydantic.types.PaymentCardNumber` [`pydantic_extra_types.PaymentCardNumber`](#color-and-payment-card-numbers-moved-to-pydantic-extra-types) `pydantic.utils.version_info` [`pydantic.version.version_info`](/docs/validation/latest/api/pydantic/version/#pydantic.version.version_info) `pydantic.error_wrappers.ValidationError` [`pydantic.ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) `pydantic.utils.to_camel` [`pydantic.alias_generators.to_pascal`](/docs/validation/latest/api/pydantic/config/#pydantic.alias_generators.to_pascal) `pydantic.utils.to_lower_camel` [`pydantic.alias_generators.to_camel`](/docs/validation/latest/api/pydantic/config/#pydantic.alias_generators.to_camel) `pydantic.PyObject` [`pydantic.ImportString`](/docs/validation/latest/api/pydantic/types/#pydantic.types.ImportString) ## Deprecated and moved in Pydantic V2 Pydantic V1 Pydantic V2 `pydantic.tools.schema_of` `pydantic.deprecated.tools.schema_of` `pydantic.tools.parse_obj_as` `pydantic.deprecated.tools.parse_obj_as` `pydantic.tools.schema_json_of` `pydantic.deprecated.tools.schema_json_of` `pydantic.json.pydantic_encoder` `pydantic.deprecated.json.pydantic_encoder` `pydantic.validate_arguments` `pydantic.deprecated.decorator.validate_arguments` `pydantic.json.custom_pydantic_encoder` `pydantic.deprecated.json.custom_pydantic_encoder` `pydantic.json.ENCODERS_BY_TYPE` `pydantic.deprecated.json.ENCODERS_BY_TYPE` `pydantic.json.timedelta_isoformat` `pydantic.deprecated.json.timedelta_isoformat` `pydantic.decorator.validate_arguments` `pydantic.deprecated.decorator.validate_arguments` `pydantic.class_validators.validator` `pydantic.deprecated.class_validators.validator` `pydantic.class_validators.root_validator` `pydantic.deprecated.class_validators.root_validator` `pydantic.utils.deep_update` `pydantic.v1.utils.deep_update` `pydantic.utils.GetterDict` `pydantic.v1.utils.GetterDict` `pydantic.utils.lenient_issubclass` `pydantic.v1.utils.lenient_issubclass` `pydantic.utils.lenient_isinstance` `pydantic.v1.utils.lenient_isinstance` `pydantic.utils.is_valid_field` `pydantic.v1.utils.is_valid_field` `pydantic.utils.update_not_none` `pydantic.v1.utils.update_not_none` `pydantic.utils.import_string` `pydantic.v1.utils.import_string` `pydantic.utils.Representation` `pydantic.v1.utils.Representation` `pydantic.utils.ROOT_KEY` `pydantic.v1.utils.ROOT_KEY` `pydantic.utils.smart_deepcopy` `pydantic.v1.utils.smart_deepcopy` `pydantic.utils.sequence_like` `pydantic.v1.utils.sequence_like` ## Removed in Pydantic V2 - `pydantic.ConstrainedBytes` - `pydantic.ConstrainedDate` - `pydantic.ConstrainedDecimal` - `pydantic.ConstrainedFloat` - `pydantic.ConstrainedFrozenSet` - `pydantic.ConstrainedInt` - `pydantic.ConstrainedList` - `pydantic.ConstrainedSet` - `pydantic.ConstrainedStr` - `pydantic.JsonWrapper` - `pydantic.NoneBytes` - This was an alias to `None | bytes`. - `pydantic.NoneStr` - This was an alias to `None | str`. - `pydantic.NoneStrBytes` - This was an alias to `None | str | bytes`. - `pydantic.Protocol` - `pydantic.Required` - `pydantic.StrBytes` - This was an alias to `str | bytes`. - `pydantic.compiled` - `pydantic.config.get_config` - `pydantic.config.inherit_config` - `pydantic.config.prepare_config` - `pydantic.create_model_from_namedtuple` - `pydantic.create_model_from_typeddict` - `pydantic.dataclasses.create_pydantic_model_from_dataclass` - `pydantic.dataclasses.make_dataclass_validator` - `pydantic.dataclasses.set_validation` - `pydantic.datetime_parse.parse_date` - `pydantic.datetime_parse.parse_time` - `pydantic.datetime_parse.parse_datetime` - `pydantic.datetime_parse.parse_duration` - `pydantic.error_wrappers.ErrorWrapper` - `pydantic.errors.AnyStrMaxLengthError` - `pydantic.errors.AnyStrMinLengthError` - `pydantic.errors.ArbitraryTypeError` - `pydantic.errors.BoolError` - `pydantic.errors.BytesError` - `pydantic.errors.CallableError` - `pydantic.errors.ClassError` - `pydantic.errors.ColorError` - `pydantic.errors.ConfigError` - `pydantic.errors.DataclassTypeError` - `pydantic.errors.DateError` - `pydantic.errors.DateNotInTheFutureError` - `pydantic.errors.DateNotInThePastError` - `pydantic.errors.DateTimeError` - `pydantic.errors.DecimalError` - `pydantic.errors.DecimalIsNotFiniteError` - `pydantic.errors.DecimalMaxDigitsError` - `pydantic.errors.DecimalMaxPlacesError` - `pydantic.errors.DecimalWholeDigitsError` - `pydantic.errors.DictError` - `pydantic.errors.DurationError` - `pydantic.errors.EmailError` - `pydantic.errors.EnumError` - `pydantic.errors.EnumMemberError` - `pydantic.errors.ExtraError` - `pydantic.errors.FloatError` - `pydantic.errors.FrozenSetError` - `pydantic.errors.FrozenSetMaxLengthError` - `pydantic.errors.FrozenSetMinLengthError` - `pydantic.errors.HashableError` - `pydantic.errors.IPv4AddressError` - `pydantic.errors.IPv4InterfaceError` - `pydantic.errors.IPv4NetworkError` - `pydantic.errors.IPv6AddressError` - `pydantic.errors.IPv6InterfaceError` - `pydantic.errors.IPv6NetworkError` - `pydantic.errors.IPvAnyAddressError` - `pydantic.errors.IPvAnyInterfaceError` - `pydantic.errors.IPvAnyNetworkError` - `pydantic.errors.IntEnumError` - `pydantic.errors.IntegerError` - `pydantic.errors.InvalidByteSize` - `pydantic.errors.InvalidByteSizeUnit` - `pydantic.errors.InvalidDiscriminator` - `pydantic.errors.InvalidLengthForBrand` - `pydantic.errors.JsonError` - `pydantic.errors.JsonTypeError` - `pydantic.errors.ListError` - `pydantic.errors.ListMaxLengthError` - `pydantic.errors.ListMinLengthError` - `pydantic.errors.ListUniqueItemsError` - `pydantic.errors.LuhnValidationError` - `pydantic.errors.MissingDiscriminator` - `pydantic.errors.MissingError` - `pydantic.errors.NoneIsAllowedError` - `pydantic.errors.NoneIsNotAllowedError` - `pydantic.errors.NotDigitError` - `pydantic.errors.NotNoneError` - `pydantic.errors.NumberNotGeError` - `pydantic.errors.NumberNotGtError` - `pydantic.errors.NumberNotLeError` - `pydantic.errors.NumberNotLtError` - `pydantic.errors.NumberNotMultipleError` - `pydantic.errors.PathError` - `pydantic.errors.PathNotADirectoryError` - `pydantic.errors.PathNotAFileError` - `pydantic.errors.PathNotExistsError` - `pydantic.errors.PatternError` - `pydantic.errors.PyObjectError` - `pydantic.errors.PydanticTypeError` - `pydantic.errors.PydanticValueError` - `pydantic.errors.SequenceError` - `pydantic.errors.SetError` - `pydantic.errors.SetMaxLengthError` - `pydantic.errors.SetMinLengthError` - `pydantic.errors.StrError` - `pydantic.errors.StrRegexError` - `pydantic.errors.StrictBoolError` - `pydantic.errors.SubclassError` - `pydantic.errors.TimeError` - `pydantic.errors.TupleError` - `pydantic.errors.TupleLengthError` - `pydantic.errors.UUIDError` - `pydantic.errors.UUIDVersionError` - `pydantic.errors.UrlError` - `pydantic.errors.UrlExtraError` - `pydantic.errors.UrlHostError` - `pydantic.errors.UrlHostTldError` - `pydantic.errors.UrlPortError` - `pydantic.errors.UrlSchemeError` - `pydantic.errors.UrlSchemePermittedError` - `pydantic.errors.UrlUserInfoError` - `pydantic.errors.WrongConstantError` - `pydantic.main.validate_model` - `pydantic.networks.stricturl` - `pydantic.parse_file_as` - `pydantic.parse_raw_as` - `pydantic.stricturl` - `pydantic.tools.parse_file_as` - `pydantic.tools.parse_raw_as` - `pydantic.types.JsonWrapper` - `pydantic.types.NoneBytes` - `pydantic.types.NoneStr` - `pydantic.types.NoneStrBytes` - `pydantic.types.PyObject` - `pydantic.types.StrBytes` - `pydantic.typing.evaluate_forwardref` - `pydantic.typing.AbstractSetIntStr` - `pydantic.typing.AnyCallable` - `pydantic.typing.AnyClassMethod` - `pydantic.typing.CallableGenerator` - `pydantic.typing.DictAny` - `pydantic.typing.DictIntStrAny` - `pydantic.typing.DictStrAny` - `pydantic.typing.IntStr` - `pydantic.typing.ListStr` - `pydantic.typing.MappingIntStrAny` - `pydantic.typing.NoArgAnyCallable` - `pydantic.typing.NoneType` - `pydantic.typing.ReprArgs` - `pydantic.typing.SetStr` - `pydantic.typing.StrPath` - `pydantic.typing.TupleGenerator` - `pydantic.typing.WithArgsTypes` - `pydantic.typing.all_literal_values` - `pydantic.typing.display_as_type` - `pydantic.typing.get_all_type_hints` - `pydantic.typing.get_args` - `pydantic.typing.get_origin` - `pydantic.typing.get_sub_types` - `pydantic.typing.is_callable_type` - `pydantic.typing.is_classvar` - `pydantic.typing.is_finalvar` - `pydantic.typing.is_literal_type` - `pydantic.typing.is_namedtuple` - `pydantic.typing.is_new_type` - `pydantic.typing.is_none_type` - `pydantic.typing.is_typeddict` - `pydantic.typing.is_typeddict_special` - `pydantic.typing.is_union` - `pydantic.typing.new_type_supertype` - `pydantic.typing.resolve_annotations` - `pydantic.typing.typing_base` - `pydantic.typing.update_field_forward_refs` - `pydantic.typing.update_model_forward_refs` - `pydantic.utils.ClassAttribute` - `pydantic.utils.DUNDER_ATTRIBUTES` - `pydantic.utils.PyObjectStr` - `pydantic.utils.ValueItems` - `pydantic.utils.almost_equal_floats` - `pydantic.utils.get_discriminator_alias_and_values` - `pydantic.utils.get_model` - `pydantic.utils.get_unique_discriminator_alias` - `pydantic.utils.in_ipython` - `pydantic.utils.is_valid_identifier` - `pydantic.utils.path_type` - `pydantic.utils.validate_field_name` - `pydantic.validate_model` --- # [Version Policy](https://pydantic.dev/docs/validation/latest/get-started/version-policy/) # Version Policy First of all, we recognize that the transitions from Pydantic V1 to V2 has been and will be painful for some users. We're sorry about this pain 🙏, it was an unfortunate but necessary step to correct design mistakes of V1. **There will not be another breaking change of this magnitude!** ## Pydantic V1 Active development of V1 has already stopped, however critical bug fixes and security vulnerabilities will be fixed in V1 until the release of Pydantic V3. ## Pydantic V2 We will not intentionally make breaking changes in minor releases of V2. Functionality marked as deprecated will not be removed until the next major V3 release. Of course, some apparently safe changes and bug fixes will inevitably break some users' code -- obligatory link to [xkcd](https://xkcd.com/1172/). The following changes will **NOT** be considered breaking changes, and may occur in minor releases: - Bug fixes that may result in existing code breaking, provided that such code was relying on undocumented features/constructs. - Changing the format of JSON Schema [references](https://json-schema.org/understanding-json-schema/structuring#dollarref). - Changing the `msg`, `ctx`, and `loc` fields of [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) exceptions. `type` will not change -- if you're programmatically parsing error messages, you should use `type`. - Adding new keys to [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) exceptions -- e.g. we intend to add `line_number` and `column_number` to errors when validating JSON once we migrate to a new JSON parser. - Adding new [`ValidationError`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.ValidationError) errors. - Changing how `__repr__` behaves, even of public classes. - The contents of the [core schemas](/docs/validation/latest/internals/architecture#communicating-between-pydantic-and-pydantic-core-the-core-schema) (usually available under the [`__pydantic_core_schema__`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.__pydantic_core_schema__) attribute for Pydantic models and `core_schema` for [type adapters](/docs/validation/latest/concepts/type_adapter)) may change between releases (this is a low-level format Pydantic uses to plan how to execute validation and serialization). In all cases we will aim to minimize churn and do so only when justified by the increase of quality of Pydantic for users. ## Pydantic V3 and beyond Any associated breaking changes in the V3 release will be introduced with care. This will include bug fixes that can't be solved in V2 without introducing a change in behavior (e.g. [fixing configuration not following the MRO](https://github.com/pydantic/pydantic/issues/9992)), or changes that don't remove existing functionality or doesn't provide proper alternatives. In V3, it is expected to merged `pydantic-core` as an internal sub-module of Pydantic, meaning it won't be published as a standalone library anymore. ## Tagging conventions Pydantic uses Git tags to identify all published versions on PyPI (including alpha and beta releases), prefixed with the `v` character. Since v2.13, `pydantic-core` has been merged as a workspace member inside the `pydantic` repository, and subsequent `pydantic-core` releases are tagged as `core-vx.y.z`. ## Experimental Features At Pydantic, we like to move quickly and innovate! To that end, we may introduce experimental features in minor releases. Usage Documentation To learn more about our current experimental features, see the [experimental features documentation](/docs/validation/latest/concepts/experimental). Please keep in mind, experimental features are active works in progress. If these features are successful, they'll eventually become part of Pydantic. If unsuccessful, said features will be removed with little notice. While in its experimental phase, a feature's API and behaviors may not be stable, and it's very possible that changes made to the feature will not be backward-compatible. ### Naming Conventions We use one of the following naming conventions to indicate that a feature is experimental: 1. The feature is located in the [`experimental`](/docs/validation/latest/api/pydantic/experimental) module. In this case, you can access the feature like this: ```python from pydantic.experimental import feature_name ``` 2. The feature is located in the main module, but prefixed with `experimental_`. This case occurs when we add a new field, argument, or method to an existing data structure already within the main `pydantic` module. New features with these naming conventions are subject to change or removal, and we are looking for feedback and suggestions before making them a permanent part of Pydantic. See the [feedback section](/docs/validation/latest/concepts/experimental#feedback) for more information. ### Lifecycle of Experimental Features 1. A new feature is added, either in the [`experimental`](/docs/validation/latest/api/pydantic/experimental) module or with the `experimental_` prefix. 2. The behavior is often modified during patch/minor releases, with potential API/behavior changes. 3. If the feature is successful, we promote it to Pydantic with the following steps: a. If it was in the [`experimental`](/docs/validation/latest/api/pydantic/experimental) module, the feature is cloned to Pydantic's main module. The original experimental feature still remains in the [`experimental`](/docs/validation/latest/api/pydantic/experimental) module, but it will show a warning when used. If the feature was already in the main Pydantic module, we create a copy of the feature without the `experimental_` prefix, so the feature exists with both the official and experimental names. A deprecation warning is attached to the experimental version. b. At some point, the code of the experimental feature is removed, but there will still be a stub of the feature that provides an error message with appropriate instructions. c. As a last step, the experimental version of the feature is entirely removed from the codebase. If the feature is unsuccessful or unpopular, it's removed with little notice. A stub will remain in the location of the deprecated feature with an error message. Thanks to [streamlit](https://docs.streamlit.io/develop/quick-reference/prerelease) for the inspiration for the lifecycle and naming conventions of our new experimental feature patterns. ## Support for Python versions Pydantic will drop support for a Python version when the following conditions are met: - The Python version has reached its [expected end of life](https://devguide.python.org/versions/). - less than 5% of downloads of the most recent minor release are using that version. --- # [Why use Pydantic](https://pydantic.dev/docs/validation/latest/get-started/why/) # Why use Pydantic Today, Pydantic is downloaded many times a month and used by some of the largest and most recognisable organisations in the world. It's hard to know why so many people have adopted Pydantic since its inception six years ago, but here are a few guesses. ## Type hints powering schema validation The schema that Pydantic validates against is generally defined by Python [type hints](https://docs.python.org/3/glossary.html#term-type-hint). Type hints are great for this since, if you're writing modern Python, you already know how to use them. Using type hints also means that Pydantic integrates well with static typing tools (like [mypy](https://www.mypy-lang.org/) and [Pyright](https://github.com/microsoft/pyright/)) and IDEs (like [PyCharm](https://www.jetbrains.com/pycharm/) and [VSCode](https://code.visualstudio.com/)). Example - just type hints ```python from typing import Annotated, Literal from annotated_types import Gt from pydantic import BaseModel class Fruit(BaseModel): name: str # (1) color: Literal['red', 'green'] # (2) weight: Annotated[float, Gt(0)] # (3) bazam: dict[str, list[tuple[int, bool, float]]] # (4) print( Fruit( name='Apple', color='red', weight=4.2, bazam={'foobar': [(1, True, 0.1)]}, ) ) #> name='Apple' color='red' weight=4.2 bazam={'foobar': [(1, True, 0.1)]} ``` The `name` field is simply annotated with `str` -- any string is allowed. The [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) type is used to enforce that `color` is either `'red'` or `'green'`. Even when we want to apply constraints not encapsulated in Python types, we can use [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) and [`annotated-types`](https://github.com/annotated-types/annotated-types) to enforce constraints while still keeping typing support. I'm not claiming "bazam" is really an attribute of fruit, but rather to show that arbitrarily complex types can easily be validated. Learn more See the [documentation on supported types](/docs/validation/latest/concepts/types). ## Performance Pydantic's core validation logic is implemented in a separate package ([`pydantic-core`](https://pypi.org/project/pydantic-core)), where validation for most types is implemented in Rust. As a result, Pydantic is among the fastest data validation libraries for Python. Performance Example - Pydantic vs. dedicated code In general, dedicated code should be much faster than a general-purpose validator, but in this example Pydantic is >300% faster than dedicated code when parsing JSON and validating URLs. Performance Example ```python import json import timeit from urllib.parse import urlparse import requests from pydantic import HttpUrl, TypeAdapter reps = 7 number = 100 r = requests.get('https://api.github.com/emojis') r.raise_for_status() emojis_json = r.content def emojis_pure_python(raw_data): data = json.loads(raw_data) output = {} for key, value in data.items(): assert isinstance(key, str) url = urlparse(value) assert url.scheme in ('https', 'http') output[key] = url emojis_pure_python_times = timeit.repeat( 'emojis_pure_python(emojis_json)', globals={ 'emojis_pure_python': emojis_pure_python, 'emojis_json': emojis_json, }, repeat=reps, number=number, ) print(f'pure python: {min(emojis_pure_python_times) / number * 1000:0.2f}ms') #> pure python: 5.32ms type_adapter = TypeAdapter(dict[str, HttpUrl]) emojis_pydantic_times = timeit.repeat( 'type_adapter.validate_json(emojis_json)', globals={ 'type_adapter': type_adapter, 'HttpUrl': HttpUrl, 'emojis_json': emojis_json, }, repeat=reps, number=number, ) print(f'pydantic: {min(emojis_pydantic_times) / number * 1000:0.2f}ms') #> pydantic: 1.54ms print( f'Pydantic {min(emojis_pure_python_times) / min(emojis_pydantic_times):0.2f}x faster' ) #> Pydantic 3.45x faster ``` Unlike other performance-centric libraries written in compiled languages, Pydantic also has excellent support for customizing validation via [functional validators](#customisation). Learn more Samuel Colvin's [talk at PyCon 2023](https://youtu.be/pWZw7hYoRVU) explains how [`pydantic-core`](https://pypi.org/project/pydantic-core) works and how it integrates with Pydantic. ## Serialization Pydantic provides functionality to serialize model in three ways: 1. To a Python `dict` made up of the associated Python objects. 2. To a Python `dict` made up only of "jsonable" types. 3. To a JSON string. In all three modes, the output can be customized by excluding specific fields, excluding unset fields, excluding default values, and excluding `None` values. Example - Serialization 3 ways ```python from datetime import datetime from pydantic import BaseModel class Meeting(BaseModel): when: datetime where: bytes why: str = 'No idea' m = Meeting(when='2020-01-01T12:00', where='home') print(m.model_dump(exclude_unset=True)) #> {'when': datetime.datetime(2020, 1, 1, 12, 0), 'where': b'home'} print(m.model_dump(exclude={'where'}, mode='json')) #> {'when': '2020-01-01T12:00:00', 'why': 'No idea'} print(m.model_dump_json(exclude_defaults=True)) #> {"when":"2020-01-01T12:00:00","where":"home"} ``` Learn more See the [documentation on serialization](/docs/validation/latest/concepts/serialization). ## JSON Schema A [JSON Schema](https://json-schema.org/) can be generated for any Pydantic schema -- allowing self-documenting APIs and integration with a wide variety of tools which support the JSON Schema format. Example - JSON Schema ```python from datetime import datetime from pydantic import BaseModel class Address(BaseModel): street: str city: str zipcode: str class Meeting(BaseModel): when: datetime where: Address why: str = 'No idea' print(Meeting.model_json_schema()) """ { '$defs': { 'Address': { 'properties': { 'street': {'title': 'Street', 'type': 'string'}, 'city': {'title': 'City', 'type': 'string'}, 'zipcode': {'title': 'Zipcode', 'type': 'string'}, }, 'required': ['street', 'city', 'zipcode'], 'title': 'Address', 'type': 'object', } }, 'properties': { 'when': {'format': 'date-time', 'title': 'When', 'type': 'string'}, 'where': {'$ref': '#/$defs/Address'}, 'why': {'default': 'No idea', 'title': 'Why', 'type': 'string'}, }, 'required': ['when', 'where'], 'title': 'Meeting', 'type': 'object', } """ ``` Pydantic is compliant with the latest version of JSON Schema specification ([2020-12](https://json-schema.org/draft/2020-12/release-notes.html)), which is compatible with [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0.html). Learn more See the [documentation on JSON Schema](/docs/validation/latest/concepts/json_schema). ## Strict mode and data coercion By default, Pydantic is tolerant to common incorrect types and coerces data to the right type -- e.g. a numeric string passed to an `int` field will be parsed as an `int`. Pydantic also has as [strict mode](/docs/validation/latest/concepts/strict_mode), where types are not coerced and a validation error is raised unless the input data exactly matches the expected schema. But strict mode would be pretty useless when validating JSON data since JSON doesn't have types matching many common Python types like [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime), [`UUID`](https://docs.python.org/3/library/uuid.html#uuid.UUID) or [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes). To solve this, Pydantic can parse and validate JSON in one step. This allows sensible data conversion (e.g. when parsing strings into [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) objects). Since the JSON parsing is implemented in Rust, it's also very performant. Example - Strict mode that's actually useful ```python from datetime import datetime from pydantic import BaseModel, ValidationError class Meeting(BaseModel): when: datetime where: bytes m = Meeting.model_validate({'when': '2020-01-01T12:00', 'where': 'home'}) print(m) #> when=datetime.datetime(2020, 1, 1, 12, 0) where=b'home' try: m = Meeting.model_validate( {'when': '2020-01-01T12:00', 'where': 'home'}, strict=True ) except ValidationError as e: print(e) """ 2 validation errors for Meeting when Input should be a valid datetime [type=datetime_type, input_value='2020-01-01T12:00', input_type=str] where Input should be a valid bytes [type=bytes_type, input_value='home', input_type=str] """ m_json = Meeting.model_validate_json( '{"when": "2020-01-01T12:00", "where": "home"}' ) print(m_json) #> when=datetime.datetime(2020, 1, 1, 12, 0) where=b'home' ``` Learn more See the [documentation on strict mode](/docs/validation/latest/concepts/strict_mode). ## Dataclasses, TypedDicts, and more Pydantic provides four ways to create schemas and perform validation and serialization: 1. [`BaseModel`](/docs/validation/latest/concepts/models) -- Pydantic's own super class with many common utilities available via instance methods. 2. [Pydantic dataclasses](/docs/validation/latest/concepts/dataclasses) -- a wrapper around standard dataclasses with additional validation performed. 3. [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) -- a general way to adapt any type for validation and serialization. This allows types like [`TypedDict`](/docs/validation/latest/api/pydantic/standard_library_types#typeddict) and [`NamedTuple`](/docs/validation/latest/api/pydantic/standard_library_types#named-tuples) to be validated as well as simple types (like [`int`](https://docs.python.org/3/library/functions.html#int) or [`timedelta`](https://docs.python.org/3/library/datetime.html#datetime.timedelta)) -- [all types](/docs/validation/latest/concepts/types) supported can be used with [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter). 4. [`validate_call`](/docs/validation/latest/concepts/validation_decorator) -- a decorator to perform validation when calling a function. Example - schema based on a `TypedDict` ```python from datetime import datetime from typing_extensions import NotRequired, TypedDict from pydantic import TypeAdapter class Meeting(TypedDict): when: datetime where: bytes why: NotRequired[str] meeting_adapter = TypeAdapter(Meeting) m = meeting_adapter.validate_python( # (1) {'when': '2020-01-01T12:00', 'where': 'home'} ) print(m) #> {'when': datetime.datetime(2020, 1, 1, 12, 0), 'where': b'home'} meeting_adapter.dump_python(m, exclude={'where'}) # (2) print(meeting_adapter.json_schema()) # (3) """ { 'properties': { 'when': {'format': 'date-time', 'title': 'When', 'type': 'string'}, 'where': {'format': 'binary', 'title': 'Where', 'type': 'string'}, 'why': {'title': 'Why', 'type': 'string'}, }, 'required': ['when', 'where'], 'title': 'Meeting', 'type': 'object', } """ ``` [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) for a [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) performing validation, it can also validate JSON data directly with [`validate_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.validate_json). [`dump_python`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_python) to serialise a [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) to a python object, it can also serialise to JSON with [`dump_json`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter.dump_json). [`TypeAdapter`](/docs/validation/latest/api/pydantic/type_adapter/#pydantic.type_adapter.TypeAdapter) can also generate a JSON Schema. ## Customisation Functional validators and serializers, as well as a powerful protocol for custom types, means the way Pydantic operates can be customized on a per-field or per-type basis. Customisation Example - wrap validators "wrap validators" are new in Pydantic V2 and are one of the most powerful ways to customize validation. ```python from datetime import datetime, timezone from typing import Any from pydantic_core.core_schema import ValidatorFunctionWrapHandler from pydantic import BaseModel, field_validator class Meeting(BaseModel): when: datetime @field_validator('when', mode='wrap') def when_now( cls, input_value: Any, handler: ValidatorFunctionWrapHandler ) -> datetime: if input_value == 'now': return datetime.now() when = handler(input_value) # in this specific application we know tz naive datetimes are in UTC if when.tzinfo is None: when = when.replace(tzinfo=timezone.utc) return when print(Meeting(when='2020-01-01T12:00+01:00')) #> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=TzInfo(3600)) print(Meeting(when='now')) #> when=datetime.datetime(2032, 1, 2, 3, 4, 5, 6) print(Meeting(when='2020-01-01T12:00')) #> when=datetime.datetime(2020, 1, 1, 12, 0, tzinfo=datetime.timezone.utc) ``` Learn more See the documentation on [validators](/docs/validation/latest/concepts/validators), [custom serializers](/docs/validation/latest/concepts/serialization#serializers), and [custom types](/docs/validation/latest/concepts/types#custom-types). ## Ecosystem At the time of writing there are 466,400 repositories on GitHub and 8,119 packages on PyPI that depend on Pydantic. Some notable libraries that depend on Pydantic: - [`huggingface/transformers`](https://github.com/huggingface/transformers) 138,570 stars - [`hwchase17/langchain`](https://github.com/hwchase17/langchain) 99,542 stars - [`tiangolo/fastapi`](https://github.com/tiangolo/fastapi) 80,497 stars - [`apache/airflow`](https://github.com/apache/airflow) 38,577 stars - [`lm-sys/FastChat`](https://github.com/lm-sys/FastChat) 37,650 stars - [`microsoft/DeepSpeed`](https://github.com/microsoft/DeepSpeed) 36,521 stars - [`OpenBB-finance/OpenBBTerminal`](https://github.com/OpenBB-finance/OpenBBTerminal) 35,971 stars - [`gradio-app/gradio`](https://github.com/gradio-app/gradio) 35,740 stars - [`ray-project/ray`](https://github.com/ray-project/ray) 35,176 stars - [`pola-rs/polars`](https://github.com/pola-rs/polars) 31,698 stars - [`Lightning-AI/lightning`](https://github.com/Lightning-AI/lightning) 28,902 stars - [`mindsdb/mindsdb`](https://github.com/mindsdb/mindsdb) 27,141 stars - [`embedchain/embedchain`](https://github.com/embedchain/embedchain) 24,379 stars - [`pynecone-io/reflex`](https://github.com/pynecone-io/reflex) 21,558 stars - [`heartexlabs/label-studio`](https://github.com/heartexlabs/label-studio) 20,571 stars - [`Sanster/lama-cleaner`](https://github.com/Sanster/lama-cleaner) 20,313 stars - [`mlflow/mlflow`](https://github.com/mlflow/mlflow) 19,393 stars - [`RasaHQ/rasa`](https://github.com/RasaHQ/rasa) 19,337 stars - [`spotDL/spotify-downloader`](https://github.com/spotDL/spotify-downloader) 18,604 stars - [`chroma-core/chroma`](https://github.com/chroma-core/chroma) 17,393 stars - [`airbytehq/airbyte`](https://github.com/airbytehq/airbyte) 17,120 stars - [`openai/evals`](https://github.com/openai/evals) 15,437 stars - [`tiangolo/sqlmodel`](https://github.com/tiangolo/sqlmodel) 15,127 stars - [`ydataai/ydata-profiling`](https://github.com/ydataai/ydata-profiling) 12,687 stars - [`pyodide/pyodide`](https://github.com/pyodide/pyodide) 12,653 stars - [`dagster-io/dagster`](https://github.com/dagster-io/dagster) 12,440 stars - [`PaddlePaddle/PaddleNLP`](https://github.com/PaddlePaddle/PaddleNLP) 12,312 stars - [`matrix-org/synapse`](https://github.com/matrix-org/synapse) 11,857 stars - [`lucidrains/DALLE2-pytorch`](https://github.com/lucidrains/DALLE2-pytorch) 11,207 stars - [`great-expectations/great_expectations`](https://github.com/great-expectations/great_expectations) 10,164 stars - [`modin-project/modin`](https://github.com/modin-project/modin) 10,002 stars - [`aws/serverless-application-model`](https://github.com/aws/serverless-application-model) 9,402 stars - [`sqlfluff/sqlfluff`](https://github.com/sqlfluff/sqlfluff) 8,535 stars - [`replicate/cog`](https://github.com/replicate/cog) 8,344 stars - [`autogluon/autogluon`](https://github.com/autogluon/autogluon) 8,326 stars - [`lucidrains/imagen-pytorch`](https://github.com/lucidrains/imagen-pytorch) 8,164 stars - [`brycedrennan/imaginAIry`](https://github.com/brycedrennan/imaginAIry) 8,050 stars - [`vitalik/django-ninja`](https://github.com/vitalik/django-ninja) 7,685 stars - [`NVlabs/SPADE`](https://github.com/NVlabs/SPADE) 7,632 stars - [`bridgecrewio/checkov`](https://github.com/bridgecrewio/checkov) 7,340 stars - [`bentoml/BentoML`](https://github.com/bentoml/BentoML) 7,322 stars - [`skypilot-org/skypilot`](https://github.com/skypilot-org/skypilot) 7,113 stars - [`apache/iceberg`](https://github.com/apache/iceberg) 6,853 stars - [`deeppavlov/DeepPavlov`](https://github.com/deeppavlov/DeepPavlov) 6,777 stars - [`PrefectHQ/marvin`](https://github.com/PrefectHQ/marvin) 5,454 stars - [`NVIDIA/NeMo-Guardrails`](https://github.com/NVIDIA/NeMo-Guardrails) 4,383 stars - [`microsoft/FLAML`](https://github.com/microsoft/FLAML) 4,035 stars - [`jina-ai/discoart`](https://github.com/jina-ai/discoart) 3,846 stars - [`docarray/docarray`](https://github.com/docarray/docarray) 3,007 stars - [`aws-powertools/powertools-lambda-python`](https://github.com/aws-powertools/powertools-lambda-python) 2,980 stars - [`roman-right/beanie`](https://github.com/roman-right/beanie) 2,172 stars - [`art049/odmantic`](https://github.com/art049/odmantic) 1,096 stars More libraries using Pydantic can be found at [`Kludex/awesome-pydantic`](https://github.com/Kludex/awesome-pydantic). ## Organisations using Pydantic Some notable companies and organisations using Pydantic together with comments on why/how we know they're using Pydantic. The organisations below are included because they match one or more of the following criteria: - Using Pydantic as a dependency in a public repository. - Referring traffic to the Pydantic documentation site from an organization-internal domain -- specific referrers are not included since they're generally not in the public domain. - Direct communication between the Pydantic team and engineers employed by the organization about usage of Pydantic within the organization. We've included some extra detail where appropriate and already in the public domain. ### Adobe [`adobe/dy-sql`](https://github.com/adobe/dy-sql) uses Pydantic. ### Amazon and AWS - [powertools-lambda-python](https://github.com/aws-powertools/powertools-lambda-python) - [awslabs/gluonts](https://github.com/awslabs/gluonts) - AWS [sponsored Samuel Colvin $5,000](https://twitter.com/samuel_colvin/status/1549383169006239745) to work on Pydantic in 2022 ### Anthropic [`anthropics/anthropic-sdk-python`](https://github.com/anthropics/anthropic-sdk-python) uses Pydantic. ### Apple _(Based on the criteria described above)_ ### ASML _(Based on the criteria described above)_ ### AstraZeneca [Multiple repos](https://github.com/search?q=org%3AAstraZeneca+pydantic&type=code) in the `AstraZeneca` GitHub org depend on Pydantic. ### Cisco Systems - Pydantic is listed in their report of [Open Source Used In RADKit](https://www.cisco.com/c/dam/en_us/about/doing_business/open_source/docs/RADKit-149-1687424532.pdf). - [`cisco/webex-assistant-sdk`](https://github.com/cisco/webex-assistant-sdk) ### Capital One _(Based on the criteria described above)_ ### Comcast _(Based on the criteria described above)_ ### Datadog - Extensive use of Pydantic in [`DataDog/integrations-core`](https://github.com/DataDog/integrations-core) and other repos - Communication with engineers from Datadog about how they use Pydantic. ### Facebook [Multiple repos](https://github.com/search?q=org%3Afacebookresearch+pydantic&type=code) in the `facebookresearch` GitHub org depend on Pydantic. ### GitHub GitHub sponsored Pydantic $750 in 2022 ### Google Extensive use of Pydantic in [`google/turbinia`](https://github.com/google/turbinia) and other repos. ### HSBC _(Based on the criteria described above)_ ### IBM [Multiple repos](https://github.com/search?q=org%3AIBM+pydantic&type=code) in the `IBM` GitHub org depend on Pydantic. ### Intel _(Based on the criteria described above)_ ### Intuit _(Based on the criteria described above)_ ### Intergovernmental Panel on Climate Change [Tweet](https://twitter.com/daniel_huppmann/status/1563461797973110785) explaining how the IPCC use Pydantic. ### JPMorgan _(Based on the criteria described above)_ ### Jupyter - The developers of the Jupyter notebook are using Pydantic [for subprojects](https://github.com/pydantic/pydantic/issues/773) - Through the FastAPI-based Jupyter server [Jupyverse](https://github.com/jupyter-server/jupyverse) - [FPS](https://github.com/jupyter-server/fps)'s configuration management. ### Microsoft - [DeepSpeed](https://github.com/microsoft/DeepSpeed) deep learning optimisation library uses Pydantic extensively - [Multiple repos](https://github.com/search?q=org%3Amicrosoft%20pydantic&type=code) in the `microsoft` GitHub org depend on Pydantic, in particular their - Pydantic is also [used](https://github.com/search?q=org%3AAzure%20pydantic&type=code) in the `Azure` GitHub org - [Comments](https://github.com/tiangolo/fastapi/pull/26) on GitHub show Microsoft engineers using Pydantic as part of Windows and Office ### Molecular Science Software Institute [Multiple repos](https://github.com/search?q=org%3AMolSSI%20pydantic&type=code) in the `MolSSI` GitHub org depend on Pydantic. ### NASA [Multiple repos](https://github.com/search?q=org%3Anasa%20pydantic&type=code) in the `NASA` GitHub org depend on Pydantic. NASA are also using Pydantic via FastAPI in their JWST project to process images from the James Webb Space Telescope, see [this tweet](https://twitter.com/benjamin_falk/status/1546947039363305472). ### Netflix [Multiple repos](https://github.com/search?q=org%3Anetflix%20pydantic&type=code) in the `Netflix` GitHub org depend on Pydantic. ### NSA The [`nsacyber/WALKOFF`](https://github.com/nsacyber/WALKOFF) repo depends on Pydantic. ### NVIDIA [Multiple repositories](https://github.com/search?q=org%3ANVIDIA%20pydantic&type=code) in the `NVIDIA` GitHub org depend on Pydantic. Their "Omniverse Services" depends on Pydantic according to [their documentation](https://web.archive.org/web/20220628161919/https://docs.omniverse.nvidia.com/prod_services/prod_services/core/index.html). ### OpenAI OpenAI use Pydantic for their ChatCompletions API, as per [this](https://github.com/pydantic/pydantic/discussions/6372) discussion on GitHub. Anecdotally, OpenAI use Pydantic extensively for their internal services. ### Oracle _(Based on the criteria described above)_ ### Palantir _(Based on the criteria described above)_ ### Qualcomm _(Based on the criteria described above)_ ### Red Hat _(Based on the criteria described above)_ ### Revolut Anecdotally, all internal services at Revolut are built with FastAPI and therefore Pydantic. ### Robusta The [`robusta-dev/robusta`](https://github.com/robusta-dev/robusta) repo depends on Pydantic. ### Salesforce Salesforce [sponsored Samuel Colvin $10,000](https://twitter.com/samuel_colvin/status/1501288247670063104) to work on Pydantic in 2022. ### Starbucks _(Based on the criteria described above)_ ### Texas Instruments _(Based on the criteria described above)_ ### Twilio _(Based on the criteria described above)_ ### Twitter Twitter's [`the-algorithm`](https://github.com/twitter/the-algorithm) repo where they [open sourced](https://blog.twitter.com/engineering/en_us/topics/open-source/2023/twitter-recommendation-algorithm) their recommendation engine uses Pydantic. ### UK Home Office _(Based on the criteria described above)_ --- # [](https://pydantic.dev/docs/validation/latest/) --- # [AWS Lambda](https://pydantic.dev/docs/validation/latest/integrations/aws_lambda/) # AWS Lambda `pydantic` integrates well with AWS Lambda functions. In this guide, we'll discuss how to setup `pydantic` for an AWS Lambda function. ## Installing Python libraries for AWS Lambda functions There are many ways to utilize Python libraries in AWS Lambda functions. As outlined in the [AWS Lambda documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html), the most common approaches include: - Using a [`.zip` file archive](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html) to package your code and dependencies - Using [AWS Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/python-layers.html) to share libraries across multiple functions - Using a [container image](https://docs.aws.amazon.com/lambda/latest/dg/python-image.html) to package your code and dependencies All of these approaches can be used with `pydantic`. The best approach for you will depend on your specific requirements and constraints. We'll cover the first two cases more in-depth here, as dependency management with a container image is more straightforward. If you're using a container image, you might find [this comment](https://github.com/pydantic/pydantic/issues/6557#issuecomment-1699456562) helpful for installing `pydantic`. Tip If you use `pydantic` across multiple functions, you may want to consider AWS Lambda Layers, which support seamless sharing of libraries across multiple functions. Regardless of the dependencies management approach you choose, it's beneficial to adhere to these guidelines to ensure a smooth dependency management process. ## Installing `pydantic` for AWS Lambda functions When you're building your `.zip` file archive with your code and dependencies or organizing your `.zip` file for a Lambda Layer, you'll likely use a local virtual environment to install and manage your dependencies. This can be a bit tricky if you're using `pip` because `pip` installs wheels compiled for your local platform, which may not be compatible with the Lambda environment. Thus, we suggest you use a command similar to the following: Terminal ```bash pip install --platform manylinux2014_x86_64 # (1) --target= # (2) --implementation cp # (3) --python-version 3.10 # (4) --only-binary=:all: # (5) --upgrade pydantic # (6) ``` Use the platform corresponding to your Lambda runtime. Specify the directory where you want to install the package (often `python` for Lambda Layers). Use the CPython implementation. The Python version must be compatible with the Lambda runtime. This flag ensures that the package is installed pre-built binary wheels. The latest version of `pydantic` will be installed. ## Troubleshooting ### Missing `pydantic_core` module The ```text no module named `pydantic_core._pydantic_core` ``` error is a common issue that indicates you have installed `pydantic` incorrectly. To debug this issue, you can try the following steps (before the failing import): 1. Check the contents of the installed `pydantic-core` package. Are the compiled library and its type stubs both present? ```python from importlib.metadata import files print([file for file in files('pydantic-core') if file.name.startswith('_pydantic_core')]) """ [PackagePath('pydantic_core/_pydantic_core.pyi'), PackagePath('pydantic_core/_pydantic_core.cpython-312-x86_64-linux-gnu.so')] """ ``` You should expect to see two files like those printed above. The compiled library file should have the `.so` or `.pyd` extension with a name that varies according to the OS and Python version. 2. Check that your lambda's Python version is compatible with the compiled library version found above. ```python import sysconfig print(sysconfig.get_config_var("EXT_SUFFIX")) #> '.cpython-312-x86_64-linux-gnu.so' ``` You should expect to see the same suffix here as the compiled library, for example here we see this suffix `.cpython-312-x86_64-linux-gnu.so` indeed matches `_pydantic_core.cpython-312-x86_64-linux-gnu.so`. If these two checks do not match, your build steps have not installed the correct native code for your lambda's target platform. You should adjust your build steps to change the version of the installed library which gets installed. Most likely errors: - Your OS or CPU architecture is mismatched (e.g. darwin vs x86\_64-linux-gnu). Try passing correct `--platform` argument to `pip install` when installing your lambda dependencies, or build inside a linux docker container for the correct platform. Possible platforms at the moment include `--platform manylinux2014_x86_64` or `--platform manylinux2014_aarch64`, but these may change with a future Pydantic major release. - Your Python version is mismatched (e.g. `cpython-310` vs `cpython-312`). Try passing correct `--python-version` argument to `pip install`, or otherwise change the Python version used on your build. ### No package metadata was found for `email-validator` Pydantic uses `version` from `importlib.metadata` to [check what version](https://github.com/pydantic/pydantic/pull/6033) of `email-validator` is installed. This package versioning mechanism is somewhat incompatible with AWS Lambda, even though it's the industry standard for versioning packages in Python. There are a few ways to fix this issue: If you're deploying your lambda with the serverless framework, it's likely that the appropriate metadata for the `email-validator` package is not being included in your deployment package. Tools like [`serverless-python-requirements`](https://github.com/serverless/serverless-python-requirements/tree/master) remove metadata to reduce package size. You can fix this issue by setting the `slim` setting to false in your `serverless.yml` file: ```yaml pythonRequirements: dockerizePip: non-linux slim: false fileName: requirements.txt ``` You can read more about this fix, and other `slim` settings that might be relevant in this [blog post](https://biercoff.com/how-to-fix-package-not-found-error-importlib-metadata/). If you're using a `.zip` archive for your code and/or dependencies, make sure that your package contains the required version metadata. To do this, make sure you include the `dist-info` directory in your `.zip` archive for the `email-validator` package. This issue has been reported for other popular python libraries like [`jsonschema`](https://github.com/python-jsonschema/jsonschema/issues/584), so you can read more about the issue and potential fixes there as well. ## Extra Resources ### More Debugging Tips If you're still struggling with installing `pydantic` for your AWS Lambda, you might consult with [this issue](https://github.com/pydantic/pydantic/issues/6557), which covers a variety of problems and solutions encountered by other developers. ### Validating `event` and `context` data Check out our [blog post](https://pydantic.dev/articles/lambda-intro) to learn more about how to use `pydantic` to validate `event` and `context` data in AWS Lambda functions. --- # [datamodel-code-generator](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/datamodel_code_generator/) # datamodel-code-generator The [datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator/) project is a library and command-line utility to generate pydantic models from just about any data source, including: - OpenAPI 3 (YAML/JSON) - JSON Schema - JSON/YAML/CSV Data (which will be converted to JSON Schema) - Python dictionary (which will be converted to JSON Schema) - GraphQL schema Whenever you find yourself with any data convertible JSON but without pydantic models, this tool will allow you to generate type-safe model hierarchies on demand. ## Installation Terminal ```bash pip install datamodel-code-generator ``` ## Example In this case, datamodel-code-generator creates pydantic models from a JSON Schema file. Terminal ```bash datamodel-codegen --input person.json --input-file-type jsonschema --output model.py ``` person.json: ```json { "$id": "person.json", "$schema": "http://json-schema.org/draft-07/schema#", "title": "Person", "type": "object", "properties": { "first_name": { "type": "string", "description": "The person's first name." }, "last_name": { "type": "string", "description": "The person's last name." }, "age": { "description": "Age in years.", "type": "integer", "minimum": 0 }, "pets": { "type": "array", "items": [ { "$ref": "#/definitions/Pet" } ] }, "comment": { "type": "null" } }, "required": [ "first_name", "last_name" ], "definitions": { "Pet": { "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } } } } ``` model.py: ```python # generated by datamodel-codegen: # filename: person.json # timestamp: 2020-05-19T15:07:31+00:00 from __future__ import annotations from typing import Any from pydantic import BaseModel, Field, conint class Pet(BaseModel): name: str | None = None age: int | None = None class Person(BaseModel): first_name: str = Field(description="The person's first name.") last_name: str = Field(description="The person's last name.") age: conint(ge=0) | None = Field(None, description='Age in years.') pets: list[Pet] | None = None comment: Any | None = None ``` More information can be found on the [official documentation](https://koxudaxi.github.io/datamodel-code-generator/) --- # [devtools](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/devtools/) # devtools Note **Admission:** I (the primary developer of Pydantic) also develop python-devtools. [python-devtools](https://python-devtools.helpmanual.io/) (`pip install devtools`) provides a number of tools which are useful during Python development, including `debug()` an alternative to `print()` which formats output in a way which should be easier to read than `print` as well as giving information about which file/line the print statement is on and what value was printed. Pydantic integrates with _devtools_ by implementing the `__pretty__` method on most public classes. In particular `debug()` is useful when inspecting models: ```python from datetime import datetime from devtools import debug from pydantic import BaseModel class Address(BaseModel): street: str country: str lat: float lng: float class User(BaseModel): id: int name: str signup_ts: datetime friends: list[int] address: Address user = User( id='123', name='John Doe', signup_ts='2019-06-01 12:22', friends=[1234, 4567, 7890], address=dict(street='Testing', country='uk', lat=51.5, lng=0), ) debug(user) print('\nshould be much easier read than:\n') print('user:', user) ``` Will output in your terminal: ``` devtools_example.py:30 user: User( id=123, name='John Doe', signup_ts=datetime.datetime(2019, 6, 1, 12, 22), friends=[ 1234, 4567, 7890, ], address=Address( street='Testing', country='uk', lat=51.5, lng=0.0, ), ) (User) should be much easier read than: user: id=123 name='John Doe' signup_ts=datetime.datetime(2019, 6, 1, 12, 22) friends=[1234, 4567, 7890] address=Address(street='Testing', country='uk', lat=51.5, lng=0.0) ``` Note `python-devtools` doesn't yet support Python 3.13. --- # [Documentation](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/documentation/) # Documentation Pydantic uses [MkDocs](https://www.mkdocs.org/) for documentation, together with [mkdocstrings](https://mkdocstrings.github.io/). As such, you can make use of Pydantic's Sphinx object inventory to cross-reference the Pydantic API documentation. - [Sphinx](#tab-panel-716) - [mkdocstrings](#tab-panel-717) In your [Sphinx configuration](https://www.sphinx-doc.org/en/master/usage/configuration.html), add the following to the [`intersphinx` extension configuration](https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration): ```python intersphinx_mapping = { 'pydantic': ('https://docs.pydantic.dev/latest', None), # (1) } ``` You can also use `dev` instead of `latest` to target the latest documentation build, up to date with the [`main`](https://github.com/pydantic/pydantic/tree/main) branch. In your [MkDocs configuration](https://www.mkdocs.org/user-guide/configuration/), add the following import to your [mkdocstrings plugin configuration](https://mkdocstrings.github.io/usage/#cross-references-to-other-projects-inventories): ```yaml plugins: - mkdocstrings: handlers: python: import: - https://docs.pydantic.dev/latest/objects.inv # (1) ``` You can also use `dev` instead of `latest` to target the latest documentation build, up to date with the [`main`](https://github.com/pydantic/pydantic/tree/main) branch. --- # [Hypothesis](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/hypothesis/) # Hypothesis [Hypothesis](https://hypothesis.readthedocs.io/) is the Python library for [property-based testing](https://increment.com/testing/in-praise-of-property-based-testing/). Hypothesis can infer how to construct type-annotated classes, and supports builtin types, many standard library types, and generic types from the [`typing`](https://docs.python.org/3/library/typing.html) and [`typing_extensions`](https://pypi.org/project/typing-extensions/) modules by default. Pydantic v2.0 drops built-in support for Hypothesis and no more ships with the integrated Hypothesis plugin. Caution We are temporarily removing the Hypothesis plugin in favor of studying a different mechanism. For more information, see the issue [annotated-types/annotated-types#37](https://github.com/annotated-types/annotated-types/issues/37). The Hypothesis plugin may be back in a future release. Subscribe to [pydantic/pydantic#4682](https://github.com/pydantic/pydantic/issues/4682) for updates. --- # [Linting](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/linting/) # Linting ## Flake8 plugin If using Flake8 in your project, a [plugin](https://pypi.org/project/flake8-pydantic/) is available and can be installed using the following: Terminal ```bash pip install flake8-pydantic ``` The lint errors provided by this plugin are namespaced under the `PYDXXX` code. To ignore some unwanted rules, the Flake8 configuration can be adapted: ```ini [flake8] extend-ignore = PYD001,PYD002 ``` --- # [Mypy](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/mypy/) # Mypy Pydantic works well with [mypy](http://mypy-lang.org) right out of the box. However, Pydantic also ships with a mypy plugin that adds a number of important Pydantic-specific features that improve its ability to type-check your code. For example, consider the following script: ```python from datetime import datetime from typing import Optional from pydantic import BaseModel class Model(BaseModel): age: int first_name = 'John' last_name: Optional[str] = None signup_ts: Optional[datetime] = None list_of_ints: list[int] m = Model(age=42, list_of_ints=[1, '2', b'3']) print(m.middle_name) # not a model field! Model() # will raise a validation error for age and list_of_ints ``` Without any special configuration, mypy does not catch the [missing model field annotation](/docs/validation/latest/errors/usage_errors#model-field-missing-annotation) and errors about the `list_of_ints` argument which Pydantic parses correctly: ```text 15: error: List item 1 has incompatible type "str"; expected "int" [list-item] 15: error: List item 2 has incompatible type "bytes"; expected "int" [list-item] 16: error: "Model" has no attribute "middle_name" [attr-defined] 17: error: Missing named argument "age" for "Model" [call-arg] 17: error: Missing named argument "list_of_ints" for "Model" [call-arg] ``` But [with the plugin enabled](#enabling-the-plugin), it gives the correct errors: ```text 9: error: Untyped fields disallowed [pydantic-field] 16: error: "Model" has no attribute "middle_name" [attr-defined] 17: error: Missing named argument "age" for "Model" [call-arg] 17: error: Missing named argument "list_of_ints" for "Model" [call-arg] ``` With the pydantic mypy plugin, you can fearlessly refactor your models knowing mypy will catch any mistakes if your field names or types change. Note that mypy already supports some features without using the Pydantic plugin, such as synthesizing a `__init__` method for Pydantic models and dataclasses. See the [mypy plugin capabilities](#mypy-plugin-capabilities) for a list of additional features. The Pydantic mypy plugin is tested against the latest mypy version. Older versions might work but won't be tested. ## Enabling the Plugin To enable the plugin, just add `pydantic.mypy` to the list of plugins in your [mypy config file](https://mypy.readthedocs.io/en/latest/config_file.html): - [mypy.ini](#tab-panel-712) - [pyproject.toml](#tab-panel-713) ```ini [mypy] plugins = pydantic.mypy ``` ```toml [tool.mypy] plugins = ['pydantic.mypy'] ``` Note If you're using `pydantic.v1` models, you'll need to add `pydantic.v1.mypy` to your list of plugins. See the [plugin configuration](#configuring-the-plugin) for more details. ## Mypy plugin capabilities ### Generate a `__init__` signature for Pydantic models - Any required fields that don't have dynamically-determined aliases will be included as required keyword arguments. - If the `validate_by_name` model configuration value is set to `True`, the generated signature will use the field names rather than aliases. - The [`init_forbid_extra`](#init_forbid_extra) and [`init_typed`](#init_typed) plugin configuration values can further fine-tune the synthesized `__init__` method. ### Generate a typed signature for `model_construct` - The `model_construct` method is an alternative to model validation when input data is known to be valid and should not be parsed (see the [documentation](/docs/validation/latest/concepts/models#creating-models-without-validation)). Because this method performs no runtime validation, static checking is important to detect errors. ### Support for frozen models - If the `frozen` configuration is set to `True`, you will get an error if you try mutating a model field (see [faux immutability](/docs/validation/latest/concepts/models#faux-immutability)) ### Respect the type of the `Field`'s `default` and `default_factory` - Field with both a `default` and a `default_factory` will result in an error during static checking. - The type of the `default` and `default_factory` value must be compatible with the one of the field. ### Warn about the use of untyped fields - While defining a field without an annotation will result in a [runtime error](/docs/validation/latest/errors/usage_errors#model-field-missing-annotation), the plugin will also emit a type checking error. ### Prevent the use of required dynamic aliases See the documentation of the [`warn_required_dynamic_aliases`](#warn_required_dynamic_aliases) plugin configuration value. ## Configuring the Plugin To change the values of the plugin settings, create a section in your mypy config file called `[pydantic-mypy]`, and add any key-value pairs for settings you want to override. A configuration file with all plugin strictness flags enabled (and some other mypy strictness flags, too) might look like: - [mypy.ini](#tab-panel-714) - [pyproject.toml](#tab-panel-715) ```ini [mypy] plugins = pydantic.mypy follow_imports = silent warn_redundant_casts = True warn_unused_ignores = True disallow_any_generics = True no_implicit_reexport = True disallow_untyped_defs = True [pydantic-mypy] init_forbid_extra = True init_typed = True warn_required_dynamic_aliases = True ``` ```toml [tool.mypy] plugins = ["pydantic.mypy"] follow_imports = "silent" warn_redundant_casts = true warn_unused_ignores = true disallow_any_generics = true no_implicit_reexport = true disallow_untyped_defs = true [tool.pydantic-mypy] init_forbid_extra = true init_typed = true warn_required_dynamic_aliases = true ``` ### `init_typed` Because Pydantic performs [data conversion](/docs/validation/latest/concepts/models#data-conversion) by default, the following is still valid at runtime: ```python class Model(BaseModel): a: int Model(a='1') ``` For this reason, the plugin will use `Any` for field annotations when synthesizing the `__init__` method, unless `init_typed` is set or [strict mode](/docs/validation/latest/concepts/strict_mode) is enabled on the model. ### `init_forbid_extra` By default, Pydantic allows (and ignores) any extra provided argument: ```python class Model(BaseModel): a: int = 1 Model(unrelated=2) ``` For this reason, the plugin will add an extra `**kwargs: Any` parameter when synthesizing the `__init__` method, unless `init_forbid_extra` is set or the `extra` is set to `'forbid'`. ### `warn_required_dynamic_aliases` Whether to error when using a dynamically-determined alias or alias generator on a model with `validate_by_name` set to `False`. If such aliases are present, mypy cannot properly type check calls to `__init__`. In this case, it will default to treating all arguments as not required. Compatibility with `Any` being disallowed Some mypy configuration options (such as [`disallow_any_explicit`](https://mypy.readthedocs.io/en/stable/config_file.html#confval-disallow_any_explicit)) will error because the synthesized `__init__` method contains `Any` annotations. To circumvent the issue, you will have to enable both `init_forbid_extra` and `init_typed`. --- # [PyCharm](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/pycharm/) # PyCharm While pydantic will work well with any IDE out of the box, a [PyCharm plugin](https://plugins.jetbrains.com/plugin/12861-pydantic) offering improved pydantic integration is available on the JetBrains Plugins Repository for PyCharm. You can install the plugin for free from the plugin marketplace (PyCharm's Preferences -> Plugin -> Marketplace -> search "pydantic"). The plugin currently supports the following features: - For `pydantic.BaseModel.__init__`: - Inspection - Autocompletion - Type-checking - For fields of `pydantic.BaseModel`: - Refactor-renaming fields updates `__init__` calls, and affects sub- and super-classes - Refactor-renaming `__init__` keyword arguments updates field names, and affects sub- and super-classes More information can be found on the [official plugin page](https://plugins.jetbrains.com/plugin/12861-pydantic) and [Github repository](https://github.com/koxudaxi/pydantic-pycharm-plugin). --- # [Pyrefly](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/pyrefly/) # Pyrefly [Pyrefly](https://pyrefly.org/) is a Python type checker and language server with built-in support for a number of Pydantic-specific features. This support works out-of-the-box with Pydantic and Pyrefly installed, with no additional configuration needed. Pyrefly is available as both an [IDE extension](https://pyrefly.org/en/docs/IDE/) and a [command-line type checker](https://pyrefly.org/en/docs/installation/). ## IDE extension Pyrefly gives you IDE features such as go-to-definition and autocomplete on your Pydantic models. Here's an example of signature help, powered by Pyrefly's understanding of the Pydantic-specific `validation_alias` keyword: ![Signature help with the Pyrefly IDE extension](/docs/validation/latest/img/pyrefly.png) As you type `Model()`, Pyrefly hints that you need to use the name `x_` to populate the `x` field. ## Type checker Pyrefly can also catch errors in your code before you run it. Consider the following example: ```python from pydantic import BaseModel, ConfigDict class Model1(BaseModel, frozen=True): x: int class Model2(BaseModel): model_config = ConfigDict(frozen=True) x: int model1 = Model1(x=0) model1.x = 1 # validation error: mutating a frozen field model2 = Model2(x=0) model2.x = 1 # validation error: mutating a frozen field ``` Since `Model1` declares that it is frozen using a [standard type system feature](https://typing.python.org/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator), any type checker of your choice will catch the validation error from mutating `model1.x`. However, a type checker without special support for the Pydantic `ConfigDict` class will miss the validation error from mutating `model2.x`. Pyrefly catches both errors: ```text ERROR Cannot set field `x` [read-only] --> foo.py:11:1 | 11 | model1.x = 1 # validation error: mutating a frozen field | ^^^^^^^^ | This field belongs to a frozen Pydantic model ERROR Cannot set field `x` [read-only] --> foo.py:14:1 | 14 | model2.x = 1 # validation error: mutating a frozen field | ^^^^^^^^ | This field belongs to a frozen Pydantic model ``` See the [Pyrefly documentation](https://pyrefly.org/en/docs/pydantic/) for more information. --- # [Rich](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/rich/) # Rich Pydantic models may be printed with the [Rich](https://github.com/willmcgugan/rich) library which will add additional formatting and color to the output. Here's an example: ![Printing Pydantic models with Rich](/docs/validation/latest/img/rich_pydantic.png) See the Rich documentation on [pretty printing](https://rich.readthedocs.io/en/latest/pretty.html) for more information. --- # [Visual Studio Code](https://pydantic.dev/docs/validation/latest/integrations/dev-tools/visual_studio_code/) # Visual Studio Code Pydantic works well with any editor or IDE out of the box because it's made on top of standard Python type annotations. When using [Visual Studio Code (VS Code)](https://code.visualstudio.com/), there are some **additional editor features** supported, comparable to the ones provided by the [PyCharm plugin](/docs/validation/latest/integrations/pycharm). This means that you will have **autocompletion** (or "IntelliSense") and **error checks** for types and required arguments even while creating new Pydantic model instances. ![pydantic autocompletion in VS Code](/docs/validation/latest/img/vs_code_01.png) ## Configure VS Code To take advantage of these features, you need to make sure you configure VS Code correctly, using the recommended settings. In case you have a different configuration, here's a short overview of the steps. ### Install Pylance You should use the [Pylance](https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance) extension for VS Code. It is the recommended, next-generation, official VS Code plug-in for Python. Pylance is installed as part of the [Python Extension for VS Code](https://marketplace.visualstudio.com/items?itemName=ms-python.python) by default, so it should probably just work. Otherwise, you can double check it's installed and enabled in your editor. ### Configure your environment Then you need to make sure your editor knows the [Python environment](https://code.visualstudio.com/docs/python/python-tutorial#_install-and-use-packages) (probably a virtual environment) for your Python project. This would be the environment in where you installed Pydantic. ### Configure Pylance With the default configurations, you will get support for autocompletion, but Pylance might not check for type errors. You can enable type error checks from Pylance with these steps: - Open the "User Settings" - Search for `Type Checking Mode` - You will find an option under `Python › Analysis: Type Checking Mode` - Set it to `basic` or `strict` (by default it's `off`) ![Type Checking Mode set to strict in VS Code](/docs/validation/latest/img/vs_code_02.png) Now you will not only get autocompletion when creating new Pydantic model instances but also error checks for **required arguments**. ![Required arguments error checks in VS Code](/docs/validation/latest/img/vs_code_03.png) And you will also get error checks for **invalid data types**. ![Invalid data types error checks in VS Code](/docs/validation/latest/img/vs_code_04.png) Technical Details Pylance is the VS Code extension, it's closed source, but free to use. Underneath, Pylance uses an open source tool (also from Microsoft) called [Pyright](https://github.com/microsoft/pyright) that does all the heavy lifting. You can read more about it in the [Pylance Frequently Asked Questions](https://github.com/microsoft/pylance-release/blob/main/FAQ.md#what-is-the-relationship-between-pylance-pyright-and-the-python-extension). ### Configure mypy You might also want to configure mypy in VS Code to get mypy error checks inline in your editor (alternatively/additionally to Pylance). This would include the errors detected by the [Pydantic mypy plugin](/docs/validation/latest/integrations/mypy), if you configured it. To enable mypy in VS Code, do the following: - Open the "User Settings" - Search for `Mypy Enabled` - You will find an option under `Python › Linting: Mypy Enabled` - Check the box (by default it's unchecked) ![mypy enabled in VS Code](/docs/validation/latest/img/vs_code_05.png) ## Tips and tricks Here are some additional tips and tricks to improve your developer experience when using VS Code with Pydantic. ### Strict errors The way this additional editor support works is that Pylance will treat your Pydantic models as if they were Python's pure `dataclasses`. And it will show **strict type error checks** about the data types passed in arguments when creating a new Pydantic model instance. In this example you can see that it shows that a `str` of `'23'` is not a valid `int` for the argument `age`. ![VS Code strict type errors](/docs/validation/latest/img/vs_code_06.png) It would expect `age=23` instead of `age='23'`. Nevertheless, the design, and one of the main features of Pydantic, is that it is very **lenient with data types**. It will actually accept the `str` with value `'23'` and will convert it to an `int` with value `23`. These strict error checks are **very useful** most of the time and can help you **detect many bugs early**. But there are cases, like with `age='23'`, where they could be inconvenient by reporting a "false positive" error. * * * This example above with `age='23'` is intentionally simple, to show the error and the differences in types. But more common cases where these strict errors would be inconvenient would be when using more sophisticated data types, like `int` values for `datetime` fields, or `dict` values for Pydantic sub-models. For example, this is valid for Pydantic: ```python from pydantic import BaseModel class Knight(BaseModel): title: str age: int color: str = 'blue' class Quest(BaseModel): title: str knight: Knight quest = Quest( title='To seek the Holy Grail', knight={'title': 'Sir Lancelot', 'age': 23} ) ``` The type of the field `knight` is declared with the class `Knight` (a Pydantic model) and the code is passing a literal `dict` instead. This is still valid for Pydantic, and the `dict` would be automatically converted to a `Knight` instance. Nevertheless, it would be detected as a type error: ![VS Code strict type errors with model](/docs/validation/latest/img/vs_code_07.png) In those cases, there are several ways to disable or ignore strict errors in very specific places, while still preserving them in the rest of the code. Below are several techniques to achieve it. #### Disable type checks in a line You can disable the errors for a specific line using a comment of: ```python # type: ignore ``` or (to be specific to pylance/pyright): ```python # pyright: ignore ``` ([pyright](https://github.com/microsoft/pyright) is the language server used by Pylance.). coming back to the example with `age='23'`, it would be: ```python from pydantic import BaseModel class Knight(BaseModel): title: str age: int color: str = 'blue' lancelot = Knight(title='Sir Lancelot', age='23') # pyright: ignore ``` that way Pylance and mypy will ignore errors in that line. **Pros**: it's a simple change in that line to remove errors there. **Cons**: any other error in that line will also be omitted, including type checks, misspelled arguments, required arguments not provided, etc. #### Override the type of a variable You can also create a variable with the value you want to use and declare its type explicitly with `Any`. ```python from typing import Any from pydantic import BaseModel class Knight(BaseModel): title: str age: int color: str = 'blue' age_str: Any = '23' lancelot = Knight(title='Sir Lancelot', age=age_str) ``` that way Pylance and mypy will interpret the variable `age_str` as if they didn't know its type, instead of knowing it has a type of `str` when an `int` was expected (and then showing the corresponding error). **Pros**: errors will be ignored only for a specific value, and you will still see any additional errors for the other arguments. **Cons**: it requires importing `Any` and a new variable in a new line for each argument that needs ignoring errors. #### Override the type of a value with `cast` The same idea from the previous example can be put on the same line with the help of `cast()`. This way, the type declaration of the value is overridden inline, without requiring another variable. ```python from typing import Any, cast from pydantic import BaseModel class Knight(BaseModel): title: str age: int color: str = 'blue' lancelot = Knight(title='Sir Lancelot', age=cast(Any, '23')) ``` `cast(Any, '23')` doesn't affect the value, it's still just `'23'`, but now Pylance and mypy will assume it is of type `Any`, which means, they will act as if they didn't know the type of the value. So, this is the equivalent of the previous example, without the additional variable. **Pros**: errors will be ignored only for a specific value, and you will still see any additional errors for the other arguments. There's no need for additional variables. **Cons**: it requires importing `Any` and `cast`, and if you are not used to using `cast()`, it could seem strange at first. ### Config in class arguments Pydantic has a rich set of Model Configurations available. These configurations can be set in an internal `class Config` on each model: ```python from pydantic import BaseModel class Knight(BaseModel): model_config = dict(frozen=True) title: str age: int color: str = 'blue' ``` or passed as keyword arguments when defining the model class: ```python from pydantic import BaseModel class Knight(BaseModel, frozen=True): title: str age: int color: str = 'blue' ``` The specific configuration **`frozen`** (in beta) has a special meaning. It prevents other code from changing a model instance once it's created, keeping it **"frozen"**. When using the second version to declare `frozen=True` (with **keyword arguments** in the class definition), Pylance can use it to help you check in your code and **detect errors** when something is trying to set values in a model that is "frozen". ![VS Code strict type errors with model](/docs/validation/latest/img/vs_code_08.png) ## Adding a default with `Field` Pylance/pyright requires `default` to be a keyword argument to `Field` in order to infer that the field is optional. ```python from pydantic import BaseModel, Field class Knight(BaseModel): title: str = Field(default='Sir Lancelot') # this is okay age: int = Field( 23 ) # this works fine at runtime but will case an error for pyright lance = Knight() # error: Argument missing for parameter "age" ``` This is a limitation of dataclass transforms and cannot be fixed in pydantic. ## Technical Details Caution As a Pydantic user, you don't need the details below. Feel free to skip the rest of this section. These details are only useful for other library authors, etc. This additional editor support works by making use of the [`@dataclass_transform` decorator](https://typing.python.org/en/latest/spec/dataclasses.html#the-dataclass-transform-decorator) (introduced by [PEP 681](https://peps.python.org/pep-0681/)). The standard provides a way for libraries like Pydantic and others to tell editors and tools that they (the editors) should treat these libraries (e.g. Pydantic) as if they were dataclasses, providing autocompletion, type checks, etc. --- # [LLMs](https://pydantic.dev/docs/validation/latest/integrations/llms/) # LLMs The Pydantic documentation is available in the [llms.txt](https://llmstxt.org/) format. This format is defined in Markdown and suited for large language models. Two formats are available: - [llms.txt](https://docs.pydantic.dev/latest/llms.txt): a file containing a brief description of the project, along with links to the different sections of the documentation. The structure of this file is described in details in the [format documentation](https://llmstxt.org/#format). - [llms-full.txt](https://docs.pydantic.dev/latest/llms-full.txt): Similar to the `llms.txt` file, but every link content is included. Note that this file may be too large for some LLMs. As of today, these files _cannot_ be natively leveraged by LLM frameworks or IDEs. Alternatively, a [MCP server](https://modelcontextprotocol.io/) can be implemented to properly parse the `llms.txt` file. --- # [Pydantic Logfire](https://pydantic.dev/docs/validation/latest/integrations/logfire/) # Pydantic Logfire Pydantic integrates seamlessly with **Pydantic Logfire**, an observability platform built by us on the same belief as our open source library -- that the most powerful tools can be easy to use. ## Getting Started Logfire has an out-of-the-box Pydantic integration that lets you understand the data passing through your Pydantic models and get analytics on validations. For existing Pydantic users, it delivers unparalleled insights into your usage of Pydantic models. [Getting started](https://logfire.pydantic.dev/docs/) with Logfire can be done in three simple steps: 1. Set up your Logfire account. 2. Install the Logfire SDK. 3. Instrument your project. ### Basic Usage Once you've got Logfire set up, you can start using it to monitor your Pydantic models and get insights into your data validation: ```python from datetime import date import logfire from pydantic import BaseModel logfire.configure() # (1) class User(BaseModel): name: str country_code: str dob: date user = User(name='Anne', country_code='USA', dob='2000-01-01') logfire.info('user processed: {user!r}', user=user) # (2) ``` The `logfire.configure()` call is all you need to instrument your project with Logfire. The `logfire.info()` call logs the `user` object to Logfire, with builtin support for Pydantic models. ![basic pydantic logfire usage](/docs/validation/latest/img/basic_logfire.png) ### Pydantic Instrumentation You can even record information about the validation process automatically by using the builtin [Pydantic integration](https://logfire.pydantic.dev/docs/why-logfire/pydantic/): ```python from datetime import date import logfire from pydantic import BaseModel logfire.configure() logfire.instrument_pydantic() # (1) class User(BaseModel): name: str country_code: str dob: date User(name='Anne', country_code='USA', dob='2000-01-01') User(name='David', country_code='GBR', dob='invalid-dob') ``` The `logfire.instrument_pydantic()` call automatically logs validation information for all Pydantic models in your project. You'll see each successful and failed validation logged in Logfire: ![logfire instrumentation](/docs/validation/latest/img/logfire_instrument.png) And you can investigate each of the corresponding spans to get validation details: ![logfire span details](/docs/validation/latest/img/logfire_span.png) --- # [Architecture](https://pydantic.dev/docs/validation/latest/internals/architecture/) # Architecture Note This section is part of the _internals_ documentation, and is partly targeted to contributors. Starting with Pydantic V2, part of the codebase is written in Rust in a separate package called `pydantic-core`. This was done partly in order to improve validation and serialization performance (with the cost of limited customization and extendibility of the internal logic). This architecture documentation will first cover how the two `pydantic` and `pydantic-core` packages interact together, then will go through the architecture specifics for various patterns (model definition, validation, serialization, JSON Schema). Usage of the Pydantic library can be divided into two parts: - Model definition, done in the `pydantic` package. - Model validation and serialization, done in the `pydantic-core` package. ## Model definition Whenever a Pydantic [`BaseModel`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel) is defined, the metaclass will analyze the body of the model to collect a number of elements: - Defined annotations to build model fields (collected in the [`model_fields`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_fields) attribute). - Model configuration, set with [`model_config`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_config). - Additional validators/serializers. - Private attributes, class variables, identification of generic parametrization, etc. ### Communicating between `pydantic` and `pydantic-core`: the core schema We then need a way to communicate the collected information from the model definition to `pydantic-core`, so that validation and serialization is performed accordingly. To do so, Pydantic uses the concept of a core schema: a structured (and serializable) Python dictionary (represented using [`TypedDict`](https://docs.python.org/3/library/typing.html#typing.TypedDict) definitions) describing a specific validation and serialization logic. It is the core data structure used to communicate between the `pydantic` and `pydantic-core` packages. Every core schema has a required `type` key, and extra properties depending on this `type`. The generation of a core schema is handled in a single place, by the `GenerateSchema` class (no matter if it is for a Pydantic model or anything else). Note It is not possible to define a custom core schema. A core schema needs to be understood by the `pydantic-core` package, and as such we only support a fixed number of core schema types. This is also part of the reason why the `GenerateSchema` isn't truly exposed and properly documented. The core schema definitions can be found in the [`pydantic_core.core_schema`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema) module. In the case of a Pydantic model, a core schema will be constructed and set as the [`__pydantic_core_schema__`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.__pydantic_core_schema__) attribute. To illustrate what a core schema looks like, we will take the example of the [`bool`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.bool_schema) core schema: ```python class BoolSchema(TypedDict, total=False): type: Required[Literal['bool']] strict: bool ref: str metadata: Any serialization: SerSchema ``` When defining a Pydantic model with a boolean field: ```python from pydantic import BaseModel, Field class Model(BaseModel): foo: bool = Field(strict=True) ``` The core schema for the `foo` field will look like: ```python { 'type': 'bool', 'strict': True, } ``` As seen in the [`BoolSchema`](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.bool_schema) definition, the serialization logic is also defined in the core schema. If we were to define a custom serialization function for `foo` , the `serialization` key would look like: For example using the [`field_serializer`](/docs/validation/latest/api/pydantic/functional_serializers/#pydantic.functional_serializers.field_serializer) decorator: ```python class Model(BaseModel): foo: bool = Field(strict=True) @field_serializer('foo', mode='plain') def serialize_foo(self, value: bool) -> Any: ... ``` ```python { 'type': 'function-plain', 'function': , 'is_field_serializer': True, 'info_arg': False, 'return_schema': {'type': 'int'}, } ``` Note that this is also a core schema definition, just that it is only relevant for `pydantic-core` during serialization. Core schemas cover a broad scope, and are used whenever we want to communicate between the Python and Rust side. While the previous examples were related to validation and serialization, it could in theory be used for anything: error management, extra metadata, etc. ### JSON Schema generation You may have noticed that the previous serialization core schema has a `return_schema` key. This is because the core schema is also used to generate the corresponding JSON Schema. Similar to how the core schema is generated, the JSON Schema generation is handled by the [`GenerateJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema) class. The [`generate`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema.generate) method is the main entry point and is given the core schema of that model. Coming back to our `bool` field example, the [`bool_schema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema.bool_schema) method will be given the previously generated [boolean core schema](/docs/validation/latest/api/pydantic-core/pydantic_core_schema/#pydantic_core.core_schema.bool_schema) and will return the following JSON Schema: ```json { {"type": "boolean"} } ``` ### Customizing the core schema and JSON schema Usage Documentation [Custom types](/docs/validation/latest/concepts/types#custom-types) [Implementing `__get_pydantic_core_schema__`](/docs/validation/latest/concepts/json_schema#implementing-__get_pydantic_core_schema__) [Implementing `__get_pydantic_json_schema__`](/docs/validation/latest/concepts/json_schema#implementing-__get_pydantic_json_schema__) While the `GenerateSchema` and [`GenerateJsonSchema`](/docs/validation/latest/api/pydantic/json_schema/#pydantic.json_schema.GenerateJsonSchema) classes handle the creation of the corresponding schemas, Pydantic offers a way to customize them in some cases, following a wrapper pattern. This customization is done through the `__get_pydantic_core_schema__` and `__get_pydantic_json_schema__` methods. To understand this wrapper pattern, we will take the example of metadata classes used with [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), where the `__get_pydantic_core_schema__` method can be used: ```python from typing import Annotated, Any from pydantic_core import CoreSchema from pydantic import GetCoreSchemaHandler, TypeAdapter class MyStrict: @classmethod def __get_pydantic_core_schema__( cls, source: Any, handler: GetCoreSchemaHandler ) -> CoreSchema: schema = handler(source) # (1) schema['strict'] = True return schema class MyGt: @classmethod def __get_pydantic_core_schema__( cls, source: Any, handler: GetCoreSchemaHandler ) -> CoreSchema: schema = handler(source) # (2) schema['gt'] = 1 return schema ta = TypeAdapter(Annotated[int, MyStrict(), MyGt()]) ``` `MyStrict` is the first annotation to be applied. At this point, `schema = {'type': 'int'}`. `MyGt` is the last annotation to be applied. At this point, `schema = {'type': 'int', 'strict': True}`. When the `GenerateSchema` class builds the core schema for `Annotated[int, MyStrict(), MyGt()]`, it will create an instance of a `GetCoreSchemaHandler` to be passed to the `MyGt.__get_pydantic_core_schema__` method. In the case of our [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated) pattern, the `GetCoreSchemaHandler` is defined in a nested way. Calling it will recursively call the other `__get_pydantic_core_schema__` methods until it reaches the `int` annotation, where a simple `{'type': 'int'}` schema is returned. The `source` argument depends on the core schema generation pattern. In the case of [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated), the `source` will be the type being annotated. When [defining a custom type](/docs/validation/latest/concepts/types#as-a-method-on-a-custom-type), the `source` will be the actual class where `__get_pydantic_core_schema__` is defined. ## Model validation and serialization While model definition was scoped to the _class_ level (i.e. when defining your model), model validation and serialization happens at the _instance_ level. Both these concepts are handled in `pydantic-core` (providing a 5 to 20 performance increase compared to Pydantic V1), by using the previously built core schema. `pydantic-core` exposes a [`SchemaValidator`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaValidator) and [`SchemaSerializer`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaSerializer) class to perform these tasks: ```python from pydantic import BaseModel class Model(BaseModel): foo: int model = Model.model_validate({'foo': 1}) # (1) dumped = model.model_dump() # (2) ``` The provided data is sent to `pydantic-core` by using the [`SchemaValidator.validate_python`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaValidator.validate_python) method. `pydantic-core` will validate (following the core schema of the model) the data and populate the model's `__dict__` attribute. The `model` instance is sent to `pydantic-core` by using the [`SchemaSerializer.to_python`](/docs/validation/latest/api/pydantic-core/pydantic_core/#pydantic_core.SchemaSerializer.to_python) method. `pydantic-core` will read the instance's `__dict__` attribute and built the appropriate result (again, following the core schema of the model). --- # [Resolving Annotations](https://pydantic.dev/docs/validation/latest/internals/resolving_annotations/) # Resolving Annotations Note This section is part of the _internals_ documentation, and is partly targeted to contributors. Pydantic heavily relies on [type hints](https://docs.python.org/3/glossary.html#term-type-hint) at runtime to build schemas for validation, serialization, etc. While type hints were primarily introduced for static type checkers (such as [Mypy](https://www.mypy-lang.org/) or [Pyright](https://github.com/microsoft/pyright/)), they are accessible (and sometimes evaluated) at runtime. This means that the following would fail at runtime, because `Node` has yet to be defined in the current module: ```python class Node: """Binary tree node.""" # NameError: name 'Node' is not defined: def __init__(self, l: Node, r: Node) -> None: self.left = l self.right = r ``` To circumvent this issue, forward references can be used (by wrapping the annotation in quotes). In Python 3.7, [PEP 563](https://peps.python.org/pep-0563/) introduced the concept of _postponed evaluation of annotations_, meaning with the `from __future__ import annotations` [future statement](https://docs.python.org/3/reference/simple_stmts.html#future), type hints are stringified by default: ```python from __future__ import annotations from pydantic import BaseModel class Foo(BaseModel): f: MyType # Given the future import above, this is equivalent to: # f: 'MyType' type MyType = int print(Foo.__annotations__) #> {'f': 'MyType'} ``` ## The challenges of runtime evaluation Static type checkers make use of the AST to analyze the defined annotations. Regarding the previous example, this has the benefit of being able to understand what `MyType` refers to when analyzing the class definition of `Foo`, even if `MyType` isn't yet defined at runtime. However, for runtime tools such as Pydantic, it is more challenging to correctly resolve these forward annotations. The Python standard library provides some tools to do so ([`typing.get_type_hints()`](https://docs.python.org/3/library/typing.html#typing.get_type_hints), [`inspect.get_annotations()`](https://docs.python.org/3/library/inspect.html#inspect.get_annotations)), but they come with some limitations. Thus, they are being re-implemented in Pydantic with improved support for edge cases. As Pydantic as grown, it's adapted to support many edge cases requiring irregular patterns for annotation evaluation. Some of these use cases aren't necessarily sound from a static type checking perspective. In v2.10, the internal logic was refactored in an attempt to simplify and standardize annotation evaluation. Admittedly, backwards compatibility posed some challenges, and there is still some noticeable scar tissue in the codebase because of this.There's a hope that [PEP 649](https://peps.python.org/pep-0649/) (introduced in Python 3.14) will greatly simplify the process, especially when it comes to dealing with locals of a function. To evaluate forward references, Pydantic roughly follows the same logic as described in the documentation of the [`typing.get_type_hints()`](https://docs.python.org/3/library/typing.html#typing.get_type_hints) function. That is, the built-in [`eval()`](https://docs.python.org/3/library/functions.html#eval) function is used by passing the forward reference, a global, and a local namespace. The namespace fetching logic is defined in the sections below. ## Resolving annotations at class definition The following example will be used as a reference throughout this section: ```python # module1.py: type MyType = int class Base: f1: 'MyType' # module2.py: from pydantic import BaseModel from module1 import Base type MyType = str def inner() -> None: type InnerType = bool class Model(BaseModel, Base): type LocalType = bytes f2: 'MyType' f3: 'InnerType' f4: 'LocalType' f5: 'UnknownType' type InnerType2 = complex ``` When the `Model` class is being built, different [namespaces](https://docs.python.org/3/glossary.html#term-namespace) are at play. For each base class of the `Model`'s [MRO](https://docs.python.org/3/glossary.html#term-method-resolution-order) (in reverse order -- that is, starting with `Base`), the following logic is applied: 1. Fetch the `__annotations__` key from the current base class' `__dict__`, if present. For `Base`, this will be `{'f1': 'MyType'}`. 2. Iterate over the `__annotations__` items and try to evaluate the annotation [1](#user-content-fn-1) using a custom wrapper around the built-in [`eval()`](https://docs.python.org/3/library/functions.html#eval) function. This function takes two `globals` and `locals` arguments: - The current module's `__dict__` is naturally used as `globals`. For `Base`, this will be `sys.modules['module1'].__dict__`. - For the `locals` argument, Pydantic will try to resolve symbols in the following namespaces, sorted by highest priority: - A namespace created on the fly, containing the current class name (`{cls.__name__: cls}`). This is done in order to support recursive references. - The locals of the current class (i.e. `cls.__dict__`). For `Model`, this will include `LocalType`. - The parent namespace of the class, if different from the globals described above. This is the [locals](https://docs.python.org/3/reference/datamodel.html#frame.f_locals) of the frame where the class is being defined. For `Base`, because the class is being defined in the module directly, this namespace won't be used as it will result in the globals being used again. For `Model`, the parent namespace is the locals of the frame of `inner()`. 3. If the annotation failed to evaluate, it is kept as is, so that the model can be rebuilt at a later stage. This will be the case for `f5`. The following table lists the resolved type annotations for every field, once the `Model` class has been created: Field name Resolved annotation `f1` [`int`](https://docs.python.org/3/library/functions.html#int) `f2` [`str`](https://docs.python.org/3/library/stdtypes.html#str) `f3` [`bool`](https://docs.python.org/3/library/functions.html#bool) `f4` [`bytes`](https://docs.python.org/3/library/stdtypes.html#bytes) `f5` `'UnknownType'` ### Limitations and backwards compatibility concerns While the namespace fetching logic is trying to be as accurate as possible, we still face some limitations: - The locals of the current class (`cls.__dict__`) may include irrelevant entries, most of them being dunder attributes. This means that the following annotation: `f: '__doc__'` will successfully (and unexpectedly) be resolved. - When the `Model` class is being created inside a function, we keep a copy of the [locals](https://docs.python.org/3/reference/datamodel.html#frame.f_locals) of the frame. This copy only includes the symbols defined in the locals when `Model` is being defined, meaning `InnerType2` won't be included (and will **not be** if doing a model rebuild at a later point!). - To avoid memory leaks, we use [weak references](https://docs.python.org/3/library/weakref.html#module-weakref) to the locals of the function, meaning some forward references might not resolve outside the function (1). - Locals of the function are only taken into account for Pydantic models, but this pattern does not apply to dataclasses, typed dictionaries or named tuples. 1. Here is an example: ```python def func(): A = int class Model(BaseModel): f: 'A | Forward' return Model Model = func() Model.model_rebuild(_types_namespace={'Forward': str}) # pydantic.errors.PydanticUndefinedAnnotation: name 'A' is not defined ``` For backwards compatibility reasons, and to be able to support valid use cases without having to rebuild models, the namespace logic described above is a bit different when it comes to core schema generation. Taking the following example: ```python from dataclasses import dataclass from pydantic import BaseModel @dataclass class Foo: a: 'Bar | None' = None class Bar(BaseModel): b: Foo ``` Once the fields for `Bar` have been collected (meaning annotations resolved), the `GenerateSchema` class converts every field into a core schema. When it encounters another class-like field type (such as a dataclass), it will try to evaluate annotations, following roughly the same logic as [described above](#resolving-annotations-at-class-definition). However, to evaluate the `'Bar | None'` annotation, `Bar` needs to be present in the globals or locals, which is normally _not_ the case: `Bar` is being created, so it is not "assigned" to the current module's `__dict__` at that point. To avoid having to call [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) on `Bar`, both the parent namespace (if `Bar` was to be defined inside a function, and [the namespace provided during a model rebuild](#model-rebuild-semantics)) and the `{Bar.__name__: Bar}` namespace are included in the locals during annotations evaluation of `Foo` (with the lowest priority) . This backwards compatibility logic can introduce some inconsistencies, such as the following: ```python from dataclasses import dataclass from pydantic import BaseModel @dataclass class Foo: # `a` and `b` shouldn't resolve: a: 'Model' b: 'Inner' def func(): Inner = int class Model(BaseModel): foo: Foo Model.__pydantic_complete__ #> True, should be False. ``` ## Resolving annotations when rebuilding a model When a forward reference fails to evaluate, Pydantic will silently fail and stop the core schema generation process. This can be seen by inspecting the `__pydantic_core_schema__` of a model class: ```python from pydantic import BaseModel class Foo(BaseModel): f: 'MyType' Foo.__pydantic_core_schema__ #> ``` If you then properly define `MyType`, you can rebuild the model: ```python type MyType = int Foo.model_rebuild() Foo.__pydantic_core_schema__ #> {'type': 'model', 'schema': {...}, ...} ``` The [`model_rebuild()`](/docs/validation/latest/api/pydantic/base_model/#pydantic.BaseModel.model_rebuild) method uses a _rebuild namespace_, with the following semantics: - If an explicit `_types_namespace` argument is provided, it is used as the rebuild namespace. - If no namespace is provided, the namespace where the method is called will be used as the rebuild namespace. This _rebuild namespace_ will be merged with the model's parent namespace (if it was defined in a function) and used as is (see the [backwards compatibility logic](#backwards-compatibility-logic) described above). ## Footnotes 1. This is done unconditionally, as forward annotations can be only present _as part_ of a type hint (e.g. `Optional['int']`), as dictated by the [typing specification](https://typing.readthedocs.io/en/latest/spec/annotations.html#string-annotations). [↩](#user-content-fnref-1) --- # [Pydantic People](https://pydantic.dev/docs/validation/latest/pydantic-people/pydantic_people/) # Pydantic People Pydantic has an amazing community of contributors, reviewers, and experts that help propel the project forward. Here, we celebrate those people and their contributions. ## Maintainers These are the current maintainers of the Pydantic repository. Feel free to tag us if you have questions, review requests, or feature requests for which you'd like feedback! [ ![](https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4) @samuelcolvin ](https://github.com/samuelcolvin) [ ![](https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4) @dmontagu ](https://github.com/dmontagu) [ ![](https://avatars.githubusercontent.com/u/1939362?u=b4b48981c3a097daaad16c4c5417aa7a3e5e32d9&v=4) @davidhewitt ](https://github.com/davidhewitt) [ ![](https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4) @Viicos ](https://github.com/Viicos) [ ![](https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4) @adriangb ](https://github.com/adriangb) [ ![](https://avatars.githubusercontent.com/u/3627481?u=9bb2e0cf1c5ef3d0609d2e639a135b7b4ca8b463&v=4) @alexmojaki ](https://github.com/alexmojaki) [ ![](https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4) @Kludex ](https://github.com/Kludex) [ ![](https://avatars.githubusercontent.com/u/3122442?u=f387fc2dbc0c681f23e80e2ad705790fafcec9a2&v=4) @hramezani ](https://github.com/hramezani) ## Experts These are the users that have helped others the most with questions in GitHub through _all time_. [ ![](https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4) @samuelcolvin ](https://github.com/samuelcolvin) Questions replied: 296 [ ![](https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4) @Viicos ](https://github.com/Viicos) Questions replied: 232 [ ![](https://avatars.githubusercontent.com/u/18406791?u=4853940cf5eeffb5bbb9ba06ad862f28bc68d69e&v=4) @PrettyWood ](https://github.com/PrettyWood) Questions replied: 143 [ ![](https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4) @uriyyo ](https://github.com/uriyyo) Questions replied: 96 [ ![](https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4) @dmontagu ](https://github.com/dmontagu) Questions replied: 55 [ ![](https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4) @adriangb ](https://github.com/adriangb) Questions replied: 42 [ ![](https://avatars.githubusercontent.com/u/54324534?u=acc3756515d6f87acc91e36a4478557cba9d9dac&v=4) @sydney-runkle ](https://github.com/sydney-runkle) Questions replied: 38 [ ![](https://avatars.githubusercontent.com/u/3122442?u=f387fc2dbc0c681f23e80e2ad705790fafcec9a2&v=4) @hramezani ](https://github.com/hramezani) Questions replied: 23 [ ![](https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4) @Kludex ](https://github.com/Kludex) Questions replied: 22 [ ![](https://avatars.githubusercontent.com/u/2184855?u=5670768b7efda993c4887d91df3cf330dc7bc9de&v=4) @lesnik512 ](https://github.com/lesnik512) Questions replied: 21 [ ![](https://avatars.githubusercontent.com/u/1765494?u=5b1ab7c582db4b4016fa31affe977d10af108ad4&v=4) @harunyasar ](https://github.com/harunyasar) Questions replied: 17 [ ![](https://avatars.githubusercontent.com/u/48211033?u=5ca15d25319ce589da76d7891144ddc8480d8b6d&v=4) @janas-adam ](https://github.com/janas-adam) Questions replied: 15 [ ![](https://avatars.githubusercontent.com/u/4216559?u=360a36fb602cded27273cbfc0afc296eece90662&v=4) @nymous ](https://github.com/nymous) Questions replied: 13 [ ![](https://avatars.githubusercontent.com/u/40807730?v=4) @ybressler ](https://github.com/ybressler) Questions replied: 3 ### Most active users last month These are the users that have helped others the most with questions in GitHub during the last month. [ ![](https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4) @Viicos ](https://github.com/Viicos) Questions replied: 3 ## Top contributors These are the users that have created the most pull requests that have been _merged_. [ ![](https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4) @Viicos ](https://github.com/Viicos) Contributions: 491 [ ![](https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4) @samuelcolvin ](https://github.com/samuelcolvin) Contributions: 408 [ ![](https://avatars.githubusercontent.com/u/54324534?u=acc3756515d6f87acc91e36a4478557cba9d9dac&v=4) @sydney-runkle ](https://github.com/sydney-runkle) Contributions: 382 [ ![](https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4) @dmontagu ](https://github.com/dmontagu) Contributions: 316 [ ![](https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4) @adriangb ](https://github.com/adriangb) Contributions: 199 [ ![](https://avatars.githubusercontent.com/u/3122442?u=f387fc2dbc0c681f23e80e2ad705790fafcec9a2&v=4) @hramezani ](https://github.com/hramezani) Contributions: 199 [ ![](https://avatars.githubusercontent.com/u/18406791?u=4853940cf5eeffb5bbb9ba06ad862f28bc68d69e&v=4) @PrettyWood ](https://github.com/PrettyWood) Contributions: 122 [ ![](https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4) @Kludex ](https://github.com/Kludex) Contributions: 112 [ ![](https://avatars.githubusercontent.com/u/1939362?u=b4b48981c3a097daaad16c4c5417aa7a3e5e32d9&v=4) @davidhewitt ](https://github.com/davidhewitt) Contributions: 89 [ ![](https://avatars.githubusercontent.com/u/370316?u=eb206070cfe47f242d5fcea2e6c7514f4d0f27f5&v=4) @tpdorsey ](https://github.com/tpdorsey) Contributions: 71 [ ![](https://avatars.githubusercontent.com/u/38705?v=4) @lig ](https://github.com/lig) Contributions: 49 [ ![](https://avatars.githubusercontent.com/u/16239342?u=8454ae029661131445080f023e1efccc29166485&v=4) @pyup-bot ](https://github.com/pyup-bot) Contributions: 46 [ ![](https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4) @tiangolo ](https://github.com/tiangolo) Contributions: 22 [ ![](https://avatars.githubusercontent.com/u/36469655?u=f67d8fa6d67d35d2f5ebd5b15e24efeb41036fd3&v=4) @Bobronium ](https://github.com/Bobronium) Contributions: 19 [ ![](https://avatars.githubusercontent.com/u/3627481?u=9bb2e0cf1c5ef3d0609d2e639a135b7b4ca8b463&v=4) @alexmojaki ](https://github.com/alexmojaki) Contributions: 18 [ ![](https://avatars.githubusercontent.com/u/1087619?u=cd78c4f602bf9f9667277dd0af9302a7fe9dd75a&v=4) @Gr1N ](https://github.com/Gr1N) Contributions: 17 [ ![](https://avatars.githubusercontent.com/u/1271289?u=b83b0a82b2c95990d93cefbeb8f548d9f2f090c2&v=4) @misrasaurabh1 ](https://github.com/misrasaurabh1) Contributions: 16 [ ![](https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4) @uriyyo ](https://github.com/uriyyo) Contributions: 15 [ ![](https://avatars.githubusercontent.com/u/6400248?u=88cadd1dd6376e7000934e93712c5eb0138c1616&v=4) @pilosus ](https://github.com/pilosus) Contributions: 12 [ ![](https://avatars.githubusercontent.com/u/52716203?u=21b53ce4115062b1e20cb513e64ca0000c2ef127&v=4) @yezz123 ](https://github.com/yezz123) Contributions: 12 [ ![](https://avatars.githubusercontent.com/u/30130371?v=4) @cdce8p ](https://github.com/cdce8p) Contributions: 12 [ ![](https://avatars.githubusercontent.com/u/89458301?u=75f53e971fcba3ff61836c389505a420bddd865c&v=4) @kc0506 ](https://github.com/kc0506) Contributions: 12 [ ![](https://avatars.githubusercontent.com/u/1148665?u=b69e6fe797302f025a2d125e377e27f8ea0b8058&v=4) @StephenBrown2 ](https://github.com/StephenBrown2) Contributions: 10 [ ![](https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4) @koxudaxi ](https://github.com/koxudaxi) Contributions: 9 [ ![](https://avatars.githubusercontent.com/u/19784933?v=4) @aminalaee ](https://github.com/aminalaee) Contributions: 8 [ ![](https://avatars.githubusercontent.com/u/70970900?u=573a3175906348e0d1529104d56b391e93ca0250&v=4) @NeevCohen ](https://github.com/NeevCohen) Contributions: 8 [ ![](https://avatars.githubusercontent.com/u/31134424?u=e8afd95a97b5556c467d1be27788950e67378ef1&v=4) @layday ](https://github.com/layday) Contributions: 7 [ ![](https://avatars.githubusercontent.com/u/1049817?u=b42e1148d23ea9039b325975bbea3ff8c5b4e3ec&v=4) @daviskirk ](https://github.com/daviskirk) Contributions: 7 [ ![](https://avatars.githubusercontent.com/u/1609449?u=922abf0524b47739b37095e553c99488814b05db&v=4) @tlambert03 ](https://github.com/tlambert03) Contributions: 7 [ ![](https://avatars.githubusercontent.com/u/1769841?u=44e83d7974f0ab5c431340f1669d98f781594980&v=4) @dgasmith ](https://github.com/dgasmith) Contributions: 6 [ ![](https://avatars.githubusercontent.com/u/202696?v=4) @Atheuz ](https://github.com/Atheuz) Contributions: 6 [ ![](https://avatars.githubusercontent.com/u/3709715?u=0745d1d2473894c33f3b35f0b965d71cc9aec553&v=4) @cclauss ](https://github.com/cclauss) Contributions: 6 [ ![](https://avatars.githubusercontent.com/u/16639270?u=faa71bcfb3273a32cd81711a56998e115bca7fcc&v=4) @AdolfoVillalobos ](https://github.com/AdolfoVillalobos) Contributions: 6 [ ![](https://avatars.githubusercontent.com/u/159434?u=45706bfe14e7ff6afceb81b01f8316efa808ee65&v=4) @DouweM ](https://github.com/DouweM) Contributions: 6 [ ![](https://avatars.githubusercontent.com/u/6339494?u=893876f31ce65fa8ad8cfcc592392a77f0f8af38&v=4) @nuno-andre ](https://github.com/nuno-andre) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/9677399?u=386c330f212ce467ce7119d9615c75d0e9b9f1ce&v=4) @ofek ](https://github.com/ofek) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/59469646?u=86d6a20768cc4cc65622eafd86672147321bd8f8&v=4) @JensHeinrich ](https://github.com/JensHeinrich) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/25489980?u=1e9b5cbbbb1516fbea6da00429e4eef0ef79e4e6&v=4) @ornariece ](https://github.com/ornariece) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/9328433?u=8546519cb04223cd878285d72c27850b5f3f0882&v=4) @mschoettle ](https://github.com/mschoettle) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/44468031?u=1590b6d141e6cbcc1862a95959b9a134fdb1f108&v=4) @karta9821 ](https://github.com/karta9821) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/181558744?u=e91b9d6f486298d4687e06be4a32857049ae4c2a&v=4) @Rohan5commit ](https://github.com/Rohan5commit) Contributions: 5 [ ![](https://avatars.githubusercontent.com/u/1734544?v=4) @hmvp ](https://github.com/hmvp) Contributions: 4 [ ![](https://avatars.githubusercontent.com/u/24581770?v=4) @retnikt ](https://github.com/retnikt) Contributions: 4 [ ![](https://avatars.githubusercontent.com/u/197540?v=4) @therefromhere ](https://github.com/therefromhere) Contributions: 4 [ ![](https://avatars.githubusercontent.com/u/10811879?v=4) @JeanArhancet ](https://github.com/JeanArhancet) Contributions: 4 [ ![](https://avatars.githubusercontent.com/u/164513?v=4) @commonism ](https://github.com/commonism) Contributions: 4 [ ![](https://avatars.githubusercontent.com/u/12939780?v=4) @MarkusSintonen ](https://github.com/MarkusSintonen) Contributions: 4 ## Top Reviewers These are the users that have reviewed the most Pull Requests from others, assisting with code quality, documentation, bug fixes, feature requests, etc. [ ![](https://avatars.githubusercontent.com/u/4039449?u=42eb3b833047c8c4b4f647a031eaef148c16d93f&v=4) @samuelcolvin ](https://github.com/samuelcolvin) Reviews: 706 [ ![](https://avatars.githubusercontent.com/u/54324534?u=acc3756515d6f87acc91e36a4478557cba9d9dac&v=4) @sydney-runkle ](https://github.com/sydney-runkle) Reviews: 691 [ ![](https://avatars.githubusercontent.com/u/65306057?u=fcd677dc1b9bef12aa103613e5ccb3f8ce305af9&v=4) @Viicos ](https://github.com/Viicos) Reviews: 557 [ ![](https://avatars.githubusercontent.com/u/3122442?u=f387fc2dbc0c681f23e80e2ad705790fafcec9a2&v=4) @hramezani ](https://github.com/hramezani) Reviews: 534 [ ![](https://avatars.githubusercontent.com/u/35119617?u=540f30c937a6450812628b9592a1dfe91bbe148e&v=4) @dmontagu ](https://github.com/dmontagu) Reviews: 532 [ ![](https://avatars.githubusercontent.com/u/1755071?u=612704256e38d6ac9cbed24f10e4b6ac2da74ecb&v=4) @adriangb ](https://github.com/adriangb) Reviews: 428 [ ![](https://avatars.githubusercontent.com/u/7353520?u=df8a3f06ba8f55ae1967a3e2d5ed882903a4e330&v=4) @Kludex ](https://github.com/Kludex) Reviews: 261 [ ![](https://avatars.githubusercontent.com/u/1939362?u=b4b48981c3a097daaad16c4c5417aa7a3e5e32d9&v=4) @davidhewitt ](https://github.com/davidhewitt) Reviews: 260 [ ![](https://avatars.githubusercontent.com/u/18406791?u=4853940cf5eeffb5bbb9ba06ad862f28bc68d69e&v=4) @PrettyWood ](https://github.com/PrettyWood) Reviews: 211 [ ![](https://avatars.githubusercontent.com/u/38705?v=4) @lig ](https://github.com/lig) Reviews: 103 [ ![](https://avatars.githubusercontent.com/u/370316?u=eb206070cfe47f242d5fcea2e6c7514f4d0f27f5&v=4) @tpdorsey ](https://github.com/tpdorsey) Reviews: 77 [ ![](https://avatars.githubusercontent.com/in/718456?v=4) @hyperlint-ai-deprecated ](https://github.com/apps/hyperlint-ai-deprecated) Reviews: 57 [ ![](https://avatars.githubusercontent.com/u/1326112?u=cb5d06e73a9e1998141b1641aa88e443c6717651&v=4) @tiangolo ](https://github.com/tiangolo) Reviews: 45 [ ![](https://avatars.githubusercontent.com/u/159434?u=45706bfe14e7ff6afceb81b01f8316efa808ee65&v=4) @DouweM ](https://github.com/DouweM) Reviews: 43 [ ![](https://avatars.githubusercontent.com/u/3627481?u=9bb2e0cf1c5ef3d0609d2e639a135b7b4ca8b463&v=4) @alexmojaki ](https://github.com/alexmojaki) Reviews: 33 [ ![](https://avatars.githubusercontent.com/u/36469655?u=f67d8fa6d67d35d2f5ebd5b15e24efeb41036fd3&v=4) @Bobronium ](https://github.com/Bobronium) Reviews: 27 [ ![](https://avatars.githubusercontent.com/u/38759997?u=d7ed300a53abb0765bfb12362203dd5255c29dee&v=4) @friendlymatthew ](https://github.com/friendlymatthew) Reviews: 21 [ ![](https://avatars.githubusercontent.com/u/1087619?u=cd78c4f602bf9f9667277dd0af9302a7fe9dd75a&v=4) @Gr1N ](https://github.com/Gr1N) Reviews: 17 [ ![](https://avatars.githubusercontent.com/u/1148665?u=b69e6fe797302f025a2d125e377e27f8ea0b8058&v=4) @StephenBrown2 ](https://github.com/StephenBrown2) Reviews: 17 [ ![](https://avatars.githubusercontent.com/u/12939780?v=4) @MarkusSintonen ](https://github.com/MarkusSintonen) Reviews: 16 [ ![](https://avatars.githubusercontent.com/u/40807730?u=fa12d64259ccf9eca18847102335ee6408cb9eaa&v=4) @ybressler ](https://github.com/ybressler) Reviews: 15 [ ![](https://avatars.githubusercontent.com/u/32038156?u=c26ca9b821fcf6499b84db75f553d4980bf8d023&v=4) @uriyyo ](https://github.com/uriyyo) Reviews: 11 [ ![](https://avatars.githubusercontent.com/u/630670?u=507d8577b4b3670546b449c4c2ccbc5af40d72f7&v=4) @koxudaxi ](https://github.com/koxudaxi) Reviews: 10 [ ![](https://avatars.githubusercontent.com/u/1049817?u=b42e1148d23ea9039b325975bbea3ff8c5b4e3ec&v=4) @daviskirk ](https://github.com/daviskirk) Reviews: 10 [ ![](https://avatars.githubusercontent.com/u/52716203?u=21b53ce4115062b1e20cb513e64ca0000c2ef127&v=4) @yezz123 ](https://github.com/yezz123) Reviews: 10 [ ![](https://avatars.githubusercontent.com/u/12229877?u=abc44dbce4bb3eca2def638bd0d4ab4cfef91b74&v=4) @Zac-HD ](https://github.com/Zac-HD) Reviews: 8 [ ![](https://avatars.githubusercontent.com/u/31134424?u=e8afd95a97b5556c467d1be27788950e67378ef1&v=4) @layday ](https://github.com/layday) Reviews: 7 [ ![](https://avatars.githubusercontent.com/u/89458301?u=75f53e971fcba3ff61836c389505a420bddd865c&v=4) @kc0506 ](https://github.com/kc0506) Reviews: 7 [ ![](https://avatars.githubusercontent.com/u/6400248?u=88cadd1dd6376e7000934e93712c5eb0138c1616&v=4) @pilosus ](https://github.com/pilosus) Reviews: 6 [ ![](https://avatars.githubusercontent.com/u/13108583?u=0d34d39c0628091596c9d5ebb4e802009e8c4aca&v=4) @Kilo59 ](https://github.com/Kilo59) Reviews: 6 [ ![](https://avatars.githubusercontent.com/u/10811879?v=4) @JeanArhancet ](https://github.com/JeanArhancet) Reviews: 6 [ ![](https://avatars.githubusercontent.com/u/36001403?u=51045ee35d6c53867638517e8dcf817927d77e85&v=4) @andresliszt ](https://github.com/andresliszt) Reviews: 6 [ ![](https://avatars.githubusercontent.com/u/1609449?u=922abf0524b47739b37095e553c99488814b05db&v=4) @tlambert03 ](https://github.com/tlambert03) Reviews: 5 [ ![](https://avatars.githubusercontent.com/u/537700?u=d6cc48076a656f94710d8e1266c92792b8c9d7c4&v=4) @christianbundy ](https://github.com/christianbundy) Reviews: 5 [ ![](https://avatars.githubusercontent.com/u/16438204?u=f700f440b89e715795c3bc091800b8d3f39c58d9&v=4) @nix010 ](https://github.com/nix010) Reviews: 5 [ ![](https://avatars.githubusercontent.com/u/44468031?u=1590b6d141e6cbcc1862a95959b9a134fdb1f108&v=4) @karta9821 ](https://github.com/karta9821) Reviews: 5 [ ![](https://avatars.githubusercontent.com/u/413772?v=4) @graingert ](https://github.com/graingert) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/1734544?v=4) @hmvp ](https://github.com/hmvp) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/5042313?u=8917c345dcb528733073ff1ce8a512e33f548512&v=4) @wozniakty ](https://github.com/wozniakty) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/6339494?u=893876f31ce65fa8ad8cfcc592392a77f0f8af38&v=4) @nuno-andre ](https://github.com/nuno-andre) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/2099618?u=a9899c1fea247d500e5368a1157a392bcd82e81d&v=4) @antdking ](https://github.com/antdking) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/662249?u=15313dec91bae789685e4abb3c2152251de41948&v=4) @dimaqq ](https://github.com/dimaqq) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/57028336?u=387c51980cb3734c41543ae2276a23736906bdb9&v=4) @DetachHead ](https://github.com/DetachHead) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/59469646?u=86d6a20768cc4cc65622eafd86672147321bd8f8&v=4) @JensHeinrich ](https://github.com/JensHeinrich) Reviews: 4 [ ![](https://avatars.githubusercontent.com/u/3709715?u=0745d1d2473894c33f3b35f0b965d71cc9aec553&v=4) @cclauss ](https://github.com/cclauss) Reviews: 4 ## About the data The data displayed above is calculated monthly via the Github GraphQL API (see [source code](https://github.com/pydantic/pydantic/tree/main/.github/actions/people/people.py), many thanks to [Sebastián Ramírez](https://github.com/tiangolo) for the script from which we based this logic). Depending on changing conditions, the thresholds for the different categories of contributors may change in the future.