3.3 KiB
Pydantic source notes
Repo: pydantic/pydantic
Local checkout: /home/ubuntu/repos/rodin-sources/pydantic
Why this repo is useful
- Pydantic is a strong source for boundary-object patterns: validating incoming data, preserving typed state, and serializing back out explicitly.
- It is also useful for validation-hook design because the docs distinguish several validator phases and call out their tradeoffs clearly.
Models are explicit validation + serialization boundaries
Repeated evidence
pydantic/main.py:119-145definesBaseModelas the central abstraction and documents that models carry schema, field metadata, and decorator metadata.pydantic/main.py:201-205explicitly exposes model-level serializer and validator machinery as core parts of the abstraction.docs/index.md:68-82shows external data entering through model construction.docs/index.md:82-89immediately turns the model back into a plain data structure withmodel_dump().docs/index.md:109-152shows invalid boundary data raisingValidationErrorwith structured per-field errors instead of silently degrading.
Why it matters
Repeated signal: Pydantic models are meant to sit at I/O boundaries. Input is validated/coerced at construction time; output is serialized through an explicit dump step.
Caveat / counterexample
The strong pattern is not "models are your whole domain model." The evidence here is boundary-oriented: construct from external data, then call model_dump() when leaving the boundary again.
Validators are narrow and phase-aware
Repeated evidence
docs/concepts/validators.md:91-114shows anafterfield validator that checks one parsed field and must return the validated value.docs/concepts/validators.md:160-167explains thatbeforevalidators run prior to internal parsing and therefore receive raw input.docs/concepts/validators.md:220-252demonstrates abeforevalidator that reshapes raw input and then lets normal item validation continue.
Why it matters
Repeated signal: the best validator hooks are small in scope and explicit about phase:
beforefor raw-input normalizationafterfor post-parse invariants
This prevents validation logic from becoming an opaque second parser.
Validator mode choice has real behavioral consequences
Repeated evidence
docs/concepts/validators.md:160-164warns thatbeforevalidators should avoid careless mutation when raising later, especially with unions.docs/concepts/validators.md:254-255states thatplainvalidators terminate validation immediately.docs/concepts/validators.md:273-283shows the consequence directly: aPlainValidatorcan return'invalid'for a field annotated asint, and Pydantic will accept it.
Why it matters
Repeated signal: validator mode is not just an implementation detail. It changes whether core type validation still runs.
Caveat / counterexample
This is the sharpest anti-pattern in the repo: plain validators are powerful, but they can bypass the type guarantee a reader expects from the annotation. Use them only when terminating validation is the actual goal.
Pattern candidates supported by this repo
- use typed models at I/O boundaries
- serialize explicitly with
model_dump() - keep validators field-scoped and phase-aware
- treat
plainvalidators as an escape hatch, not the default