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
Remove flattening of schemas before inlining and add schema walking caches #7473
Conversation
This brings |
Deploying with Cloudflare Pages
|
a8d8025
to
02bf0b7
Compare
397cfe6
to
062d460
Compare
8546841
to
0ebdd74
Compare
This required some changes to FastAPI's assertions about OpenAPI schemas, we should review them and confirm they're good before moving forward: https://github.com/tiangolo/fastapi/pull/10272/files |
ec9313b
to
52ead99
Compare
This comment was marked as outdated.
This comment was marked as outdated.
please review |
Ended up not, not sure what CI is running (locally I still get failures without these changes) but this PR is the same as |
This is now running in This is the current flamegraph: The vast majority of the time is spent in Rust (@davidhewitt could this be made faster by using pythonize to parse the schema or something?), and then comes generating the schema (I still think there's a lot of improvement that can and should be done here), the ref stuff and discriminated union stuff is now a distant third. |
], | ||
), | ||
cs.list_schema(cs.list_schema(cs.int_schema())), | ||
cs.list_schema(cs.list_schema(cs.int_schema(ref='int'), ref='list_of_ints')), |
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.
We're now preserving the ref
even when we inline.
IntModel = Model[int] | ||
|
||
assert IntModel.model_validate({'a': '1'}).a == 1 | ||
|
||
sig = signature(IntModel) |
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 really weird! If I don't call model_validate
the signature is different. It seems like some weirdness with generics. @dmontagu any thoughts?
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 think this PR is quite complex so I would like to move the removal of copying to another PR if possible. Some questions...
@@ -189,13 +204,13 @@ def _build_schema_type_to_method(self) -> dict[core_schema.CoreSchemaType, Recur | |||
return mapping | |||
|
|||
def walk(self, schema: core_schema.CoreSchema, f: Walk) -> core_schema.CoreSchema: | |||
return f(schema.copy(), self._walk) | |||
return f(schema, self._walk) |
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.
Does this have behavioural changes (e.g. walking schema now mutates inplace rather than copying)?
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.
Not really, I think we don’t mutate in place anyway
state = _DefinitionsState( | ||
definitions={}, | ||
ref_counts=defaultdict(int), | ||
involved_in_recursion={}, | ||
current_recursion_ref_count=defaultdict(int), | ||
) |
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.
What's the motivation for moving into a state? I guess it makes closures smaller, but causes lots of dictionary lookups?
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.
So that it can be easily stored in a single metadata key
if 'serialization' in s: | ||
return False |
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.
What's the motivation for this check? Seems somewhat surprising to me that serialization override prevents inlining.
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.
We use this to modify serialization on a type without globally modifying a type. That is, you can wrap a type with a serializer
Co-authored-by: David Hewitt <1939362+davidhewitt@users.noreply.github.com>
I’ll be splitting this PR up into multiple smaller PRs:
|
Needs pydantic/pydantic-core#965
Selected Reviewer: @dmontagu