Merge pull request #134 from dz0ny/fix/number_parsing

Fix number validator
This commit is contained in:
A 2019-05-21 13:19:07 +01:00 committed by GitHub
commit 98f72bff1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 8 deletions

View file

@ -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, )):

View file

@ -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)

View file

@ -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):