new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Pydantic · API reference · all subjects

basemodel fundamentals

33 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Type coercion enabled by default outside strict mode

Unless using strict mode, Pydantic applies type coercion in most cases. For instance, a field typed as int accepts strings like '123'. This also applies to collection types: list[str] also accepts tuples, sets, and other sequence types.

Avoid unions for type coercion goals

Avoid using unions such as int | str if the goal is to coerce str to int via a validator. Unions require checking for each type before using the field, making the code cumbersome.

Avoid forward annotations and string literals for types

Avoid using from __future__ import annotations if possible, as it stringifies all annotations and causes challenges for Pydantic to evaluate them. Only use explicit string quotes for self-referential types that aren't yet defined. In Python >= 3.14, annotation evaluation is deferred, so string annotations should not be used at all.

Pydantic is for external untrusted data validation

Pydantic is dataclasses with runtime validation, leveraging type hints. It is primarily useful when dealing with external untrusted data, such as when defining an HTTP API. It is generally not recommended to use Pydantic to define classes that are instantiated within user code, as this loses flexibility and makes it harder to perform post-init changes. Vanilla classes or standard library dataclasses are usually better for internal code.

Use explicit type aliases for recursive types

For recursive type aliases, use Python 3.12+ explicit type alias syntax (type JsonValue = ...) or typing_extensions.TypeAliasType instead of string-quoted TypeAlias, as Pydantic cannot evaluate quoted recursive aliases.

Model subclass inheritance serialization pitfall

When using model subclasses without discriminators, Pydantic serializes according to the declared type annotation, not the runtime value. For example, if Main has model: Base and model is assigned a Sub1 instance, model_dump() will serialize only Base fields, missing Sub1-specific fields. Validation also uses the declared type, not the runtime type.

Use discriminated unions for polymorphic models

For polymorphic model hierarchies, use discriminated unions with Annotated[Sub1 | Sub2, Field(discriminator='type')] where each subclass has a Literal type field that distinguishes them. This ensures correct serialization and validation behavior for subclass instances.

Use generics for polymorphic models alternative

An alternative to discriminated unions for polymorphic model hierarchies is using generics: class Main[BaseT: Base](BaseModel): model: BaseT. This allows proper validation and serialization of subclass instances.

Polymorphic serialization for subclass fields

In Pydantic >= 2.13, polymorphic serialization can be used to serialize subclass instances according to their runtime type. In Pydantic < 2.13, serializing-as-any can be used as a last resort to achieve similar behavior.

Basic Pydantic model example with Field and type hints

Example showing basic Pydantic model usage: from datetime import date; from pydantic import BaseModel, Field; class Person(BaseModel): name: str; age: int = Field(description='The age of the person'); birthdate: date | None = None; p = Person(name='John', age=20, birthdate='1970-01-01'). This demonstrates field validation, type hints, Field metadata, and automatic type coercion of date strings.

Discriminated union example for polymorphic models

Example using discriminated unions: class Base(BaseModel): base_field: int; class Sub1(Base): type: Literal['sub1']; sub1_field: str; class Sub2(Base): type: Literal['sub2']; sub2_field: bool; Subs = Annotated[Sub1 | Sub2, Field(discriminator='type')]; class Main(BaseModel): model: Subs. This ensures correct serialization and validation of subclass instances.

Generic models for polymorphic inheritance example

Example using generics for polymorphic models: class Base(BaseModel): base_field: int; class Sub1(Base): sub1_field: str; class Main[BaseT: Base](BaseModel): model: BaseT; m = Main[Sub1](model={'base_field': 1, 'sub1_field': 'test'}). This ensures correct validation and serialization.

BaseModel field validation with custom validator

A BaseModel field can have both constraints (like gt=0) and custom validation logic via field_validator. The example shows a country field validated with both existence checks and a custom validator that rejects invalid country values based on context.

Basic BaseModel example with field definitions

Example showing BaseModel usage: from pydantic import BaseModel. Fields are declared with type hints (e.g., id: int, name: str = 'John Doe', signup_ts: Optional[datetime] = None, friends: list[int] = []). When instantiating with external_data dict containing type-incompatible values, Pydantic automatically coerces them to match the declared types.

BaseModel basic structure and validation

