@@ -39,9 +39,6 @@ class Schema(object):
3939 """Represents an OpenAPI Schema."""
4040
4141 DEFAULT_CAST_CALLABLE_GETTER = {
42- SchemaType .INTEGER : int ,
43- SchemaType .NUMBER : float ,
44- SchemaType .BOOLEAN : forcebool ,
4542 }
4643
4744 STRING_FORMAT_CALLABLE_GETTER = {
@@ -69,7 +66,7 @@ def __init__(
6966 self , schema_type = None , model = None , properties = None , items = None ,
7067 schema_format = None , required = None , default = None , nullable = False ,
7168 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 ,
7370 min_length = None , max_length = None , pattern = None , unique_items = False ,
7471 minimum = None , maximum = None , multiple_of = None ,
7572 exclusive_minimum = False , exclusive_maximum = False ,
@@ -149,27 +146,31 @@ def get_all_required_properties_names(self):
149146
150147 return set (required )
151148
152- def get_cast_mapping (self , custom_formatters = None ):
149+ def get_cast_mapping (self , custom_formatters = None , strict = True ):
153150 pass_defaults = lambda f : functools .partial (
154- f , custom_formatters = custom_formatters )
151+ f , custom_formatters = custom_formatters , strict = strict )
155152 mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
156153 mapping .update ({
157154 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 ),
158158 SchemaType .ANY : pass_defaults (self ._unmarshal_any ),
159159 SchemaType .ARRAY : pass_defaults (self ._unmarshal_collection ),
160160 SchemaType .OBJECT : pass_defaults (self ._unmarshal_object ),
161161 })
162162
163163 return defaultdict (lambda : lambda x : x , mapping )
164164
165- def cast (self , value , custom_formatters = None ):
165+ def cast (self , value , custom_formatters = None , strict = True ):
166166 """Cast value to schema type"""
167167 if value is None :
168168 if not self .nullable :
169169 raise InvalidSchemaValue ("Null value for non-nullable schema" , value , self .type )
170170 return self .default
171171
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 )
173174
174175 if self .type is not SchemaType .STRING and value == '' :
175176 return None
@@ -181,12 +182,12 @@ def cast(self, value, custom_formatters=None):
181182 raise InvalidSchemaValue (
182183 "Failed to cast value {value} to type {type}" , value , self .type )
183184
184- def unmarshal (self , value , custom_formatters = None ):
185+ def unmarshal (self , value , custom_formatters = None , strict = True ):
185186 """Unmarshal parameter from the value."""
186187 if self .deprecated :
187188 warnings .warn ("The schema is deprecated" , DeprecationWarning )
188189
189- casted = self .cast (value , custom_formatters = custom_formatters )
190+ casted = self .cast (value , custom_formatters = custom_formatters , strict = strict )
190191
191192 if casted is None and not self .required :
192193 return None
@@ -197,7 +198,10 @@ def unmarshal(self, value, custom_formatters=None):
197198
198199 return casted
199200
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+
201205 try :
202206 schema_format = SchemaFormat (self .format )
203207 except ValueError :
@@ -217,7 +221,25 @@ def _unmarshal_string(self, value, custom_formatters=None):
217221 raise InvalidCustomFormatSchemaValue (
218222 "Failed to format value {value} to format {type}: {exception}" , value , self .format , exc )
219223
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 ):
221243 types_resolve_order = [
222244 SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
223245 SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
@@ -233,16 +255,21 @@ def _unmarshal_any(self, value, custom_formatters=None):
233255
234256 raise NoValidSchema (value )
235257
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+
237262 if self .items is None :
238263 raise UndefinedItemsSchema (self .type )
239264
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+ )
242269 return list (map (f , value ))
243270
244271 def _unmarshal_object (self , value , model_factory = None ,
245- custom_formatters = None ):
272+ custom_formatters = None , strict = True ):
246273 if not isinstance (value , (dict , )):
247274 raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
248275
@@ -271,7 +298,7 @@ def _unmarshal_object(self, value, model_factory=None,
271298 return model_factory .create (properties , name = self .model )
272299
273300 def _unmarshal_properties (self , value , one_of_schema = None ,
274- custom_formatters = None ):
301+ custom_formatters = None , strict = True ):
275302 all_props = self .get_all_properties ()
276303 all_props_names = self .get_all_properties_names ()
277304 all_req_props_names = self .get_all_required_properties_names ()
@@ -285,14 +312,15 @@ def _unmarshal_properties(self, value, one_of_schema=None,
285312
286313 value_props_names = value .keys ()
287314 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 :
289316 raise UndefinedSchemaProperty (extra_props )
290317
291318 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 )
296324
297325 for prop_name , prop in iteritems (all_props ):
298326 try :
@@ -516,13 +544,14 @@ def _validate_properties(self, value, one_of_schema=None,
516544
517545 value_props_names = value .keys ()
518546 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 :
520548 raise UndefinedSchemaProperty (extra_props )
521549
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 )
526555
527556 for prop_name , prop in iteritems (all_props ):
528557 try :
0 commit comments