@@ -39,9 +39,6 @@ class Schema(object):
39
39
"""Represents an OpenAPI Schema."""
40
40
41
41
DEFAULT_CAST_CALLABLE_GETTER = {
42
- SchemaType .INTEGER : int ,
43
- SchemaType .NUMBER : float ,
44
- SchemaType .BOOLEAN : forcebool ,
45
42
}
46
43
47
44
STRING_FORMAT_CALLABLE_GETTER = {
@@ -69,7 +66,7 @@ def __init__(
69
66
self , schema_type = None , model = None , properties = None , items = None ,
70
67
schema_format = None , required = None , default = None , nullable = False ,
71
68
enum = None , deprecated = False , all_of = None , one_of = None ,
72
- additional_properties = None , min_items = None , max_items = None ,
69
+ additional_properties = True , min_items = None , max_items = None ,
73
70
min_length = None , max_length = None , pattern = None , unique_items = False ,
74
71
minimum = None , maximum = None , multiple_of = None ,
75
72
exclusive_minimum = False , exclusive_maximum = False ,
@@ -149,27 +146,31 @@ def get_all_required_properties_names(self):
149
146
150
147
return set (required )
151
148
152
- def get_cast_mapping (self , custom_formatters = None ):
149
+ def get_cast_mapping (self , custom_formatters = None , strict = True ):
153
150
pass_defaults = lambda f : functools .partial (
154
- f , custom_formatters = custom_formatters )
151
+ f , custom_formatters = custom_formatters , strict = strict )
155
152
mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
156
153
mapping .update ({
157
154
SchemaType .STRING : pass_defaults (self ._unmarshal_string ),
155
+ SchemaType .BOOLEAN : pass_defaults (self ._unmarshal_boolean ),
156
+ SchemaType .INTEGER : pass_defaults (self ._unmarshal_integer ),
157
+ SchemaType .NUMBER : pass_defaults (self ._unmarshal_number ),
158
158
SchemaType .ANY : pass_defaults (self ._unmarshal_any ),
159
159
SchemaType .ARRAY : pass_defaults (self ._unmarshal_collection ),
160
160
SchemaType .OBJECT : pass_defaults (self ._unmarshal_object ),
161
161
})
162
162
163
163
return defaultdict (lambda : lambda x : x , mapping )
164
164
165
- def cast (self , value , custom_formatters = None ):
165
+ def cast (self , value , custom_formatters = None , strict = True ):
166
166
"""Cast value to schema type"""
167
167
if value is None :
168
168
if not self .nullable :
169
169
raise InvalidSchemaValue ("Null value for non-nullable schema" , value , self .type )
170
170
return self .default
171
171
172
- cast_mapping = self .get_cast_mapping (custom_formatters = custom_formatters )
172
+ cast_mapping = self .get_cast_mapping (
173
+ custom_formatters = custom_formatters , strict = strict )
173
174
174
175
if self .type is not SchemaType .STRING and value == '' :
175
176
return None
@@ -181,12 +182,12 @@ def cast(self, value, custom_formatters=None):
181
182
raise InvalidSchemaValue (
182
183
"Failed to cast value {value} to type {type}" , value , self .type )
183
184
184
- def unmarshal (self , value , custom_formatters = None ):
185
+ def unmarshal (self , value , custom_formatters = None , strict = True ):
185
186
"""Unmarshal parameter from the value."""
186
187
if self .deprecated :
187
188
warnings .warn ("The schema is deprecated" , DeprecationWarning )
188
189
189
- casted = self .cast (value , custom_formatters = custom_formatters )
190
+ casted = self .cast (value , custom_formatters = custom_formatters , strict = strict )
190
191
191
192
if casted is None and not self .required :
192
193
return None
@@ -197,7 +198,10 @@ def unmarshal(self, value, custom_formatters=None):
197
198
198
199
return casted
199
200
200
- def _unmarshal_string (self , value , custom_formatters = None ):
201
+ def _unmarshal_string (self , value , custom_formatters = None , strict = True ):
202
+ if strict and not isinstance (value , (text_type , binary_type )):
203
+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
204
+
201
205
try :
202
206
schema_format = SchemaFormat (self .format )
203
207
except ValueError :
@@ -217,7 +221,25 @@ def _unmarshal_string(self, value, custom_formatters=None):
217
221
raise InvalidCustomFormatSchemaValue (
218
222
"Failed to format value {value} to format {type}: {exception}" , value , self .format , exc )
219
223
220
- def _unmarshal_any (self , value , custom_formatters = None ):
224
+ def _unmarshal_integer (self , value , custom_formatters = None , strict = True ):
225
+ if strict and not isinstance (value , (integer_types , )):
226
+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
227
+
228
+ return int (value )
229
+
230
+ def _unmarshal_number (self , value , custom_formatters = None , strict = True ):
231
+ if strict and not isinstance (value , (float , )):
232
+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
233
+
234
+ return float (value )
235
+
236
+ def _unmarshal_boolean (self , value , custom_formatters = None , strict = True ):
237
+ if strict and not isinstance (value , (bool , )):
238
+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
239
+
240
+ return forcebool (value )
241
+
242
+ def _unmarshal_any (self , value , custom_formatters = None , strict = True ):
221
243
types_resolve_order = [
222
244
SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
223
245
SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
@@ -233,16 +255,21 @@ def _unmarshal_any(self, value, custom_formatters=None):
233
255
234
256
raise NoValidSchema (value )
235
257
236
- def _unmarshal_collection (self , value , custom_formatters = None ):
258
+ def _unmarshal_collection (self , value , custom_formatters = None , strict = True ):
259
+ if not isinstance (value , (list , tuple )):
260
+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
261
+
237
262
if self .items is None :
238
263
raise UndefinedItemsSchema (self .type )
239
264
240
- f = functools .partial (self .items .unmarshal ,
241
- custom_formatters = custom_formatters )
265
+ f = functools .partial (
266
+ self .items .unmarshal ,
267
+ custom_formatters = custom_formatters , strict = strict ,
268
+ )
242
269
return list (map (f , value ))
243
270
244
271
def _unmarshal_object (self , value , model_factory = None ,
245
- custom_formatters = None ):
272
+ custom_formatters = None , strict = True ):
246
273
if not isinstance (value , (dict , )):
247
274
raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
248
275
@@ -271,7 +298,7 @@ def _unmarshal_object(self, value, model_factory=None,
271
298
return model_factory .create (properties , name = self .model )
272
299
273
300
def _unmarshal_properties (self , value , one_of_schema = None ,
274
- custom_formatters = None ):
301
+ custom_formatters = None , strict = True ):
275
302
all_props = self .get_all_properties ()
276
303
all_props_names = self .get_all_properties_names ()
277
304
all_req_props_names = self .get_all_required_properties_names ()
@@ -285,14 +312,15 @@ def _unmarshal_properties(self, value, one_of_schema=None,
285
312
286
313
value_props_names = value .keys ()
287
314
extra_props = set (value_props_names ) - set (all_props_names )
288
- if extra_props and self .additional_properties is None :
315
+ if extra_props and self .additional_properties is False :
289
316
raise UndefinedSchemaProperty (extra_props )
290
317
291
318
properties = {}
292
- for prop_name in extra_props :
293
- prop_value = value [prop_name ]
294
- properties [prop_name ] = self .additional_properties .unmarshal (
295
- prop_value , custom_formatters = custom_formatters )
319
+ if self .additional_properties is not True :
320
+ for prop_name in extra_props :
321
+ prop_value = value [prop_name ]
322
+ properties [prop_name ] = self .additional_properties .unmarshal (
323
+ prop_value , custom_formatters = custom_formatters )
296
324
297
325
for prop_name , prop in iteritems (all_props ):
298
326
try :
@@ -516,13 +544,14 @@ def _validate_properties(self, value, one_of_schema=None,
516
544
517
545
value_props_names = value .keys ()
518
546
extra_props = set (value_props_names ) - set (all_props_names )
519
- if extra_props and self .additional_properties is None :
547
+ if extra_props and self .additional_properties is False :
520
548
raise UndefinedSchemaProperty (extra_props )
521
549
522
- for prop_name in extra_props :
523
- prop_value = value [prop_name ]
524
- self .additional_properties .validate (
525
- prop_value , custom_formatters = custom_formatters )
550
+ if self .additional_properties is not True :
551
+ for prop_name in extra_props :
552
+ prop_value = value [prop_name ]
553
+ self .additional_properties .validate (
554
+ prop_value , custom_formatters = custom_formatters )
526
555
527
556
for prop_name , prop in iteritems (all_props ):
528
557
try :
0 commit comments