6
6
from typing import Type
7
7
from typing import Union
8
8
9
+ from backports .cached_property import cached_property
9
10
from jsonschema .protocols import Validator
10
11
from openapi_schema_validator import OAS30Validator
11
12
41
42
from openapi_core .unmarshalling .schemas .util import build_format_checker
42
43
43
44
45
+ class SchemaValidatorsFactory :
46
+
47
+ CONTEXTS = {
48
+ UnmarshalContext .REQUEST : "write" ,
49
+ UnmarshalContext .RESPONSE : "read" ,
50
+ }
51
+
52
+ def __init__ (
53
+ self ,
54
+ schema_validator_class : Type [Validator ],
55
+ custom_formatters : Optional [CustomFormattersDict ] = None ,
56
+ context : Optional [UnmarshalContext ] = None ,
57
+ ):
58
+ self .schema_validator_class = schema_validator_class
59
+ if custom_formatters is None :
60
+ custom_formatters = {}
61
+ self .custom_formatters = custom_formatters
62
+ self .context = context
63
+
64
+ def create (self , schema : Spec ) -> Validator :
65
+ resolver = schema .accessor .resolver # type: ignore
66
+ custom_format_checks = {
67
+ name : formatter .validate
68
+ for name , formatter in self .custom_formatters .items ()
69
+ }
70
+ format_checker = build_format_checker (** custom_format_checks )
71
+ kwargs = {
72
+ "resolver" : resolver ,
73
+ "format_checker" : format_checker ,
74
+ }
75
+ if self .context is not None :
76
+ kwargs [self .CONTEXTS [self .context ]] = True
77
+ with schema .open () as schema_dict :
78
+ return self .schema_validator_class (schema_dict , ** kwargs )
79
+
80
+
44
81
class SchemaUnmarshallersFactory :
45
82
46
83
UNMARSHALLERS : Dict [str , Type [BaseSchemaUnmarshaller ]] = {
@@ -60,11 +97,6 @@ class SchemaUnmarshallersFactory:
60
97
"any" : AnyUnmarshaller ,
61
98
}
62
99
63
- CONTEXT_VALIDATION = {
64
- UnmarshalContext .REQUEST : "write" ,
65
- UnmarshalContext .RESPONSE : "read" ,
66
- }
67
-
68
100
def __init__ (
69
101
self ,
70
102
schema_validator_class : Type [Validator ],
@@ -77,6 +109,14 @@ def __init__(
77
109
self .custom_formatters = custom_formatters
78
110
self .context = context
79
111
112
+ @cached_property
113
+ def validators_factory (self ) -> SchemaValidatorsFactory :
114
+ return SchemaValidatorsFactory (
115
+ self .schema_validator_class ,
116
+ self .custom_formatters ,
117
+ self .context ,
118
+ )
119
+
80
120
def create (
81
121
self , schema : Spec , type_override : Optional [str ] = None
82
122
) -> BaseSchemaUnmarshaller :
@@ -87,7 +127,7 @@ def create(
87
127
if schema .getkey ("deprecated" , False ):
88
128
warnings .warn ("The schema is deprecated" , DeprecationWarning )
89
129
90
- validator = self .get_validator (schema )
130
+ validator = self .validators_factory . create (schema )
91
131
92
132
schema_format = schema .getkey ("format" )
93
133
formatter = self .custom_formatters .get (schema_format )
@@ -97,29 +137,29 @@ def create(
97
137
schema_type , str
98
138
):
99
139
return MultiTypeUnmarshaller (
100
- schema , validator , formatter , self , context = self .context
140
+ schema ,
141
+ validator ,
142
+ formatter ,
143
+ self .validators_factory ,
144
+ self ,
145
+ context = self .context ,
101
146
)
102
147
if schema_type in self .COMPLEX_UNMARSHALLERS :
103
148
complex_klass = self .COMPLEX_UNMARSHALLERS [schema_type ]
104
149
return complex_klass (
105
- schema , validator , formatter , self , context = self .context
150
+ schema ,
151
+ validator ,
152
+ formatter ,
153
+ self .validators_factory ,
154
+ self ,
155
+ context = self .context ,
106
156
)
107
157
108
158
klass = self .UNMARSHALLERS [schema_type ]
109
- return klass (schema , validator , formatter )
110
-
111
- def get_validator (self , schema : Spec ) -> Validator :
112
- resolver = schema .accessor .resolver # type: ignore
113
- custom_format_checks = {
114
- name : formatter .validate
115
- for name , formatter in self .custom_formatters .items ()
116
- }
117
- format_checker = build_format_checker (** custom_format_checks )
118
- kwargs = {
119
- "resolver" : resolver ,
120
- "format_checker" : format_checker ,
121
- }
122
- if self .context is not None :
123
- kwargs [self .CONTEXT_VALIDATION [self .context ]] = True
124
- with schema .open () as schema_dict :
125
- return self .schema_validator_class (schema_dict , ** kwargs )
159
+ return klass (
160
+ schema ,
161
+ validator ,
162
+ formatter ,
163
+ self .validators_factory ,
164
+ self ,
165
+ )
0 commit comments