Skip to content

Commit e04087d

Browse files
committed
Updating unmarshal and validation methods' signatures to propagate the context until reaching the properties.
1 parent f97307d commit e04087d

File tree

3 files changed

+62
-34
lines changed

3 files changed

+62
-34
lines changed

openapi_core/schema/media_types/models.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ def deserialize(self, value):
3232
deserializer = self.get_dererializer()
3333
return deserializer(value)
3434

35-
def unmarshal(self, value, custom_formatters=None):
35+
@requires_context
36+
def unmarshal(self, value, custom_formatters=None, context=None):
3637
if not self.schema:
3738
return value
3839

@@ -42,12 +43,15 @@ def unmarshal(self, value, custom_formatters=None):
4243
raise InvalidMediaTypeValue(exc)
4344

4445
try:
45-
unmarshalled = self.schema.unmarshal(deserialized, custom_formatters=custom_formatters)
46+
unmarshalled = self.schema.unmarshal(
47+
deserialized, custom_formatters=custom_formatters,
48+
context=context)
4649
except OpenAPISchemaError as exc:
4750
raise InvalidMediaTypeValue(exc)
4851

4952
try:
5053
return self.schema.validate(
51-
unmarshalled, custom_formatters=custom_formatters)
54+
unmarshalled, custom_formatters=custom_formatters,
55+
context=context)
5256
except OpenAPISchemaError as exc:
5357
raise InvalidMediaTypeValue(exc)

openapi_core/schema/parameters/models.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
MissingRequiredParameter, MissingParameter, InvalidParameterValue,
1010
EmptyParameterValue,
1111
)
12-
from openapi_core.schema.schemas.enums import SchemaType
12+
from openapi_core.schema.schemas.enums import SchemaType, UnmarshalContext
1313
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
1414

1515
log = logging.getLogger(__name__)
1616

1717

18+
_CONTEXT = UnmarshalContext.REQUEST
19+
20+
1821
class Parameter(object):
1922
"""Represents an OpenAPI operation Parameter."""
2023

@@ -112,13 +115,14 @@ def unmarshal(self, value, custom_formatters=None):
112115
unmarshalled = self.schema.unmarshal(
113116
deserialized,
114117
custom_formatters=custom_formatters,
115-
strict=False,
118+
strict=False, context=_CONTEXT
116119
)
117120
except OpenAPISchemaError as exc:
118121
raise InvalidParameterValue(self.name, exc)
119122

120123
try:
121124
return self.schema.validate(
122-
unmarshalled, custom_formatters=custom_formatters)
125+
unmarshalled, custom_formatters=custom_formatters,
126+
context=_CONTEXT)
123127
except OpenAPISchemaError as exc:
124128
raise InvalidParameterValue(self.name, exc)

openapi_core/schema/schemas/models.py

Lines changed: 48 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@
1111
from six import iteritems, integer_types, binary_type, text_type
1212

1313
from openapi_core.extensions.models.factories import ModelFactory
14-
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
14+
from openapi_core.schema.schemas.enums import (
15+
SchemaFormat, SchemaType, UnmarshalContext
16+
)
1517
from openapi_core.schema.schemas.exceptions import (
1618
InvalidSchemaValue, UndefinedSchemaProperty, MissingSchemaProperty,
1719
OpenAPISchemaError, NoOneOfSchema, MultipleOneOfSchema, NoValidSchema,
1820
UndefinedItemsSchema, InvalidCustomFormatSchemaValue, InvalidSchemaProperty,
1921
UnmarshallerStrictTypeError,
2022
)
2123
from openapi_core.schema.schemas.util import (
22-
forcebool, format_date, format_datetime, format_byte, format_uuid,
24+
requires_context, format_date, format_datetime, format_byte, format_uuid,
2325
format_number,
2426
)
2527
from openapi_core.schema.schemas.validators import (
@@ -161,7 +163,8 @@ def get_all_required_properties_names(self):
161163

162164
return set(required)
163165

164-
def get_cast_mapping(self, custom_formatters=None, strict=True):
166+
def get_cast_mapping(self, custom_formatters=None, strict=True,
167+
context=None):
165168
primitive_unmarshallers = self.get_primitive_unmarshallers(
166169
custom_formatters=custom_formatters)
167170

@@ -171,7 +174,7 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
171174
)
172175

