|
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