Skip to content

Commit c3f9ada

Browse files
authored
Merge pull request #184 from p1c2u/refactor/move-casters-to-subpackage
Move casters to separate subpackage
2 parents 09bff35 + 368f688 commit c3f9ada

File tree

10 files changed

+98
-43
lines changed

10 files changed

+98
-43
lines changed

openapi_core/casting/__init__.py

Whitespace-only changes.

openapi_core/casting/schemas/__init__.py

Whitespace-only changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from openapi_core.schema.schemas.types import NoValue
2+
3+
4+
class PrimitiveCaster(object):
5+
6+
def __init__(self, caster_callable):
7+
self.caster_callable = caster_callable
8+
9+
def __call__(self, value):
10+
if value in (None, NoValue):
11+
return value
12+
return self.caster_callable(value)
13+
14+
15+
class DummyCaster(object):
16+
17+
def __call__(self, value):
18+
return value
19+
20+
21+
class ArrayCaster(object):
22+
23+
def __init__(self, schema, casters_factory):
24+
self.schema = schema
25+
self.casters_factory = casters_factory
26+
27+
@property
28+
def items_caster(self):
29+
return self.casters_factory.create(self.schema.items)
30+
31+
def __call__(self, value):
32+
if value in (None, NoValue):
33+
return value
34+
return list(map(self.items_caster, value))
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import attr
2+
3+
from openapi_core.exceptions import OpenAPIError
4+
5+
6+
@attr.s(hash=True)
7+
class CastError(OpenAPIError):
8+
"""Schema cast operation error"""
9+
value = attr.ib()
10+
type = attr.ib()
11+
12+
def __str__(self):
13+
return "Failed to cast value {value} to type {type}".format(
14+
value=self.value, type=self.type)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from openapi_core.schema.schemas.enums import SchemaType
2+
3+
from openapi_core.casting.schemas.casters import (
4+
PrimitiveCaster, DummyCaster, ArrayCaster
5+
)
6+
from openapi_core.casting.schemas.util import forcebool
7+
8+
9+
class SchemaCastersFactory(object):
10+
11+
DUMMY_CASTER = DummyCaster()
12+
PRIMITIVE_CASTERS = {
13+
SchemaType.STRING: DUMMY_CASTER,
14+
SchemaType.INTEGER: PrimitiveCaster(int),
15+
SchemaType.NUMBER: PrimitiveCaster(float),
16+
SchemaType.BOOLEAN: PrimitiveCaster(forcebool),
17+
SchemaType.OBJECT: DUMMY_CASTER,
18+
SchemaType.ANY: DUMMY_CASTER,
19+
}
20+
COMPLEX_CASTERS = {
21+
SchemaType.ARRAY: ArrayCaster,
22+
}
23+
24+
def create(self, schema):
25+
if schema.type in self.PRIMITIVE_CASTERS:
26+
return self.PRIMITIVE_CASTERS[schema.type]
27+
elif schema.type in self.COMPLEX_CASTERS:
28+
caster_class = self.COMPLEX_CASTERS[schema.type]
29+
return caster_class(schema=schema, casters_factory=self)

openapi_core/casting/schemas/util.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""OpenAPI core casting schemas util module"""
2+
from distutils.util import strtobool
3+
from six import string_types
4+
5+
6+
def forcebool(val):
7+
if isinstance(val, string_types):
8+
val = strtobool(val)
9+
10+
return bool(val)

openapi_core/schema/media_types/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
from openapi_core.schema.media_types.exceptions import InvalidMediaTypeValue
55
from openapi_core.schema.media_types.util import json_loads
66
from openapi_core.schema.schemas.exceptions import (
7-
CastError, ValidateError,
7+
ValidateError,
88
)
9+
from openapi_core.casting.schemas.exceptions import CastError
910
from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError
1011

1112

openapi_core/schema/parameters/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
)
1212
from openapi_core.schema.schemas.enums import SchemaType
1313
from openapi_core.schema.schemas.exceptions import (
14-
CastError, ValidateError,
14+
ValidateError,
1515
)
16+
from openapi_core.casting.schemas.exceptions import CastError
1617
from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError
1718

1819
log = logging.getLogger(__name__)

openapi_core/schema/schemas/exceptions.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,6 @@ class OpenAPISchemaError(OpenAPIMappingError):
77
pass
88

99

10-
@attr.s(hash=True)
11-
class CastError(OpenAPISchemaError):
12-
"""Schema cast operation error"""
13-
value = attr.ib()
14-
type = attr.ib()
15-
16-
def __str__(self):
17-
return "Failed to cast value {value} to type {type}".format(
18-
value=self.value, type=self.type)
19-
20-
2110
class ValidateError(OpenAPISchemaError):
2211
"""Schema validate operation error"""
2312
pass

openapi_core/schema/schemas/models.py

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
"""OpenAPI core schemas models module"""
22
import attr
33
import logging
4-
from collections import defaultdict
54
import re
65

76
from jsonschema.exceptions import ValidationError
87

98
from openapi_core.schema.schemas._format import oas30_format_checker
109
from openapi_core.schema.schemas.enums import SchemaType
11-
from openapi_core.schema.schemas.exceptions import (
12-
CastError, InvalidSchemaValue,
13-
)
10+
from openapi_core.schema.schemas.exceptions import InvalidSchemaValue
1411
from openapi_core.schema.schemas.types import NoValue
15-
from openapi_core.schema.schemas.util import forcebool
1612
from openapi_core.schema.schemas.validators import OAS30Validator
1713
from openapi_core.unmarshalling.schemas.exceptions import (
1814
UnmarshalValueError,
@@ -30,12 +26,6 @@ class Format(object):
3026
class Schema(object):
3127
"""Represents an OpenAPI Schema."""
3228

33-
TYPE_CAST_CALLABLE_GETTER = {
34-
SchemaType.INTEGER: int,
35-
SchemaType.NUMBER: float,
36-
SchemaType.BOOLEAN: forcebool,
37-
}
38-
3929
def __init__(
4030
self, schema_type=None, properties=None, items=None,
4131
schema_format=None, required=None, default=NoValue, nullable=False,
@@ -109,30 +99,17 @@ def get_all_properties_names(self):
10999
all_properties = self.get_all_properties()
110100
return set(all_properties.keys())
111101

112-
def get_cast_mapping(self):
113-
mapping = self.TYPE_CAST_CALLABLE_GETTER.copy()
114-
mapping.update({
115-
SchemaType.ARRAY: self._cast_collection,
116-
})
117-
118-
return defaultdict(lambda: lambda x: x, mapping)
119-
120102
def cast(self, value):
121103
"""Cast value from string to schema type"""
122-
if value in (None, NoValue):
123-
return value
124-
125-
cast_mapping = self.get_cast_mapping()
126-
127-
cast_callable = cast_mapping[self.type]
104+
from openapi_core.casting.schemas.exceptions import CastError
105+
from openapi_core.casting.schemas.factories import SchemaCastersFactory
106+
casters_factory = SchemaCastersFactory()
107+
caster = casters_factory.create(self)
128108
try:
129-
return cast_callable(value)
130-
except ValueError:
109+
return caster(value)
110+
except (ValueError, TypeError):
131111
raise CastError(value, self.type)
132112

133-
def _cast_collection(self, value):
134-
return list(map(self.items.cast, value))
135-
136113
def get_validator(self, resolver=None):
137114
return OAS30Validator(
138115
self.__dict__,

0 commit comments

Comments
 (0)