mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-25 11:09:53 +00:00
Merge pull request #186 from p1c2u/refactor/move-schema-validator-to-separate-subpackage
Move schema validator to separate subpackage
This commit is contained in:
commit
d644039478
18 changed files with 1055 additions and 992 deletions
|
@ -3,11 +3,10 @@ from collections import defaultdict
|
|||
|
||||
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
|
||||
from openapi_core.schema.media_types.util import json_loads
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
ValidateError,
|
||||
)
|
||||
from openapi_core.casting.schemas.exceptions import CastError
|
||||
from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError,
|
||||
)
|
||||
|
||||
|
||||
MEDIA_TYPE_DESERIALIZERS = {
|
||||
|
@ -53,13 +52,8 @@ class MediaType(object):
|
|||
if not self.schema:
|
||||
return value
|
||||
|
||||
try:
|
||||
self.schema.validate(value, resolver=resolver)
|
||||
except ValidateError as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
||||
try:
|
||||
return self.schema.unmarshal(
|
||||
value, custom_formatters=custom_formatters)
|
||||
except UnmarshalError as exc:
|
||||
value, resolver=resolver, custom_formatters=custom_formatters)
|
||||
except (ValidateError, UnmarshalError) as exc:
|
||||
raise InvalidMediaTypeValue(exc)
|
||||
|
|
|
@ -10,11 +10,10 @@ from openapi_core.schema.parameters.exceptions import (
|
|||
EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
ValidateError,
|
||||
)
|
||||
from openapi_core.casting.schemas.exceptions import CastError
|
||||
from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError,
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
@ -120,16 +119,11 @@ class Parameter(object):
|
|||
if not self.schema:
|
||||
return value
|
||||
|
||||
try:
|
||||
self.schema.validate(value, resolver=resolver)
|
||||
except ValidateError as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
||||
try:
|
||||
return self.schema.unmarshal(
|
||||
value,
|
||||
resolver=resolver,
|
||||
custom_formatters=custom_formatters,
|
||||
strict=True,
|
||||
)
|
||||
except UnmarshalError as exc:
|
||||
except (ValidateError, UnmarshalError) as exc:
|
||||
raise InvalidParameterValue(self.name, exc)
|
||||
|
|
|
@ -1,31 +1,5 @@
|
|||
import attr
|
||||
|
||||
from openapi_core.schema.exceptions import OpenAPIMappingError
|
||||
|
||||
|
||||
class OpenAPISchemaError(OpenAPIMappingError):
|
||||
pass
|
||||
|
||||
|
||||
class ValidateError(OpenAPISchemaError):
|
||||
"""Schema validate operation error"""
|
||||
pass
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidSchemaValue(ValidateError):
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
_schema_errors = attr.ib(default=None)
|
||||
_schema_errors_iter = attr.ib(factory=list)
|
||||
|
||||
@property
|
||||
def schema_errors(self):
|
||||
if self._schema_errors is None:
|
||||
self._schema_errors = list(self._schema_errors_iter)
|
||||
return self._schema_errors
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Value {value} not valid for schema of type {type}: {errors}"
|
||||
).format(value=self.value, type=self.type, errors=self.schema_errors)
|
||||
|
|
|
@ -3,13 +3,8 @@ import attr
|
|||
import logging
|
||||
import re
|
||||
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
from openapi_core.schema.schemas._format import oas30_format_checker
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import InvalidSchemaValue
|
||||
from openapi_core.schema.schemas.types import NoValue
|
||||
from openapi_core.schema.schemas.validators import OAS30Validator
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalValueError,
|
||||
)
|
||||
|
@ -110,30 +105,15 @@ class Schema(object):
|
|||
except (ValueError, TypeError):
|
||||
raise CastError(value, self.type)
|
||||
|
||||
def get_validator(self, resolver=None):
|
||||
return OAS30Validator(
|
||||
self.__dict__,
|
||||
resolver=resolver, format_checker=oas30_format_checker,
|
||||
)
|
||||
|
||||
def validate(self, value, resolver=None):
|
||||
validator = self.get_validator(resolver=resolver)
|
||||
try:
|
||||
return validator.validate(value)
|
||||
except ValidationError:
|
||||
errors_iter = validator.iter_errors(value)
|
||||
raise InvalidSchemaValue(
|
||||
value, self.type, schema_errors_iter=errors_iter)
|
||||
|
||||
def unmarshal(self, value, custom_formatters=None, strict=True):
|
||||
def unmarshal(self, value, resolver=None, custom_formatters=None):
|
||||
"""Unmarshal parameter from the value."""
|
||||
from openapi_core.unmarshalling.schemas.factories import (
|
||||
SchemaUnmarshallersFactory,
|
||||
)
|
||||
unmarshallers_factory = SchemaUnmarshallersFactory(
|
||||
custom_formatters)
|
||||
resolver, custom_formatters)
|
||||
unmarshaller = unmarshallers_factory.create(self)
|
||||
try:
|
||||
return unmarshaller(value, strict=strict)
|
||||
return unmarshaller(value)
|
||||
except ValueError as exc:
|
||||
raise UnmarshalValueError(value, self.type, exc)
|
||||
|
|
4
openapi_core/schema_validator/__init__.py
Normal file
4
openapi_core/schema_validator/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from openapi_core.schema_validator._format import oas30_format_checker
|
||||
from openapi_core.schema_validator.validators import OAS30Validator
|
||||
|
||||
__all__ = ['OAS30Validator', 'oas30_format_checker']
|
|
@ -28,60 +28,41 @@ else:
|
|||
DATETIME_RAISES += (ValueError, TypeError)
|
||||
|
||||
|
||||
class StrictFormatChecker(FormatChecker):
|
||||
|
||||
def check(self, instance, format):
|
||||
if format not in self.checkers:
|
||||
raise FormatError(
|
||||
"Format checker for %r format not found" % (format, ))
|
||||
return super(StrictFormatChecker, self).check(
|
||||
instance, format)
|
||||
|
||||
|
||||
oas30_format_checker = StrictFormatChecker()
|
||||
|
||||
|
||||
@oas30_format_checker.checks('int32')
|
||||
def is_int32(instance):
|
||||
return isinstance(instance, integer_types)
|
||||
|
||||
|
||||
@oas30_format_checker.checks('int64')
|
||||
def is_int64(instance):
|
||||
return isinstance(instance, integer_types)
|
||||
|
||||
|
||||
@oas30_format_checker.checks('float')
|
||||
def is_float(instance):
|
||||
return isinstance(instance, float)
|
||||
|
||||
|
||||
@oas30_format_checker.checks('double')
|
||||
def is_double(instance):
|
||||
# float has double precision in Python
|
||||
# It's double in CPython and Jython
|
||||
return isinstance(instance, float)
|
||||
|
||||
|
||||
@oas30_format_checker.checks('binary')
|
||||
def is_binary(instance):
|
||||
return isinstance(instance, binary_type)
|
||||
|
||||
|
||||
@oas30_format_checker.checks('byte', raises=(binascii.Error, TypeError))
|
||||
def is_byte(instance):
|
||||
if isinstance(instance, text_type):
|
||||
instance = instance.encode()
|
||||
|
||||
try:
|
||||
return b64encode(b64decode(instance)) == instance
|
||||
|
||||
|
||||
@oas30_format_checker.checks("date-time", raises=DATETIME_RAISES)
|
||||
def is_datetime(instance):
|
||||
if isinstance(instance, binary_type):
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
|
||||
def is_datetime(instance):
|
||||
if not isinstance(instance, (binary_type, text_type)):
|
||||
return False
|
||||
if not isinstance(instance, text_type):
|
||||
return True
|
||||
|
||||
if DATETIME_HAS_STRICT_RFC3339:
|
||||
return strict_rfc3339.validate_rfc3339(instance)
|
||||
|
@ -92,24 +73,63 @@ def is_datetime(instance):
|
|||
return True
|
||||
|
||||
|
||||
@oas30_format_checker.checks("date", raises=ValueError)
|
||||
def is_date(instance):
|
||||
if isinstance(instance, binary_type):
|
||||
if not isinstance(instance, (binary_type, text_type)):
|
||||
return False
|
||||
if not isinstance(instance, text_type):
|
||||
return True
|
||||
|
||||
if isinstance(instance, binary_type):
|
||||
instance = instance.decode()
|
||||
|
||||
return datetime.strptime(instance, "%Y-%m-%d")
|
||||
|
||||
|
||||
@oas30_format_checker.checks("uuid", raises=AttributeError)
|
||||
def is_uuid(instance):
|
||||
if isinstance(instance, binary_type):
|
||||
return False
|
||||
if not isinstance(instance, text_type):
|
||||
return True
|
||||
try:
|
||||
uuid_obj = UUID(instance)
|
||||
except ValueError:
|
||||
if not isinstance(instance, (binary_type, text_type)):
|
||||
return False
|
||||
|
||||
return text_type(uuid_obj) == instance
|
||||
if isinstance(instance, binary_type):
|
||||
instance = instance.decode()
|
||||
|
||||
return text_type(UUID(instance)) == instance
|
||||
|
||||
|
||||
def is_password(instance):
|
||||
return True
|
||||
|
||||
|
||||
class OASFormatChecker(FormatChecker):
|
||||
|
||||
checkers = {
|
||||
'int32': (is_int32, ()),
|
||||
'int64': (is_int64, ()),
|
||||
'float': (is_float, ()),
|
||||
'double': (is_double, ()),
|
||||
'byte': (is_byte, (binascii.Error, TypeError)),
|
||||
'binary': (is_binary, ()),
|
||||
'date': (is_date, (ValueError, )),
|
||||
'date-time': (is_datetime, DATETIME_RAISES),
|
||||
'password': (is_password, ()),
|
||||
# non standard
|
||||
'uuid': (is_uuid, (AttributeError, ValueError)),
|
||||
}
|
||||
|
||||
def check(self, instance, format):
|
||||
if format not in self.checkers:
|
||||
raise FormatError(
|
||||
"Format checker for %r format not found" % (format, ))
|
||||
|
||||
func, raises = self.checkers[format]
|
||||
result, cause = None, None
|
||||
try:
|
||||
result = func(instance)
|
||||
except raises as e:
|
||||
cause = e
|
||||
|
||||
if not result:
|
||||
raise FormatError(
|
||||
"%r is not a %r" % (instance, format), cause=cause,
|
||||
)
|
||||
return result
|
||||
|
||||
|
||||
oas30_format_checker = OASFormatChecker()
|
|
@ -1,8 +1,8 @@
|
|||
from jsonschema import _legacy_validators, _utils, _validators
|
||||
from jsonschema.validators import create
|
||||
|
||||
from openapi_core.schema.schemas import _types as oas_types
|
||||
from openapi_core.schema.schemas import _validators as oas_validators
|
||||
from openapi_core.schema_validator import _types as oas_types
|
||||
from openapi_core.schema_validator import _validators as oas_validators
|
||||
|
||||
|
||||
BaseOAS30Validator = create(
|
|
@ -8,6 +8,11 @@ class UnmarshalError(OpenAPIError):
|
|||
pass
|
||||
|
||||
|
||||
class ValidateError(UnmarshalError):
|
||||
"""Schema validate operation error"""
|
||||
pass
|
||||
|
||||
|
||||
class UnmarshallerError(UnmarshalError):
|
||||
"""Unmarshaller error"""
|
||||
pass
|
||||
|
@ -30,8 +35,20 @@ class UnmarshalValueError(UnmarshalError):
|
|||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidCustomFormatSchemaValue(UnmarshallerError):
|
||||
"""Value failed to format with custom formatter"""
|
||||
class InvalidSchemaValue(ValidateError):
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
schema_errors = attr.ib(factory=tuple)
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
"Value {value} not valid for schema of type {type}: {errors}"
|
||||
).format(value=self.value, type=self.type, errors=self.schema_errors)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class InvalidSchemaFormatValue(UnmarshallerError):
|
||||
"""Value failed to format with formatter"""
|
||||
value = attr.ib()
|
||||
type = attr.ib()
|
||||
original_exception = attr.ib()
|
||||
|
@ -53,14 +70,3 @@ class FormatterNotFoundError(UnmarshallerError):
|
|||
def __str__(self):
|
||||
return "Formatter not found for {format} format".format(
|
||||
format=self.type_format)
|
||||
|
||||
|
||||
@attr.s(hash=True)
|
||||
class UnmarshallerStrictTypeError(UnmarshallerError):
|
||||
value = attr.ib()
|
||||
types = attr.ib()
|
||||
|
||||
def __str__(self):
|
||||
types = ', '.join(list(map(str, self.types)))
|
||||
return "Value {value} is not one of types: {types}".format(
|
||||
value=self.value, types=types)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from copy import deepcopy
|
||||
import warnings
|
||||
|
||||
from openapi_core.schema.schemas.enums import SchemaType, SchemaFormat
|
||||
from openapi_core.schema_validator import OAS30Validator
|
||||
from openapi_core.schema_validator import oas30_format_checker
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
FormatterNotFoundError,
|
||||
)
|
||||
|
@ -25,7 +28,8 @@ class SchemaUnmarshallersFactory(object):
|
|||
SchemaType.ANY: AnyUnmarshaller,
|
||||
}
|
||||
|
||||
def __init__(self, custom_formatters=None):
|
||||
def __init__(self, resolver=None, custom_formatters=None):
|
||||
self.resolver = resolver
|
||||
if custom_formatters is None:
|
||||
custom_formatters = {}
|
||||
self.custom_formatters = custom_formatters
|
||||
|
@ -42,21 +46,31 @@ class SchemaUnmarshallersFactory(object):
|
|||
|
||||
elif schema_type in self.COMPLEX_UNMARSHALLERS:
|
||||
klass = self.COMPLEX_UNMARSHALLERS[schema_type]
|
||||
kwargs = dict(schema=schema, unmarshallers_factory=self)
|
||||
kwargs = dict(
|
||||
schema=schema, unmarshallers_factory=self)
|
||||
|
||||
formatter = self.get_formatter(klass.FORMATTERS, schema.format)
|
||||
|
||||
if formatter is None:
|
||||
raise FormatterNotFoundError(schema.format)
|
||||
|
||||
return klass(formatter, **kwargs)
|
||||
validator = self.get_validator(schema)
|
||||
|
||||
def get_formatter(self, formatters, type_format=SchemaFormat.NONE):
|
||||
return klass(formatter, validator, **kwargs)
|
||||
|
||||
def get_formatter(self, default_formatters, type_format=SchemaFormat.NONE):
|
||||
try:
|
||||
schema_format = SchemaFormat(type_format)
|
||||
except ValueError:
|
||||
return self.custom_formatters.get(type_format)
|
||||
else:
|
||||
if schema_format == SchemaFormat.NONE:
|
||||
return lambda x: x
|
||||
return formatters.get(schema_format)
|
||||
return default_formatters.get(schema_format)
|
||||
|
||||
def get_validator(self, schema):
|
||||
format_checker = deepcopy(oas30_format_checker)
|
||||
for name, formatter in self.custom_formatters.items():
|
||||
format_checker.checks(name)(formatter.validate)
|
||||
return OAS30Validator(
|
||||
schema.__dict__,
|
||||
resolver=self.resolver, format_checker=format_checker,
|
||||
)
|
||||
|
|
18
openapi_core/unmarshalling/schemas/formatters.py
Normal file
18
openapi_core/unmarshalling/schemas/formatters.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
class Formatter(object):
|
||||
|
||||
def validate(self, value):
|
||||
return True
|
||||
|
||||
def unmarshal(self, value):
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def from_callables(cls, validate=None, unmarshal=None):
|
||||
attrs = {}
|
||||
if validate is not None:
|
||||
attrs['validate'] = staticmethod(validate)
|
||||
if unmarshal is not None:
|
||||
attrs['unmarshal'] = staticmethod(unmarshal)
|
||||
|
||||
klass = type('Formatter', (cls, ), attrs)
|
||||
return klass()
|
|
@ -1,19 +1,22 @@
|
|||
from functools import partial
|
||||
import logging
|
||||
|
||||
from six import text_type, binary_type, integer_types
|
||||
from six import text_type, binary_type
|
||||
from six import iteritems
|
||||
|
||||
from openapi_core.extensions.models.factories import ModelFactory
|
||||
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import (
|
||||
ValidateError,
|
||||
)
|
||||
from openapi_core.schema.schemas.types import NoValue
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError,
|
||||
InvalidCustomFormatSchemaValue,
|
||||
UnmarshallerStrictTypeError,
|
||||
from openapi_core.schema_validator._types import (
|
||||
is_array, is_bool, is_integer,
|
||||
is_object, is_number, is_string,
|
||||
)
|
||||
from openapi_core.schema_validator._format import oas30_format_checker
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
UnmarshalError, ValidateError, InvalidSchemaValue,
|
||||
InvalidSchemaFormatValue,
|
||||
)
|
||||
from openapi_core.unmarshalling.schemas.formatters import Formatter
|
||||
from openapi_core.unmarshalling.schemas.util import (
|
||||
forcebool, format_date, format_datetime, format_byte, format_uuid,
|
||||
format_number,
|
||||
|
@ -22,133 +25,142 @@ from openapi_core.unmarshalling.schemas.util import (
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StrictUnmarshaller(object):
|
||||
|
||||
STRICT_TYPES = ()
|
||||
|
||||
def __call__(self, value, strict=True):
|
||||
if strict and not self._is_strict(value):
|
||||
raise UnmarshallerStrictTypeError(value, self.STRICT_TYPES)
|
||||
|
||||
return value
|
||||
|
||||
def _is_strict(self, value):
|
||||
if not self.STRICT_TYPES:
|
||||
return True
|
||||
|
||||
return isinstance(value, self.STRICT_TYPES)
|
||||
|
||||
|
||||
class PrimitiveTypeUnmarshaller(StrictUnmarshaller):
|
||||
class PrimitiveTypeUnmarshaller(object):
|
||||
|
||||
FORMATTERS = {}
|
||||
|
||||
def __init__(self, formatter, schema):
|
||||
def __init__(self, formatter, validator, schema):
|
||||
self.formatter = formatter
|
||||
self.validator = validator
|
||||
self.schema = schema
|
||||
|
||||
def __call__(self, value=NoValue, strict=True):
|
||||
def __call__(self, value=NoValue):
|
||||
if value is NoValue:
|
||||
value = self.schema.default
|
||||
if value is None:
|
||||
return
|
||||
value = super(PrimitiveTypeUnmarshaller, self).__call__(
|
||||
value, strict=strict)
|
||||
|
||||
return self.format(value)
|
||||
self.validate(value)
|
||||
|
||||
def format(self, value):
|
||||
return self.unmarshal(value)
|
||||
|
||||
def _formatter_validate(self, value):
|
||||
result = self.formatter.validate(value)
|
||||
if not result:
|
||||
raise InvalidSchemaValue(value, self.schema.type)
|
||||
|
||||
def validate(self, value):
|
||||
errors_iter = self.validator.iter_errors(value)
|
||||
errors = tuple(errors_iter)
|
||||
if errors:
|
||||
raise InvalidSchemaValue(
|
||||
value, self.schema.type, schema_errors=errors)
|
||||
|
||||
def unmarshal(self, value):
|
||||
try:
|
||||
return self.formatter(value)
|
||||
return self.formatter.unmarshal(value)
|
||||
except ValueError as exc:
|
||||
raise InvalidCustomFormatSchemaValue(
|
||||
raise InvalidSchemaFormatValue(
|
||||
value, self.schema.format, exc)
|
||||
|
||||
|
||||
class StringUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
STRICT_TYPES = (text_type, binary_type)
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: text_type,
|
||||
SchemaFormat.PASSWORD: text_type,
|
||||
SchemaFormat.DATE: format_date,
|
||||
SchemaFormat.DATETIME: format_datetime,
|
||||
SchemaFormat.BINARY: binary_type,
|
||||
SchemaFormat.UUID: format_uuid,
|
||||
SchemaFormat.BYTE: format_byte,
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_string, None), text_type),
|
||||
SchemaFormat.PASSWORD: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='password'), text_type),
|
||||
SchemaFormat.DATE: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='date'), format_date),
|
||||
SchemaFormat.DATETIME: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='date-time'),
|
||||
format_datetime),
|
||||
SchemaFormat.BINARY: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='binary'), binary_type),
|
||||
SchemaFormat.UUID: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='uuid'), format_uuid),
|
||||
SchemaFormat.BYTE: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='byte'), format_byte),
|
||||
}
|
||||
|
||||
|
||||
class IntegerUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
STRICT_TYPES = integer_types
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: int,
|
||||
SchemaFormat.INT32: int,
|
||||
SchemaFormat.INT64: int,
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_integer, None), int),
|
||||
SchemaFormat.INT32: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='int32'), int),
|
||||
SchemaFormat.INT64: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='int64'), int),
|
||||
}
|
||||
|
||||
|
||||
class NumberUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
STRICT_TYPES = (float, ) + integer_types
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: format_number,
|
||||
SchemaFormat.FLOAT: float,
|
||||
SchemaFormat.DOUBLE: float,
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_number, None), format_number),
|
||||
SchemaFormat.FLOAT: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='float'), float),
|
||||
SchemaFormat.DOUBLE: Formatter.from_callables(
|
||||
partial(oas30_format_checker.check, format='double'), float),
|
||||
}
|
||||
|
||||
|
||||
class BooleanUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
STRICT_TYPES = (bool, )
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: forcebool,
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_bool, None), forcebool),
|
||||
}
|
||||
|
||||
|
||||
class ComplexUnmarshaller(PrimitiveTypeUnmarshaller):
|
||||
|
||||
def __init__(self, formatter, schema, unmarshallers_factory):
|
||||
super(ComplexUnmarshaller, self).__init__(formatter, schema)
|
||||
def __init__(self, formatter, validator, schema, unmarshallers_factory):
|
||||
super(ComplexUnmarshaller, self).__init__(formatter, validator, schema)
|
||||
self.unmarshallers_factory = unmarshallers_factory
|
||||
|
||||
|
||||
class ArrayUnmarshaller(ComplexUnmarshaller):
|
||||
|
||||
STRICT_TYPES = (list, tuple)
|
||||
FORMATTERS = {}
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_array, None), list),
|
||||
}
|
||||
|
||||
@property
|
||||
def items_unmarshaller(self):
|
||||
return self.unmarshallers_factory.create(self.schema.items)
|
||||
|
||||
def __call__(self, value=NoValue, strict=True):
|
||||
value = super(ArrayUnmarshaller, self).__call__(value, strict=strict)
|
||||
|
||||
self.unmarshallers_factory.create(self.schema.items)
|
||||
def __call__(self, value=NoValue):
|
||||
value = super(ArrayUnmarshaller, self).__call__(value)
|
||||
|
||||
return list(map(self.items_unmarshaller, value))
|
||||
|
||||
|
||||
class ObjectUnmarshaller(ComplexUnmarshaller):
|
||||
|
||||
STRICT_TYPES = (dict, )
|
||||
FORMATTERS = {}
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: Formatter.from_callables(
|
||||
partial(is_object, None), dict),
|
||||
}
|
||||
|
||||
@property
|
||||
def model_factory(self):
|
||||
return ModelFactory()
|
||||
|
||||
def __call__(self, value=NoValue, strict=True):
|
||||
value = super(ObjectUnmarshaller, self).__call__(value, strict=strict)
|
||||
def __call__(self, value=NoValue):
|
||||
value = super(ObjectUnmarshaller, self).__call__(value)
|
||||
|
||||
if self.schema.one_of:
|
||||
properties = None
|
||||
for one_of_schema in self.schema.one_of:
|
||||
try:
|
||||
unmarshalled = self._unmarshal_properties(
|
||||
value, one_of_schema, strict=strict)
|
||||
value, one_of_schema)
|
||||
except (UnmarshalError, ValueError):
|
||||
pass
|
||||
else:
|
||||
|
@ -169,8 +181,7 @@ class ObjectUnmarshaller(ComplexUnmarshaller):
|
|||
|
||||
return properties
|
||||
|
||||
def _unmarshal_properties(
|
||||
self, value=NoValue, one_of_schema=None, strict=True):
|
||||
def _unmarshal_properties(self, value=NoValue, one_of_schema=None):
|
||||
all_props = self.schema.get_all_properties()
|
||||
all_props_names = self.schema.get_all_properties_names()
|
||||
|
||||
|
@ -187,8 +198,7 @@ class ObjectUnmarshaller(ComplexUnmarshaller):
|
|||
for prop_name in extra_props:
|
||||
prop_value = value[prop_name]
|
||||
properties[prop_name] = self.unmarshallers_factory.create(
|
||||
self.schema.additional_properties)(
|
||||
prop_value, strict=strict)
|
||||
self.schema.additional_properties)(prop_value)
|
||||
|
||||
for prop_name, prop in iteritems(all_props):
|
||||
try:
|
||||
|
@ -199,31 +209,37 @@ class ObjectUnmarshaller(ComplexUnmarshaller):
|
|||
prop_value = prop.default
|
||||
|
||||
properties[prop_name] = self.unmarshallers_factory.create(
|
||||
prop)(prop_value, strict=strict)
|
||||
prop)(prop_value)
|
||||
|
||||
return properties
|
||||
|
||||
|
||||
class AnyUnmarshaller(ComplexUnmarshaller):
|
||||
|
||||
FORMATTERS = {
|
||||
SchemaFormat.NONE: Formatter(),
|
||||
}
|
||||
|
||||
SCHEMA_TYPES_ORDER = [
|
||||
SchemaType.OBJECT, SchemaType.ARRAY, SchemaType.BOOLEAN,
|
||||
SchemaType.INTEGER, SchemaType.NUMBER, SchemaType.STRING,
|
||||
]
|
||||
|
||||
def __call__(self, value=NoValue, strict=True):
|
||||
def __call__(self, value=NoValue):
|
||||
one_of_schema = self._get_one_of_schema(value)
|
||||
if one_of_schema:
|
||||
return self.unmarshallers_factory.create(one_of_schema)(
|
||||
value, strict=strict)
|
||||
return self.unmarshallers_factory.create(one_of_schema)(value)
|
||||
|
||||
for schema_type in self.SCHEMA_TYPES_ORDER:
|
||||
try:
|
||||
unmarshaller = self.unmarshallers_factory.create(
|
||||
self.schema, type_override=schema_type)
|
||||
return unmarshaller(value, strict=strict)
|
||||
except (UnmarshalError, ValueError):
|
||||
# validate with validator of formatter (usualy type validator)
|
||||
try:
|
||||
unmarshaller._formatter_validate(value)
|
||||
except ValidateError:
|
||||
continue
|
||||
else:
|
||||
return unmarshaller(value)
|
||||
|
||||
log.warning("failed to unmarshal any type")
|
||||
return value
|
||||
|
@ -232,8 +248,9 @@ class AnyUnmarshaller(ComplexUnmarshaller):
|
|||
if not self.schema.one_of:
|
||||
return
|
||||
for subschema in self.schema.one_of:
|
||||
unmarshaller = self.unmarshallers_factory.create(subschema)
|
||||
try:
|
||||
subschema.validate(value)
|
||||
unmarshaller.validate(value)
|
||||
except ValidateError:
|
||||
continue
|
||||
else:
|
||||
|
|
|
@ -13,12 +13,12 @@ from openapi_core.schema.parameters.exceptions import (
|
|||
MissingRequiredParameter, InvalidParameterValue, EmptyParameterValue,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.exceptions import InvalidSchemaValue
|
||||
from openapi_core.schema.servers.exceptions import InvalidServer
|
||||
from openapi_core.shortcuts import (
|
||||
create_spec, validate_parameters, validate_body,
|
||||
)
|
||||
from openapi_core.testing import MockRequest, MockResponse
|
||||
from openapi_core.unmarshalling.schemas.exceptions import InvalidSchemaValue
|
||||
from openapi_core.validation.request.datatypes import RequestParameters
|
||||
from openapi_core.validation.request.validators import RequestValidator
|
||||
from openapi_core.validation.response.validators import ResponseValidator
|
||||
|
@ -182,7 +182,6 @@ class TestPetstore(object):
|
|||
type=SchemaType.OBJECT,
|
||||
value=data_json,
|
||||
schema_errors=original_exc.schema_errors,
|
||||
schema_errors_iter=original_exc._schema_errors_iter,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -3,6 +3,7 @@ import pytest
|
|||
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
|
||||
from openapi_core.schema.media_types.models import MediaType
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.unmarshalling.schemas.formatters import Formatter
|
||||
|
||||
|
||||
class TestMediaTypeCast(object):
|
||||
|
@ -35,16 +36,20 @@ class TestParameterUnmarshal(object):
|
|||
media_type.unmarshal(value)
|
||||
|
||||
def test_schema_custom_format_invalid(self):
|
||||
def custom_formatter(value):
|
||||
|
||||
class CustomFormatter(Formatter):
|
||||
def unmarshal(self, value):
|
||||
raise ValueError
|
||||
formatter = CustomFormatter()
|
||||
custom_format = 'custom'
|
||||
custom_formatters = {
|
||||
custom_format: formatter,
|
||||
}
|
||||
schema = Schema(
|
||||
'string',
|
||||
schema_format='custom',
|
||||
schema_format=custom_format,
|
||||
_source={'type': 'string', 'format': 'custom'},
|
||||
)
|
||||
custom_formatters = {
|
||||
'custom': custom_formatter,
|
||||
}
|
||||
media_type = MediaType('application/json', schema=schema)
|
||||
value = 'test'
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ from openapi_core.schema.parameters.exceptions import (
|
|||
from openapi_core.schema.parameters.enums import ParameterStyle
|
||||
from openapi_core.schema.parameters.models import Parameter
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.unmarshalling.schemas.formatters import Formatter
|
||||
|
||||
|
||||
class TestParameterInit(object):
|
||||
|
@ -93,16 +94,20 @@ class TestParameterUnmarshal(object):
|
|||
param.unmarshal(value)
|
||||
|
||||
def test_query_schema_custom_format_invalid(self):
|
||||
def custom_formatter(value):
|
||||
|
||||
class CustomFormatter(Formatter):
|
||||
def unmarshal(self, value):
|
||||
raise ValueError
|
||||
formatter = CustomFormatter()
|
||||
custom_format = 'custom'
|
||||
custom_formatters = {
|
||||
custom_format: formatter,
|
||||
}
|
||||
schema = Schema(
|
||||
'string',
|
||||
schema_format='custom',
|
||||
schema_format=custom_format,
|
||||
_source={'type': 'string', 'format': 'custom'},
|
||||
)
|
||||
custom_formatters = {
|
||||
'custom': custom_formatter,
|
||||
}
|
||||
param = Parameter('param', 'query', schema=schema)
|
||||
value = 'test'
|
||||
|
||||
|
|
|
@ -4,21 +4,16 @@ import uuid
|
|||
import mock
|
||||
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,
|
||||
)
|
||||
from openapi_core.schema.schemas.enums import SchemaType
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.schema.schemas.types import NoValue
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
InvalidCustomFormatSchemaValue,
|
||||
InvalidSchemaFormatValue,
|
||||
FormatterNotFoundError,
|
||||
UnmarshalError,
|
||||
UnmarshallerStrictTypeError,
|
||||
InvalidSchemaValue,
|
||||
)
|
||||
|
||||
from six import b, u
|
||||
from openapi_core.unmarshalling.schemas.formatters import Formatter
|
||||
|
||||
|
||||
class TestSchemaIteritems(object):
|
||||
|
@ -55,7 +50,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema(schema_type)
|
||||
value = ''
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_valid(self):
|
||||
|
@ -67,23 +62,22 @@ class TestSchemaUnmarshal(object):
|
|||
assert result == value
|
||||
|
||||
def test_string_format_uuid_valid(self):
|
||||
schema = Schema(SchemaType.STRING, schema_format=SchemaFormat.UUID)
|
||||
schema = Schema(SchemaType.STRING, schema_format='uuid')
|
||||
value = str(uuid.uuid4())
|
||||
|
||||
result = schema.unmarshal(value)
|
||||
|
||||
assert result == uuid.UUID(value)
|
||||
|
||||
def test_string_format_uuid_uuid_quirks_valid(self):
|
||||
schema = Schema(SchemaType.STRING, schema_format=SchemaFormat.UUID)
|
||||
def test_string_format_uuid_uuid_quirks_invalid(self):
|
||||
schema = Schema(SchemaType.STRING, schema_format='uuid')
|
||||
value = uuid.uuid4()
|
||||
|
||||
result = schema.unmarshal(value, strict=False)
|
||||
|
||||
assert result == value
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_format_password(self):
|
||||
schema = Schema(SchemaType.STRING, schema_format=SchemaFormat.PASSWORD)
|
||||
schema = Schema(SchemaType.STRING, schema_format='password')
|
||||
value = 'password'
|
||||
|
||||
result = schema.unmarshal(value)
|
||||
|
@ -94,7 +88,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('string')
|
||||
value = 1.23
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_string_default(self):
|
||||
|
@ -132,27 +126,39 @@ class TestSchemaUnmarshal(object):
|
|||
assert result == datetime.datetime(2018, 1, 2, 0, 0)
|
||||
|
||||
def test_string_format_custom(self):
|
||||
def custom_formatter(value):
|
||||
return 'x-custom'
|
||||
formatted = 'x-custom'
|
||||
|
||||
class CustomFormatter(Formatter):
|
||||
def unmarshal(self, value):
|
||||
return formatted
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
formatter = CustomFormatter()
|
||||
custom_formatters = {
|
||||
custom_format: formatter,
|
||||
}
|
||||
|
||||
result = schema.unmarshal(
|
||||
value, custom_formatters={custom_format: custom_formatter})
|
||||
result = schema.unmarshal(value, custom_formatters=custom_formatters)
|
||||
|
||||
assert result == custom_formatter(value)
|
||||
assert result == formatted
|
||||
|
||||
def test_string_format_custom_value_error(self):
|
||||
def custom_formatter(value):
|
||||
|
||||
class CustomFormatter(Formatter):
|
||||
def unmarshal(self, value):
|
||||
raise ValueError
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
formatter = CustomFormatter()
|
||||
custom_formatters = {
|
||||
custom_format: formatter,
|
||||
}
|
||||
|
||||
with pytest.raises(InvalidCustomFormatSchemaValue):
|
||||
with pytest.raises(InvalidSchemaFormatValue):
|
||||
schema.unmarshal(
|
||||
value, custom_formatters={custom_format: custom_formatter})
|
||||
value, custom_formatters=custom_formatters)
|
||||
|
||||
def test_string_format_unknown(self):
|
||||
unknown_format = 'unknown'
|
||||
|
@ -187,7 +193,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer')
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_integer_enum_invalid(self):
|
||||
|
@ -234,7 +240,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('integer')
|
||||
value = 'abc'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_array_valid(self):
|
||||
|
@ -249,14 +255,14 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('array', items=Schema('string'))
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_array_of_integer_string_invalid(self):
|
||||
schema = Schema('array', items=Schema('integer'))
|
||||
value = '123'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_boolean_valid(self):
|
||||
|
@ -271,7 +277,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('boolean')
|
||||
value = 'True'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_number_valid(self):
|
||||
|
@ -286,7 +292,7 @@ class TestSchemaUnmarshal(object):
|
|||
schema = Schema('number')
|
||||
value = '1.23'
|
||||
|
||||
with pytest.raises(UnmarshallerStrictTypeError):
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.unmarshal(value)
|
||||
|
||||
def test_number_int(self):
|
||||
|
@ -329,737 +335,3 @@ class TestSchemaUnmarshal(object):
|
|||
def test_schema_any(self):
|
||||
schema = Schema()
|
||||
assert schema.unmarshal('string') == 'string'
|
||||
|
||||
|
||||
class TestSchemaValidate(object):
|
||||
|
||||
@pytest.mark.parametrize('schema_type', [
|
||||
'boolean', 'array', 'integer', 'number', 'string',
|
||||
])
|
||||
def test_null(self, schema_type):
|
||||
schema = Schema(schema_type)
|
||||
value = None
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('schema_type', [
|
||||
'boolean', 'array', 'integer', 'number', 'string',
|
||||
])
|
||||
def test_nullable(self, schema_type):
|
||||
schema = Schema(schema_type, nullable=True)
|
||||
value = None
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason="validation does not care about custom formats atm")
|
||||
def test_string_format_custom_missing(self):
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [False, True])
|
||||
def test_boolean(self, value):
|
||||
schema = Schema('boolean')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3.14, u('true'), [True, False]])
|
||||
def test_boolean_invalid(self, value):
|
||||
schema = Schema('boolean')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [(1, 2)])
|
||||
def test_array_no_schema(self, value):
|
||||
schema = Schema('array')
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2]])
|
||||
def test_array(self, value):
|
||||
schema = Schema('array', items=Schema('integer'))
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 1, 3.14, u('true'), (3, 4)])
|
||||
def test_array_invalid(self, value):
|
||||
schema = Schema('array')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3])
|
||||
def test_integer(self, value):
|
||||
schema = Schema('integer')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 3.14, u('true'), [1, 2]])
|
||||
def test_integer_invalid(self, value):
|
||||
schema = Schema('integer')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_integer_minimum_invalid(self, value):
|
||||
schema = Schema('integer', minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_integer_minimum(self, value):
|
||||
schema = Schema('integer', minimum=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_integer_maximum_invalid(self, value):
|
||||
schema = Schema('integer', maximum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_integer_maximum(self, value):
|
||||
schema = Schema('integer', maximum=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 4])
|
||||
def test_integer_multiple_of_invalid(self, value):
|
||||
schema = Schema('integer', multiple_of=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 6, 18])
|
||||
def test_integer_multiple_of(self, value):
|
||||
schema = Schema('integer', multiple_of=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3.14])
|
||||
def test_number(self, value):
|
||||
schema = Schema('number')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 'true', [1, 3]])
|
||||
def test_number_invalid(self, value):
|
||||
schema = Schema('number')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_number_minimum_invalid(self, value):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 4, 5])
|
||||
def test_number_minimum(self, value):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 3])
|
||||
def test_number_exclusive_minimum_invalid(self, value):
|
||||
schema = Schema('number', minimum=3, exclusive_minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_number_exclusive_minimum(self, value):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_number_maximum_invalid(self, value):
|
||||
schema = Schema('number', maximum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 3])
|
||||
def test_number_maximum(self, value):
|
||||
schema = Schema('number', maximum=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 4, 5])
|
||||
def test_number_exclusive_maximum_invalid(self, value):
|
||||
schema = Schema('number', maximum=3, exclusive_maximum=True)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_number_exclusive_maximum(self, value):
|
||||
schema = Schema('number', maximum=3, exclusive_maximum=True)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 4])
|
||||
def test_number_multiple_of_invalid(self, value):
|
||||
schema = Schema('number', multiple_of=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 6, 18])
|
||||
def test_number_multiple_of(self, value):
|
||||
schema = Schema('number', multiple_of=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u('true'), b('test')])
|
||||
def test_string(self, value):
|
||||
schema = Schema('string')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 1, 3.14, [1, 3]])
|
||||
def test_string_invalid(self, value):
|
||||
schema = Schema('string')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('test'), False, 1, 3.14, [1, 3],
|
||||
datetime.datetime(1989, 1, 2),
|
||||
])
|
||||
def test_string_format_date_invalid(self, value):
|
||||
schema = Schema('string', schema_format='date')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02'), u('2018-01-02'),
|
||||
])
|
||||
def test_string_format_date(self, value):
|
||||
schema = Schema('string', schema_format='date')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('12345678-1234-5678-1234-567812345678'),
|
||||
])
|
||||
def test_string_format_uuid(self, value):
|
||||
schema = Schema('string', schema_format='uuid')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('true'), False, 1, 3.14, [1, 3],
|
||||
datetime.date(2018, 1, 2), datetime.datetime(2018, 1, 2, 23, 59, 59),
|
||||
])
|
||||
def test_string_format_uuid_invalid(self, value):
|
||||
schema = Schema('string', schema_format='uuid')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('true'), False, 1, 3.14, [1, 3],
|
||||
u('1989-01-02'),
|
||||
])
|
||||
def test_string_format_datetime_invalid(self, value):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
u('2018-01-02T23:59:59Z'),
|
||||
])
|
||||
@mock.patch(
|
||||
'openapi_core.schema.schemas._format.'
|
||||
'DATETIME_HAS_STRICT_RFC3339', True
|
||||
)
|
||||
@mock.patch(
|
||||
'openapi_core.schema.schemas._format.'
|
||||
'DATETIME_HAS_ISODATE', False
|
||||
)
|
||||
def test_string_format_datetime_strict_rfc3339(self, value):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
u('2018-01-02T23:59:59Z'),
|
||||
])
|
||||
@mock.patch(
|
||||
'openapi_core.schema.schemas._format.'
|
||||
'DATETIME_HAS_STRICT_RFC3339', False
|
||||
)
|
||||
@mock.patch(
|
||||
'openapi_core.schema.schemas._format.'
|
||||
'DATETIME_HAS_ISODATE', True
|
||||
)
|
||||
def test_string_format_datetime_isodate(self, value):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('true'), False, 1, 3.14, [1, 3], u('1989-01-02'),
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
])
|
||||
def test_string_format_binary_invalid(self, value):
|
||||
schema = Schema('string', schema_format='binary')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('stream'), b('text'),
|
||||
])
|
||||
def test_string_format_binary(self, value):
|
||||
schema = Schema('string', schema_format='binary')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('dGVzdA=='), u('dGVzdA=='),
|
||||
])
|
||||
def test_string_format_byte(self, value):
|
||||
schema = Schema('string', schema_format='byte')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('tsssst'), b('tsssst'), b('tesddddsdsdst'),
|
||||
])
|
||||
def test_string_format_byte_invalid(self, value):
|
||||
schema = Schema('string', schema_format='byte')
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('test'), b('stream'), datetime.date(1989, 1, 2),
|
||||
datetime.datetime(1989, 1, 2, 0, 0, 0),
|
||||
])
|
||||
def test_string_format_unknown(self, value):
|
||||
unknown_format = 'unknown'
|
||||
schema = Schema('string', schema_format=unknown_format)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), u("a"), u("ab")])
|
||||
def test_string_min_length_invalid(self, value):
|
||||
schema = Schema('string', min_length=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("abc"), u("abcd")])
|
||||
def test_string_min_length(self, value):
|
||||
schema = Schema('string', min_length=3)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), ])
|
||||
def test_string_max_length_invalid_schema(self, value):
|
||||
schema = Schema('string', max_length=-1)
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("ab"), u("abc")])
|
||||
def test_string_max_length_invalid(self, value):
|
||||
schema = Schema('string', max_length=1)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), u("a")])
|
||||
def test_string_max_length(self, value):
|
||||
schema = Schema('string', max_length=1)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u("foo"), u("bar")])
|
||||
def test_string_pattern_invalid(self, value):
|
||||
schema = Schema('string', pattern='baz')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("bar"), u("foobar")])
|
||||
def test_string_pattern(self, value):
|
||||
schema = Schema('string', pattern='bar')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', ['true', False, 1, 3.14, [1, 3]])
|
||||
def test_object_not_an_object(self, value):
|
||||
schema = Schema('object')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [Model(), ])
|
||||
def test_object_multiple_one_of(self, value):
|
||||
one_of = [
|
||||
Schema('object'), Schema('object'),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_defferent_type_one_of(self, value):
|
||||
one_of = [
|
||||
Schema('integer'), Schema('string'),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_no_one_of(self, value):
|
||||
one_of = [
|
||||
Schema(
|
||||
'object',
|
||||
properties={'test1': Schema('string')},
|
||||
required=['test1', ],
|
||||
),
|
||||
Schema(
|
||||
'object',
|
||||
properties={'test2': Schema('string')},
|
||||
required=['test2', ],
|
||||
),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'foo': u("FOO"),
|
||||
},
|
||||
{
|
||||
'foo': u("FOO"),
|
||||
'bar': u("BAR"),
|
||||
},
|
||||
])
|
||||
def test_unambiguous_one_of(self, value):
|
||||
one_of = [
|
||||
Schema(
|
||||
'object',
|
||||
properties={
|
||||
'foo': Schema('string'),
|
||||
},
|
||||
additional_properties=False,
|
||||
required=['foo'],
|
||||
),
|
||||
Schema(
|
||||
'object',
|
||||
properties={
|
||||
'foo': Schema('string'),
|
||||
'bar': Schema('string'),
|
||||
},
|
||||
additional_properties=False,
|
||||
required=['foo', 'bar'],
|
||||
),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_default_property(self, value):
|
||||
schema = Schema('object', default='value1')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [Model(), ])
|
||||
def test_object_min_properties_invalid_schema(self, value):
|
||||
schema = Schema('object', min_properties=-1)
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_min_properties_invalid(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
min_properties=4,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_min_properties(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
min_properties=1,
|
||||
)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [Model(), ])
|
||||
def test_object_max_properties_invalid_schema(self, value):
|
||||
schema = Schema('object', max_properties=-1)
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_max_properties_invalid(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
max_properties=0,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_max_properties(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
max_properties=3,
|
||||
)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries(self, value):
|
||||
schema = Schema('object')
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries_false(self, value):
|
||||
schema = Schema('object', additional_properties=False)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries_object(self, value):
|
||||
additional_properties = Schema('integer')
|
||||
schema = Schema('object', additional_properties=additional_properties)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [[], [1], [1, 2]])
|
||||
def test_list_min_items_invalid(self, value):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
min_items=3,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[], [1], [1, 2]])
|
||||
def test_list_min_items(self, value):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
min_items=0,
|
||||
)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [[], ])
|
||||
def test_list_max_items_invalid_schema(self, value):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
max_items=-1,
|
||||
)
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2], [2, 3, 4]])
|
||||
def test_list_max_items_invalid(self, value):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
max_items=1,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2, 1], [2, 2]])
|
||||
def test_list_unique_items_invalid(self, value):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
unique_items=True,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
schema.validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': u('content'),
|
||||
},
|
||||
{
|
||||
'somestr': u('content'),
|
||||
'someint': 123,
|
||||
},
|
||||
])
|
||||
def test_object_with_properties(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={
|
||||
'somestr': Schema('string'),
|
||||
'someint': Schema('integer'),
|
||||
},
|
||||
)
|
||||
|
||||
result = schema.validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'somestr': {},
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': [
|
||||
'content1', 'content2'
|
||||
],
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': 123,
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': 'content',
|
||||
'someint': 123,
|
||||
'not_in_scheme_prop': 123,
|
||||
},
|
||||
])
|
||||
def test_object_with_invalid_properties(self, value):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={
|
||||
'somestr': Schema('string'),
|
||||
'someint': Schema('integer'),
|
||||
},
|
||||
additional_properties=False,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
schema.validate(value)
|
||||
|
|
761
tests/unit/unmarshalling/test_validate.py
Normal file
761
tests/unit/unmarshalling/test_validate.py
Normal file
|
@ -0,0 +1,761 @@
|
|||
import datetime
|
||||
|
||||
import mock
|
||||
import pytest
|
||||
|
||||
from openapi_core.extensions.models.models import Model
|
||||
from openapi_core.schema.schemas.exceptions import OpenAPISchemaError
|
||||
from openapi_core.schema.schemas.models import Schema
|
||||
from openapi_core.unmarshalling.schemas.factories import (
|
||||
SchemaUnmarshallersFactory,
|
||||
)
|
||||
from openapi_core.unmarshalling.schemas.exceptions import (
|
||||
FormatterNotFoundError, InvalidSchemaValue,
|
||||
)
|
||||
|
||||
from six import b, u
|
||||
|
||||
|
||||
class TestSchemaValidate(object):
|
||||
|
||||
@pytest.fixture
|
||||
def validator_factory(self):
|
||||
def create_validator(schema):
|
||||
return SchemaUnmarshallersFactory().create(schema)
|
||||
return create_validator
|
||||
|
||||
@pytest.mark.parametrize('schema_type', [
|
||||
'boolean', 'array', 'integer', 'number', 'string',
|
||||
])
|
||||
def test_null(self, schema_type, validator_factory):
|
||||
schema = Schema(schema_type)
|
||||
value = None
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('schema_type', [
|
||||
'boolean', 'array', 'integer', 'number', 'string',
|
||||
])
|
||||
def test_nullable(self, schema_type, validator_factory):
|
||||
schema = Schema(schema_type, nullable=True)
|
||||
value = None
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason="validation does not care about custom formats atm")
|
||||
def test_string_format_custom_missing(self, validator_factory):
|
||||
custom_format = 'custom'
|
||||
schema = Schema('string', schema_format=custom_format)
|
||||
value = 'x'
|
||||
|
||||
with pytest.raises(OpenAPISchemaError):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [False, True])
|
||||
def test_boolean(self, value, validator_factory):
|
||||
schema = Schema('boolean')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3.14, u('true'), [True, False]])
|
||||
def test_boolean_invalid(self, value, validator_factory):
|
||||
schema = Schema('boolean')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [(1, 2)])
|
||||
def test_array_no_schema(self, value, validator_factory):
|
||||
schema = Schema('array')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2]])
|
||||
def test_array(self, value, validator_factory):
|
||||
schema = Schema('array', items=Schema('integer'))
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 1, 3.14, u('true'), (3, 4)])
|
||||
def test_array_invalid(self, value, validator_factory):
|
||||
schema = Schema('array')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3])
|
||||
def test_integer(self, value, validator_factory):
|
||||
schema = Schema('integer')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 3.14, u('true'), [1, 2]])
|
||||
def test_integer_invalid(self, value, validator_factory):
|
||||
schema = Schema('integer')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_integer_minimum_invalid(self, value, validator_factory):
|
||||
schema = Schema('integer', minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_integer_minimum(self, value, validator_factory):
|
||||
schema = Schema('integer', minimum=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_integer_maximum_invalid(self, value, validator_factory):
|
||||
schema = Schema('integer', maximum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_integer_maximum(self, value, validator_factory):
|
||||
schema = Schema('integer', maximum=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 4])
|
||||
def test_integer_multiple_of_invalid(self, value, validator_factory):
|
||||
schema = Schema('integer', multiple_of=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 6, 18])
|
||||
def test_integer_multiple_of(self, value, validator_factory):
|
||||
schema = Schema('integer', multiple_of=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 3.14])
|
||||
def test_number(self, value, validator_factory):
|
||||
schema = Schema('number')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 'true', [1, 3]])
|
||||
def test_number_invalid(self, value, validator_factory):
|
||||
schema = Schema('number')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_number_minimum_invalid(self, value, validator_factory):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 4, 5])
|
||||
def test_number_minimum(self, value, validator_factory):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 3])
|
||||
def test_number_exclusive_minimum_invalid(self, value, validator_factory):
|
||||
schema = Schema('number', minimum=3, exclusive_minimum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_number_exclusive_minimum(self, value, validator_factory):
|
||||
schema = Schema('number', minimum=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [4, 5, 6])
|
||||
def test_number_maximum_invalid(self, value, validator_factory):
|
||||
schema = Schema('number', maximum=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 3])
|
||||
def test_number_maximum(self, value, validator_factory):
|
||||
schema = Schema('number', maximum=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 4, 5])
|
||||
def test_number_exclusive_maximum_invalid(self, value, validator_factory):
|
||||
schema = Schema('number', maximum=3, exclusive_maximum=True)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [0, 1, 2])
|
||||
def test_number_exclusive_maximum(self, value, validator_factory):
|
||||
schema = Schema('number', maximum=3, exclusive_maximum=True)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [1, 2, 4])
|
||||
def test_number_multiple_of_invalid(self, value, validator_factory):
|
||||
schema = Schema('number', multiple_of=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [3, 6, 18])
|
||||
def test_number_multiple_of(self, value, validator_factory):
|
||||
schema = Schema('number', multiple_of=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u('true'), b('test')])
|
||||
def test_string(self, value, validator_factory):
|
||||
schema = Schema('string')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [False, 1, 3.14, [1, 3]])
|
||||
def test_string_invalid(self, value, validator_factory):
|
||||
schema = Schema('string')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('test'), False, 1, 3.14, [1, 3],
|
||||
datetime.datetime(1989, 1, 2),
|
||||
])
|
||||
def test_string_format_date_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='date')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02'), u('2018-01-02'),
|
||||
])
|
||||
def test_string_format_date(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='date')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('12345678-1234-5678-1234-567812345678'),
|
||||
])
|
||||
def test_string_format_uuid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='uuid')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('true'), False, 1, 3.14, [1, 3],
|
||||
datetime.date(2018, 1, 2), datetime.datetime(2018, 1, 2, 23, 59, 59),
|
||||
])
|
||||
def test_string_format_uuid_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='uuid')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('true'), u('true'), False, 1, 3.14, [1, 3],
|
||||
u('1989-01-02'),
|
||||
])
|
||||
def test_string_format_datetime_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
u('2018-01-02T23:59:59Z'),
|
||||
])
|
||||
@mock.patch(
|
||||
'openapi_core.schema_validator._format.'
|
||||
'DATETIME_HAS_STRICT_RFC3339', True
|
||||
)
|
||||
@mock.patch(
|
||||
'openapi_core.schema_validator._format.'
|
||||
'DATETIME_HAS_ISODATE', False
|
||||
)
|
||||
def test_string_format_datetime_strict_rfc3339(
|
||||
self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
u('2018-01-02T23:59:59Z'),
|
||||
])
|
||||
@mock.patch(
|
||||
'openapi_core.schema_validator._format.'
|
||||
'DATETIME_HAS_STRICT_RFC3339', False
|
||||
)
|
||||
@mock.patch(
|
||||
'openapi_core.schema_validator._format.'
|
||||
'DATETIME_HAS_ISODATE', True
|
||||
)
|
||||
def test_string_format_datetime_isodate(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='date-time')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('true'), False, 1, 3.14, [1, 3], u('1989-01-02'),
|
||||
u('1989-01-02T00:00:00Z'),
|
||||
])
|
||||
def test_string_format_binary_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='binary')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('stream'), b('text'),
|
||||
])
|
||||
def test_string_format_binary(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='binary')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
b('dGVzdA=='), u('dGVzdA=='),
|
||||
])
|
||||
def test_string_format_byte(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='byte')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('tsssst'), b('tsssst'), b('tesddddsdsdst'),
|
||||
])
|
||||
def test_string_format_byte_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', schema_format='byte')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
u('test'), b('stream'), datetime.date(1989, 1, 2),
|
||||
datetime.datetime(1989, 1, 2, 0, 0, 0),
|
||||
])
|
||||
def test_string_format_unknown(self, value, validator_factory):
|
||||
unknown_format = 'unknown'
|
||||
schema = Schema('string', schema_format=unknown_format)
|
||||
|
||||
with pytest.raises(FormatterNotFoundError):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), u("a"), u("ab")])
|
||||
def test_string_min_length_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', min_length=3)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("abc"), u("abcd")])
|
||||
def test_string_min_length(self, value, validator_factory):
|
||||
schema = Schema('string', min_length=3)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), ])
|
||||
def test_string_max_length_invalid_schema(self, value, validator_factory):
|
||||
schema = Schema('string', max_length=-1)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("ab"), u("abc")])
|
||||
def test_string_max_length_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', max_length=1)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u(""), u("a")])
|
||||
def test_string_max_length(self, value, validator_factory):
|
||||
schema = Schema('string', max_length=1)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [u("foo"), u("bar")])
|
||||
def test_string_pattern_invalid(self, value, validator_factory):
|
||||
schema = Schema('string', pattern='baz')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [u("bar"), u("foobar")])
|
||||
def test_string_pattern(self, value, validator_factory):
|
||||
schema = Schema('string', pattern='bar')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', ['true', False, 1, 3.14, [1, 3]])
|
||||
def test_object_not_an_object(self, value, validator_factory):
|
||||
schema = Schema('object')
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [Model(), ])
|
||||
def test_object_multiple_one_of(self, value, validator_factory):
|
||||
one_of = [
|
||||
Schema('object'), Schema('object'),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_defferent_type_one_of(self, value, validator_factory):
|
||||
one_of = [
|
||||
Schema('integer'), Schema('string'),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_no_one_of(self, value, validator_factory):
|
||||
one_of = [
|
||||
Schema(
|
||||
'object',
|
||||
properties={'test1': Schema('string')},
|
||||
required=['test1', ],
|
||||
),
|
||||
Schema(
|
||||
'object',
|
||||
properties={'test2': Schema('string')},
|
||||
required=['test2', ],
|
||||
),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'foo': u("FOO"),
|
||||
},
|
||||
{
|
||||
'foo': u("FOO"),
|
||||
'bar': u("BAR"),
|
||||
},
|
||||
])
|
||||
def test_unambiguous_one_of(self, value, validator_factory):
|
||||
one_of = [
|
||||
Schema(
|
||||
'object',
|
||||
properties={
|
||||
'foo': Schema('string'),
|
||||
},
|
||||
additional_properties=False,
|
||||
required=['foo'],
|
||||
),
|
||||
Schema(
|
||||
'object',
|
||||
properties={
|
||||
'foo': Schema('string'),
|
||||
'bar': Schema('string'),
|
||||
},
|
||||
additional_properties=False,
|
||||
required=['foo', 'bar'],
|
||||
),
|
||||
]
|
||||
schema = Schema('object', one_of=one_of)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_default_property(self, value, validator_factory):
|
||||
schema = Schema('object', default='value1')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_min_properties_invalid_schema(
|
||||
self, value, validator_factory):
|
||||
schema = Schema('object', min_properties=2)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_min_properties_invalid(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
min_properties=4,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_min_properties(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
min_properties=1,
|
||||
)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{}, ])
|
||||
def test_object_max_properties_invalid_schema(
|
||||
self, value, validator_factory):
|
||||
schema = Schema('object', max_properties=-1)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_max_properties_invalid(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
max_properties=0,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{'a': 1},
|
||||
{'a': 1, 'b': 2},
|
||||
{'a': 1, 'b': 2, 'c': 3},
|
||||
])
|
||||
def test_object_max_properties(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={k: Schema('number')
|
||||
for k in ['a', 'b', 'c']},
|
||||
max_properties=3,
|
||||
)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries(self, value, validator_factory):
|
||||
schema = Schema('object')
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries_false(
|
||||
self, value, validator_factory):
|
||||
schema = Schema('object', additional_properties=False)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [{'additional': 1}, ])
|
||||
def test_object_additional_propetries_object(
|
||||
self, value, validator_factory):
|
||||
additional_properties = Schema('integer')
|
||||
schema = Schema('object', additional_properties=additional_properties)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [[], [1], [1, 2]])
|
||||
def test_list_min_items_invalid(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
min_items=3,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[], [1], [1, 2]])
|
||||
def test_list_min_items(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
min_items=0,
|
||||
)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [[], ])
|
||||
def test_list_max_items_invalid_schema(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
max_items=-1,
|
||||
)
|
||||
|
||||
with pytest.raises(InvalidSchemaValue):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2], [2, 3, 4]])
|
||||
def test_list_max_items_invalid(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
max_items=1,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [[1, 2, 1], [2, 2]])
|
||||
def test_list_unique_items_invalid(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'array',
|
||||
items=Schema('number'),
|
||||
unique_items=True,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
validator_factory(schema).validate(value)
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': u('content'),
|
||||
},
|
||||
{
|
||||
'somestr': u('content'),
|
||||
'someint': 123,
|
||||
},
|
||||
])
|
||||
def test_object_with_properties(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={
|
||||
'somestr': Schema('string'),
|
||||
'someint': Schema('integer'),
|
||||
},
|
||||
)
|
||||
|
||||
result = validator_factory(schema).validate(value)
|
||||
|
||||
assert result is None
|
||||
|
||||
@pytest.mark.parametrize('value', [
|
||||
{
|
||||
'somestr': {},
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': [
|
||||
'content1', 'content2'
|
||||
],
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': 123,
|
||||
'someint': 123,
|
||||
},
|
||||
{
|
||||
'somestr': 'content',
|
||||
'someint': 123,
|
||||
'not_in_scheme_prop': 123,
|
||||
},
|
||||
])
|
||||
def test_object_with_invalid_properties(self, value, validator_factory):
|
||||
schema = Schema(
|
||||
'object',
|
||||
properties={
|
||||
'somestr': Schema('string'),
|
||||
'someint': Schema('integer'),
|
||||
},
|
||||
additional_properties=False,
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
validator_factory(schema).validate(value)
|
Loading…
Reference in a new issue