-
Notifications
You must be signed in to change notification settings - Fork 246
/
nested_schema.py
93 lines (79 loc) · 2.73 KB
/
nested_schema.py
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())