18
18
CastError , InvalidSchemaValue ,
19
19
UnmarshallerError , UnmarshalValueError , UnmarshalError ,
20
20
)
21
+ from openapi_core .schema .schemas .types import NoValue
21
22
from openapi_core .schema .schemas .util import (
22
23
forcebool , format_date , format_datetime , format_byte , format_uuid ,
23
24
format_number ,
@@ -46,16 +47,16 @@ class Schema(object):
46
47
}
47
48
48
49
def __init__ (
49
- self , schema_type = None , model = None , properties = None , items = None ,
50
- schema_format = None , required = None , default = None , nullable = False ,
50
+ self , schema_type = None , properties = None , items = None ,
51
+ schema_format = None , required = None , default = NoValue , nullable = False ,
51
52
enum = None , deprecated = False , all_of = None , one_of = None ,
52
53
additional_properties = True , min_items = None , max_items = None ,
53
54
min_length = None , max_length = None , pattern = None , unique_items = False ,
54
55
minimum = None , maximum = None , multiple_of = None ,
55
56
exclusive_minimum = False , exclusive_maximum = False ,
56
- min_properties = None , max_properties = None , _source = None ):
57
+ min_properties = None , max_properties = None , extensions = None ,
58
+ _source = None ):
57
59
self .type = SchemaType (schema_type )
58
- self .model = model
59
60
self .properties = properties and dict (properties ) or {}
60
61
self .items = items
61
62
self .format = schema_format
@@ -84,6 +85,8 @@ def __init__(
84
85
self .max_properties = int (max_properties )\
85
86
if max_properties is not None else None
86
87
88
+ self .extensions = extensions and dict (extensions ) or {}
89
+
87
90
self ._all_required_properties_cache = None
88
91
self ._all_optional_properties_cache = None
89
92
@@ -100,6 +103,9 @@ def to_dict(self):
100
103
def __getitem__ (self , name ):
101
104
return self .properties [name ]
102
105
106
+ def has_default (self ):
107
+ return not self .default is NoValue
108
+
103
109
def get_all_properties (self ):
104
110
properties = self .properties .copy ()
105
111
@@ -149,7 +155,7 @@ def get_cast_mapping(self):
149
155
150
156
def cast (self , value ):
151
157
"""Cast value from string to schema type"""
152
- if value is None :
158
+ if value in ( None , NoValue ) :
153
159
return value
154
160
155
161
cast_mapping = self .get_cast_mapping ()
@@ -198,51 +204,17 @@ def validate(self, value, resolver=None):
198
204
199
205
def unmarshal (self , value , custom_formatters = None , strict = True ):
200
206
"""Unmarshal parameter from the value."""
201
- if self .deprecated :
202
- warnings .warn ("The schema is deprecated" , DeprecationWarning )
203
- if value is None :
204
- if not self .nullable :
205
- raise UnmarshalError (
206
- "Null value for non-nullable schema" , value , self .type )
207
- return self .default
208
-
209
- if self .enum and value not in self .enum :
210
- raise UnmarshalError ("Invalid value for enum: {0}" .format (value ))
211
-
212
- unmarshal_mapping = self .get_unmarshal_mapping (
213
- custom_formatters = custom_formatters , strict = strict )
214
-
215
- if self .type is not SchemaType .STRING and value == '' :
216
- return None
217
-
218
- unmarshal_callable = unmarshal_mapping [self .type ]
207
+ from openapi_core .unmarshalling .schemas .factories import (
208
+ SchemaUnmarshallersFactory ,
209
+ )
210
+ unmarshallers_factory = SchemaUnmarshallersFactory (
211
+ custom_formatters )
212
+ unmarshaller = unmarshallers_factory .create (self )
219
213
try :
220
- unmarshalled = unmarshal_callable (value )
214
+ return unmarshaller (value , strict = strict )
221
215
except ValueError as exc :
222
216
raise UnmarshalValueError (value , self .type , exc )
223
217
224
- return unmarshalled
225
-
226
- def get_primitive_unmarshallers (self , ** options ):
227
- from openapi_core .schema .schemas .unmarshallers import (
228
- StringUnmarshaller , BooleanUnmarshaller , IntegerUnmarshaller ,
229
- NumberUnmarshaller ,
230
- )
231
-
232
- unmarshallers_classes = {
233
- SchemaType .STRING : StringUnmarshaller ,
234
- SchemaType .BOOLEAN : BooleanUnmarshaller ,
235
- SchemaType .INTEGER : IntegerUnmarshaller ,
236
- SchemaType .NUMBER : NumberUnmarshaller ,
237
- }
238
-
239
- unmarshallers = dict (
240
- (t , klass (** options ))
241
- for t , klass in unmarshallers_classes .items ()
242
- )
243
-
244
- return unmarshallers
245
-
246
218
def _unmarshal_any (self , value , custom_formatters = None , strict = True ):
247
219
types_resolve_order = [
248
220
SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
@@ -276,79 +248,3 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
276
248
277
249
log .warning ("failed to unmarshal any type" )
278
250
return value
279
-
280
- def _unmarshal_collection (self , value , custom_formatters = None , strict = True ):
281
- if not isinstance (value , (list , tuple )):
282
- raise ValueError ("Invalid value for collection: {0}" .format (value ))
283
-
284
- f = functools .partial (
285
- self .items .unmarshal ,
286
- custom_formatters = custom_formatters , strict = strict ,
287
- )
288
- return list (map (f , value ))
289
-
290
- def _unmarshal_object (self , value , model_factory = None ,
291
- custom_formatters = None , strict = True ):
292
- if not isinstance (value , (dict , )):
293
- raise ValueError ("Invalid value for object: {0}" .format (value ))
294
-
295
- model_factory = model_factory or ModelFactory ()
296
-
297
- if self .one_of :
298
- properties = None
299
- for one_of_schema in self .one_of :
300
- try :
301
- unmarshalled = self ._unmarshal_properties (
302
- value , one_of_schema , custom_formatters = custom_formatters )
303
- except (UnmarshalError , ValueError ):
304
- pass
305
- else :
306
- if properties is not None :
307
- log .warning ("multiple valid oneOf schemas found" )
308
- continue
309
- properties = unmarshalled
310
-
311
- if properties is None :
312
- log .warning ("valid oneOf schema not found" )
313
-
314
- else :
315
- properties = self ._unmarshal_properties (
316
- value , custom_formatters = custom_formatters )
317
-
318
- return model_factory .create (properties , name = self .model )
319
-
320
- def _unmarshal_properties (self , value , one_of_schema = None ,
321
- custom_formatters = None , strict = True ):
322
- all_props = self .get_all_properties ()
323
- all_props_names = self .get_all_properties_names ()
324
- all_req_props_names = self .get_all_required_properties_names ()
325
-
326
- if one_of_schema is not None :
327
- all_props .update (one_of_schema .get_all_properties ())
328
- all_props_names |= one_of_schema .\
329
- get_all_properties_names ()
330
- all_req_props_names |= one_of_schema .\
331
- get_all_required_properties_names ()
332
-
333
- value_props_names = value .keys ()
334
- extra_props = set (value_props_names ) - set (all_props_names )
335
-
336
- properties = {}
337
- if self .additional_properties is not True :
338
- for prop_name in extra_props :
339
- prop_value = value [prop_name ]
340
- properties [prop_name ] = self .additional_properties .unmarshal (
341
- prop_value , custom_formatters = custom_formatters )
342
-
343
- for prop_name , prop in iteritems (all_props ):
344
- try :
345
- prop_value = value [prop_name ]
346
- except KeyError :
347
- if not prop .nullable and not prop .default :
348
- continue
349
- prop_value = prop .default
350
-
351
- properties [prop_name ] = prop .unmarshal (
352
- prop_value , custom_formatters = custom_formatters )
353
-
354
- return properties
0 commit comments