BaseModel is defined by inheriting from pydantic.BaseModel. Fields are declared with type hints and optional default values. Pydantic validates input data against these type hints, automatically converting types when possible (e.g., string '123' to int 123, string '2017-06-01 12:22' to datetime object).

Pydantic version 2 is a ground-up rewrite with breaking changes

Pydantic V2 is a ground-up rewrite that offers many new features, performance improvements, and some breaking changes compared to Pydantic V1. Pydantic V2 ships with the latest version of Pydantic V1 built in, allowing incremental upgrades via 'from pydantic import v1 as pydantic_v1'.

Pydantic requires Python 3.10 or later

Pydantic requires Python 3.10 or later and uses pure, canonical Python type hints for data validation.

model_fields class attribute

The model_fields class attribute is a mapping of field names to FieldInfo instances and can only be accessed from the class object, not instances (as of v2.11). For Pydantic dataclasses, use the __pydantic_fields__ attribute instead. Each FieldInfo instance contains properties like annotation, alias, and metadata.

Forward annotations with from __future__ import annotations

Pydantic supports forward annotations by using the `from __future__ import annotations` statement introduced in PEP 563. This allows type annotations to be treated as strings, enabling the use of types before they are defined in the code.

Forward annotations can be wrapped in quotes

Type annotations can be wrapped in quotes to create forward references. This is an alternative to using `from __future__ import annotations` and allows referencing types that are not yet defined.

Self-referencing recursive models

Pydantic supports models with self-referencing fields. These annotations are resolved during model creation. Within a model, you can either add `from __future__ import annotations` import or wrap the annotation in a string like 'Foo | None' to reference the model itself.

Example: self-referencing model with forward annotation

```python from pydantic import BaseModel class Foo(BaseModel): a: int = 123 sibling: 'Foo | None' = None print(Foo()) #> a=123 sibling=None print(Foo(sibling={'a': '321'})) #> a=123 sibling=Foo(a=321, sibling=None) ``` This example demonstrates a self-referencing model where the type annotation is wrapped in a string.

Example: forward annotations with from __future__

```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 ``` This example demonstrates that with `from __future__ import annotations`, forward annotations are automatically supported.

ClassVar exclusion from model fields

Attributes annotated with ClassVar are properly treated by Pydantic as class variables and will not become fields on model instances. They are excluded from validation and serialization.

Validation term definition in Pydantic

In Pydantic, '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. ValidationError is raised when data cannot be successfully parsed into a model instance. This differs from the strict dictionary definition of validation as checking existing data.

Attribute copying during validation

Arguments passed to the model constructor are copied during validation to perform validation and coercion without mutating the original input data. Exception: Pydantic does not copy models in some situations; you can override this with model_config['revalidate_instances'] = 'always'.

BaseModel field ordering preservation

Field order is preserved in the model JSON Schema, in validation errors, and when serializing data. The model_fields attribute preserves the order of fields as defined in the model class.

Warning on naming collisions in field definitions

When defining models, avoid naming collisions between field names and type annotations. For example, 'int: int | None = None' will not behave as expected due to how Python evaluates annotated assignment statements and will result in a validation error.

BaseModel default field mutability

By default, models are mutable and field values can be changed through attribute assignment, unless configured otherwise with frozen=True.

BaseModel model_config attribute

model_config is a class attribute where ConfigDict configuration values are set to customize the model's behavior. It accepts various configuration values described in the configuration documentation.

BaseModel basic definition

BaseModel is the primary way to define schemas in Pydantic. Models are classes that inherit from BaseModel and define fields as annotated attributes. After parsing and validation, Pydantic guarantees that the fields of the model instance will conform to the field types defined on the model.

Data type coercion and conversion

Pydantic may cast input data to force it to conform to model field types, and this may result in a loss of information. For example, a float input of 3.000 becomes int 3, a string '2.72' becomes float 2.72. For collections, concrete types like list[int] are recommended over abstract types like Sequence, as Pydantic will convert tuple input to list.

Nested models support

Pydantic supports complex hierarchical data structures by using models themselves as types in annotations. Self-referencing models are supported using forward annotations. When creating models without validation using model_construct(), nested dictionaries must be manually converted to model instances.

Give your agent this brain