-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Add initial architeture documentation #10077
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Deploying pydantic-docs with
|
Latest commit: |
b4e61ee
|
Status: | ✅ Deploy successful! |
Preview URL: | https://ee7a3294.pydantic-docs.pages.dev |
Branch Preview URL: | https://architecture-docs.pydantic-docs.pages.dev |
CodSpeed Performance ReportMerging #10077 will not alter performanceComparing Summary
|
174f6d6
to
6e9048a
Compare
The JSON Schema generation of a model is handled by the [`GenerateJsonSchema`][pydantic.json_schema.GenerateJsonSchema] class. | ||
The [`generate`][pydantic.json_schema.GenerateJsonSchema.generate] method is the main entry point and is given the core schema of that model. | ||
|
||
### Customizing the core schema and JSON schema |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section goes a bit too much into some details imo. The goal was to document that __get_pydantic_core_schema__
is a general pattern used throughout the code base, but it doesn't necessarily apply to the Annotated
pattern.
the `source` will be the type being annotated. When [defining a custom type](concepts/types.md#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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section should definitely be expanded to document how this validation and serialization is performed (and not only state that it happens in pydantic-core
). But I'll need to dive deeper in the Rust code base first.
6e9048a
to
a0e58cd
Compare
a0e58cd
to
d96c8ec
Compare
Having a schema could be nice, probably once the section about |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonderful start here. I think this will be a super helpful tool for contributors looking to get some more context about internal patterns, as well as advanced users looking to customize schemas.
I think there's a bit of restructuring to do to make this a bit more intuitive, and I've left some line by line comments. In general, I think that you have a good pattern going regarding the mixing of high level concept explanation mixed with examples with context.
docs/architecture.md
Outdated
@@ -0,0 +1,185 @@ | |||
Starting with Pydantic V2, part of the codebase is written in Rust in a separate package called `pydantic-core`. | |||
This architecture documentation will partly focus on how the two `pydantic` and `pydantic-core` packages interacts together. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something that touches on a few of the other things covered, like:
This architecture documentation will first cover how pydantic
and pydantic-core
interact, then will delve into architecture specifics for various patterns, such as model definition, validation, and serialization.
@@ -0,0 +1,185 @@ | |||
Starting with Pydantic V2, part of the codebase is written in Rust in a separate package called `pydantic-core`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a bit more of a "why" here - primarily, performance of course.
docs/architecture.md
Outdated
Once the model class is successfully built, a core schema for the model will be constructed | ||
and set as the [`__pydantic_core_schema__`][pydantic.main.BaseModel.__pydantic_core_schema__] | ||
attribute (this is done by the `GenerateSchema` class). A core schema is a structured Python | ||
dictionary (represented using [`TypedDict`][typing.TypedDict] definitions) representing 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`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great start here. Maybe we could title this subsection "pydantic-core
schema or something similar to give a bit more context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I restructured this section to first talk about what exactly is a core schema, and then give the example of our model class core schema and the corresponding __pydantic_core_schema__
(which is specific to models, not necessarily core schemas).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And also edited the title of the section.
docs/architecture.md
Outdated
!!! 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` is private and not documented. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately (imo) we do sort of document it, though we've sort of shied away from further documentation bc we want to reserve some rights to modify how we generate core schema. So we might want to reword here.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gah, an interesting pattern. Not my favorite, but definitely helpful (and efficient in a lot of contexts) 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well in this case from what I saw the return_schema
is also used by pydantic-core
but I'm not sure in which context. But I felt having this return_schema
here made a nice transition to JSON Schema generation. After all, GenerateJsonSchema.generate
is the main entry point and is given the core schema so it makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial review of your changes looks good. I'm going to do another pass tomorrow morning with a fresh mind.
@@ -1,5 +1,10 @@ | |||
Starting with Pydantic V2, part of the codebase is written in Rust in a separate package called `pydantic-core`. | |||
This architecture documentation will partly focus on how the two `pydantic` and `pydantic-core` packages interacts together. | |||
This was done partly in order to improve validation and serialization performance (with the cost of limited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm not sure if we want to advertise this as a cost
which has a pretty negative connotation, but I get your point.
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). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 🚀 !
``` | ||
|
||
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, meant to just comment (not approve, yet)
Other than linting issues, I'm happy to merge this. We've marked the page as a draft, and I'd rather go ahead with a first draft to make things easier for contributors 🚀. Great work @Viicos. I'll take a pass over this before we release v2.9 to further develop the docs. |
Fixes #9627
Change Summary
Related issue number
Checklist