mirror of
https://github.com/correl/openapi-core.git
synced 2024-12-28 19:19:23 +00:00
Support unmarshaling string with format keyword
This commit is contained in:
parent
2487d0e5c1
commit
d4f65a2ed2
3 changed files with 68 additions and 3 deletions
|
@ -6,12 +6,12 @@ import warnings
|
|||
from six import iteritems
|
||||
|
||||
from openapi_core.extensions.models.factories import ModelFactory
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
InvalidSchemaValue, UndefinedSchemaProperty, MissingSchemaProperty,
|
||||
OpenAPISchemaError, NoOneOfSchema, MultipleOneOfSchema,
|
||||
)
|
||||
from openapi_core.schema.schemas.util import forcebool
|
||||
from openapi_core.schema.schemas.util import forcebool, format_date
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -25,6 +25,10 @@ class Schema(object):
|
|||
SchemaType.BOOLEAN: forcebool,
|
||||
}
|
||||
|
||||
FORMAT_CALLABLE_GETTER = defaultdict(lambda: lambda x: x, {
|
||||
SchemaFormat.DATE.value: format_date,
|
||||
})
|
||||
|
||||
def __init__(
|
||||
self, schema_type=None, model=None, properties=None, items=None,
|
||||
schema_format=None, required=None, default=None, nullable=False,
|
||||
|
@ -92,6 +96,7 @@ class Schema(object):
|
|||
def get_cast_mapping(self):
|
||||
mapping = self.DEFAULT_CAST_CALLABLE_GETTER.copy()
|
||||
mapping.update({
|
||||
SchemaType.STRING: self._unmarshal_string,
|
||||
SchemaType.ARRAY: self._unmarshal_collection,
|
||||
SchemaType.OBJECT: self._unmarshal_object,
|
||||
})
|
||||
|
@ -110,7 +115,7 @@ class Schema(object):
|
|||
|
||||
cast_mapping = self.get_cast_mapping()
|
||||
|
||||
if self.type in cast_mapping and value == '':
|
||||
if self.type is not SchemaType.STRING and value == '':
|
||||
return None
|
||||
|
||||
cast_callable = cast_mapping[self.type]
|
||||
|
@ -139,6 +144,16 @@ class Schema(object):
|
|||
|
||||
return casted
|
||||
|
||||
def _unmarshal_string(self, value):
|
||||
formatter = self.FORMAT_CALLABLE_GETTER[self.format]
|
||||
try:
|
||||
return formatter(value)
|
||||
except ValueError:
|
||||
raise InvalidSchemaValue(
|
||||
"Failed to format value of {0} to {1}".format(
|
||||
value, self.format)
|
||||
)
|
||||
|
||||
def _unmarshal_collection(self, value):
|
||||
return list(map(self.items.unmarshal, value))
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""OpenAPI core schemas util module"""
|
||||
import datetime
|
||||
from distutils.util import strtobool
|
||||
from json import dumps
|
||||
from six import string_types
|
||||
|
@ -13,3 +14,7 @@ def forcebool(val):
|
|||
|
||||
def dicthash(d):
|
||||
return hash(dumps(d, sort_keys=True))
|
||||
|
||||
|
||||
def format_date(value):
|
||||
return datetime.datetime.strptime(value, '%Y-%m-%d').date()
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import datetime
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
|
@ -64,6 +66,49 @@ class TestSchemaUnmarshal(object):
|
|||
|
||||
assert result == default_value
|
||||
|
||||
def test_string_format_date(self):
|
||||
schema = Schema('string', schema_format='date')
|
||||
value = '2018-01-02'
|
||||
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == datetime.date(2018, 1, 2)
|
||||
|
||||
def test_string_format_custom(self):
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
|
||||
with mock.patch.dict(
|
||||
Schema.FORMAT_CALLABLE_GETTER,
|
||||
{custom_format: lambda x: x + '-custom'},
|
||||
):
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == 'x-custom'
|
||||
|
||||
def test_string_format_unknown(self):
|
||||
unknown_format = 'unknown'
|
||||
schema = Schema('string', schema_format=unknown_format)
|
||||
value = 'x'
|
||||
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == 'x'
|
||||
|
||||
def test_string_format_invalid_value(self):
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
|
||||
with mock.patch.dict(
|
||||
Schema.FORMAT_CALLABLE_GETTER,
|
||||
{custom_format: mock.Mock(side_effect=ValueError())},
|
||||
), pytest.raises(
|
||||
InvalidSchemaValue, message='Failed to format value'
|
||||
):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_valid(self):
|
||||
schema = Schema('integer')
|
||||
value = '123'
|
||||
|
|
Loading…
Reference in a new issue