Skip to content

Commit d6c5c76

Browse files
committed
Separate schema casting and validation
1 parent 7aaa517 commit d6c5c76

File tree

5 files changed

+67
-3
lines changed

5 files changed

+67
-3
lines changed

openapi_core/schema/media_types/models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ def unmarshal(self, value):
4242
raise InvalidMediaTypeValue(str(exc))
4343

4444
try:
45-
return self.schema.unmarshal(deserialized)
45+
unmarshalled = self.schema.unmarshal(deserialized)
46+
except InvalidSchemaValue as exc:
47+
raise InvalidMediaTypeValue(str(exc))
48+
49+
try:
50+
return self.schema.validate(unmarshalled)
4651
except InvalidSchemaValue as exc:
4752
raise InvalidMediaTypeValue(str(exc))

openapi_core/schema/parameters/models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ def unmarshal(self, value):
112112
raise InvalidParameterValue(str(exc))
113113

114114
try:
115-
return self.schema.unmarshal(deserialized)
115+
unmarshalled = self.schema.unmarshal(deserialized)
116+
except InvalidSchemaValue as exc:
117+
raise InvalidParameterValue(str(exc))
118+
119+
try:
120+
return self.schema.validate(unmarshalled)
116121
except InvalidSchemaValue as exc:
117122
raise InvalidParameterValue(str(exc))

openapi_core/schema/responses/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ def __init__(
1717
self.links = links and dict(links) or {}
1818

1919
def __getitem__(self, mimetype):
20+
return self.get_content_type(mimetype)
21+
22+
def get_content_type(self, mimetype):
2023
try:
2124
return self.content[mimetype]
2225
except MimeTypeNotFound:

openapi_core/schema/schemas/models.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections import defaultdict
44
import warnings
55

6-
from six import iteritems
6+
from six import iteritems, integer_types, binary_type, text_type
77

88
from openapi_core.extensions.models.factories import ModelFactory
99
from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
@@ -12,6 +12,9 @@
1212
OpenAPISchemaError, NoOneOfSchema, MultipleOneOfSchema,
1313
)
1414
from openapi_core.schema.schemas.util import forcebool, format_date
15+
from openapi_core.schema.schemas.validators import (
16+
TypeValidator, AttributeValidator,
17+
)
1518

1619
log = logging.getLogger(__name__)
1720

@@ -29,6 +32,16 @@ class Schema(object):
2932
SchemaFormat.DATE.value: format_date,
3033
})
3134

35+
VALIDATOR_CALLABLE_GETTER = {
36+
None: lambda x: x,
37+
SchemaType.BOOLEAN: TypeValidator(bool),
38+
SchemaType.INTEGER: TypeValidator(integer_types),
39+
SchemaType.NUMBER: TypeValidator(integer_types, float),
40+
SchemaType.STRING: TypeValidator(binary_type, text_type),
41+
SchemaType.ARRAY: TypeValidator(list, tuple),
42+
SchemaType.OBJECT: AttributeValidator('__class__'),
43+
}
44+
3245
def __init__(
3346
self, schema_type=None, model=None, properties=None, items=None,
3447
schema_format=None, required=None, default=None, nullable=False,
@@ -222,3 +235,19 @@ def _unmarshal_properties(self, value, one_of_schema=None):
222235
prop_value = prop.default
223236
properties[prop_name] = prop.unmarshal(prop_value)
224237
return properties
238+
239+
def validate(self, value):
240+
if value is None:
241+
if not self.nullable:
242+
raise InvalidSchemaValue("Null value for non-nullable schema")
243+
return self.default
244+
245+
validator = self.VALIDATOR_CALLABLE_GETTER[self.type]
246+
247+
if not validator(value):
248+
raise InvalidSchemaValue(
249+
"Value of {0} not valid type of {1}".format(
250+
value, self.type.value)
251+
)
252+
253+
return value
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class TypeValidator(object):
2+
3+
def __init__(self, *types):
4+
self.types = types
5+
6+
def __call__(self, value):
7+
if not isinstance(value, self.types):
8+
return False
9+
10+
return True
11+
12+
13+
class AttributeValidator(object):
14+
15+
def __init__(self, attribute):
16+
self.attribute = attribute
17+
18+
def __call__(self, value):
19+
if not hasattr(value, self.attribute):
20+
return False
21+
22+
return True

0 commit comments

Comments
 (0)