From 7d903a8907b1350e2fa78a4554b1043d7bf243cd Mon Sep 17 00:00:00 2001 From: Daniel Bradburn Date: Sat, 2 Mar 2019 21:44:01 +0100 Subject: [PATCH 1/3] Add support for one-of with any type --- openapi_core/schema/schemas/models.py | 34 +++++++++++++++++++++------ tests/integration/test_petstore.py | 5 ++-- tests/unit/schema/test_schemas.py | 27 +++++++++++++++++++++ 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/openapi_core/schema/schemas/models.py b/openapi_core/schema/schemas/models.py index 7353dd0..8088898 100644 --- a/openapi_core/schema/schemas/models.py +++ b/openapi_core/schema/schemas/models.py @@ -219,6 +219,9 @@ class Schema(object): else: raise InvalidSchemaValue(msg, value, self.format) else: + if self.enum and value not in self.enum: + raise InvalidSchemaValue( + "Value {value} not in enum choices: {type}", value, self.enum) formatstring = self.STRING_FORMAT_CALLABLE_GETTER[schema_format] try: @@ -251,13 +254,30 @@ class Schema(object): SchemaType.INTEGER, SchemaType.NUMBER, SchemaType.STRING, ] cast_mapping = self.get_cast_mapping() - for schema_type in types_resolve_order: - cast_callable = cast_mapping[schema_type] - try: - return cast_callable(value) - # @todo: remove ValueError when validation separated - except (OpenAPISchemaError, TypeError, ValueError): - continue + if self.one_of: + result = None + for subschema in self.one_of: + try: + casted = subschema.cast(value, custom_formatters) + except (OpenAPISchemaError, TypeError, ValueError): + continue + else: + if result is not None: + raise MultipleOneOfSchema(self.type) + result = casted + + if result is None: + raise NoOneOfSchema(self.type) + + return result + else: + for schema_type in types_resolve_order: + cast_callable = cast_mapping[schema_type] + try: + return cast_callable(value) + # @todo: remove ValueError when validation separated + except (OpenAPISchemaError, TypeError, ValueError): + continue raise NoValidSchema(value) diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py index ceab793..702efbd 100644 --- a/tests/integration/test_petstore.py +++ b/tests/integration/test_petstore.py @@ -1,5 +1,6 @@ import json import pytest +from datetime import datetime from base64 import b64encode from uuid import UUID from six import iteritems, text_type @@ -1213,7 +1214,7 @@ class TestPetstore(object): assert parameters == {} assert isinstance(body, BaseModel) - assert body.created == created + assert body.created == datetime(2016, 4, 16, 16, 6, 5) assert body.name == pet_name code = 400 @@ -1257,7 +1258,7 @@ class TestPetstore(object): ) parameters = request.get_parameters(spec) - with pytest.raises(NoValidSchema): + with pytest.raises(InvalidMediaTypeValue): request.get_body(spec) assert parameters == {} diff --git a/tests/unit/schema/test_schemas.py b/tests/unit/schema/test_schemas.py index b66dad7..0e9e8bf 100644 --- a/tests/unit/schema/test_schemas.py +++ b/tests/unit/schema/test_schemas.py @@ -269,6 +269,33 @@ class TestSchemaUnmarshal(object): with pytest.raises(InvalidSchemaValue): schema.unmarshal(value) + def test_schema_any_one_of(self): + schema = Schema(one_of=[ + Schema('string'), + Schema('array', items=Schema('string')), + ]) + assert schema.unmarshal(['hello']) == ['hello'] + + def test_schema_any_one_of_mutiple(self): + schema = Schema(one_of=[ + Schema('array', items=Schema('string')), + Schema('array', items=Schema('number')), + ]) + with pytest.raises(MultipleOneOfSchema): + schema.unmarshal([]) + + def test_schema_any_one_of_no_valid(self): + schema = Schema(one_of=[ + Schema('array', items=Schema('string')), + Schema('array', items=Schema('number')), + ]) + with pytest.raises(NoOneOfSchema): + schema.unmarshal({}) + + def test_schema_any(self): + schema = Schema() + assert schema.unmarshal('string') == 'string' + class TestSchemaValidate(object): From d742a03f0fe3cec3268f5641670e39e7c602af3d Mon Sep 17 00:00:00 2001 From: Daniel Bradburn Date: Sat, 8 Jun 2019 11:03:58 +0200 Subject: [PATCH 2/3] remove unused import --- openapi_core/schema/schemas/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openapi_core/schema/schemas/models.py b/openapi_core/schema/schemas/models.py index 8088898..bdc4b51 100644 --- a/openapi_core/schema/schemas/models.py +++ b/openapi_core/schema/schemas/models.py @@ -2,7 +2,6 @@ import attr import functools import logging -from base64 import b64decode, b64encode from collections import defaultdict from datetime import date, datetime from uuid import UUID From a1596ea8c38b913a44962be95a4b4cff7e71986d Mon Sep 17 00:00:00 2001 From: Daniel Bradburn Date: Sat, 8 Jun 2019 11:21:59 +0200 Subject: [PATCH 3/3] remove unused import --- tests/integration/test_petstore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py index 702efbd..4c92c91 100644 --- a/tests/integration/test_petstore.py +++ b/tests/integration/test_petstore.py @@ -20,7 +20,7 @@ from openapi_core.schema.request_bodies.models import RequestBody from openapi_core.schema.responses.models import Response from openapi_core.schema.schemas.enums import SchemaType from openapi_core.schema.schemas.exceptions import ( - NoValidSchema, InvalidSchemaProperty, InvalidSchemaValue, + InvalidSchemaProperty, InvalidSchemaValue, ) from openapi_core.schema.schemas.models import Schema from openapi_core.schema.servers.exceptions import InvalidServer