HomeArchitecture x-rays

Python

The architecture of Pydantic, x-rayed

Pydantic's x-ray is really three codebases sharing a package: the v2 public API, a _internal/ engine room that translates your type hints into pydantic-core schemas, and an entire frozen copy of v1 kept for migration. At 104 components it's the largest Python repo in this gallery — and the most deliberate about which parts you're allowed to touch.

Auto-generated by archsteer xray v0.4.1 against pydantic/pydantic@c9688f4 (pydantic/) on 2026-07-05. Read-only static analysis — no code executed, no architecture rules declared. Structure, not judgment.
104
components
40
modules
907
internal edges
4
runtime deps

Module dependency graph

Top 14 modules by connectivity; an arrow means "imports from".

graph LR
    m0["__init__"]
    m1["_internal"]
    m2["_migration"]
    m3["config"]
    m4["dataclasses"]
    m5["deprecated"]
    m6["errors"]
    m7["fields"]
    m8["json_schema"]
    m9["main"]
    m10["type_adapter"]
    m11["types"]
    m12["typing"]
    m13["warnings"]
    m0 --> m2
    m0 --> m3
    m0 --> m4
    m0 --> m5
    m0 --> m6
    m0 --> m7
    m0 --> m8
    m0 --> m9
    m0 --> m10
    m0 --> m11
    m0 --> m12
    m0 --> m13
    m1 --> m0
    m1 --> m3
    m1 --> m4
    m1 --> m6
    m1 --> m7
    m1 --> m8
    m1 --> m9
    m1 --> m10
    m1 --> m11
    m1 --> m12
    m1 --> m13
    m2 --> m1
    m2 --> m6
    m2 --> m12
    m2 --> m13
    m3 --> m0
    m3 --> m1
    m3 --> m2
    m3 --> m6
    m3 --> m7
    m3 --> m12
    m3 --> m13
    m4 --> m1
    m4 --> m2
    m4 --> m3
    m4 --> m6
    m4 --> m7
    m4 --> m11
    m4 --> m12
    m4 --> m13
    m5 --> m0
    m5 --> m1
    m5 --> m4
    m5 --> m6
    m5 --> m8
    m5 --> m9
    m5 --> m10
    m5 --> m11
    m5 --> m12
    m5 --> m13
    m6 --> m1
    m6 --> m2
    m6 --> m12
    m7 --> m0
    m7 --> m1
    m7 --> m3
    m7 --> m4
    m7 --> m6
    m7 --> m8
    m7 --> m11
    m7 --> m12
    m7 --> m13
    m8 --> m0
    m8 --> m1
    m8 --> m3
    m8 --> m4
    m8 --> m6
    m8 --> m9
    m8 --> m10
    m8 --> m12
    m8 --> m13
    m9 --> m0
    m9 --> m1
    m9 --> m2
    m9 --> m3
    m9 --> m5
    m9 --> m6
    m9 --> m7
    m9 --> m8
    m9 --> m11
    m9 --> m12
    m9 --> m13
    m10 --> m0
    m10 --> m1
    m10 --> m3
    m10 --> m4
    m10 --> m6
    m10 --> m8
    m10 --> m9
    m10 --> m11
    m10 --> m12
    m11 --> m0
    m11 --> m1
    m11 --> m2
    m11 --> m4
    m11 --> m6
    m11 --> m8
    m11 --> m12
    m11 --> m13
    m12 --> m2

Components by module

_internal · 28v1 · 26deprecated · 8experimental · 4plugin · 3__init__ · 1_migration · 1alias_generators · 1aliases · 1annotated_handlers · 1class_validators · 1color · 1config · 1dataclasses · 1datetime_parse · 1decorator · 1

Most connected components

Top 20 of 104 by exported API surface and dependency count.

