Move casters to separate subpackage

This commit is contained in:
p1c2u 2020-01-23 22:48:34 +00:00
parent ca63475826
commit 368f6882e5
10 changed files with 98 additions and 43 deletions

View file

View file

View file

@ -0,0 +1,34 @@
from openapi_core.schema.schemas.types import NoValue
class PrimitiveCaster(object):
def __init__(self, caster_callable):
self.caster_callable = caster_callable
def __call__(self, value):
if value in (None, NoValue):
return value
return self.caster_callable(value)
class DummyCaster(object):
def __call__(self, value):
return value
class ArrayCaster(object):
def __init__(self, schema, casters_factory):
self.schema = schema
self.casters_factory = casters_factory
@property
def items_caster(self):
return self.casters_factory.create(self.schema.items)
def __call__(self, value):
if value in (None, NoValue):
return value
return list(map(self.items_caster, value))

View file

@ -0,0 +1,14 @@
import attr
from openapi_core.exceptions import OpenAPIError
@attr.s(hash=True)
class CastError(OpenAPIError):
"""Schema cast operation error"""
value = attr.ib()
type = attr.ib()
def __str__(self):
return "Failed to cast value {value} to type {type}".format(
value=self.value, type=self.type)

View file

@ -0,0 +1,29 @@
from openapi_core.schema.schemas.enums import SchemaType
from openapi_core.casting.schemas.casters import (
PrimitiveCaster, DummyCaster, ArrayCaster
)
from openapi_core.casting.schemas.util import forcebool
class SchemaCastersFactory(object):
DUMMY_CASTER = DummyCaster()
PRIMITIVE_CASTERS = {
SchemaType.STRING: DUMMY_CASTER,
SchemaType.INTEGER: PrimitiveCaster(int),
SchemaType.NUMBER: PrimitiveCaster(float),
SchemaType.BOOLEAN: PrimitiveCaster(forcebool),
SchemaType.OBJECT: DUMMY_CASTER,
SchemaType.ANY: DUMMY_CASTER,
}
COMPLEX_CASTERS = {
SchemaType.ARRAY: ArrayCaster,
}
def create(self, schema):
if schema.type in self.PRIMITIVE_CASTERS:
return self.PRIMITIVE_CASTERS[schema.type]
elif schema.type in self.COMPLEX_CASTERS:
caster_class = self.COMPLEX_CASTERS[schema.type]
return caster_class(schema=schema, casters_factory=self)

View file

@ -0,0 +1,10 @@
"""OpenAPI core casting schemas util module"""
from distutils.util import strtobool
from six import string_types
def forcebool(val):
if isinstance(val, string_types):
val = strtobool(val)
return bool(val)

View file

@ -5,8 +5,9 @@ from json import loads
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
from openapi_core.schema.schemas.exceptions import ( from openapi_core.schema.schemas.exceptions import (
CastError, ValidateError, 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

View file

@ -11,8 +11,9 @@ from openapi_core.schema.parameters.exceptions import (
) )
from openapi_core.schema.schemas.enums import SchemaType from openapi_core.schema.schemas.enums import SchemaType
from openapi_core.schema.schemas.exceptions import ( from openapi_core.schema.schemas.exceptions import (
CastError, ValidateError, 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
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View file

@ -7,17 +7,6 @@ class OpenAPISchemaError(OpenAPIMappingError):
pass pass
@attr.s(hash=True)
class CastError(OpenAPISchemaError):
"""Schema cast operation error"""
value = attr.ib()
type = attr.ib()
def __str__(self):
return "Failed to cast value {value} to type {type}".format(
value=self.value, type=self.type)
class ValidateError(OpenAPISchemaError): class ValidateError(OpenAPISchemaError):
"""Schema validate operation error""" """Schema validate operation error"""
pass pass

View file

@ -1,18 +1,14 @@
"""OpenAPI core schemas models module""" """OpenAPI core schemas models module"""
import attr import attr
import logging import logging
from collections import defaultdict
import re import re
from jsonschema.exceptions import ValidationError from jsonschema.exceptions import ValidationError
from openapi_core.schema.schemas._format import oas30_format_checker from openapi_core.schema.schemas._format import oas30_format_checker
from openapi_core.schema.schemas.enums import SchemaType from openapi_core.schema.schemas.enums import SchemaType
from openapi_core.schema.schemas.exceptions import ( from openapi_core.schema.schemas.exceptions import InvalidSchemaValue
CastError, InvalidSchemaValue,
)
from openapi_core.schema.schemas.types import NoValue from openapi_core.schema.schemas.types import NoValue
from openapi_core.schema.schemas.util import forcebool
from openapi_core.schema.schemas.validators import OAS30Validator from openapi_core.schema.schemas.validators import OAS30Validator
from openapi_core.unmarshalling.schemas.exceptions import ( from openapi_core.unmarshalling.schemas.exceptions import (
UnmarshalValueError, UnmarshalValueError,
@ -30,12 +26,6 @@ class Format(object):
class Schema(object): class Schema(object):
"""Represents an OpenAPI Schema.""" """Represents an OpenAPI Schema."""
TYPE_CAST_CALLABLE_GETTER = {
SchemaType.INTEGER: int,
SchemaType.NUMBER: float,
SchemaType.BOOLEAN: forcebool,
}
def __init__( def __init__(
self, schema_type=None, properties=None, items=None, self, schema_type=None, properties=None, items=None,
schema_format=None, required=None, default=NoValue, nullable=False, schema_format=None, required=None, default=NoValue, nullable=False,
@ -109,30 +99,17 @@ class Schema(object):
all_properties = self.get_all_properties() all_properties = self.get_all_properties()
return set(all_properties.keys()) return set(all_properties.keys())
def get_cast_mapping(self):
mapping = self.TYPE_CAST_CALLABLE_GETTER.copy()
mapping.update({
SchemaType.ARRAY: self._cast_collection,
})
return defaultdict(lambda: lambda x: x, mapping)
def cast(self, value): def cast(self, value):
"""Cast value from string to schema type""" """Cast value from string to schema type"""
if value in (None, NoValue): from openapi_core.casting.schemas.exceptions import CastError
return value from openapi_core.casting.schemas.factories import SchemaCastersFactory
casters_factory = SchemaCastersFactory()
cast_mapping = self.get_cast_mapping() caster = casters_factory.create(self)
cast_callable = cast_mapping[self.type]
try: try:
return cast_callable(value) return caster(value)
except ValueError: except (ValueError, TypeError):
raise CastError(value, self.type) raise CastError(value, self.type)
def _cast_collection(self, value):
return list(map(self.items.cast, value))
def get_validator(self, resolver=None): def get_validator(self, resolver=None):
return OAS30Validator( return OAS30Validator(
self.__dict__, self.__dict__,