Date-time format unmarshal tz fix

This commit is contained in:
p1c2u 2020-04-11 13:45:46 +01:00
parent 1270d5a6b9
commit dc8bd4d335
7 changed files with 29 additions and 11 deletions

View file

@ -1,6 +1,8 @@
from functools import partial from functools import partial
import logging import logging
from isodate.isodatetime import parse_datetime
from openapi_schema_validator._types import ( from openapi_schema_validator._types import (
is_array, is_bool, is_integer, is_array, is_bool, is_integer,
is_object, is_number, is_string, is_object, is_number, is_string,
@ -20,7 +22,7 @@ from openapi_core.unmarshalling.schemas.exceptions import (
) )
from openapi_core.unmarshalling.schemas.formatters import Formatter from openapi_core.unmarshalling.schemas.formatters import Formatter
from openapi_core.unmarshalling.schemas.util import ( from openapi_core.unmarshalling.schemas.util import (
forcebool, format_date, format_datetime, format_byte, format_uuid, forcebool, format_date, format_byte, format_uuid,
format_number, format_number,
) )
@ -77,7 +79,7 @@ class StringUnmarshaller(PrimitiveTypeUnmarshaller):
partial(oas30_format_checker.check, format='date'), format_date), partial(oas30_format_checker.check, format='date'), format_date),
SchemaFormat.DATETIME: Formatter.from_callables( SchemaFormat.DATETIME: Formatter.from_callables(
partial(oas30_format_checker.check, format='date-time'), partial(oas30_format_checker.check, format='date-time'),
format_datetime), parse_datetime),
SchemaFormat.BINARY: Formatter.from_callables( SchemaFormat.BINARY: Formatter.from_callables(
partial(oas30_format_checker.check, format='binary'), binary_type), partial(oas30_format_checker.check, format='binary'), binary_type),
SchemaFormat.UUID: Formatter.from_callables( SchemaFormat.UUID: Formatter.from_callables(

View file

@ -3,7 +3,6 @@ from base64 import b64decode
import datetime import datetime
from distutils.util import strtobool from distutils.util import strtobool
from six import string_types, text_type, integer_types from six import string_types, text_type, integer_types
import strict_rfc3339
from uuid import UUID from uuid import UUID
@ -18,11 +17,6 @@ def format_date(value):
return datetime.datetime.strptime(value, '%Y-%m-%d').date() return datetime.datetime.strptime(value, '%Y-%m-%d').date()
def format_datetime(value):
timestamp = strict_rfc3339.rfc3339_to_timestamp(value)
return datetime.datetime.utcfromtimestamp(timestamp)
def format_uuid(value): def format_uuid(value):
if isinstance(value, UUID): if isinstance(value, UUID):
return value return value

View file

@ -1,3 +1,4 @@
isodate==0.6.0
openapi-spec-validator openapi-spec-validator
openapi-schema-validator openapi-schema-validator
six six

View file

@ -1,3 +1,4 @@
isodate==0.6.0
openapi-spec-validator openapi-spec-validator
openapi-schema-validator openapi-schema-validator
six six

View file

@ -23,6 +23,7 @@ python_requires = >= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*
setup_requires = setup_requires =
setuptools setuptools
install_requires = install_requires =
isodate
openapi-spec-validator openapi-spec-validator
openapi-schema-validator openapi-schema-validator
six six

View file

@ -3,6 +3,7 @@ import pytest
from datetime import datetime from datetime import datetime
from base64 import b64encode from base64 import b64encode
from uuid import UUID from uuid import UUID
from isodate.tzinfo import UTC
from six import text_type from six import text_type
from openapi_core.casting.schemas.exceptions import CastError from openapi_core.casting.schemas.exceptions import CastError
@ -1090,7 +1091,7 @@ class TestPetstore(object):
assert parameters == RequestParameters() assert parameters == RequestParameters()
assert isinstance(body, BaseModel) assert isinstance(body, BaseModel)
assert body.created == datetime(2016, 4, 16, 16, 6, 5) assert body.created == datetime(2016, 4, 16, 16, 6, 5, tzinfo=UTC)
assert body.name == pet_name assert body.name == pet_name
code = 400 code = 400

View file

@ -1,6 +1,7 @@
import datetime import datetime
import uuid import uuid
from isodate.tzinfo import UTC, FixedOffset
import pytest import pytest
from openapi_core.schema.media_types.models import MediaType from openapi_core.schema.media_types.models import MediaType
@ -199,13 +200,30 @@ class TestSchemaUnmarshallerCall(object):
assert result == datetime.date(2018, 1, 2) assert result == datetime.date(2018, 1, 2)
def test_string_format_datetime(self, unmarshaller_factory): def test_string_format_datetime_invalid(self, unmarshaller_factory):
schema = Schema('string', schema_format='date-time')
value = '2018-01-02T00:00:00'
with pytest.raises(InvalidSchemaValue):
unmarshaller_factory(schema)(value)
def test_string_format_datetime_utc(self, unmarshaller_factory):
schema = Schema('string', schema_format='date-time') schema = Schema('string', schema_format='date-time')
value = '2018-01-02T00:00:00Z' value = '2018-01-02T00:00:00Z'
result = unmarshaller_factory(schema)(value) result = unmarshaller_factory(schema)(value)
assert result == datetime.datetime(2018, 1, 2, 0, 0) tzinfo = UTC
assert result == datetime.datetime(2018, 1, 2, 0, 0, tzinfo=tzinfo)
def test_string_format_datetime_tz(self, unmarshaller_factory):
schema = Schema('string', schema_format='date-time')
value = '2020-04-01T12:00:00+02:00'
result = unmarshaller_factory(schema)(value)
tzinfo = FixedOffset(2)
assert result == datetime.datetime(2020, 4, 1, 12, 0, 0, tzinfo=tzinfo)
def test_string_format_custom(self, unmarshaller_factory): def test_string_format_custom(self, unmarshaller_factory):
formatted = 'x-custom' formatted = 'x-custom'