66from typing import Type
77from typing import Union
88
9+ from backports .cached_property import cached_property
910from jsonschema .protocols import Validator
1011from openapi_schema_validator import OAS30Validator
1112
4142from openapi_core .unmarshalling .schemas .util import build_format_checker
4243
4344
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+
4481class SchemaUnmarshallersFactory :
4582
4683 UNMARSHALLERS : Dict [str , Type [BaseSchemaUnmarshaller ]] = {
@@ -60,11 +97,6 @@ class SchemaUnmarshallersFactory:
6097 "any" : AnyUnmarshaller ,
6198 }
6299
63- CONTEXT_VALIDATION = {
64- UnmarshalContext .REQUEST : "write" ,
65- UnmarshalContext .RESPONSE : "read" ,
66- }
67-
68100 def __init__ (
69101 self ,
70102 schema_validator_class : Type [Validator ],
@@ -77,6 +109,14 @@ def __init__(
77109 self .custom_formatters = custom_formatters
78110 self .context = context
79111
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+
80120 def create (
81121 self , schema : Spec , type_override : Optional [str ] = None
82122 ) -> BaseSchemaUnmarshaller :
@@ -87,7 +127,7 @@ def create(
87127 if schema .getkey ("deprecated" , False ):
88128 warnings .warn ("The schema is deprecated" , DeprecationWarning )
89129
90- validator = self .get_validator (schema )
130+ validator = self .validators_factory . create (schema )
91131
92132 schema_format = schema .getkey ("format" )
93133 formatter = self .custom_formatters .get (schema_format )
@@ -97,29 +137,29 @@ def create(
97137 schema_type , str
98138 ):
99139 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 ,
101146 )
102147 if schema_type in self .COMPLEX_UNMARSHALLERS :
103148 complex_klass = self .COMPLEX_UNMARSHALLERS [schema_type ]
104149 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 ,
106156 )
107157
108158 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