@@ -38,7 +38,13 @@ class Format(object):
38
38
class Schema (object ):
39
39
"""Represents an OpenAPI Schema."""
40
40
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 = {
42
48
}
43
49
44
50
STRING_FORMAT_CALLABLE_GETTER = {
@@ -155,7 +161,46 @@ def get_all_required_properties_names(self):
155
161
156
162
return set (required )
157
163
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 ):
159
204
primitive_unmarshallers = self .get_primitive_unmarshallers (
160
205
custom_formatters = custom_formatters )
161
206
@@ -166,7 +211,7 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
166
211
167
212
pass_defaults = lambda f : functools .partial (
168
213
f , custom_formatters = custom_formatters , strict = strict )
169
- mapping = self .DEFAULT_CAST_CALLABLE_GETTER .copy ()
214
+ mapping = self .DEFAULT_UNMARSHAL_CALLABLE_GETTER .copy ()
170
215
mapping .update (primitive_unmarshallers_partial )
171
216
mapping .update ({
172
217
SchemaType .ANY : pass_defaults (self ._unmarshal_any ),
@@ -176,15 +221,10 @@ def get_cast_mapping(self, custom_formatters=None, strict=True):
176
221
177
222
return defaultdict (lambda : lambda x : x , mapping )
178
223
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 )
188
228
if value is None :
189
229
if not self .nullable :
190
230
raise InvalidSchemaValue ("Null value for non-nullable schema" , value , self .type )
@@ -194,33 +234,26 @@ def cast(self, value, custom_formatters=None, strict=True):
194
234
raise InvalidSchemaValue (
195
235
"Value {value} not in enum choices: {type}" , value , self .enum )
196
236
197
- cast_mapping = self .get_cast_mapping (
237
+ unmarshal_mapping = self .get_unmarshal_mapping (
198
238
custom_formatters = custom_formatters , strict = strict )
199
239
200
240
if self .type is not SchemaType .STRING and value == '' :
201
241
return None
202
242
203
- cast_callable = cast_mapping [self .type ]
243
+ unmarshal_callable = unmarshal_mapping [self .type ]
204
244
try :
205
- return cast_callable (value )
245
+ unmarshalled = unmarshal_callable (value )
206
246
except UnmarshallerStrictTypeError :
207
247
raise InvalidSchemaValue (
208
248
"Value {value} is not of type {type}" , value , self .type )
209
249
except ValueError :
210
250
raise InvalidSchemaValue (
211
251
"Failed to cast value {value} to type {type}" , value , self .type )
212
252
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 :
221
254
return None
222
255
223
- return casted
256
+ return unmarshalled
224
257
225
258
def get_primitive_unmarshallers (self , ** options ):
226
259
from openapi_core .schema .schemas .unmarshallers import (
@@ -247,28 +280,28 @@ def _unmarshal_any(self, value, custom_formatters=None, strict=True):
247
280
SchemaType .OBJECT , SchemaType .ARRAY , SchemaType .BOOLEAN ,
248
281
SchemaType .INTEGER , SchemaType .NUMBER , SchemaType .STRING ,
249
282
]
250
- cast_mapping = self .get_cast_mapping ()
283
+ unmarshal_mapping = self .get_unmarshal_mapping ()
251
284
if self .one_of :
252
285
result = None
253
286
for subschema in self .one_of :
254
287
try :
255
- casted = subschema .cast (value , custom_formatters )
288
+ unmarshalled = subschema .unmarshal (value , custom_formatters )
256
289
except (OpenAPISchemaError , TypeError , ValueError ):
257
290
continue
258
291
else :
259
292
if result is not None :
260
293
raise MultipleOneOfSchema (self .type )
261
- result = casted
294
+ result = unmarshalled
262
295
263
296
if result is None :
264
297
raise NoOneOfSchema (self .type )
265
298
266
299
return result
267
300
else :
268
301
for schema_type in types_resolve_order :
269
- cast_callable = cast_mapping [schema_type ]
302
+ unmarshal_callable = unmarshal_mapping [schema_type ]
270
303
try :
271
- return cast_callable (value )
304
+ return unmarshal_callable (value )
272
305
except UnmarshallerStrictTypeError :
273
306
continue
274
307
# @todo: remove ValueError when validation separated
0 commit comments