Merge pull request #184 from p1c2u/refactor/move-casters-to-subpackage

Move casters to separate subpackage
This commit is contained in:
A 2020-01-27 13:24:08 +00:00 committed by GitHub
commit c3f9adadaa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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

@ -4,8 +4,9 @@ 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 (
CastError, ValidateError,
ValidateError,
)
from openapi_core.casting.schemas.exceptions import CastError
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.exceptions import (
CastError, ValidateError,
ValidateError,
)
from openapi_core.casting.schemas.exceptions import CastError
from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError
log = logging.getLogger(__name__)

View file

@ -7,17 +7,6 @@ class OpenAPISchemaError(OpenAPIMappingError):
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):
"""Schema validate operation error"""
pass

View file

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