173176
pass_defaults = lambda f: functools.partial(
174-
f, custom_formatters=custom_formatters, strict=strict)
177+
f, custom_formatters=custom_formatters, strict=strict, context=context)
175178
mapping = self.DEFAULT_CAST_CALLABLE_GETTER.copy()
176179
mapping.update(primitive_unmarshallers_partial)
177180
mapping.update({
@@ -189,7 +192,8 @@ def are_additional_properties_allowed(self, one_of_schema=None):
189192
one_of_schema.additional_properties is not False)
190193
)
191194

192-
def cast(self, value, custom_formatters=None, strict=True):
195+
@requires_context
196+
def cast(self, value, custom_formatters=None, strict=True, context=None):
193197
"""Cast value to schema type"""
194198
if value is None:
195199
if not self.nullable:
@@ -201,7 +205,7 @@ def cast(self, value, custom_formatters=None, strict=True):
201205
"Value {value} not in enum choices: {type}", value, self.enum)
202206

203207
cast_mapping = self.get_cast_mapping(
204-
custom_formatters=custom_formatters, strict=strict)
208+
custom_formatters=custom_formatters, strict=strict, context=context)
205209

206210
if self.type is not SchemaType.STRING and value == '':
207211
return None
@@ -216,12 +220,14 @@ def cast(self, value, custom_formatters=None, strict=True):
216220
raise InvalidSchemaValue(
217221
"Failed to cast value {value} to type {type}", value, self.type)
218222

219-
def unmarshal(self, value, custom_formatters=None, strict=True):
223+
@requires_context
224+
def unmarshal(self, value, custom_formatters=None, strict=True,
225+
context=None):
220226
"""Unmarshal parameter from the value."""
221227
if self.deprecated:
222228
warnings.warn("The schema is deprecated", DeprecationWarning)
223229

224-
casted = self.cast(value, custom_formatters=custom_formatters, strict=strict)
230+
casted = self.cast(value, custom_formatters=custom_formatters, strict=strict, context=context)
225231

226232
if casted is None and not self.required:
227233
return None
@@ -248,17 +254,20 @@ def get_primitive_unmarshallers(self, **options):
248254

249255
return unmarshallers
250256

251-
def _unmarshal_any(self, value, custom_formatters=None, strict=True):
257+
@requires_context
258+
def _unmarshal_any(self, value, custom_formatters=None, strict=True,
259+
context=None):
252260
types_resolve_order = [
253261
SchemaType.OBJECT, SchemaType.ARRAY, SchemaType.BOOLEAN,
254262
SchemaType.INTEGER, SchemaType.NUMBER, SchemaType.STRING,
255263
]
256-
cast_mapping = self.get_cast_mapping()
264+
cast_mapping = self.get_cast_mapping(custom_formatters, strict, context)
257265
if self.one_of:
258266
result = None
259267
for subschema in self.one_of:
260268
try:
261-
casted = subschema.cast(value, custom_formatters)
269+
casted = subschema.cast(value, custom_formatters,
270+
strict, context)
262271
except (OpenAPISchemaError, TypeError, ValueError):
263272
continue
264273
else:
@@ -283,7 +292,9 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
283292

284293
raise NoValidSchema(value)
285294

286-
def _unmarshal_collection(self, value, custom_formatters=None, strict=True):
295+
@requires_context
296+
def _unmarshal_collection(self, value, custom_formatters=None, strict=True,
297+
context=None):
287298
if not isinstance(value, (list, tuple)):
288299
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
289300

@@ -292,12 +303,13 @@ def _unmarshal_collection(self, value, custom_formatters=None, strict=True):
292303

293304
f = functools.partial(
294305
self.items.unmarshal,
295-
custom_formatters=custom_formatters, strict=strict,
306+
custom_formatters=custom_formatters, strict=strict, context=context
296307
)
297308
return list(map(f, value))
298309

310+
@requires_context
299311
def _unmarshal_object(self, value, model_factory=None,
300-
custom_formatters=None, strict=True):
312+
custom_formatters=None, strict=True, context=None):
301313
if not isinstance(value, (dict, )):
302314
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
303315

