mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-22 03:00:10 +00:00
Move param deserializers to separate subpackage
This commit is contained in:
parent
7b87cf9019
commit
58d5c26fee
12 changed files with 141 additions and 94 deletions
0
openapi_core/deserializing/__init__.py
Normal file
0
openapi_core/deserializing/__init__.py
Normal file
14
openapi_core/deserializing/exceptions.py
Normal file
14
openapi_core/deserializing/exceptions.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import attr
|
||||
|
||||
from openapi_core.exceptions import OpenAPIError
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class DeserializeError(OpenAPIError):
|
||||
"""Deserialize operation error"""
|
||||
value = attr.ib()
|
||||
style = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Failed to deserialize value {value} with style {style}".format(
|
||||
value=self.value, style=self.style)
|
0
openapi_core/deserializing/parameters/__init__.py
Normal file
0
openapi_core/deserializing/parameters/__init__.py
Normal file
26
openapi_core/deserializing/parameters/deserializers.py
Normal file
26
openapi_core/deserializing/parameters/deserializers.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from openapi_core.deserializing.exceptions import DeserializeError
|
||||
from openapi_core.deserializing.parameters.exceptions import (
|
||||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.parameters.enums import ParameterLocation
|
||||
from openapi_core.schema.schemas.types import NoValue
|
||||
|
||||
|
||||
class PrimitiveDeserializer(object):
|
||||
|
||||
def __init__(self, param, deserializer_callable):
|
||||
self.param = param
|
||||
self.deserializer_callable = deserializer_callable
|
||||
|
||||
def __call__(self, value):
|
||||
if (self.param.location == ParameterLocation.QUERY and value == "" and
|
||||
not self.param.allow_empty_value):
|
||||
raise EmptyParameterValue(
|
||||
value, self.param.style, self.param.name)
|
||||
|
||||
if not self.param.aslist or self.param.explode:
|
||||
return value
|
||||
try:
|
||||
return self.deserializer_callable(value)
|
||||
except (ValueError, TypeError, AttributeError) as exc:
|
||||
raise DeserializeError(value, self.param.style)
|
11
openapi_core/deserializing/parameters/exceptions.py
Normal file
11
openapi_core/deserializing/parameters/exceptions.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
import attr
|
||||
|
||||
from openapi_core.deserializing.exceptions import DeserializeError
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class EmptyParameterValue(DeserializeError):
|
||||
name = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Value of parameter cannot be empty: {0}".format(self.name)
|
26
openapi_core/deserializing/parameters/factories.py
Normal file
26
openapi_core/deserializing/parameters/factories.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import warnings
|
||||
|
||||
from openapi_core.deserializing.parameters.deserializers import (
|
||||
PrimitiveDeserializer,
|
||||
)
|
||||
from openapi_core.schema.parameters.enums import ParameterStyle
|
||||
|
||||
|
||||
class ParameterDeserializersFactory(object):
|
||||
|
||||
PARAMETER_STYLE_DESERIALIZERS = {
|
||||
ParameterStyle.FORM: lambda x: x.split(','),
|
||||
ParameterStyle.SIMPLE: lambda x: x.split(','),
|
||||
ParameterStyle.SPACE_DELIMITED: lambda x: x.split(' '),
|
||||
ParameterStyle.PIPE_DELIMITED: lambda x: x.split('|'),
|
||||
}
|
||||
|
||||
def create(self, param):
|
||||
if param.deprecated:
|
||||
warnings.warn(
|
||||
"{0} parameter is deprecated".format(param.name),
|
||||
DeprecationWarning,
|
||||
)
|
||||
|
||||
deserialize_callable = self.PARAMETER_STYLE_DESERIALIZERS[param.style]
|
||||
return PrimitiveDeserializer(param, deserialize_callable)
|
|
@ -27,21 +27,3 @@ class MissingRequiredParameter(MissingParameterError):
|
|||
|
||||
def __str__(self):
|
||||
return "Missing required parameter: {0}".format(self.name)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class EmptyParameterValue(OpenAPIParameterError):
|
||||
name = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Value of parameter cannot be empty: {0}".format(self.name)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidParameterValue(OpenAPIParameterError):
|
||||
name = attr.ib()
|
||||
original_exception = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid parameter value for `{0}`: {1}".format(
|
||||
self.name, self.original_exception)
|
||||
|
|
|
@ -5,12 +5,7 @@ import warnings
|
|||
from openapi_core.schema.parameters.enums import (
|
||||
ParameterLocation, ParameterStyle,
|
||||
)
|
||||
from openapi_core.schema.parameters.exceptions import (
|
||||
MissingRequiredParameter, MissingParameter, InvalidParameterValue,
|
||||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.casting.schemas.exceptions import CastError
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -18,13 +13,6 @@ log = logging.getLogger(__name__)
|
|||
class Parameter(object):
|
||||
"""Represents an OpenAPI operation Parameter."""
|
||||
|
||||
PARAMETER_STYLE_DESERIALIZERS = {
|
||||
ParameterStyle.FORM: lambda x: x.split(','),
|
||||
ParameterStyle.SIMPLE: lambda x: x.split(','),
|
||||
ParameterStyle.SPACE_DELIMITED: lambda x: x.split(' '),
|
||||
ParameterStyle.PIPE_DELIMITED: lambda x: x.split('|'),
|
||||
}
|
||||
|
||||
def __init__(
|
||||
self, name, location, schema=None, required=False,
|
||||
deprecated=False, allow_empty_value=False,
|
||||
|
@ -61,29 +49,3 @@ class Parameter(object):
|
|||
@property
|
||||
def default_explode(self):
|
||||
return self.style == ParameterStyle.FORM
|
||||
|
||||
def get_dererializer(self):
|
||||
return self.PARAMETER_STYLE_DESERIALIZERS[self.style]
|
||||
|
||||
def deserialize(self, value):
|
||||
if not self.aslist or self.explode:
|
||||
return value
|
||||
|
||||
deserializer = self.get_dererializer()
|
||||
return deserializer(value)
|
||||
|
||||
def deserialise(self, value):
|
||||
if self.deprecated:
|
||||
warnings.warn(
|
||||
"{0} parameter is deprecated".format(self.name),
|
||||
DeprecationWarning,
|
||||
)
|
||||
|
||||
if (self.location == ParameterLocation.QUERY and value == "" and
|
||||
not self.allow_empty_value):
|
||||
raise EmptyParameterValue(self.name)
|
||||
|
||||
try:
|
||||
return self.deserialize(value)
|
||||
except (ValueError, AttributeError) as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
|
|
@ -3,10 +3,12 @@ from itertools import chain
|
|||
from six import iteritems
|
||||
|
||||
from openapi_core.casting.schemas.exceptions import CastError
|
||||
from openapi_core.deserializing.exceptions import DeserializeError
|
||||
from openapi_core.schema.media_types.exceptions import (
|
||||
InvalidMediaTypeValue, InvalidContentType,
|
||||
)
|
||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||
from openapi_core.schema.parameters.enums import ParameterLocation
|
||||
from openapi_core.schema.parameters.exceptions import (
|
||||
OpenAPIParameterError, MissingRequiredParameter, MissingParameter,
|
||||
)
|
||||
|
@ -110,8 +112,9 @@ class RequestValidator(object):
|
|||
casted = param.schema.default
|
||||
else:
|
||||
try:
|
||||
deserialised = self._deserialise(param, raw_value)
|
||||
except OpenAPIParameterError as exc:
|
||||
deserialised = self._deserialise_parameter(
|
||||
param, raw_value)
|
||||
except DeserializeError as exc:
|
||||
errors.append(exc)
|
||||
continue
|
||||
|
||||
|
@ -146,7 +149,7 @@ class RequestValidator(object):
|
|||
return None, [exc, ]
|
||||
|
||||
try:
|
||||
deserialised = self._deserialise(media_type, raw_body)
|
||||
deserialised = self._deserialise_media_type(media_type, raw_body)
|
||||
except InvalidMediaTypeValue as exc:
|
||||
return None, [exc, ]
|
||||
|
||||
|
@ -183,9 +186,17 @@ class RequestValidator(object):
|
|||
raise MissingRequestBody(request)
|
||||
return request.body
|
||||
|
||||
def _deserialise(self, param_or_media_type, value):
|
||||
def _deserialise_media_type(self, param_or_media_type, value):
|
||||
return param_or_media_type.deserialise(value)
|
||||
|
||||
def _deserialise_parameter(self, param, value):
|
||||
from openapi_core.deserializing.parameters.factories import (
|
||||
ParameterDeserializersFactory,
|
||||
)
|
||||
deserializers_factory = ParameterDeserializersFactory()
|
||||
deserializer = deserializers_factory.create(param)
|
||||
return deserializer(value)
|
||||
|
||||
def _cast(self, param_or_media_type, value):
|
||||
# return param_or_media_type.cast(value)
|
||||
if not param_or_media_type.schema:
|
||||
|
|
|
@ -6,10 +6,14 @@ from uuid import UUID
|
|||
from six import text_type
|
||||
|
||||
from openapi_core.casting.schemas.exceptions import CastError
|
||||
from openapi_core.deserializing.exceptions import DeserializeError
|
||||
from openapi_core.deserializing.parameters.exceptions import (
|
||||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.extensions.models.models import BaseModel
|
||||
from openapi_core.schema.media_types.exceptions import InvalidContentType
|
||||
from openapi_core.schema.parameters.exceptions import (
|
||||
MissingRequiredParameter, InvalidParameterValue, EmptyParameterValue,
|
||||
MissingRequiredParameter,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
|
@ -273,7 +277,7 @@ class TestPetstore(object):
|
|||
path_pattern=path_pattern, args=query_params,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidParameterValue):
|
||||
with pytest.raises(DeserializeError):
|
||||
validate_parameters(spec, request)
|
||||
|
||||
body = validate_body(spec, request)
|
||||
|
|
43
tests/unit/deserializing/test_deserialize.py
Normal file
43
tests/unit/deserializing/test_deserialize.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import pytest
|
||||
|
||||
from openapi_core.deserializing.parameters.factories import (
|
||||
ParameterDeserializersFactory,
|
||||
)
|
||||
from openapi_core.deserializing.parameters.exceptions import (
|
||||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.parameters.models import Parameter
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def deserializer_factory():
|
||||
def create_deserializer(param):
|
||||
return ParameterDeserializersFactory().create(param)
|
||||
return create_deserializer
|
||||
|
||||
|
||||
class TestParameterDeserialise(object):
|
||||
|
||||
def test_deprecated(self, deserializer_factory):
|
||||
param = Parameter('param', 'query', deprecated=True)
|
||||
value = 'test'
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
result = deserializer_factory(param)(value)
|
||||
|
||||
assert result == value
|
||||
|
||||
def test_query_empty(self, deserializer_factory):
|
||||
param = Parameter('param', 'query')
|
||||
value = ''
|
||||
|
||||
with pytest.raises(EmptyParameterValue):
|
||||
deserializer_factory(param)(value)
|
||||
|
||||
def test_query_valid(self, deserializer_factory):
|
||||
param = Parameter('param', 'query')
|
||||
value = 'test'
|
||||
|
||||
result = deserializer_factory(param)(value)
|
||||
|
||||
assert result == value
|
|
@ -1,8 +1,3 @@
|
|||
import pytest
|
||||
|
||||
from openapi_core.schema.parameters.exceptions import (
|
||||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.parameters.enums import ParameterStyle
|
||||
from openapi_core.schema.parameters.models import Parameter
|
||||
|
||||
|
@ -36,30 +31,3 @@ class TestParameterInit(object):
|
|||
assert param.allow_empty_value is False
|
||||
assert param.style == ParameterStyle.FORM
|
||||
assert param.explode is True
|
||||
|
||||
|
||||
class TestParameterDeserialise(object):
|
||||
|
||||
def test_deprecated(self):
|
||||
param = Parameter('param', 'query', deprecated=True)
|
||||
value = 'test'
|
||||
|
||||
with pytest.warns(DeprecationWarning):
|
||||
result = param.deserialise(value)
|
||||
|
||||
assert result == value
|
||||
|
||||
def test_query_empty(self):
|
||||
param = Parameter('param', 'query')
|
||||
value = ''
|
||||
|
||||
with pytest.raises(EmptyParameterValue):
|
||||
param.deserialise(value)
|
||||
|
||||
def test_query_valid(self):
|
||||
param = Parameter('param', 'query')
|
||||
value = 'test'
|
||||
|
||||
result = param.deserialise(value)
|
||||
|
||||
assert result == value
|
||||
|
|
Loading…
Reference in a new issue