1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from pydantic_core import core_schema as cs
N = 5 # arbitrary number that takes ~0.05s per run
class MyModel:
# __slots__ is not required, but it avoids __pydantic_fields_set__ falling into __dict__
__slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__'
def schema_using_defs() -> cs.CoreSchema:
definitions: list[cs.CoreSchema] = [
{'type': 'int', 'ref': 'int'},
{
'type': 'model',
'cls': MyModel,
'schema': {
'type': 'model-fields',
'fields': {
str(c): {'type': 'model-field', 'schema': {'type': 'definition-ref', 'schema_ref': 'int'}}
for c in range(N)
},
},
'ref': f'model_{N}',
},
]
level = N
for level in reversed(range(N)):
definitions.append(
{
'type': 'model',
'cls': MyModel,
'schema': {
'type': 'model-fields',
'fields': {
str(c): {
'type': 'model-field',
'schema': {'type': 'definition-ref', 'schema_ref': f'model_{level+1}'},
}
for c in range(N)
},
},
'ref': f'model_{level}',
}
)
return {
'type': 'definitions',
'definitions': definitions,
'schema': {'type': 'definition-ref', 'schema_ref': 'model_0'},
}
def inlined_schema() -> cs.CoreSchema:
level = N
schema: cs.CoreSchema = {
'type': 'model',
'cls': MyModel,
'schema': {
'type': 'model-fields',
'fields': {str(c): {'type': 'model-field', 'schema': {'type': 'int'}} for c in range(N)},
},
'ref': f'model_{N}',
}
for level in reversed(range(N)):
schema = {
'type': 'model',
'cls': MyModel,
'schema': {
'type': 'model-fields',
'fields': {str(c): {'type': 'model-field', 'schema': schema} for c in range(N)},
},
'ref': f'model_{level}',
}
return schema
def input_data_valid(levels: int = N) -> Any:
data = {str(c): 1 for c in range(N)}
for _ in range(levels):
data = {str(c): data for c in range(N)}
return data
if __name__ == '__main__':
from pydantic_core import SchemaValidator
SchemaValidator(schema_using_defs()).validate_python(input_data_valid())
SchemaValidator(inlined_schema()).validate_python(input_data_valid())
|