mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-22 03:00:10 +00:00
Merge pull request #134 from dz0ny/fix/number_parsing
Fix number validator
This commit is contained in:
commit
98f72bff1b
3 changed files with 64 additions and 8 deletions
|
@ -20,6 +20,7 @@ from openapi_core.schema.schemas.exceptions import (
|
|||
)
|
||||
from openapi_core.schema.schemas.util import (
|
||||
forcebool, format_date, format_datetime, format_byte, format_uuid,
|
||||
format_number,
|
||||
)
|
||||
from openapi_core.schema.schemas.validators import (
|
||||
TypeValidator, AttributeValidator,
|
||||
|
@ -51,11 +52,19 @@ class Schema(object):
|
|||
SchemaFormat.BYTE: Format(format_byte, TypeValidator(text_type)),
|
||||
}
|
||||
|
||||
NUMBER_FORMAT_CALLABLE_GETTER = {
|
||||
SchemaFormat.NONE: Format(format_number, TypeValidator(
|
||||
integer_types + (float, ), exclude=bool)),
|
||||
SchemaFormat.FLOAT: Format(float, TypeValidator(float)),
|
||||
SchemaFormat.DOUBLE: Format(float, TypeValidator(float)),
|
||||
}
|
||||
|
||||
TYPE_VALIDATOR_CALLABLE_GETTER = {
|
||||
SchemaType.ANY: lambda x: True,
|
||||
SchemaType.BOOLEAN: TypeValidator(bool),
|
||||
SchemaType.INTEGER: TypeValidator(integer_types, exclude=bool),
|
||||
SchemaType.NUMBER: TypeValidator(integer_types, float, exclude=bool),
|
||||
SchemaType.NUMBER: TypeValidator(
|
||||
integer_types + (float, ), exclude=bool),
|
||||
SchemaType.STRING: TypeValidator(
|
||||
text_type, date, datetime, binary_type, UUID),
|
||||
SchemaType.ARRAY: TypeValidator(list, tuple),
|
||||
|
@ -229,16 +238,33 @@ class Schema(object):
|
|||
"Failed to format value {value} to format {type}: {exception}", value, self.format, exc)
|
||||
|
||||
def _unmarshal_integer(self, value, custom_formatters=None, strict=True):
|
||||
if strict and not isinstance(value, (integer_types, )):
|
||||
if strict and not isinstance(value, integer_types):
|
||||
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
|
||||
|
||||
return int(value)
|
||||
|
||||
def _unmarshal_number(self, value, custom_formatters=None, strict=True):
|
||||
if strict and not isinstance(value, (float, )):
|
||||
if strict and not isinstance(value, (float, ) + integer_types):
|
||||
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
|
||||
|
||||
return float(value)
|
||||
try:
|
||||
schema_format = SchemaFormat(self.format)
|
||||
except ValueError:
|
||||
msg = "Unsupported format {type} unmarshalling for value {value}"
|
||||
if custom_formatters is not None:
|
||||
formatnumber = custom_formatters.get(self.format)
|
||||
if formatnumber is None:
|
||||
raise InvalidSchemaValue(msg, value, self.format)
|
||||
else:
|
||||
raise InvalidSchemaValue(msg, value, self.format)
|
||||
else:
|
||||
formatnumber = self.NUMBER_FORMAT_CALLABLE_GETTER[schema_format]
|
||||
|
||||
try:
|
||||
return formatnumber.unmarshal(value)
|
||||
except ValueError as exc:
|
||||
raise InvalidCustomFormatSchemaValue(
|
||||
"Failed to format value {value} to format {type}: {exception}", value, self.format, exc)
|
||||
|
||||
def _unmarshal_boolean(self, value, custom_formatters=None, strict=True):
|
||||
if strict and not isinstance(value, (bool, )):
|
||||
|
|
|
@ -3,7 +3,7 @@ from base64 import b64decode
|
|||
import datetime
|
||||
from distutils.util import strtobool
|
||||
from json import dumps
|
||||
from six import string_types, text_type
|
||||
from six import string_types, text_type, integer_types
|
||||
import strict_rfc3339
|
||||
from uuid import UUID
|
||||
|
||||
|
@ -36,3 +36,10 @@ def format_uuid(value):
|
|||
|
||||
def format_byte(value, encoding='utf8'):
|
||||
return text_type(b64decode(value), encoding)
|
||||
|
||||
|
||||
def format_number(value):
|
||||
if isinstance(value, integer_types + (float, )):
|
||||
return value
|
||||
|
||||
return float(value)
|
||||
|
|
|
@ -270,12 +270,35 @@ class TestSchemaUnmarshal(object):
|
|||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_number_int_invalid(self):
|
||||
def test_number_int(self):
|
||||
schema = Schema('number')
|
||||
value = 1
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
assert result == 1
|
||||
assert type(result) == int
|
||||
|
||||
def test_number_float(self):
|
||||
schema = Schema('number')
|
||||
value = 1.2
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == 1.2
|
||||
assert type(result) == float
|
||||
|
||||
def test_number_format_float(self):
|
||||
schema = Schema('number', schema_format='float')
|
||||
value = 1.2
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == 1.2
|
||||
|
||||
def test_number_format_double(self):
|
||||
schema = Schema('number', schema_format='double')
|
||||
value = 1.2
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == 1.2
|
||||
|
||||
|
||||
class TestSchemaValidate(object):
|
||||
|
|
Loading…
Reference in a new issue