|
20 | 20 | ) |
21 | 21 | from openapi_core.schema.schemas.util import ( |
22 | 22 | forcebool, format_date, format_datetime, format_byte, format_uuid, |
| 23 | + format_number, |
23 | 24 | ) |
24 | 25 | from openapi_core.schema.schemas.validators import ( |
25 | 26 | TypeValidator, AttributeValidator, |
@@ -51,11 +52,19 @@ class Schema(object): |
51 | 52 | SchemaFormat.BYTE: Format(format_byte, TypeValidator(text_type)), |
52 | 53 | } |
53 | 54 |
|
| 55 | + NUMBER_FORMAT_CALLABLE_GETTER = { |
| 56 | + SchemaFormat.NONE: Format(format_number, TypeValidator( |
| 57 | + integer_types + (float, ), exclude=bool)), |
| 58 | + SchemaFormat.FLOAT: Format(float, TypeValidator(float)), |
| 59 | + SchemaFormat.DOUBLE: Format(float, TypeValidator(float)), |
| 60 | + } |
| 61 | + |
54 | 62 | TYPE_VALIDATOR_CALLABLE_GETTER = { |
55 | 63 | SchemaType.ANY: lambda x: True, |
56 | 64 | SchemaType.BOOLEAN: TypeValidator(bool), |
57 | 65 | SchemaType.INTEGER: TypeValidator(integer_types, exclude=bool), |
58 | | - SchemaType.NUMBER: TypeValidator(integer_types, float, exclude=bool), |
| 66 | + SchemaType.NUMBER: TypeValidator( |
| 67 | + integer_types + (float, ), exclude=bool), |
59 | 68 | SchemaType.STRING: TypeValidator( |
60 | 69 | text_type, date, datetime, binary_type, UUID), |
61 | 70 | SchemaType.ARRAY: TypeValidator(list, tuple), |
@@ -229,16 +238,33 @@ def _unmarshal_string(self, value, custom_formatters=None, strict=True): |
229 | 238 | "Failed to format value {value} to format {type}: {exception}", value, self.format, exc) |
230 | 239 |
|
231 | 240 | def _unmarshal_integer(self, value, custom_formatters=None, strict=True): |
232 | | - if strict and not isinstance(value, (integer_types, )): |
| 241 | + if strict and not isinstance(value, integer_types): |
233 | 242 | raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type) |
234 | 243 |
|
235 | 244 | return int(value) |
236 | 245 |
|
237 | 246 | def _unmarshal_number(self, value, custom_formatters=None, strict=True): |
238 | | - if strict and not isinstance(value, (float, )): |
| 247 | + if strict and not isinstance(value, (float, ) + integer_types): |
239 | 248 | raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type) |
240 | 249 |
|
241 | | - return float(value) |
| 250 | + try: |
| 251 | + schema_format = SchemaFormat(self.format) |
| 252 | + except ValueError: |
| 253 | + msg = "Unsupported format {type} unmarshalling for value {value}" |
| 254 | + if custom_formatters is not None: |
| 255 | + formatnumber = custom_formatters.get(self.format) |
| 256 | + if formatnumber is None: |
| 257 | + raise InvalidSchemaValue(msg, value, self.format) |
| 258 | + else: |
| 259 | + raise InvalidSchemaValue(msg, value, self.format) |
| 260 | + else: |
| 261 | + formatnumber = self.NUMBER_FORMAT_CALLABLE_GETTER[schema_format] |
| 262 | + |
| 263 | + try: |
| 264 | + return formatnumber.unmarshal(value) |
| 265 | + except ValueError as exc: |
| 266 | + raise InvalidCustomFormatSchemaValue( |
| 267 | + "Failed to format value {value} to format {type}: {exception}", value, self.format, exc) |
242 | 268 |
|
243 | 269 | def _unmarshal_boolean(self, value, custom_formatters=None, strict=True): |
244 | 270 | if strict and not isinstance(value, (bool, )): |
|
0 commit comments