Skip to content

Commit 1f8a079

Browse files
committed
unmarshaller finders refactor
1 parent bc78dee commit 1f8a079

File tree

10 files changed

+277
-167
lines changed

10 files changed

+277
-167
lines changed

openapi_core/schema/schemas.py

-8
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,4 @@
77
def get_all_properties(schema: Spec) -> Dict[str, Any]:
88
properties = schema.get("properties", {})
99
properties_dict = dict(list(properties.items()))
10-
11-
if "allOf" not in schema:
12-
return properties_dict
13-
14-
for subschema in schema / "allOf":
15-
subschema_props = get_all_properties(subschema)
16-
properties_dict.update(subschema_props)
17-
1810
return properties_dict

openapi_core/unmarshalling/schemas/factories.py

+65-25
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from typing import Type
77
from typing import Union
88

9+
from backports.cached_property import cached_property
910
from jsonschema.protocols import Validator
1011
from openapi_schema_validator import OAS30Validator
1112

@@ -41,6 +42,42 @@
4142
from 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+
4481
class 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

Comments
 (0)