From d43a10b121efec80e3c975e385b1d949064def26 Mon Sep 17 00:00:00 2001 From: p1c2u Date: Mon, 20 Feb 2023 08:14:56 +0000 Subject: [PATCH] shortcuts refactor --- openapi_core/__init__.py | 12 + openapi_core/shortcuts.py | 290 +++++++++++++-- tests/integration/test_petstore.py | 309 +++++++++------- tests/unit/test_shortcuts.py | 565 +++++++++++++++++++++++++---- 4 files changed, 925 insertions(+), 251 deletions(-) diff --git a/openapi_core/__init__.py b/openapi_core/__init__.py index 75f382c8..05711ee1 100644 --- a/openapi_core/__init__.py +++ b/openapi_core/__init__.py @@ -1,10 +1,16 @@ """OpenAPI core module""" +from openapi_core.shortcuts import unmarshal_apicall_request +from openapi_core.shortcuts import unmarshal_apicall_response from openapi_core.shortcuts import unmarshal_request from openapi_core.shortcuts import unmarshal_response from openapi_core.shortcuts import unmarshal_webhook_request from openapi_core.shortcuts import unmarshal_webhook_response +from openapi_core.shortcuts import validate_apicall_request +from openapi_core.shortcuts import validate_apicall_response from openapi_core.shortcuts import validate_request from openapi_core.shortcuts import validate_response +from openapi_core.shortcuts import validate_webhook_request +from openapi_core.shortcuts import validate_webhook_response from openapi_core.spec import Spec from openapi_core.unmarshalling.request import RequestValidator from openapi_core.unmarshalling.request import V3RequestUnmarshaller @@ -47,8 +53,14 @@ "Spec", "unmarshal_request", "unmarshal_response", + "unmarshal_apicall_request", "unmarshal_webhook_request", + "unmarshal_apicall_response", "unmarshal_webhook_response", + "validate_apicall_request", + "validate_webhook_request", + "validate_apicall_response", + "validate_webhook_response", "validate_request", "validate_response", "V30RequestUnmarshaller", diff --git a/openapi_core/shortcuts.py b/openapi_core/shortcuts.py index 91a5fc3e..3ffe688e 100644 --- a/openapi_core/shortcuts.py +++ b/openapi_core/shortcuts.py @@ -1,4 +1,4 @@ -"""OpenAPI core validation shortcuts module""" +"""OpenAPI core shortcuts module""" import warnings from typing import Any from typing import Dict @@ -29,12 +29,6 @@ from openapi_core.unmarshalling.request.types import ( WebhookRequestUnmarshallerType, ) -from openapi_core.unmarshalling.request.unmarshallers import ( - BaseAPICallRequestUnmarshaller, -) -from openapi_core.unmarshalling.request.unmarshallers import ( - BaseWebhookRequestUnmarshaller, -) from openapi_core.unmarshalling.response import V30ResponseUnmarshaller from openapi_core.unmarshalling.response import V31ResponseUnmarshaller from openapi_core.unmarshalling.response import V31WebhookResponseUnmarshaller @@ -58,9 +52,19 @@ from openapi_core.validation.request import V30RequestValidator from openapi_core.validation.request import V31RequestValidator from openapi_core.validation.request import V31WebhookRequestValidator +from openapi_core.validation.request.protocols import RequestValidator +from openapi_core.validation.request.protocols import WebhookRequestValidator +from openapi_core.validation.request.types import AnyRequestValidatorType +from openapi_core.validation.request.types import RequestValidatorType +from openapi_core.validation.request.types import WebhookRequestValidatorType from openapi_core.validation.response import V30ResponseValidator from openapi_core.validation.response import V31ResponseValidator from openapi_core.validation.response import V31WebhookResponseValidator +from openapi_core.validation.response.protocols import ResponseValidator +from openapi_core.validation.response.protocols import WebhookResponseValidator +from openapi_core.validation.response.types import AnyResponseValidatorType +from openapi_core.validation.response.types import ResponseValidatorType +from openapi_core.validation.response.types import WebhookResponseValidatorType AnyRequest = Union[Request, WebhookRequest] @@ -92,7 +96,7 @@ def get_classes(spec: Spec) -> SpecClasses: return SpecFinder(SPECS).get_classes(spec) -def unmarshal_request( +def unmarshal_apicall_request( request: Request, spec: Spec, base_url: Optional[str] = None, @@ -140,7 +144,46 @@ def unmarshal_webhook_request( return result -def unmarshal_response( +def unmarshal_request( + request: AnyRequest, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[AnyRequestUnmarshallerType] = None, + **unmarshaller_kwargs: Any, +) -> RequestUnmarshalResult: + if not isinstance(request, (Request, WebhookRequest)): + raise TypeError("'request' argument is not type of (Webhook)Request") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if isinstance(request, WebhookRequest): + if cls is None or issubclass(cls, WebhookRequestUnmarshaller): + return unmarshal_webhook_request( + request, + spec, + base_url=base_url, + cls=cls, + **unmarshaller_kwargs, + ) + else: + raise TypeError( + "'cls' argument is not type of WebhookRequestUnmarshaller" + ) + else: + if cls is None or issubclass(cls, RequestUnmarshaller): + return unmarshal_apicall_request( + request, + spec, + base_url=base_url, + cls=cls, + **unmarshaller_kwargs, + ) + else: + raise TypeError( + "'cls' argument is not type of RequestUnmarshaller" + ) + + +def unmarshal_apicall_response( request: Request, response: Response, spec: Spec, @@ -194,14 +237,58 @@ def unmarshal_webhook_response( return result +def unmarshal_response( + request: AnyRequest, + response: Response, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[AnyResponseUnmarshallerType] = None, + **unmarshaller_kwargs: Any, +) -> ResponseUnmarshalResult: + if not isinstance(request, (Request, WebhookRequest)): + raise TypeError("'request' argument is not type of (Webhook)Request") + if not isinstance(response, Response): + raise TypeError("'response' argument is not type of Response") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if isinstance(request, WebhookRequest): + if cls is None or issubclass(cls, WebhookResponseUnmarshaller): + return unmarshal_webhook_response( + request, + response, + spec, + base_url=base_url, + cls=cls, + **unmarshaller_kwargs, + ) + else: + raise TypeError( + "'cls' argument is not type of WebhookResponseUnmarshaller" + ) + else: + if cls is None or issubclass(cls, ResponseUnmarshaller): + return unmarshal_apicall_response( + request, + response, + spec, + base_url=base_url, + cls=cls, + **unmarshaller_kwargs, + ) + else: + raise TypeError( + "'cls' argument is not type of ResponseUnmarshaller" + ) + + def validate_request( request: AnyRequest, spec: Spec, base_url: Optional[str] = None, validator: Optional[SpecRequestValidatorProxy] = None, - cls: Optional[AnyRequestUnmarshallerType] = None, + cls: Optional[AnyRequestValidatorType] = None, **validator_kwargs: Any, -) -> RequestUnmarshalResult: +) -> Optional[RequestUnmarshalResult]: if isinstance(spec, (Request, WebhookRequest)) and isinstance( request, Spec ): @@ -226,24 +313,49 @@ def validate_request( result.raise_for_errors() return result + # redirect to unmarshaller for backward compatibility + if cls is None or issubclass( + cls, (RequestUnmarshaller, WebhookRequestUnmarshaller) + ): + warnings.warn( + "validate_request is deprecated for unmarshalling data " + "and it will not return any result in the future. " + "Use unmarshal_request function instead.", + DeprecationWarning, + ) + return unmarshal_request( + request, + spec=spec, + base_url=base_url, + cls=cls, + **validator_kwargs, + ) if isinstance(request, WebhookRequest): - if cls is None or issubclass(cls, WebhookRequestUnmarshaller): - return unmarshal_webhook_request( - request, spec, base_url=base_url, cls=cls, **validator_kwargs + if cls is None or issubclass(cls, WebhookRequestValidator): + validate_webhook_request( + request, + spec, + base_url=base_url, + cls=cls, + **validator_kwargs, ) + return None else: raise TypeError( - "'cls' argument is not type of WebhookRequestUnmarshaller" + "'cls' argument is not type of WebhookRequestValidator" ) - elif isinstance(request, Request): - if cls is None or issubclass(cls, RequestUnmarshaller): - return unmarshal_request( - request, spec, base_url=base_url, cls=cls, **validator_kwargs + else: + if cls is None or issubclass(cls, RequestValidator): + validate_apicall_request( + request, + spec, + base_url=base_url, + cls=cls, + **validator_kwargs, ) + return None else: - raise TypeError( - "'cls' argument is not type of RequestUnmarshaller" - ) + raise TypeError("'cls' argument is not type of RequestValidator") def validate_response( @@ -252,9 +364,9 @@ def validate_response( spec: Union[Spec, Response], base_url: Optional[str] = None, validator: Optional[SpecResponseValidatorProxy] = None, - cls: Optional[AnyResponseUnmarshallerType] = None, + cls: Optional[AnyResponseValidatorType] = None, **validator_kwargs: Any, -) -> ResponseUnmarshalResult: +) -> Optional[ResponseUnmarshalResult]: if ( isinstance(request, Spec) and isinstance(response, (Request, WebhookRequest)) @@ -284,9 +396,27 @@ def validate_response( result.raise_for_errors() return result + # redirect to unmarshaller for backward compatibility + if cls is None or issubclass( + cls, (ResponseUnmarshaller, WebhookResponseUnmarshaller) + ): + warnings.warn( + "validate_response is deprecated for unmarshalling data " + "and it will not return any result in the future. " + "Use unmarshal_response function instead.", + DeprecationWarning, + ) + return unmarshal_response( + request, + response, + spec=spec, + base_url=base_url, + cls=cls, + **validator_kwargs, + ) if isinstance(request, WebhookRequest): - if cls is None or issubclass(cls, WebhookResponseUnmarshaller): - return unmarshal_webhook_response( + if cls is None or issubclass(cls, WebhookResponseValidator): + validate_webhook_response( request, response, spec, @@ -294,13 +424,14 @@ def validate_response( cls=cls, **validator_kwargs, ) + return None else: raise TypeError( - "'cls' argument is not type of WebhookResponseUnmarshaller" + "'cls' argument is not type of WebhookResponseValidator" ) - elif isinstance(request, Request): - if cls is None or issubclass(cls, ResponseUnmarshaller): - return unmarshal_response( + else: + if cls is None or issubclass(cls, ResponseValidator): + validate_apicall_response( request, response, spec, @@ -308,7 +439,100 @@ def validate_response( cls=cls, **validator_kwargs, ) + return None else: - raise TypeError( - "'cls' argument is not type of ResponseUnmarshaller" - ) + raise TypeError("'cls' argument is not type of ResponseValidator") + + +def validate_apicall_request( + request: Request, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[RequestValidatorType] = None, + **validator_kwargs: Any, +) -> None: + if not isinstance(request, Request): + raise TypeError("'request' argument is not type of Request") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if cls is None: + classes = get_classes(spec) + cls = classes.request_validator_cls + if not issubclass(cls, RequestValidator): + raise TypeError("'cls' argument is not type of RequestValidator") + v = cls(spec, base_url=base_url, **validator_kwargs) + return v.validate(request) + + +def validate_webhook_request( + request: WebhookRequest, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[WebhookRequestValidatorType] = None, + **validator_kwargs: Any, +) -> None: + if not isinstance(request, WebhookRequest): + raise TypeError("'request' argument is not type of WebhookRequest") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if cls is None: + classes = get_classes(spec) + cls = classes.webhook_request_validator_cls + if cls is None: + raise SpecError("Validator class not found") + if not issubclass(cls, WebhookRequestValidator): + raise TypeError( + "'cls' argument is not type of WebhookRequestValidator" + ) + v = cls(spec, base_url=base_url, **validator_kwargs) + return v.validate(request) + + +def validate_apicall_response( + request: Request, + response: Response, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[ResponseValidatorType] = None, + **validator_kwargs: Any, +) -> None: + if not isinstance(request, Request): + raise TypeError("'request' argument is not type of Request") + if not isinstance(response, Response): + raise TypeError("'response' argument is not type of Response") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if cls is None: + classes = get_classes(spec) + cls = classes.response_validator_cls + if not issubclass(cls, ResponseValidator): + raise TypeError("'cls' argument is not type of ResponseValidator") + v = cls(spec, base_url=base_url, **validator_kwargs) + return v.validate(request, response) + + +def validate_webhook_response( + request: WebhookRequest, + response: Response, + spec: Spec, + base_url: Optional[str] = None, + cls: Optional[WebhookResponseValidatorType] = None, + **validator_kwargs: Any, +) -> None: + if not isinstance(request, WebhookRequest): + raise TypeError("'request' argument is not type of WebhookRequest") + if not isinstance(response, Response): + raise TypeError("'response' argument is not type of Response") + if not isinstance(spec, Spec): + raise TypeError("'spec' argument is not type of Spec") + if cls is None: + classes = get_classes(spec) + cls = classes.webhook_response_validator_cls + if cls is None: + raise SpecError("Validator class not found") + if not issubclass(cls, WebhookResponseValidator): + raise TypeError( + "'cls' argument is not type of WebhookResponseValidator" + ) + v = cls(spec, base_url=base_url, **validator_kwargs) + return v.validate(request, response) diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py index 3f2b2781..5ab2ea42 100644 --- a/tests/integration/test_petstore.py +++ b/tests/integration/test_petstore.py @@ -1,13 +1,14 @@ import json from base64 import b64encode from dataclasses import is_dataclass -from dataclasses import make_dataclass from datetime import datetime from uuid import UUID import pytest from isodate.tzinfo import UTC +from openapi_core import unmarshal_request +from openapi_core import unmarshal_response from openapi_core import validate_request from openapi_core import validate_response from openapi_core.casting.schemas.exceptions import CastError @@ -16,7 +17,6 @@ from openapi_core.deserializing.parameters.exceptions import ( EmptyQueryParameterValue, ) -from openapi_core.spec import Spec from openapi_core.templating.media_types.exceptions import MediaTypeNotFound from openapi_core.templating.paths.exceptions import ServerNotFound from openapi_core.templating.security.exceptions import SecurityNotFound @@ -44,8 +44,18 @@ from openapi_core.validation.request.exceptions import ParameterError from openapi_core.validation.request.exceptions import RequestBodyError from openapi_core.validation.request.exceptions import SecurityError +from openapi_core.validation.request.validators import V30RequestBodyValidator +from openapi_core.validation.request.validators import ( + V30RequestParametersValidator, +) +from openapi_core.validation.request.validators import ( + V30RequestSecurityValidator, +) from openapi_core.validation.response.exceptions import InvalidData from openapi_core.validation.response.exceptions import MissingRequiredHeader +from openapi_core.validation.response.validators import ( + V30ResponseDataValidator, +) from openapi_core.validation.schemas.exceptions import InvalidSchemaValue @@ -100,7 +110,7 @@ def test_get_pets(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller, @@ -118,7 +128,8 @@ def test_get_pets(self, spec): } response = MockResponse(data, headers=headers) - response_result = validate_response(request, response, spec=spec) + with pytest.warns(DeprecationWarning): + response_result = validate_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -157,7 +168,7 @@ def test_get_pets_response(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -177,7 +188,7 @@ def test_get_pets_response(self, spec): data = json.dumps(data_json) response = MockResponse(data) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -215,7 +226,7 @@ def test_get_pets_response_no_schema(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -225,7 +236,7 @@ def test_get_pets_response_no_schema(self, spec): response = MockResponse(data, status_code=404, mimetype="text/html") with pytest.warns(UserWarning): - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert response_result.data == data @@ -260,7 +271,7 @@ def test_get_pets_invalid_response(self, spec, response_unmarshaller): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -284,7 +295,7 @@ def test_get_pets_invalid_response(self, spec, response_unmarshaller): request, response, spec=spec, - cls=V30ResponseDataUnmarshaller, + cls=V30ResponseDataValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -331,7 +342,7 @@ def test_get_pets_ids_param(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -343,7 +354,7 @@ def test_get_pets_ids_param(self, spec): data = json.dumps(data_json) response = MockResponse(data) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -381,7 +392,7 @@ def test_get_pets_tags_param(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -393,7 +404,7 @@ def test_get_pets_tags_param(self, spec): data = json.dumps(data_json) response = MockResponse(data) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -424,7 +435,7 @@ def test_get_pets_parameter_deserialization_error(self, spec): ) assert type(exc_info.value.__cause__) is DeserializeError - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -450,11 +461,11 @@ def test_get_pets_wrong_parameter_type(self, spec): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) assert type(exc_info.value.__cause__) is CastError - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -475,10 +486,10 @@ def test_get_pets_raises_missing_required_param(self, spec): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -504,11 +515,11 @@ def test_get_pets_empty_value(self, spec): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) assert type(exc_info.value.__cause__) is EmptyQueryParameterValue - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -545,7 +556,7 @@ def test_get_pets_allow_empty_value(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -581,7 +592,7 @@ def test_get_pets_none_value(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -619,7 +630,7 @@ def test_get_pets_param_order(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -660,7 +671,7 @@ def test_get_pets_param_coordinates(self, spec): assert result.parameters.query["coordinates"].lat == coordinates["lat"] assert result.parameters.query["coordinates"].lon == coordinates["lon"] - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -710,7 +721,7 @@ def test_post_birds(self, spec, spec_dict): cookies=cookies, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -723,7 +734,7 @@ def test_post_birds(self, spec, spec_dict): ) assert result.parameters.cookie["userdata"].name == "user1" - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -739,7 +750,7 @@ def test_post_birds(self, spec, spec_dict): assert result.body.address.city == pet_city assert result.body.healthy == pet_healthy - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestSecurityUnmarshaller, @@ -787,7 +798,7 @@ def test_post_cats(self, spec, spec_dict): cookies=cookies, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -802,7 +813,7 @@ def test_post_cats(self, spec, spec_dict): }, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -858,7 +869,7 @@ def test_post_cats_boolean_string(self, spec, spec_dict): cookies=cookies, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -873,9 +884,10 @@ def test_post_cats_boolean_string(self, spec, spec_dict): }, ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -916,11 +928,12 @@ def test_post_no_one_of_schema(self, spec): cookies=cookies, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -935,7 +948,7 @@ def test_post_no_one_of_schema(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -968,11 +981,12 @@ def test_post_cats_only_required_body(self, spec, spec_dict): cookies=cookies, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -983,9 +997,10 @@ def test_post_cats_only_required_body(self, spec, spec_dict): }, ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1020,11 +1035,12 @@ def test_post_pets_raises_invalid_mimetype(self, spec): cookies=cookies, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -1039,7 +1055,7 @@ def test_post_pets_raises_invalid_mimetype(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is MediaTypeNotFound @@ -1072,12 +1088,13 @@ def test_post_pets_missing_cookie(self, spec, spec_dict): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1115,12 +1132,13 @@ def test_post_pets_missing_header(self, spec, spec_dict): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1159,14 +1177,14 @@ def test_post_pets_raises_invalid_server_error(self, spec): validate_request( request, spec=spec, - cls=V30RequestParametersUnmarshaller, + cls=V30RequestParametersValidator, ) with pytest.raises(ServerNotFound): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) data_id = 1 @@ -1188,7 +1206,7 @@ def test_post_pets_raises_invalid_server_error(self, spec): request, response, spec=spec, - cls=V30ResponseDataUnmarshaller, + cls=V30ResponseDataValidator, ) def test_get_pet_invalid_security(self, spec): @@ -1210,7 +1228,7 @@ def test_get_pet_invalid_security(self, spec): validate_request( request, spec=spec, - cls=V30RequestSecurityUnmarshaller, + cls=V30RequestSecurityValidator, ) assert exc_info.value.__cause__ == SecurityNotFound( @@ -1236,11 +1254,12 @@ def test_get_pet(self, spec): headers=headers, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1248,17 +1267,19 @@ def test_get_pet(self, spec): } ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None - result = validate_request( - request, - spec=spec, - cls=V30RequestSecurityUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestSecurityUnmarshaller, + ) assert result.security == { "petstore_auth": auth, @@ -1278,7 +1299,7 @@ def test_get_pet(self, spec): data = json.dumps(data_json) response = MockResponse(data) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1300,11 +1321,12 @@ def test_get_pet_not_found(self, spec): view_args=view_args, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1312,9 +1334,10 @@ def test_get_pet_not_found(self, spec): } ) - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None @@ -1329,7 +1352,7 @@ def test_get_pet_not_found(self, spec): data = json.dumps(data_json) response = MockResponse(data, status_code=404) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1351,11 +1374,12 @@ def test_get_pet_wildcard(self, spec): view_args=view_args, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1363,7 +1387,7 @@ def test_get_pet_wildcard(self, spec): } ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller, @@ -1375,7 +1399,7 @@ def test_get_pet_wildcard(self, spec): response = MockResponse(data, mimetype="image/png") with pytest.warns(UserWarning): - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert response_result.data == data @@ -1391,7 +1415,7 @@ def test_get_tags(self, spec): path_pattern=path_pattern, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1399,9 +1423,10 @@ def test_get_tags(self, spec): assert result.parameters == Parameters() - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None @@ -1409,7 +1434,8 @@ def test_get_tags(self, spec): data = json.dumps(data_json) response = MockResponse(data) - response_result = validate_response(request, response, spec=spec) + with pytest.warns(DeprecationWarning): + response_result = validate_response(request, response, spec=spec) assert response_result.errors == [] assert response_result.data == data_json @@ -1433,7 +1459,7 @@ def test_post_tags_extra_body_properties(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1445,7 +1471,7 @@ def test_post_tags_extra_body_properties(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -1463,7 +1489,7 @@ def test_post_tags_empty_body(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1475,7 +1501,7 @@ def test_post_tags_empty_body(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -1493,7 +1519,7 @@ def test_post_tags_wrong_property_type(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1505,7 +1531,7 @@ def test_post_tags_wrong_property_type(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -1526,17 +1552,19 @@ def test_post_tags_additional_properties(self, spec): data=data, ) - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters() - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert is_dataclass(result.body) assert result.body.name == pet_name @@ -1554,7 +1582,8 @@ def test_post_tags_additional_properties(self, spec): data = json.dumps(data_json) response = MockResponse(data, status_code=404) - response_result = validate_response(request, response, spec=spec) + with pytest.warns(DeprecationWarning): + response_result = validate_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1582,7 +1611,7 @@ def test_post_tags_created_now(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1590,7 +1619,7 @@ def test_post_tags_created_now(self, spec): assert result.parameters == Parameters() - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -1611,7 +1640,7 @@ def test_post_tags_created_now(self, spec): data = json.dumps(data_json) response = MockResponse(data, status_code=404) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1639,7 +1668,7 @@ def test_post_tags_created_datetime(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1647,9 +1676,10 @@ def test_post_tags_created_datetime(self, spec): assert result.parameters == Parameters() - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert is_dataclass(result.body) assert result.body.created == datetime( @@ -1670,12 +1700,13 @@ def test_post_tags_created_datetime(self, spec): response_data = json.dumps(response_data_json) response = MockResponse(response_data, status_code=404) - result = validate_response( - request, - response, - spec=spec, - cls=V30ResponseDataUnmarshaller, - ) + with pytest.warns(DeprecationWarning): + result = validate_response( + request, + response, + spec=spec, + cls=V30ResponseDataUnmarshaller, + ) assert is_dataclass(result.data) assert result.data.code == code @@ -1683,7 +1714,7 @@ def test_post_tags_created_datetime(self, spec): assert result.data.rootCause == rootCause assert result.data.additionalinfo == additionalinfo - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1711,7 +1742,7 @@ def test_post_tags_created_invalid_type(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1723,7 +1754,7 @@ def test_post_tags_created_invalid_type(self, spec): validate_request( request, spec=spec, - cls=V30RequestBodyUnmarshaller, + cls=V30RequestBodyValidator, ) assert type(exc_info.value.__cause__) is InvalidSchemaValue @@ -1741,7 +1772,7 @@ def test_post_tags_created_invalid_type(self, spec): data = json.dumps(data_json) response = MockResponse(data, status_code=404) - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert is_dataclass(response_result.data) @@ -1767,7 +1798,7 @@ def test_delete_tags_with_requestbody(self, spec): data=data, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1775,7 +1806,7 @@ def test_delete_tags_with_requestbody(self, spec): assert result.parameters == Parameters() - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -1815,7 +1846,7 @@ def test_delete_tags_no_requestbody(self, spec): path_pattern=path_pattern, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1823,7 +1854,7 @@ def test_delete_tags_no_requestbody(self, spec): assert result.parameters == Parameters() - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) @@ -1841,7 +1872,7 @@ def test_delete_tags_raises_missing_required_response_header( path_pattern=path_pattern, ) - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestParametersUnmarshaller, @@ -1849,7 +1880,7 @@ def test_delete_tags_raises_missing_required_response_header( assert result.parameters == Parameters() - result = validate_request( + result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller ) diff --git a/tests/unit/test_shortcuts.py b/tests/unit/test_shortcuts.py index 796722e3..1c14e694 100644 --- a/tests/unit/test_shortcuts.py +++ b/tests/unit/test_shortcuts.py @@ -4,12 +4,18 @@ from openapi_core import RequestValidator from openapi_core import ResponseValidator +from openapi_core import unmarshal_apicall_request +from openapi_core import unmarshal_apicall_response from openapi_core import unmarshal_request from openapi_core import unmarshal_response from openapi_core import unmarshal_webhook_request from openapi_core import unmarshal_webhook_response +from openapi_core import validate_apicall_request +from openapi_core import validate_apicall_response from openapi_core import validate_request from openapi_core import validate_response +from openapi_core import validate_webhook_request +from openapi_core import validate_webhook_response from openapi_core.exceptions import SpecError from openapi_core.protocols import Request from openapi_core.protocols import Response @@ -22,9 +28,23 @@ from openapi_core.unmarshalling.request.unmarshallers import ( WebhookRequestUnmarshaller, ) +from openapi_core.unmarshalling.response.datatypes import ( + ResponseUnmarshalResult, +) from openapi_core.unmarshalling.response.unmarshallers import ( APICallResponseUnmarshaller, ) +from openapi_core.unmarshalling.response.unmarshallers import ( + WebhookResponseUnmarshaller, +) +from openapi_core.validation.request.validators import APICallRequestValidator +from openapi_core.validation.request.validators import WebhookRequestValidator +from openapi_core.validation.response.validators import ( + APICallResponseValidator, +) +from openapi_core.validation.response.validators import ( + WebhookResponseValidator, +) class MockClass: @@ -32,82 +52,69 @@ class MockClass: schema_unmarshallers_factory = None unmarshal_calls = [] + validate_calls = [] return_unmarshal = None @classmethod - def setUp(cls, return_unmarshal): + def setUp(cls, return_unmarshal=None): cls.unmarshal_calls = [] + cls.validate_calls = [] cls.return_unmarshal = return_unmarshal -class MockReqClass(MockClass): - assert_request = None +class MockReqValidator(MockClass): + def validate(self, req): + self.validate_calls.append((req,)) - @classmethod - def setUp(cls, return_unmarshal, assert_request): - super().setUp(return_unmarshal) - cls.assert_request = assert_request +class MockReqUnmarshaller(MockClass): def unmarshal(self, req): - self.unmarshal_calls.append([req]) - assert req == self.assert_request + self.unmarshal_calls.append((req,)) return self.return_unmarshal -class MockRespClass(MockClass): - assert_request = None - assert_response = None +class MockRespValidator(MockClass): + def validate(self, req, resp): + self.validate_calls.append((req, resp)) - @classmethod - def setUp(cls, return_unmarshal, assert_request, assert_response): - super().setUp(return_unmarshal) - cls.assert_request = assert_request - cls.assert_response = assert_response +class MockRespUnmarshaller(MockClass): def unmarshal(self, req, resp): - self.unmarshal_calls.append([req, resp]) - assert req == self.assert_request - assert resp == self.assert_response + self.unmarshal_calls.append((req, resp)) return self.return_unmarshal -class TestUnmarshalRequest: +@pytest.fixture(autouse=True) +def setup(): + MockClass.setUp() + yield + + +class TestUnmarshalAPICallRequest: def test_spec_not_detected(self, spec_invalid): request = mock.Mock(spec=Request) with pytest.raises(SpecError): - unmarshal_request(request, spec=spec_invalid) + unmarshal_apicall_request(request, spec=spec_invalid) def test_request_type_invalid(self, spec_v31): request = mock.sentinel.request with pytest.raises(TypeError): - unmarshal_request(request, spec=spec_v31) + unmarshal_apicall_request(request, spec=spec_v31) def test_spec_type_invalid(self): request = mock.Mock(spec=Request) spec = mock.sentinel.spec with pytest.raises(TypeError): - unmarshal_request(request, spec=spec) + unmarshal_apicall_request(request, spec=spec) def test_cls_type_invalid(self, spec_v31): request = mock.Mock(spec=Request) with pytest.raises(TypeError): - unmarshal_request(request, spec=spec_v31, cls=Exception) - - @mock.patch( - "openapi_core.unmarshalling.request.unmarshallers.APICallRequestUnmarshaller." - "unmarshal", - ) - def test_request(self, mock_unmarshal, spec_v31): - request = mock.Mock(spec=Request) - - result = unmarshal_request(request, spec=spec_v31) - - assert result == mock_unmarshal.return_value - mock_unmarshal.assert_called_once_with(request) + unmarshal_apicall_request(request, spec=spec_v31, cls=Exception) class TestUnmarshalWebhookRequest: @@ -136,6 +143,12 @@ def test_cls_type_invalid(self, spec_v31): with pytest.raises(TypeError): unmarshal_webhook_request(request, spec=spec_v31, cls=Exception) + def test_spec_oas30_validator_not_found(self, spec_v30): + request = mock.Mock(spec=WebhookRequest) + + with pytest.raises(SpecError): + unmarshal_webhook_request(request, spec=spec_v30) + @mock.patch( "openapi_core.unmarshalling.request.unmarshallers.WebhookRequestUnmarshaller." "unmarshal", @@ -149,6 +162,86 @@ def test_request(self, mock_unmarshal, spec_v31): mock_unmarshal.assert_called_once_with(request) +class TestUnmarshalRequest: + def test_spec_not_detected(self, spec_invalid): + request = mock.Mock(spec=Request) + + with pytest.raises(SpecError): + unmarshal_request(request, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + + with pytest.raises(TypeError): + unmarshal_request(request, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=Request) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + unmarshal_request(request, spec=spec) + + @pytest.mark.parametrize("req", [Request, WebhookRequest]) + def test_cls_type_invalid(self, spec_v31, req): + request = mock.Mock(spec=req) + + with pytest.raises(TypeError): + unmarshal_request(request, spec=spec_v31, cls=Exception) + + @mock.patch( + "openapi_core.unmarshalling.request.unmarshallers.APICallRequestUnmarshaller." + "unmarshal", + ) + def test_request(self, mock_unmarshal, spec_v31): + request = mock.Mock(spec=Request) + + result = unmarshal_request(request, spec=spec_v31) + + assert result == mock_unmarshal.return_value + mock_unmarshal.assert_called_once_with(request) + + +class TestUnmarshalAPICallResponse: + def test_spec_not_detected(self, spec_invalid): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + + with pytest.raises(SpecError): + unmarshal_apicall_response(request, response, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + response = mock.Mock(spec=Response) + + with pytest.raises(TypeError): + unmarshal_apicall_response(request, response, spec=spec_v31) + + def test_response_type_invalid(self, spec_v31): + request = mock.Mock(spec=Request) + response = mock.sentinel.response + + with pytest.raises(TypeError): + unmarshal_apicall_response(request, response, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + unmarshal_apicall_response(request, response, spec=spec) + + def test_cls_type_invalid(self, spec_v31): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + + with pytest.raises(TypeError): + unmarshal_apicall_response( + request, response, spec=spec_v31, cls=Exception + ) + + class TestUnmarshalResponse: def test_spec_not_detected(self, spec_invalid): request = mock.Mock(spec=Request) @@ -179,8 +272,9 @@ def test_spec_type_invalid(self): with pytest.raises(TypeError): unmarshal_response(request, response, spec=spec) - def test_cls_type_invalid(self, spec_v31): - request = mock.Mock(spec=Request) + @pytest.mark.parametrize("req", [Request, WebhookRequest]) + def test_cls_type_invalid(self, spec_v31, req): + request = mock.Mock(spec=req) response = mock.Mock(spec=Response) with pytest.raises(TypeError): @@ -239,6 +333,13 @@ def test_cls_type_invalid(self, spec_v31): request, response, spec=spec_v31, cls=Exception ) + def test_spec_oas30_validator_not_found(self, spec_v30): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + + with pytest.raises(SpecError): + unmarshal_webhook_response(request, response, spec=spec_v30) + @mock.patch( "openapi_core.unmarshalling.response.unmarshallers.WebhookResponseUnmarshaller." "unmarshal", @@ -253,12 +354,97 @@ def test_request_response(self, mock_unmarshal, spec_v31): mock_unmarshal.assert_called_once_with(request, response) +class TestValidateAPICallRequest: + def test_spec_not_detected(self, spec_invalid): + request = mock.Mock(spec=Request) + + with pytest.raises(SpecError): + validate_apicall_request(request, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + + with pytest.raises(TypeError): + validate_apicall_request(request, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=Request) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + validate_apicall_request(request, spec=spec) + + def test_cls_type_invalid(self, spec_v31): + request = mock.Mock(spec=Request) + + with pytest.raises(TypeError): + validate_apicall_request(request, spec=spec_v31, cls=Exception) + + @mock.patch( + "openapi_core.validation.request.validators.APICallRequestValidator." + "validate", + ) + def test_request(self, mock_validate, spec_v31): + request = mock.Mock(spec=Request) + + result = validate_apicall_request(request, spec=spec_v31) + + assert result == mock_validate.return_value + mock_validate.assert_called_once_with(request) + + +class TestValidateWebhookRequest: + def test_spec_not_detected(self, spec_invalid): + request = mock.Mock(spec=WebhookRequest) + + with pytest.raises(SpecError): + validate_webhook_request(request, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + + with pytest.raises(TypeError): + validate_webhook_request(request, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=WebhookRequest) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + validate_webhook_request(request, spec=spec) + + def test_cls_type_invalid(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + + with pytest.raises(TypeError): + validate_webhook_request(request, spec=spec_v31, cls=Exception) + + def test_spec_oas30_validator_not_found(self, spec_v30): + request = mock.Mock(spec=WebhookRequest) + + with pytest.raises(SpecError): + validate_webhook_request(request, spec=spec_v30) + + @mock.patch( + "openapi_core.validation.request.validators.WebhookRequestValidator." + "validate", + ) + def test_request(self, mock_validate, spec_v31): + request = mock.Mock(spec=WebhookRequest) + + result = validate_webhook_request(request, spec=spec_v31) + + assert result == mock_validate.return_value + mock_validate.assert_called_once_with(request) + + class TestValidateRequest: def test_spec_not_detected(self, spec_invalid): request = mock.Mock(spec=Request) with pytest.raises(SpecError): - validate_request(request, spec=spec_invalid) + with pytest.warns(DeprecationWarning): + validate_request(request, spec=spec_invalid) def test_request_type_invalid(self, spec_v31): request = mock.sentinel.request @@ -280,7 +466,8 @@ def test_spec_type_invalid(self): def test_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=Request) - result = validate_request(request, spec=spec_v31) + with pytest.warns(DeprecationWarning): + result = validate_request(request, spec=spec_v31) assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request) @@ -307,7 +494,8 @@ def test_request_error(self, mock_unmarshal, spec_v31): mock_unmarshal.return_value = ResultMock(error_to_raise=ValueError) with pytest.raises(ValueError): - validate_request(request, spec=spec_v31) + with pytest.warns(DeprecationWarning): + validate_request(request, spec=spec_v31) mock_unmarshal.assert_called_once_with(request) @@ -325,20 +513,90 @@ def test_validator(self, spec_v31): spec_v31, request, base_url=None ) - def test_cls(self, spec_v31): + def test_cls_apicall(self, spec_v31): request = mock.Mock(spec=Request) - unmarshal = mock.Mock(spec=RequestUnmarshalResult) TestAPICallReq = type( "TestAPICallReq", - (MockReqClass, APICallRequestUnmarshaller), + (MockReqValidator, APICallRequestValidator), {}, ) - TestAPICallReq.setUp(unmarshal, request) result = validate_request(request, spec=spec_v31, cls=TestAPICallReq) + assert result is None + assert TestAPICallReq.validate_calls == [ + (request,), + ] + + def test_cls_apicall_unmarshaller(self, spec_v31): + request = mock.Mock(spec=Request) + unmarshal = mock.Mock(spec=RequestUnmarshalResult) + TestAPICallReq = type( + "TestAPICallReq", + (MockReqUnmarshaller, APICallRequestUnmarshaller), + {}, + ) + TestAPICallReq.setUp(unmarshal) + + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec_v31, cls=TestAPICallReq + ) + + assert result == unmarshal + assert TestAPICallReq.unmarshal_calls == [ + (request,), + ] + + def test_cls_webhook(self, spec_v31): + request = mock.Mock(spec=Request) + TestWebhookReq = type( + "TestWebhookReq", + (MockReqValidator, WebhookRequestValidator), + {}, + ) + + result = validate_request(request, spec=spec_v31, cls=TestWebhookReq) + + assert result is None + assert TestWebhookReq.validate_calls == [ + (request,), + ] + + def test_webhook_cls(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + TestWebhookReq = type( + "TestWebhookReq", + (MockReqValidator, WebhookRequestValidator), + {}, + ) + + result = validate_request(request, spec=spec_v31, cls=TestWebhookReq) + + assert result is None + assert TestWebhookReq.validate_calls == [ + (request,), + ] + + def test_cls_webhook_unmarshaller(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + unmarshal = mock.Mock(spec=RequestUnmarshalResult) + TestWebhookReq = type( + "TestWebhookReq", + (MockReqUnmarshaller, WebhookRequestUnmarshaller), + {}, + ) + TestWebhookReq.setUp(unmarshal) + + with pytest.warns(DeprecationWarning): + result = validate_request( + request, spec=spec_v31, cls=TestWebhookReq + ) + assert result == unmarshal - assert len(TestAPICallReq.unmarshal_calls) == 1 + assert TestWebhookReq.unmarshal_calls == [ + (request,), + ] def test_cls_invalid(self, spec_v31): request = mock.Mock(spec=Request) @@ -353,7 +611,8 @@ def test_cls_invalid(self, spec_v31): def test_webhook_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=WebhookRequest) - result = validate_request(request, spec=spec_v31) + with pytest.warns(DeprecationWarning): + result = validate_request(request, spec=spec_v31) assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request) @@ -362,7 +621,8 @@ def test_webhook_request_validator_not_found(self, spec_v30): request = mock.Mock(spec=WebhookRequest) with pytest.raises(SpecError): - validate_request(request, spec=spec_v30) + with pytest.warns(DeprecationWarning): + validate_request(request, spec=spec_v30) @mock.patch( "openapi_core.unmarshalling.request.unmarshallers.WebhookRequestUnmarshaller." @@ -373,30 +633,129 @@ def test_webhook_request_error(self, mock_unmarshal, spec_v31): mock_unmarshal.return_value = ResultMock(error_to_raise=ValueError) with pytest.raises(ValueError): - validate_request(request, spec=spec_v31) + with pytest.warns(DeprecationWarning): + validate_request(request, spec=spec_v31) mock_unmarshal.assert_called_once_with(request) - def test_webhook_cls(self, spec_v31): + def test_webhook_cls_invalid(self, spec_v31): request = mock.Mock(spec=WebhookRequest) - unmarshal = mock.Mock(spec=RequestUnmarshalResult) - TestWebhookReq = type( - "TestWebhookReq", - (MockReqClass, WebhookRequestUnmarshaller), - {}, - ) - TestWebhookReq.setUp(unmarshal, request) - result = validate_request(request, spec=spec_v31, cls=TestWebhookReq) + with pytest.raises(TypeError): + validate_request(request, spec=spec_v31, cls=Exception) - assert result == unmarshal - assert len(TestWebhookReq.unmarshal_calls) == 1 - def test_webhook_cls_invalid(self, spec_v31): +class TestValidateAPICallResponse: + def test_spec_not_detected(self, spec_invalid): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + + with pytest.raises(SpecError): + validate_apicall_response(request, response, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + response = mock.Mock(spec=Response) + + with pytest.raises(TypeError): + validate_apicall_response(request, response, spec=spec_v31) + + def test_response_type_invalid(self, spec_v31): + request = mock.Mock(spec=Request) + response = mock.sentinel.response + + with pytest.raises(TypeError): + validate_apicall_response(request, response, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + validate_apicall_response(request, response, spec=spec) + + def test_cls_type_invalid(self, spec_v31): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + + with pytest.raises(TypeError): + validate_apicall_response( + request, response, spec=spec_v31, cls=Exception + ) + + @mock.patch( + "openapi_core.validation.response.validators.APICallResponseValidator." + "validate", + ) + def test_request_response(self, mock_validate, spec_v31): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + + result = validate_apicall_response(request, response, spec=spec_v31) + + assert result == mock_validate.return_value + mock_validate.assert_called_once_with(request, response) + + +class TestValidateWebhookResponse: + def test_spec_not_detected(self, spec_invalid): request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + + with pytest.raises(SpecError): + validate_webhook_response(request, response, spec=spec_invalid) + + def test_request_type_invalid(self, spec_v31): + request = mock.sentinel.request + response = mock.Mock(spec=Response) with pytest.raises(TypeError): - validate_request(request, spec=spec_v31, cls=Exception) + validate_webhook_response(request, response, spec=spec_v31) + + def test_response_type_invalid(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + response = mock.sentinel.response + + with pytest.raises(TypeError): + validate_webhook_response(request, response, spec=spec_v31) + + def test_spec_type_invalid(self): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + spec = mock.sentinel.spec + + with pytest.raises(TypeError): + validate_webhook_response(request, response, spec=spec) + + def test_cls_type_invalid(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + + with pytest.raises(TypeError): + validate_webhook_response( + request, response, spec=spec_v31, cls=Exception + ) + + def test_spec_oas30_validator_not_found(self, spec_v30): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + + with pytest.raises(SpecError): + validate_webhook_response(request, response, spec=spec_v30) + + @mock.patch( + "openapi_core.validation.response.validators.WebhookResponseValidator." + "validate", + ) + def test_request_response(self, mock_validate, spec_v31): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + + result = validate_webhook_response(request, response, spec=spec_v31) + + assert result == mock_validate.return_value + mock_validate.assert_called_once_with(request, response) class TestValidateResponse: @@ -405,7 +764,8 @@ def test_spec_not_detected(self, spec_invalid): response = mock.Mock(spec=Response) with pytest.raises(SpecError): - validate_response(request, response, spec=spec_invalid) + with pytest.warns(DeprecationWarning): + validate_response(request, response, spec=spec_invalid) def test_request_type_invalid(self, spec_v31): request = mock.sentinel.request @@ -437,7 +797,8 @@ def test_request_response(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=Request) response = mock.Mock(spec=Response) - result = validate_response(request, response, spec=spec_v31) + with pytest.warns(DeprecationWarning): + result = validate_response(request, response, spec=spec_v31) assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request, response) @@ -466,7 +827,8 @@ def test_request_response_error(self, mock_unmarshal, spec_v31): mock_unmarshal.return_value = ResultMock(error_to_raise=ValueError) with pytest.raises(ValueError): - validate_response(request, response, spec=spec_v31) + with pytest.warns(DeprecationWarning): + validate_response(request, response, spec=spec_v31) mock_unmarshal.assert_called_once_with(request, response) @@ -485,23 +847,65 @@ def test_validator(self, spec_v31): spec_v31, request, response, base_url=None ) - def test_cls(self, spec_v31): + def test_cls_apicall(self, spec_v31): request = mock.Mock(spec=Request) response = mock.Mock(spec=Response) - unmarshal = mock.Mock(spec=RequestUnmarshalResult) TestAPICallResp = type( "TestAPICallResp", - (MockRespClass, APICallResponseUnmarshaller), + (MockRespValidator, APICallResponseValidator), {}, ) - TestAPICallResp.setUp(unmarshal, request, response) result = validate_response( request, response, spec=spec_v31, cls=TestAPICallResp ) + assert result is None + assert TestAPICallResp.validate_calls == [ + (request, response), + ] + + def test_cls_apicall_unmarshaller(self, spec_v31): + request = mock.Mock(spec=Request) + response = mock.Mock(spec=Response) + unmarshal = mock.Mock(spec=ResponseUnmarshalResult) + TestAPICallReq = type( + "TestAPICallReq", + (MockRespUnmarshaller, APICallResponseUnmarshaller), + {}, + ) + TestAPICallReq.setUp(unmarshal) + + with pytest.warns(DeprecationWarning): + result = validate_response( + request, response, spec=spec_v31, cls=TestAPICallReq + ) + assert result == unmarshal - assert len(TestAPICallResp.unmarshal_calls) == 1 + assert TestAPICallReq.unmarshal_calls == [ + (request, response), + ] + + def test_cls_webhook_unmarshaller(self, spec_v31): + request = mock.Mock(spec=WebhookRequest) + response = mock.Mock(spec=Response) + unmarshal = mock.Mock(spec=ResponseUnmarshalResult) + TestWebhookReq = type( + "TestWebhookReq", + (MockRespUnmarshaller, WebhookResponseUnmarshaller), + {}, + ) + TestWebhookReq.setUp(unmarshal) + + with pytest.warns(DeprecationWarning): + result = validate_response( + request, response, spec=spec_v31, cls=TestWebhookReq + ) + + assert result == unmarshal + assert TestWebhookReq.unmarshal_calls == [ + (request, response), + ] def test_cls_type_invalid(self, spec_v31): request = mock.Mock(spec=Request) @@ -515,7 +919,8 @@ def test_webhook_response_validator_not_found(self, spec_v30): response = mock.Mock(spec=Response) with pytest.raises(SpecError): - validate_response(request, response, spec=spec_v30) + with pytest.warns(DeprecationWarning): + validate_response(request, response, spec=spec_v30) @mock.patch( "openapi_core.unmarshalling.response.unmarshallers.WebhookResponseUnmarshaller." @@ -525,7 +930,8 @@ def test_webhook_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=WebhookRequest) response = mock.Mock(spec=Response) - result = validate_response(request, response, spec=spec_v31) + with pytest.warns(DeprecationWarning): + result = validate_response(request, response, spec=spec_v31) assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request, response) @@ -540,27 +946,28 @@ def test_webhook_request_error(self, mock_unmarshal, spec_v31): mock_unmarshal.return_value = ResultMock(error_to_raise=ValueError) with pytest.raises(ValueError): - validate_response(request, response, spec=spec_v31) + with pytest.warns(DeprecationWarning): + validate_response(request, response, spec=spec_v31) mock_unmarshal.assert_called_once_with(request, response) def test_webhook_cls(self, spec_v31): request = mock.Mock(spec=WebhookRequest) response = mock.Mock(spec=Response) - unmarshal = mock.Mock(spec=RequestUnmarshalResult) TestWebhookResp = type( "TestWebhookResp", - (MockRespClass, APICallResponseUnmarshaller), + (MockRespValidator, WebhookResponseValidator), {}, ) - TestWebhookResp.setUp(unmarshal, request, response) result = validate_response( request, response, spec=spec_v31, cls=TestWebhookResp ) - assert result == unmarshal - assert len(TestWebhookResp.unmarshal_calls) == 1 + assert result is None + assert TestWebhookResp.validate_calls == [ + (request, response), + ] def test_webhook_cls_type_invalid(self, spec_v31): request = mock.Mock(spec=WebhookRequest) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy