-
Notifications
You must be signed in to change notification settings - Fork 243
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
skip recursion checks for non-recursive definitions #989
Conversation
state.recursion_guard.decr_depth(); | ||
output | ||
let definition = state.definitions.get(self.validator_id).unwrap(); | ||
if definition.recursive { |
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.
If I comment out this block I get a segfault in the test suite which gives me confidence the recursion detection is working correctly.
let value_id = extra.rec_guard.add(value, self.serializer_id).map_err(py_err_se_err)?; | ||
let comb_serializer = extra.definitions.get(self.serializer_id).unwrap(); | ||
let r = comb_serializer.serde_serialize(value, serializer, include, exclude, extra); | ||
let definition = extra.definitions.get(self.serializer_id).unwrap(); | ||
let r = definition | ||
.value | ||
.serde_serialize(value, serializer, include, exclude, extra); | ||
extra.rec_guard.pop(value_id, self.serializer_id); |
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 wonder if we can / should skip recursion on serializing too?
let value_id = extra.rec_guard.add(value, self.serializer_id)?; | ||
let comb_serializer = extra.definitions.get(self.serializer_id).unwrap(); | ||
let r = comb_serializer.to_python(value, include, exclude, extra); | ||
let definition = extra.definitions.get(self.serializer_id).unwrap(); | ||
let r = definition.value.to_python(value, include, exclude, extra); | ||
extra.rec_guard.pop(value_id, self.serializer_id); |
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.
Similar question about serializer recursion.
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #989 +/- ##
==========================================
- Coverage 92.99% 92.98% -0.01%
==========================================
Files 106 106
Lines 15844 15881 +37
Branches 35 35
==========================================
+ Hits 14734 14767 +33
- Misses 1103 1107 +4
Partials 7 7
Continue to review full report in Codecov by Sentry.
|
CodSpeed Performance ReportMerging #989 will improve performances by 52.98%Comparing Summary
Benchmarks breakdown
|
This unfortunately doesn't work: from typing import Optional
from pydantic import BaseModel
from pydantic_core import CoreSchema, SchemaValidator
class ModelA(BaseModel):
b: 'Optional[ModelB]'
class ModelB(BaseModel):
a: Optional[ModelA]
cyclic_data = {}
cyclic_data['a'] = {'b': cyclic_data}
schema: CoreSchema = {
'type': 'definitions',
'schema': {
'type': 'definition-ref',
'schema_ref': '__main__.ModelB:5168279104',
},
'definitions': [
{
'type': 'model',
'cls': ModelA,
'schema': {
'type': 'model-fields',
'fields': {
'b': {
'type': 'model-field',
'schema': {
'type': 'nullable',
'schema': {
'type': 'definition-ref',
'schema_ref': '__main__.ModelB:5168279104'
}
}
}
},
'model_name': 'ModelA'
},
'ref': '__main__.ModelA:5168251248'
},
{
'type': 'model',
'cls': ModelB,
'schema': {
'type': 'model-fields',
'fields': {
'a': {
'type': 'model-field',
'schema': {
'type': 'nullable',
'schema': {
'type': 'definition-ref',
'schema_ref': '__main__.ModelA:5168251248'
}
}
}
},
'model_name': 'ModelB'
},
'ref': '__main__.ModelB:5168279104'
}
]
}
validator = SchemaValidator(schema)
validator.validate_python(cyclic_data) # segfault |
Right yes that's a more complex case; I think we could analyze all the dependencies of definitions in a similar fashion to how this detects recursion, to detect cycles. Will probably follow up next week. |
That's already what we're doing in Python. If we have to do that here there's not much of a win. |
Change Summary
Detects recursion at the
pydantic-core
level, so thatpydantic
doesn't have to, enabling low-level performance wins without needing to inline core schemas.Related issue number
Related to pydantic/pydantic#7611
Checklist
pydantic-core
(except for expected changes)