mirror of
https://github.com/correl/openapi-core.git
synced 2024-12-29 11:09:25 +00:00
Merge pull request #168 from p1c2u/feature/schema-exceptions-refactor
Schema exceptions refactor
This commit is contained in:
commit
4c4636a263
10 changed files with 183 additions and 149 deletions
|
@ -4,7 +4,9 @@ from collections import defaultdict
|
|||
from json import loads
|
||||
|
||||
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
|
||||
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
CastError, ValidateError, UnmarshalError,
|
||||
)
|
||||
|
||||
|
||||
MEDIA_TYPE_DESERIALIZERS = {
|
||||
|
@ -37,20 +39,25 @@ class MediaType(object):
|
|||
return value
|
||||
|
||||
try:
|
||||
return self.deserialize(value)
|
||||
deserialized = self.deserialize(value)
|
||||
except ValueError as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
||||
try:
|
||||
return self.schema.cast(deserialized)
|
||||
except CastError as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
||||
def unmarshal(self, value, custom_formatters=None, resolver=None):
|
||||
if not self.schema:
|
||||
return value
|
||||
|
||||
try:
|
||||
self.schema.validate(value, resolver=resolver)
|
||||
except OpenAPISchemaError as exc:
|
||||
except ValidateError as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
||||
try:
|
||||
return self.schema.unmarshal(value, custom_formatters=custom_formatters)
|
||||
except OpenAPISchemaError as exc:
|
||||
except UnmarshalError as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
|
|
@ -7,8 +7,13 @@ class OpenAPIParameterError(OpenAPIMappingError):
|
|||
pass
|
||||
|
||||
|
||||
class MissingParameterError(OpenAPIParameterError):
|
||||
"""Missing parameter error"""
|
||||
pass
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class MissingParameter(OpenAPIParameterError):
|
||||
class MissingParameter(MissingParameterError):
|
||||
name = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
|
@ -16,7 +21,7 @@ class MissingParameter(OpenAPIParameterError):
|
|||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class MissingRequiredParameter(OpenAPIParameterError):
|
||||
class MissingRequiredParameter(MissingParameterError):
|
||||
name = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -10,7 +10,9 @@ from openapi_core.schema.parameters.exceptions import (
|
|||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
CastError, ValidateError, UnmarshalError,
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -110,7 +112,7 @@ class Parameter(object):
|
|||
|
||||
try:
|
||||
return self.schema.cast(deserialized)
|
||||
except OpenAPISchemaError as exc:
|
||||
except CastError as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
||||
def unmarshal(self, value, custom_formatters=None, resolver=None):
|
||||
|
@ -119,7 +121,7 @@ class Parameter(object):
|
|||
|
||||
try:
|
||||
self.schema.validate(value, resolver=resolver)
|
||||
except OpenAPISchemaError as exc:
|
||||
except ValidateError as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
||||
try:
|
||||
|
@ -128,5 +130,5 @@ class Parameter(object):
|
|||
custom_formatters=custom_formatters,
|
||||
strict=True,
|
||||
)
|
||||
except OpenAPISchemaError as exc:
|
||||
except UnmarshalError as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
|
|
@ -8,72 +8,95 @@ class OpenAPISchemaError(OpenAPIMappingError):
|
|||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class NoValidSchema(OpenAPISchemaError):
|
||||
value = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "No valid schema found for value: {0}".format(self.value)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class UndefinedItemsSchema(OpenAPISchemaError):
|
||||
type = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Null value for schema type {0}".format(self.type)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidSchemaValue(OpenAPISchemaError):
|
||||
msg = attr.ib()
|
||||
class CastError(OpenAPISchemaError):
|
||||
"""Schema cast operation error"""
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return self.msg.format(value=self.value, type=self.type)
|
||||
return "Failed to cast value {value} to type {type}".format(
|
||||
value=self.value, type=self.type)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidCustomFormatSchemaValue(InvalidSchemaValue):
|
||||
original_exception = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return self.msg.format(value=self.value, type=self.type, exception=self.original_exception)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class UndefinedSchemaProperty(OpenAPISchemaError):
|
||||
extra_props = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Extra unexpected properties found in schema: {0}".format(self.extra_props)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidSchemaProperty(OpenAPISchemaError):
|
||||
property_name = attr.ib()
|
||||
original_exception = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Invalid schema property {0}: {1}".format(self.property_name, self.original_exception)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class MissingSchemaProperty(OpenAPISchemaError):
|
||||
property_name = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Missing schema property: {0}".format(self.property_name)
|
||||
|
||||
|
||||
class UnmarshallerError(OpenAPIMappingError):
|
||||
class ValidateError(OpenAPISchemaError):
|
||||
"""Schema validate operation error"""
|
||||
pass
|
||||
|
||||
|
||||
class UnmarshalError(OpenAPISchemaError):
|
||||
"""Schema unmarshal operation error"""
|
||||
pass
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class UnmarshalValueError(UnmarshalError):
|
||||
"""Failed to unmarshal value to type"""
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
original_exception = attr.ib(default=None)
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Failed to unmarshal value {value} to type {type}: {exception}"
|
||||
).format(
|
||||
value=self.value, type=self.type,
|
||||
exception=self.original_exception,
|
||||
)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidSchemaValue(ValidateError):
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
schema_errors = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
errors = list(self.schema_errors)
|
||||
return (
|
||||
"Value {value} not valid for schema of type {type}: {errors}"
|
||||
).format(value=self.value, type=self.type, errors=errors)
|
||||
|
||||
|
||||
class UnmarshallerError(UnmarshalError):
|
||||
"""Unmarshaller error"""
|
||||
pass
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidCustomFormatSchemaValue(UnmarshallerError):
|
||||
"""Value failed to format with custom formatter"""
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
original_exception = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Failed to format value {value} to format {type}: {exception}"
|
||||
).format(
|
||||
value=self.value, type=self.type,
|
||||
exception=self.original_exception,
|
||||
)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class FormatterNotFoundError(UnmarshallerError):
|
||||
"""Formatter not found to unmarshal"""
|
||||
value = attr.ib()
|
||||
type_format = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Formatter not found for {format} format "
|
||||
"to unmarshal value {value}"
|
||||
).format(format=self.type_format, value=self.value)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class UnmarshallerStrictTypeError(UnmarshallerError):
|
||||
value = attr.ib()
|
||||
types = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
return "Value {value} is not one of types {types}".format(
|
||||
self.value, self.types)
|
||||
types = ', '.join(list(map(str, self.types)))
|
||||
return "Value {value} is not one of types: {types}".format(
|
||||
value=self.value, types=types)
|
||||
|
|
|
@ -15,10 +15,8 @@ from openapi_core.extensions.models.factories import ModelFactory
|
|||
from openapi_core.schema.schemas._format import oas30_format_checker
|
||||
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
InvalidSchemaValue, UndefinedSchemaProperty, MissingSchemaProperty,
|
||||
OpenAPISchemaError, NoValidSchema,
|
||||
UndefinedItemsSchema, InvalidCustomFormatSchemaValue, InvalidSchemaProperty,
|
||||
UnmarshallerStrictTypeError,
|
||||
CastError, InvalidSchemaValue,
|
||||
UnmarshallerError, UnmarshalValueError, UnmarshalError,
|
||||
)
|
||||
from openapi_core.schema.schemas.util import (
|
||||
forcebool, format_date, format_datetime, format_byte, format_uuid,
|
||||
|
@ -141,13 +139,6 @@ class Schema(object):
|
|||
|
||||
return set(required)
|
||||
|
||||
def are_additional_properties_allowed(self, one_of_schema=None):
|
||||
return (
|
||||
(self.additional_properties is not False) and
|
||||
(one_of_schema is None or
|
||||
one_of_schema.additional_properties is not False)
|
||||
)
|
||||
|
||||
def get_cast_mapping(self):
|
||||
mapping = self.TYPE_CAST_CALLABLE_GETTER.copy()
|
||||
mapping.update({
|
||||
|
@ -167,8 +158,7 @@ class Schema(object):
|
|||
try:
|
||||
return cast_callable(value)
|
||||
except ValueError:
|
||||
raise InvalidSchemaValue(
|
||||
"Failed to cast value {value} to type {type}", value, self.type)
|
||||
raise CastError(value, self.type)
|
||||
|
||||
def _cast_collection(self, value):
|
||||
return list(map(self.items.cast, value))
|
||||
|
@ -203,8 +193,8 @@ class Schema(object):
|
|||
try:
|
||||
return validator.validate(value)
|
||||
except ValidationError:
|
||||
# TODO: pass validation errors
|
||||
raise InvalidSchemaValue("Value not valid for schema", value, self.type)
|
||||
errors_iter = validator.iter_errors(value)
|
||||
raise InvalidSchemaValue(value, self.type, errors_iter)
|
||||
|
||||
def unmarshal(self, value, custom_formatters=None, strict=True):
|
||||
"""Unmarshal parameter from the value."""
|
||||
|
@ -212,12 +202,12 @@ class Schema(object):
|
|||
warnings.warn("The schema is deprecated", DeprecationWarning)
|
||||
if value is None:
|
||||
if not self.nullable:
|
||||
raise InvalidSchemaValue("Null value for non-nullable schema", value, self.type)
|
||||
raise UnmarshalError(
|
||||
"Null value for non-nullable schema", value, self.type)
|
||||
return self.default
|
||||
|
||||
if self.enum and value not in self.enum:
|
||||
raise InvalidSchemaValue(
|
||||
"Value {value} not in enum choices: {type}", value, self.enum)
|
||||
raise UnmarshalError("Invalid value for enum: {0}".format(value))
|
||||
|
||||
unmarshal_mapping = self.get_unmarshal_mapping(
|
||||
custom_formatters=custom_formatters, strict=strict)
|
||||
|
@ -228,12 +218,8 @@ class Schema(object):
|
|||
unmarshal_callable = unmarshal_mapping[self.type]
|
||||
try:
|
||||
unmarshalled = unmarshal_callable(value)
|
||||
except UnmarshallerStrictTypeError:
|
||||
raise InvalidSchemaValue(
|
||||
"Value {value} is not of type {type}", value, self.type)
|
||||
except ValueError:
|
||||
raise InvalidSchemaValue(
|
||||
"Failed to unmarshal value {value} to type {type}", value, self.type)
|
||||
except ValueError as exc:
|
||||
raise UnmarshalValueError(value, self.type, exc)
|
||||
|
||||
return unmarshalled
|
||||
|
||||
|
@ -268,7 +254,7 @@ class Schema(object):
|
|||
for subschema in self.one_of:
|
||||
try:
|
||||
unmarshalled = subschema.unmarshal(value, custom_formatters)
|
||||
except (OpenAPISchemaError, TypeError, ValueError):
|
||||
except UnmarshalError:
|
||||
continue
|
||||
else:
|
||||
if result is not None:
|
||||
|
@ -285,9 +271,7 @@ class Schema(object):
|
|||
unmarshal_callable = unmarshal_mapping[schema_type]
|
||||
try:
|
||||
return unmarshal_callable(value)
|
||||
except UnmarshallerStrictTypeError:
|
||||
continue
|
||||
except (OpenAPISchemaError, TypeError):
|
||||
except (UnmarshalError, ValueError):
|
||||
continue
|
||||
|
||||
log.warning("failed to unmarshal any type")
|
||||
|
@ -295,7 +279,7 @@ class Schema(object):
|
|||
|
||||
def _unmarshal_collection(self, value, custom_formatters=None, strict=True):
|
||||
if not isinstance(value, (list, tuple)):
|
||||
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
|
||||
raise ValueError("Invalid value for collection: {0}".format(value))
|
||||
|
||||
f = functools.partial(
|
||||
self.items.unmarshal,
|
||||
|
@ -306,7 +290,7 @@ class Schema(object):
|
|||
def _unmarshal_object(self, value, model_factory=None,
|
||||
custom_formatters=None, strict=True):
|
||||
if not isinstance(value, (dict, )):
|
||||
raise InvalidSchemaValue("Value {value} is not of type {type}", value, self.type)
|
||||
raise ValueError("Invalid value for object: {0}".format(value))
|
||||
|
||||
model_factory = model_factory or ModelFactory()
|
||||
|
||||
|
@ -316,7 +300,7 @@ class Schema(object):
|
|||
try:
|
||||
unmarshalled = self._unmarshal_properties(
|
||||
value, one_of_schema, custom_formatters=custom_formatters)
|
||||
except OpenAPISchemaError:
|
||||
except (UnmarshalError, ValueError):
|
||||
pass
|
||||
else:
|
||||
if properties is not None:
|
||||
|
@ -348,10 +332,6 @@ class Schema(object):
|
|||
|
||||
value_props_names = value.keys()
|
||||
extra_props = set(value_props_names) - set(all_props_names)
|
||||
extra_props_allowed = self.are_additional_properties_allowed(
|
||||
one_of_schema)
|
||||
if extra_props and not extra_props_allowed:
|
||||
raise UndefinedSchemaProperty(extra_props)
|
||||
|
||||
properties = {}
|
||||
if self.additional_properties is not True:
|
||||
|
@ -364,8 +344,6 @@ class Schema(object):
|
|||
try:
|
||||
prop_value = value[prop_name]
|
||||
except KeyError:
|
||||
if prop_name in all_req_props_names:
|
||||
raise MissingSchemaProperty(prop_name)
|
||||
if not prop.nullable and not prop.default:
|
||||
continue
|
||||
prop_value = prop.default
|
||||
|
|
|
@ -2,10 +2,9 @@ from six import text_type, binary_type, integer_types
|
|||
|
||||
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
InvalidSchemaValue, InvalidCustomFormatSchemaValue,
|
||||
OpenAPISchemaError,
|
||||
InvalidSchemaProperty,
|
||||
InvalidCustomFormatSchemaValue,
|
||||
UnmarshallerStrictTypeError,
|
||||
FormatterNotFoundError,
|
||||
)
|
||||
from openapi_core.schema.schemas.util import (
|
||||
forcebool, format_date, format_datetime, format_byte, format_uuid,
|
||||
|
@ -49,17 +48,12 @@ class PrimitiveTypeUnmarshaller(StrictUnmarshaller):
|
|||
formatter = formatters.get(schema_format)
|
||||
|
||||
if formatter is None:
|
||||
raise InvalidSchemaValue(
|
||||
"Unsupported format {type} unmarshalling "
|
||||
"for value {value}",
|
||||
value, type_format)
|
||||
raise FormatterNotFoundError(value, type_format)
|
||||
|
||||
try:
|
||||
return formatter(value)
|
||||
except ValueError as exc:
|
||||
raise InvalidCustomFormatSchemaValue(
|
||||
"Failed to format value {value} to format {type}: {exception}",
|
||||
value, type_format, exc)
|
||||
raise InvalidCustomFormatSchemaValue(value, type_format, exc)
|
||||
|
||||
def get_formatters(self):
|
||||
return self.FORMATTERS
|
||||
|
|
|
@ -2,8 +2,16 @@
|
|||
from itertools import chain
|
||||
from six import iteritems
|
||||
|
||||
from openapi_core.schema.exceptions import OpenAPIMappingError
|
||||
from openapi_core.schema.parameters.exceptions import MissingParameter
|
||||
from openapi_core.schema.media_types.exceptions import (
|
||||
InvalidMediaTypeValue, InvalidContentType,
|
||||
)
|
||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||
from openapi_core.schema.parameters.exceptions import (
|
||||
OpenAPIParameterError, MissingRequiredParameter,
|
||||
)
|
||||
from openapi_core.schema.paths.exceptions import InvalidPath
|
||||
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.validation.request.datatypes import (
|
||||
RequestParameters, RequestValidationResult,
|
||||
)
|
||||
|
@ -20,7 +28,7 @@ class RequestValidator(object):
|
|||
try:
|
||||
server = self.spec.get_server(request.full_url_pattern)
|
||||
# don't process if server errors
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidServer as exc:
|
||||
return RequestValidationResult([exc, ], None, None)
|
||||
|
||||
operation_pattern = get_operation_pattern(
|
||||
|
@ -29,10 +37,14 @@ class RequestValidator(object):
|
|||
|
||||
try:
|
||||
path = self.spec[operation_pattern]
|
||||
except InvalidPath as exc:
|
||||
return RequestValidationResult([exc, ], None, None)
|
||||
|
||||
try:
|
||||
operation = self.spec.get_operation(
|
||||
operation_pattern, request.method)
|
||||
# don't process if operation errors
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidOperation as exc:
|
||||
return RequestValidationResult([exc, ], None, None)
|
||||
|
||||
params, params_errors = self._get_parameters(
|
||||
|
@ -59,15 +71,15 @@ class RequestValidator(object):
|
|||
seen.add((param_name, param.location.value))
|
||||
try:
|
||||
raw_value = param.get_raw_value(request)
|
||||
except MissingParameter:
|
||||
continue
|
||||
except OpenAPIMappingError as exc:
|
||||
except MissingRequiredParameter as exc:
|
||||
errors.append(exc)
|
||||
continue
|
||||
except OpenAPIParameterError:
|
||||
continue
|
||||
|
||||
try:
|
||||
casted = param.cast(raw_value)
|
||||
except OpenAPIMappingError as exc:
|
||||
except OpenAPIParameterError as exc:
|
||||
errors.append(exc)
|
||||
continue
|
||||
|
||||
|
@ -76,7 +88,7 @@ class RequestValidator(object):
|
|||
casted, self.custom_formatters,
|
||||
resolver=self.spec._resolver,
|
||||
)
|
||||
except OpenAPIMappingError as exc:
|
||||
except OpenAPIParameterError as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
locations.setdefault(param.location.value, {})
|
||||
|
@ -93,17 +105,17 @@ class RequestValidator(object):
|
|||
body = None
|
||||
try:
|
||||
media_type = operation.request_body[request.mimetype]
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidContentType as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
raw_body = operation.request_body.get_value(request)
|
||||
except OpenAPIMappingError as exc:
|
||||
except MissingRequestBody as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
casted = media_type.cast(raw_body)
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidMediaTypeValue as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
|
@ -111,7 +123,7 @@ class RequestValidator(object):
|
|||
casted, self.custom_formatters,
|
||||
resolver=self.spec._resolver,
|
||||
)
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidMediaTypeValue as exc:
|
||||
errors.append(exc)
|
||||
|
||||
return body, errors
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
"""OpenAPI core validation response validators module"""
|
||||
from openapi_core.schema.exceptions import OpenAPIMappingError
|
||||
from openapi_core.schema.operations.exceptions import InvalidOperation
|
||||
from openapi_core.schema.media_types.exceptions import (
|
||||
InvalidMediaTypeValue, InvalidContentType,
|
||||
)
|
||||
from openapi_core.schema.responses.exceptions import (
|
||||
InvalidResponse, MissingResponseContent,
|
||||
)
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.validation.response.datatypes import ResponseValidationResult
|
||||
from openapi_core.validation.util import get_operation_pattern
|
||||
|
||||
|
@ -14,7 +21,7 @@ class ResponseValidator(object):
|
|||
try:
|
||||
server = self.spec.get_server(request.full_url_pattern)
|
||||
# don't process if server errors
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidServer as exc:
|
||||
return ResponseValidationResult([exc, ], None, None)
|
||||
|
||||
operation_pattern = get_operation_pattern(
|
||||
|
@ -25,14 +32,14 @@ class ResponseValidator(object):
|
|||
operation = self.spec.get_operation(
|
||||
operation_pattern, request.method)
|
||||
# don't process if operation errors
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidOperation as exc:
|
||||
return ResponseValidationResult([exc, ], None, None)
|
||||
|
||||
try:
|
||||
operation_response = operation.get_response(
|
||||
str(response.status_code))
|
||||
# don't process if operation response errors
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidResponse as exc:
|
||||
return ResponseValidationResult([exc, ], None, None)
|
||||
|
||||
data, data_errors = self._get_data(response, operation_response)
|
||||
|
@ -52,17 +59,17 @@ class ResponseValidator(object):
|
|||
data = None
|
||||
try:
|
||||
media_type = operation_response[response.mimetype]
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidContentType as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
raw_data = operation_response.get_value(response)
|
||||
except OpenAPIMappingError as exc:
|
||||
except MissingResponseContent as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
casted = media_type.cast(raw_data)
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidMediaTypeValue as exc:
|
||||
errors.append(exc)
|
||||
else:
|
||||
try:
|
||||
|
@ -70,7 +77,7 @@ class ResponseValidator(object):
|
|||
casted, self.custom_formatters,
|
||||
resolver=self.spec._resolver,
|
||||
)
|
||||
except OpenAPIMappingError as exc:
|
||||
except InvalidMediaTypeValue as exc:
|
||||
errors.append(exc)
|
||||
|
||||
return data, errors
|
||||
|
|
|
@ -175,12 +175,13 @@ class TestPetstore(object):
|
|||
|
||||
response_result = response_validator.validate(request, response)
|
||||
|
||||
errors = response_result.errors[0].original_exception.schema_errors
|
||||
assert response_result.errors == [
|
||||
InvalidMediaTypeValue(
|
||||
original_exception=InvalidSchemaValue(
|
||||
msg='Value not valid for schema',
|
||||
type=SchemaType.OBJECT,
|
||||
value=data_json,
|
||||
schema_errors=errors,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -7,7 +7,9 @@ import pytest
|
|||
from openapi_core.extensions.models.models import Model
|
||||
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
InvalidSchemaValue, OpenAPISchemaError,
|
||||
InvalidSchemaValue, OpenAPISchemaError, UnmarshallerStrictTypeError,
|
||||
UnmarshalValueError, UnmarshalError, InvalidCustomFormatSchemaValue,
|
||||
FormatterNotFoundError,
|
||||
)
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
|
||||
|
@ -88,14 +90,14 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('string')
|
||||
value = 1.23
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_none(self):
|
||||
schema = Schema('string')
|
||||
value = None
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_default(self):
|
||||
|
@ -103,7 +105,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('string', default=default_value)
|
||||
value = None
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_default_nullable(self):
|
||||
|
@ -150,7 +152,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(InvalidCustomFormatSchemaValue):
|
||||
schema.unmarshal(
|
||||
value, custom_formatters={custom_format: custom_formatter})
|
||||
|
||||
|
@ -168,7 +170,10 @@ class TestSchemaUnmarshal(object):
|
|||
value = 'x'
|
||||
|
||||
with pytest.raises(
|
||||
InvalidSchemaValue, message='Failed to format value'
|
||||
FormatterNotFoundError,
|
||||
message=(
|
||||
'Formatter not found for custom format to unmarshal value x'
|
||||
),
|
||||
):
|
||||
schema.unmarshal(value)
|
||||
|
||||
|
@ -184,14 +189,14 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer')
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_enum_invalid(self):
|
||||
schema = Schema('integer', enum=[1, 2, 3])
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_enum(self):
|
||||
|
@ -206,7 +211,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer', enum=[1, 2, 3])
|
||||
value = '2'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_default(self):
|
||||
|
@ -214,7 +219,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer', default=default_value)
|
||||
value = None
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_default_nullable(self):
|
||||
|
@ -230,7 +235,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer')
|
||||
value = 'abc'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_array_valid(self):
|
||||
|
@ -245,14 +250,14 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('array', items=Schema('string'))
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalValueError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_array_of_integer_string_invalid(self):
|
||||
schema = Schema('array', items=Schema('integer'))
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshalValueError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_boolean_valid(self):
|
||||
|
@ -267,7 +272,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('boolean')
|
||||
value = 'True'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_number_valid(self):
|
||||
|
@ -282,7 +287,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('number')
|
||||
value = '1.23'
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_number_int(self):
|
||||
|
|
Loading…
Reference in a new issue