mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-25 11:09:53 +00:00
Move casters to separate subpackage
This commit is contained in:
parent
ca63475826
commit
368f6882e5
10 changed files with 98 additions and 43 deletions
0
openapi_core/casting/__init__.py
Normal file
0
openapi_core/casting/__init__.py
Normal file
0
openapi_core/casting/schemas/__init__.py
Normal file
0
openapi_core/casting/schemas/__init__.py
Normal file
34
openapi_core/casting/schemas/casters.py
Normal file
34
openapi_core/casting/schemas/casters.py
Normal 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))
|
14
openapi_core/casting/schemas/exceptions.py
Normal file
14
openapi_core/casting/schemas/exceptions.py
Normal 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)
|
29
openapi_core/casting/schemas/factories.py
Normal file
29
openapi_core/casting/schemas/factories.py
Normal 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)
|
10
openapi_core/casting/schemas/util.py
Normal file
10
openapi_core/casting/schemas/util.py
Normal 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)
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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__)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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__,
|
||||||
|
|
Loading…
Reference in a new issue