@@ -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,39 @@ 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+ return list (map (self .items .cast , value ))
195+
196+ def get_unmarshal_mapping (self , custom_formatters = None , strict = True ):
159197 primitive_unmarshallers = self .get_primitive_unmarshallers (
160198 custom_formatters = custom_formatters )
161199
@@ -166,7 +204,7 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
166204
167205 pass_defaults = lambda f : functools .partial (
168206 f , custom_formatters = custom_formatters , strict = strict )
169- mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
207+ mapping = self .DEFAULT_UNMARSHAL_CALLABLE_GETTER .copy ()
170208 mapping .update (primitive_unmarshallers_partial )
171209 mapping .update ({
172210 SchemaType .ANY : pass_defaults (self ._unmarshal_any ),
@@ -176,15 +214,10 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
176214
177215 return defaultdict (lambda : lambda x : x , mapping )
178216
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"""
217+ def unmarshal (self , value , custom_formatters = None , strict = True ):
218+ """Unmarshal parameter from the value."""
219+ if self .deprecated :
220+ warnings .warn ("The schema is deprecated" , DeprecationWarning )
188221 if value is None :
189222 if not self .nullable :
190223 raise InvalidSchemaValue ("Null value for non-nullable schema" , value , self .type )
@@ -194,33 +227,26 @@ def cast(self, value, custom_formatters=None, strict=True):
194227 raise InvalidSchemaValue (
195228 "Value {value} not in enum choices: {type}" , value , self .enum )
196229
197- cast_mapping = self .get_cast_mapping (
230+ unmarshal_mapping = self .get_unmarshal_mapping (
198231 custom_formatters = custom_formatters , strict = strict )
199232
200233 if self .type is not SchemaType .STRING and value == '' :
201234 return None
202235
203- cast_callable = cast_mapping [self .type ]
236+ unmarshal_callable = unmarshal_mapping [self .type ]
204237 try :
205- return cast_callable (value )
238+ unmarshalled = unmarshal_callable (value )
206239 except UnmarshallerStrictTypeError :
207240 raise InvalidSchemaValue (
208241 "Value {value} is not of type {type}" , value , self .type )
209242 except ValueError :
210243 raise InvalidSchemaValue (
211244 "Failed to cast value {value} to type {type}" , value , self .type )
212245
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 :
246+ if unmarshalled is None and not self .required :
221247 return None
222248
223- return casted
249+ return unmarshalled
224250
225251 def get_primitive_unmarshallers (self , ** options ):
226252 from openapi_core .schema .schemas .unmarshallers import (
@@ -247,28 +273,28 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
247273 SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
248274 SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
249275 ]
250- cast_mapping = self .get_cast_mapping ()
276+ unmarshal_mapping = self .get_unmarshal_mapping ()
251277 if self .one_of :
252278 result = None
253279 for subschema in self .one_of :
254280 try :
255- casted = subschema .cast (value , custom_formatters )
281+ unmarshalled = subschema .unmarshal (value , custom_formatters )
256282 except (OpenAPISchemaError , TypeError , ValueError ):
257283 continue
258284 else :
259285 if result is not None :
260286 raise MultipleOneOfSchema (self .type )
261- result = casted
287+ result = unmarshalled
262288
263289 if result is None :
264290 raise NoOneOfSchema (self .type )
265291
266292 return result
267293 else :
268294 for schema_type in types_resolve_order :
269- cast_callable = cast_mapping [schema_type ]
295+ unmarshal_callable = unmarshal_mapping [schema_type ]
270296 try :
271- return cast_callable (value )
297+ return unmarshal_callable (value )
272298 except UnmarshallerStrictTypeError :
273299 continue
274300 # @todo: remove ValueError when validation separated
0 commit comments