ComponentModuleKey exports
types.pytypesStrict, conint, Model, Model
v1/errors.pyv1cls_kwargs, PydanticErrorMixin, PydanticTypeError, PydanticValueError
_internal/_generate_schema.py_internalcheck_validator_fields_against_field_name, check_decorator_fields_exist, filter_field_decorator_info_by_field, apply_each_item_validators
v1/validators.pyv1str_validator, strict_str_validator, bytes_validator, strict_bytes_validator
fields.pyfields_FromFieldInfoInputs, _FieldInfoInputs, _FieldInfoAsDict, FieldInfo
networks.pynetworksUrlConstraints, _BaseUrl, _BaseMultiHostUrl, _build_type_adapter
config.pyconfigConfigDict, with_config, with_config, with_config
functional_validators.pyfunctional_validatorsAfterValidator, BeforeValidator, PlainValidator, WrapValidator
v1/schema.pyv1_apply_modify_schema, schema, model_schema, get_field_info_schema
_internal/_model_construction.py_internal_ModelNamespaceDict, NoInitField, ModelMetaclass, init_private_attributes
v1/utils.pyv1import_string, truncate, sequence_like, validate_field_name
json_schema.pyjson_schemaPydanticJsonSchemaWarning, _DefinitionsRemapping, GenerateJsonSchema, model_json_schema
v1/types.pyv1_registered, _registered, _registered, ConstrainedNumberMeta
_internal/_decorators.py_internalValidatorDecoratorInfo, FieldValidatorDecoratorInfo, RootValidatorDecoratorInfo, FieldSerializerDecoratorInfo
main.pymain_check_frozen, _model_field_setattr_handler, _private_setattr_handler, BaseModel
_internal/_fields.py_internalPydanticMetadata, PydanticExtraInfo, pydantic_general_metadata, _general_metadata_cls
_internal/_validators.py_internalsequence_validator, import_string, _import_string_logic, pattern_either_validator
_internal/_typing_extra.py_internalis_annotated, annotated_type, unpack_type, is_hashable
mypy.pymypyplugin, PydanticPlugin, PydanticPluginConfig, from_attributes_callback
_internal/_generics.py_internalLimitedDict, PydanticGenericMetadata, create_generic_submodel, _get_caller_frame_info

Declared runtime dependencies

annotated-typespydantic-coretyping-extensionstyping-inspection

What the structure teaches

The real engine isn't in this repo

Validation itself happens in pydantic-core, a separate Rust crate. What this package does is schema generation: _internal/_generate_schema.py — one of the largest components in the x-ray — walks your annotations, generics, and validators and compiles them into a core schema the Rust engine executes.

A whole major version lives in the package

The v1/ tree is a complete, importable copy of Pydantic 1.x — dozens of components kept so `from pydantic import v1` works during migrations. Shipping your previous architecture inside your current one is an expensive but honest migration strategy, and the x-ray shows exactly how much it costs.

_internal/ is a hard boundary, by convention

The private engine room is the biggest module in the graph, and public modules like types.py and main.py all point into it. The underscore prefix is the contract: everything in _internal/ can change in a minor release, so the supported surface stays small while the machinery stays free to evolve.

X-ray your own repo

This page is unedited archsteer xray output plus commentary. The same map of your codebase takes one command, runs locally, and never sends code anywhere: pip install archsteer && archsteer xray

FAQ

How is Pydantic v2 structured internally?

In three zones: a public API layer (BaseModel in main.py, types.py, fields.py), a private _internal/ package that compiles Python type annotations into core schemas, and pydantic-core — a separate Rust package that executes validation. Plus a bundled v1/ tree for backwards compatibility. The x-ray counts 104 components across 40 modules with just 4 runtime dependencies.

Why is Pydantic v2 so much faster than v1?

Because validation moved out of Python: the pydantic package compiles your model definitions into a schema once, and the Rust-based pydantic-core executes that schema for every validation call. The Python side you see in this x-ray is the compiler; the hot path lives in Rust.

How was this architecture map generated?

By running `archsteer xray` (an open-source, MIT-licensed CLI) against the pydantic/ package directory of the public GitHub repo — read-only static analysis, no code executed. Reproduce it with `pip install archsteer && archsteer xray`.

More x-rays