@@ -38,7 +38,13 @@ class Format(object):
3838class Schema (object ):
3939 """Represents an OpenAPI Schema."""
4040
41- DEFAULT_CAST_CALLABLE_GETTER = {
41+ TYPE_CAST_CALLABLE_GETTER = {
42+ SchemaType .INTEGER : int ,
43+ SchemaType .NUMBER : float ,
44+ SchemaType .BOOLEAN : forcebool ,
45+ }
46+
47+ DEFAULT_UNMARSHAL_CALLABLE_GETTER = {
4248 }
4349
4450 STRING_FORMAT_CALLABLE_GETTER = {
@@ -155,7 +161,46 @@ def get_all_required_properties_names(self):
155161
156162 return set (required )
157163
158- def get_cast_mapping (self , custom_formatters = None , strict = True ):
164+ def are_additional_properties_allowed (self , one_of_schema = None ):
165+ return (
166+ (self .additional_properties is not False ) and
167+ (one_of_schema is None or
168+ one_of_schema .additional_properties is not False )
169+ )
170+
171+ def get_cast_mapping (self ):
172+ mapping = self .TYPE_CAST_CALLABLE_GETTER .copy ()
173+ mapping .update ({
174+ SchemaType .ARRAY : self ._cast_collection ,
175+ })
176+
177+ return defaultdict (lambda : lambda x : x , mapping )
178+
179+ def cast (self , value ):
180+ """Cast value from string to schema type"""
181+ if value is None :
182+ return value
183+
184+ cast_mapping = self .get_cast_mapping ()
185+
186+ cast_callable = cast_mapping [self .type ]
187+ try :
188+ return cast_callable (value )
189+ except ValueError :
190+ raise InvalidSchemaValue (
191+ "Failed to cast value {value} to type {type}" , value , self .type )
192+
193+ def _cast_collection (self , value ):
194+ if not isinstance (value , (list , tuple )):
195+ raise InvalidSchemaValue ("Value {value} is not of type {type}" , value , self .type )
196+
197+ if self .items is None :
198+ raise UndefinedItemsSchema (self .type )
199+
200+ f = functools .partial (self .items .cast )
201+ return list (map (f , value ))
202+
203+ def get_unmarshal_mapping (self , custom_formatters = None , strict = True ):
159204 primitive_unmarshallers = self .get_primitive_unmarshallers (
160205 custom_formatters = custom_formatters )
161206
@@ -166,7 +211,7 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
166211
167212 pass_defaults = lambda f : functools .partial (
168213 f , custom_formatters = custom_formatters , strict = strict )
169- mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
214+ mapping = self .DEFAULT_UNMARSHAL_CALLABLE_GETTER .copy ()
170215 mapping .update (primitive_unmarshallers_partial )
171216 mapping .update ({
172217 SchemaType .ANY : pass_defaults (self ._unmarshal_any ),
@@ -176,15 +221,10 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
176221
177222 return defaultdict (lambda : lambda x : x , mapping )
178223
179- def are_additional_properties_allowed (self , one_of_schema = None ):
180- return (
181- (self .additional_properties is not False ) and
182- (one_of_schema is None or
183- one_of_schema .additional_properties is not False )
184- )
185-
186- def cast (self , value , custom_formatters = None , strict = True ):
187- """Cast value to schema type"""
224+ def unmarshal (self , value , custom_formatters = None , strict = True ):
225+ """Unmarshal parameter from the value."""
226+ if self .deprecated :
227+ warnings .warn ("The schema is deprecated" , DeprecationWarning )
188228 if value is None :
189229 if not self .nullable :
190230 raise InvalidSchemaValue ("Null value for non-nullable schema" , value , self .type )
@@ -194,33 +234,26 @@ def cast(self, value, custom_formatters=None, strict=True):
194234 raise InvalidSchemaValue (
195235 "Value {value} not in enum choices: {type}" , value , self .enum )
196236
197- cast_mapping = self .get_cast_mapping (
237+ unmarshal_mapping = self .get_unmarshal_mapping (
198238 custom_formatters = custom_formatters , strict = strict )
199239
200240 if self .type is not SchemaType .STRING and value == '' :
201241 return None
202242
203- cast_callable = cast_mapping [self .type ]
243+ unmarshal_callable = unmarshal_mapping [self .type ]
204244 try :
205- return cast_callable (value )
245+ unmarshalled = unmarshal_callable (value )
206246 except UnmarshallerStrictTypeError :
207247 raise InvalidSchemaValue (
208248 "Value {value} is not of type {type}" , value , self .type )
209249 except ValueError :
210250 raise InvalidSchemaValue (
211251 "Failed to cast value {value} to type {type}" , value , self .type )
212252
213- def unmarshal (self , value , custom_formatters = None , strict = True ):
214- """Unmarshal parameter from the value."""
215- if self .deprecated :
216- warnings .warn ("The schema is deprecated" , DeprecationWarning )
217-
218- casted = self .cast (value , custom_formatters = custom_formatters , strict = strict )
219-
220- if casted is None and not self .required :
253+ if unmarshalled is None and not self .required :
221254 return None
222255
223- return casted
256+ return unmarshalled
224257
225258 def get_primitive_unmarshallers (self , ** options ):
226259 from openapi_core .schema .schemas .unmarshallers import (
@@ -247,28 +280,28 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
247280 SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
248281 SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
249282 ]
250- cast_mapping = self .get_cast_mapping ()
283+ unmarshal_mapping = self .get_unmarshal_mapping ()
251284 if self .one_of :
252285 result = None
253286 for subschema in self .one_of :
254287 try :
255- casted = subschema .cast (value , custom_formatters )
288+ unmarshalled = subschema .unmarshal (value , custom_formatters )
256289 except (OpenAPISchemaError , TypeError , ValueError ):
257290 continue
258291 else :
259292 if result is not None :
260293 raise MultipleOneOfSchema (self .type )
261- result = casted
294+ result = unmarshalled
262295
263296 if result is None :
264297 raise NoOneOfSchema (self .type )
265298
266299 return result
267300 else :
268301 for schema_type in types_resolve_order :
269- cast_callable = cast_mapping [schema_type ]
302+ unmarshal_callable = unmarshal_mapping [schema_type ]
270303 try :
271- return cast_callable (value )
304+ return unmarshal_callable (value )
272305 except UnmarshallerStrictTypeError :
273306 continue
274307 # @todo: remove ValueError when validation separated
0 commit comments