@@ -308,8 +320,9 @@ def _unmarshal_object(self, value, model_factory=None,
308320
for one_of_schema in self.one_of:
309321
try:
310322
found_props = self._unmarshal_properties(
311-
value, one_of_schema, custom_formatters=custom_formatters)
312-
except OpenAPISchemaError:
323+
value, one_of_schema,
324+
custom_formatters=custom_formatters, context=context)
325+
except OpenAPISchemaError as ex:
313326
pass
314327
else:
315328
if properties is not None:
@@ -321,7 +334,7 @@ def _unmarshal_object(self, value, model_factory=None,
321334

322335
else:
323336
properties = self._unmarshal_properties(
324-
value, custom_formatters=custom_formatters)
337+
value, custom_formatters=custom_formatters, context=context)
325338

326339
return model_factory.create(properties, name=self.model)
327340

@@ -407,7 +420,8 @@ def default(x, **kw):
407420

408421
return defaultdict(lambda: default, mapping)
409422

410-
def validate(self, value, custom_formatters=None):
423+
@requires_context
424+
def validate(self, value, custom_formatters=None, context=None):
411425
if value is None:
412426
if not self.nullable:
413427
raise InvalidSchemaValue("Null value for non-nullable schema of type {type}", value, self.type)
@@ -423,11 +437,13 @@ def validate(self, value, custom_formatters=None):
423437
# structure validation
424438
validator_mapping = self.get_validator_mapping()
425439
validator_callable = validator_mapping[self.type]
426-
validator_callable(value, custom_formatters=custom_formatters)
440+
validator_callable(value, custom_formatters=custom_formatters,
441+
context=context)
427442

428443
return value
429444

430-
def _validate_collection(self, value, custom_formatters=None):
445+
@requires_context
446+
def _validate_collection(self, value, custom_formatters=None, context=None):
431447
if self.items is None:
432448
raise UndefinedItemsSchema(self.type)
433449

@@ -455,10 +471,11 @@ def _validate_collection(self, value, custom_formatters=None):
455471
raise OpenAPISchemaError("Value may not contain duplicate items")
456472

457473
f = functools.partial(self.items.validate,
458-
custom_formatters=custom_formatters)
474+
custom_formatters=custom_formatters,
475+
context=context)
459476
return list(map(f, value))
460477

461-
def _validate_number(self, value, custom_formatters=None):
478+
def _validate_number(self, value, custom_formatters=None, context=None):
462479
if self.minimum is not None:
463480
if self.exclusive_minimum and value <= self.minimum:
464481
raise InvalidSchemaValue(
@@ -480,7 +497,7 @@ def _validate_number(self, value, custom_formatters=None):
480497
"Value {value} is not a multiple of {type}",
481498
value, self.multiple_of)
482499

483-
def _validate_string(self, value, custom_formatters=None):
500+
def _validate_string(self, value, custom_formatters=None, context=None):
484501
try:
485502
schema_format = SchemaFormat(self.format)
486503
except ValueError:
@@ -529,7 +546,8 @@ def _validate_string(self, value, custom_formatters=None):
529546

530547
return True
531548

532-
def _validate_object(self, value, custom_formatters=None):
549+
@requires_context
550+
def _validate_object(self, value, custom_formatters=None, context=None):
533551
properties = value.__dict__
534552

535553
if self.one_of:
@@ -538,9 +556,10 @@ def _validate_object(self, value, custom_formatters=None):
538556
try:
539557
self._validate_properties(
540558
properties, one_of_schema,
541-
custom_formatters=custom_formatters)
542-
except OpenAPISchemaError:
543-
pass
559+
custom_formatters=custom_formatters, context=context)
560+
except OpenAPISchemaError as exc:
561+
log.debug("Failed to validate oneOf schema: {}"
562+
.format(str(exc)))
544563
else:
545564
if valid_one_of_schema is not None:
546565
raise MultipleOneOfSchema(self.type)
@@ -551,7 +570,8 @@ def _validate_object(self, value, custom_formatters=None):
551570

552571
else:
553572
self._validate_properties(properties,
554-
custom_formatters=custom_formatters)
573+
custom_formatters=custom_formatters,
574+
context=context)
555575

556576
if self.min_properties is not None:
557577
if self.min_properties < 0:

0 commit comments

Comments
 (0)