11
11
from six import iteritems , integer_types , binary_type , text_type
12
12
13
13
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
+ )
15
17
from openapi_core .schema .schemas .exceptions import (
16
18
InvalidSchemaValue , UndefinedSchemaProperty , MissingSchemaProperty ,
17
19
OpenAPISchemaError , NoOneOfSchema , MultipleOneOfSchema , NoValidSchema ,
18
20
UndefinedItemsSchema , InvalidCustomFormatSchemaValue , InvalidSchemaProperty ,
19
21
UnmarshallerStrictTypeError ,
20
22
)
21
23
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 ,
23
25
format_number ,
24
26
)
25
27
from openapi_core .schema .schemas .validators import (
@@ -161,7 +163,8 @@ def get_all_required_properties_names(self):
161
163
162
164
return set (required )
163
165
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 ):
165
168
primitive_unmarshallers = self .get_primitive_unmarshallers (
166
169
custom_formatters = custom_formatters )
167
170
@@ -171,7 +174,7 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
171
174
)
172
175
173
176
pass_defaults = lambda f : functools .partial (
174
- f , custom_formatters = custom_formatters , strict = strict )
177
+ f , custom_formatters = custom_formatters , strict = strict , context = context )
175
178
mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
176
179
mapping .update (primitive_unmarshallers_partial )
177
180
mapping .update ({
@@ -189,7 +192,8 @@ def are_additional_properties_allowed(self, one_of_schema=None):
189
192
one_of_schema .additional_properties is not False )
190
193
)
191
194
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 ):
193
197
"""Cast value to schema type"""
194
198
if value is None :
195
199
if not self .nullable :
@@ -201,7 +205,7 @@ def cast(self, value, custom_formatters=None, strict=True):
201
205
"Value {value} not in enum choices: {type}" , value , self .enum )
202
206
203
207
cast_mapping = self .get_cast_mapping (
204
- custom_formatters = custom_formatters , strict = strict )
208
+ custom_formatters = custom_formatters , strict = strict , context = context )
205
209
206
210
if self .type is not SchemaType .STRING and value == '' :
207
211
return None
@@ -216,12 +220,14 @@ def cast(self, value, custom_formatters=None, strict=True):
216
220
raise InvalidSchemaValue (
217
221
"Failed to cast value {value} to type {type}" , value , self .type )
218
222
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 ):
220
226
"""Unmarshal parameter from the value."""
221
227
if self .deprecated :
222
228
warnings .warn ("The schema is deprecated" , DeprecationWarning )
223
229
224
- casted = self .cast (value , custom_formatters = custom_formatters , strict = strict )
230
+ casted = self .cast (value , custom_formatters = custom_formatters , strict = strict , context = context )
225
231
226
232
if casted is None and not self .required :
227
233
return None
@@ -248,17 +254,20 @@ def get_primitive_unmarshallers(self, **options):
248
254
249
255
return unmarshallers
250
256
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 ):
252
260
types_resolve_order = [
253
261
SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
254
262
SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
255
263
]
256
- cast_mapping = self .get_cast_mapping ()
264
+ cast_mapping = self .get_cast_mapping (custom_formatters , strict , context )
257
265
if self .one_of :
258
266
result = None
259
267
for subschema in self .one_of :
260
268
try :
261
- casted = subschema .cast (value , custom_formatters )
269
+ casted = subschema .cast (value , custom_formatters ,
270
+ strict , context )
262
271
except (OpenAPISchemaError , TypeError , ValueError ):
263
272
continue
264
273
else :
@@ -283,7 +292,9 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
283
292
284
293
raise NoValidSchema (value )
285
294
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 ):
287
298
if not isinstance (value , (list , tuple )):
288
299
raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
289
300
@@ -292,12 +303,13 @@ def _unmarshal_collection(self, value, custom_formatters=None, strict=True):
292
303
293
304
f = functools .partial (
294
305
self .items .unmarshal ,
295
- custom_formatters = custom_formatters , strict = strict ,
306
+ custom_formatters = custom_formatters , strict = strict , context = context
296
307
)
297
308
return list (map (f , value ))
298
309
310
+ @requires_context
299
311
def _unmarshal_object (self , value , model_factory = None ,
300
- custom_formatters = None , strict = True ):
312
+ custom_formatters = None , strict = True , context = None ):
301
313
if not isinstance (value , (dict , )):
302
314
raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
303
315
@@ -308,8 +320,9 @@ def _unmarshal_object(self, value, model_factory=None,
308
320
for one_of_schema in self .one_of :
309
321
try :
310
322
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 :
313
326
pass
314
327
else :
315
328
if properties is not None :
@@ -321,7 +334,7 @@ def _unmarshal_object(self, value, model_factory=None,
321
334
322
335
else :
323
336
properties = self ._unmarshal_properties (
324
- value , custom_formatters = custom_formatters )
337
+ value , custom_formatters = custom_formatters , context = context )
325
338
326
339
return model_factory .create (properties , name = self .model )
327
340
@@ -407,7 +420,8 @@ def default(x, **kw):
407
420
408
421
return defaultdict (lambda : default , mapping )
409
422
410
- def validate (self , value , custom_formatters = None ):
423
+ @requires_context
424
+ def validate (self , value , custom_formatters = None , context = None ):
411
425
if value is None :
412
426
if not self .nullable :
413
427
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):
423
437
# structure validation
424
438
validator_mapping = self .get_validator_mapping ()
425
439
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 )
427
442
428
443
return value
429
444
430
- def _validate_collection (self , value , custom_formatters = None ):
445
+ @requires_context
446
+ def _validate_collection (self , value , custom_formatters = None , context = None ):
431
447
if self .items is None :
432
448
raise UndefinedItemsSchema (self .type )
433
449
@@ -455,10 +471,11 @@ def _validate_collection(self, value, custom_formatters=None):
455
471
raise OpenAPISchemaError ("Value may not contain duplicate items" )
456
472
457
473
f = functools .partial (self .items .validate ,
458
- custom_formatters = custom_formatters )
474
+ custom_formatters = custom_formatters ,
475
+ context = context )
459
476
return list (map (f , value ))
460
477
461
- def _validate_number (self , value , custom_formatters = None ):
478
+ def _validate_number (self , value , custom_formatters = None , context = None ):
462
479
if self .minimum is not None :
463
480
if self .exclusive_minimum and value <= self .minimum :
464
481
raise InvalidSchemaValue (
@@ -480,7 +497,7 @@ def _validate_number(self, value, custom_formatters=None):
480
497
"Value {value} is not a multiple of {type}" ,
481
498
value , self .multiple_of )
482
499
483
- def _validate_string (self , value , custom_formatters = None ):
500
+ def _validate_string (self , value , custom_formatters = None , context = None ):
484
501
try :
485
502
schema_format = SchemaFormat (self .format )
486
503
except ValueError :
@@ -529,7 +546,8 @@ def _validate_string(self, value, custom_formatters=None):
529
546
530
547
return True
531
548
532
- def _validate_object (self , value , custom_formatters = None ):
549
+ @requires_context
550
+ def _validate_object (self , value , custom_formatters = None , context = None ):
533
551
properties = value .__dict__
534
552
535
553
if self .one_of :
@@ -538,9 +556,10 @@ def _validate_object(self, value, custom_formatters=None):
538
556
try :
539
557
self ._validate_properties (
540
558
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 )))
544
563
else :
545
564
if valid_one_of_schema is not None :
546
565
raise MultipleOneOfSchema (self .type )
@@ -551,7 +570,8 @@ def _validate_object(self, value, custom_formatters=None):
551
570
552
571
else :
553
572
self ._validate_properties (properties ,
554
- custom_formatters = custom_formatters )
573
+ custom_formatters = custom_formatters ,
574
+ context = context )
555
575
556
576
if self .min_properties is not None :
557
577
if self .min_properties < 0 :
0 commit comments