diff --git a/openapi_core/shortcuts.py b/openapi_core/shortcuts.py index 3ffe688e..9f6c2c55 100644 --- a/openapi_core/shortcuts.py +++ b/openapi_core/shortcuts.py @@ -5,6 +5,8 @@ from typing import Optional from typing import Union +from lazy_object_proxy import Proxy + from openapi_core.exceptions import SpecError from openapi_core.finders import SpecClasses from openapi_core.finders import SpecFinder @@ -317,19 +319,24 @@ def validate_request( 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( + result = unmarshal_request( request, spec=spec, base_url=base_url, cls=cls, **validator_kwargs, ) + + def return_result() -> RequestUnmarshalResult: + 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 result + + return Proxy(return_result) # type: ignore if isinstance(request, WebhookRequest): if cls is None or issubclass(cls, WebhookRequestValidator): validate_webhook_request( @@ -400,13 +407,7 @@ def validate_response( 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( + result = unmarshal_response( request, response, spec=spec, @@ -414,6 +415,17 @@ def validate_response( cls=cls, **validator_kwargs, ) + + def return_result() -> ResponseUnmarshalResult: + 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 result + + return Proxy(return_result) # type: ignore if isinstance(request, WebhookRequest): if cls is None or issubclass(cls, WebhookResponseValidator): validate_webhook_response( diff --git a/poetry.lock b/poetry.lock index 8367cda6..fabf4e9a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2281,4 +2281,4 @@ starlette = ["starlette"] [metadata] lock-version = "2.0" python-versions = "^3.7.0" -content-hash = "24b4220c9c3f2c0b2892d695e4f154e4c94f4157ec0cbfb76b438cf00858d52b" +content-hash = "f52f738f6215a919fda906b40bc0f5bb92948e1d3331a61514c73bead689c5ee" diff --git a/pyproject.toml b/pyproject.toml index e1904d9b..d98de471 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,10 @@ module = [ ] ignore_missing_imports = true +[[tool.mypy.overrides]] +module = "lazy_object_proxy.*" +ignore_missing_imports = true + [tool.poetry] name = "openapi-core" version = "0.17.1" @@ -74,6 +78,7 @@ backports-cached-property = {version = "^1.0.2", python = "<3.8" } asgiref = "^3.6.0" jsonschema = "^4.17.3" multidict = {version = "^6.0.4", optional = true} +lazy-object-proxy = "^1.7.1" [tool.poetry.extras] django = ["django"] diff --git a/tests/integration/test_petstore.py b/tests/integration/test_petstore.py index 7d27ce28..d821fdec 100644 --- a/tests/integration/test_petstore.py +++ b/tests/integration/test_petstore.py @@ -97,12 +97,11 @@ def test_get_pets(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -130,8 +129,7 @@ def test_get_pets(self, spec): } response = MockResponse(data, headers=headers) - with pytest.warns(DeprecationWarning): - 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) @@ -155,12 +153,11 @@ def test_get_pets_response(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -213,12 +210,11 @@ def test_get_pets_response_no_schema(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -258,12 +254,11 @@ def test_get_pets_invalid_response(self, spec, response_unmarshaller): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -328,12 +323,11 @@ def test_get_pets_ids_param(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -378,12 +372,11 @@ def test_get_pets_tags_param(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -428,13 +421,12 @@ def test_get_pets_parameter_deserialization_error(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - with pytest.raises(ParameterValidationError) as exc_info: - validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + with pytest.raises(ParameterValidationError) as exc_info: + validate_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert type(exc_info.value.__cause__) is DeserializeError result = unmarshal_request( @@ -458,13 +450,12 @@ def test_get_pets_wrong_parameter_type(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - with pytest.raises(ParameterValidationError) as exc_info: - validate_request( - request, - spec=spec, - cls=V30RequestParametersValidator, - ) + with pytest.raises(ParameterValidationError) as exc_info: + validate_request( + request, + spec=spec, + cls=V30RequestParametersValidator, + ) assert type(exc_info.value.__cause__) is CastError result = unmarshal_request( @@ -483,13 +474,12 @@ def test_get_pets_raises_missing_required_param(self, spec): path_pattern=path_pattern, ) - with pytest.warns(DeprecationWarning): - with pytest.raises(MissingRequiredParameter): - validate_request( - request, - spec=spec, - cls=V30RequestParametersValidator, - ) + with pytest.raises(MissingRequiredParameter): + validate_request( + request, + spec=spec, + cls=V30RequestParametersValidator, + ) result = unmarshal_request( request, spec=spec, cls=V30RequestBodyUnmarshaller @@ -512,13 +502,12 @@ def test_get_pets_empty_value(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - with pytest.raises(ParameterValidationError) as exc_info: - validate_request( - request, - spec=spec, - cls=V30RequestParametersValidator, - ) + with pytest.raises(ParameterValidationError) as exc_info: + validate_request( + request, + spec=spec, + cls=V30RequestParametersValidator, + ) assert type(exc_info.value.__cause__) is EmptyQueryParameterValue result = unmarshal_request( @@ -543,12 +532,11 @@ def test_get_pets_allow_empty_value(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -579,12 +567,11 @@ def test_get_pets_none_value(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -616,12 +603,11 @@ def test_get_pets_param_order(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( query={ @@ -658,12 +644,11 @@ def test_get_pets_param_coordinates(self, spec): args=query_params, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert is_dataclass(result.parameters.query["coordinates"]) assert ( @@ -886,10 +871,9 @@ def test_post_cats_boolean_string(self, spec, spec_dict): }, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -930,12 +914,11 @@ def test_post_no_one_of_schema(self, spec): cookies=cookies, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -983,12 +966,11 @@ def test_post_cats_only_required_body(self, spec, spec_dict): cookies=cookies, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -999,10 +981,9 @@ def test_post_cats_only_required_body(self, spec, spec_dict): }, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1037,12 +1018,11 @@ def test_post_pets_raises_invalid_mimetype(self, spec): cookies=cookies, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( header={ @@ -1093,10 +1073,9 @@ def test_post_pets_missing_cookie(self, spec, spec_dict): cls=V30RequestParametersValidator, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1137,10 +1116,9 @@ def test_post_pets_missing_header(self, spec, spec_dict): cls=V30RequestParametersValidator, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) schemas = spec_dict["components"]["schemas"] pet_model = schemas["PetCreate"]["x-model"] @@ -1256,12 +1234,11 @@ def test_get_pet(self, spec): headers=headers, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1269,19 +1246,17 @@ def test_get_pet(self, spec): } ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestSecurityUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestSecurityUnmarshaller, + ) assert result.security == { "petstore_auth": auth, @@ -1323,12 +1298,11 @@ def test_get_pet_not_found(self, spec): view_args=view_args, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1336,10 +1310,9 @@ def test_get_pet_not_found(self, spec): } ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None @@ -1376,12 +1349,11 @@ def test_get_pet_wildcard(self, spec): view_args=view_args, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters( path={ @@ -1425,10 +1397,9 @@ def test_get_tags(self, spec): assert result.parameters == Parameters() - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert result.body is None @@ -1436,8 +1407,7 @@ def test_get_tags(self, spec): data = json.dumps(data_json) response = MockResponse(data) - with pytest.warns(DeprecationWarning): - 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_json @@ -1554,19 +1524,17 @@ def test_post_tags_additional_properties(self, spec): data=data, ) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, - spec=spec, - cls=V30RequestParametersUnmarshaller, - ) + result = unmarshal_request( + request, + spec=spec, + cls=V30RequestParametersUnmarshaller, + ) assert result.parameters == Parameters() - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert is_dataclass(result.body) assert result.body.name == pet_name @@ -1584,8 +1552,7 @@ def test_post_tags_additional_properties(self, spec): data = json.dumps(data_json) response = MockResponse(data, status_code=404) - with pytest.warns(DeprecationWarning): - 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) @@ -1678,10 +1645,9 @@ def test_post_tags_created_datetime(self, spec): assert result.parameters == Parameters() - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec, cls=V30RequestBodyUnmarshaller - ) + result = unmarshal_request( + request, spec=spec, cls=V30RequestBodyUnmarshaller + ) assert is_dataclass(result.body) assert result.body.created == datetime( @@ -1702,13 +1668,12 @@ def test_post_tags_created_datetime(self, spec): response_data = json.dumps(response_data_json) response = MockResponse(response_data, status_code=404) - with pytest.warns(DeprecationWarning): - result = validate_response( - request, - response, - spec=spec, - cls=V30ResponseDataUnmarshaller, - ) + result = unmarshal_response( + request, + response, + spec=spec, + cls=V30ResponseDataUnmarshaller, + ) assert is_dataclass(result.data) assert result.data.code == code @@ -1821,18 +1786,16 @@ def test_delete_tags_with_requestbody(self, spec): } response = MockResponse(data, status_code=200, headers=headers) - with pytest.warns(DeprecationWarning): - response_result = validate_response(request, response, spec=spec) + response_result = unmarshal_response(request, response, spec=spec) assert response_result.errors == [] assert response_result.data is None - with pytest.warns(DeprecationWarning): - result = validate_response( - request, - response, - spec=spec, - cls=V30ResponseHeadersUnmarshaller, - ) + result = unmarshal_response( + request, + response, + spec=spec, + cls=V30ResponseHeadersUnmarshaller, + ) assert result.headers == { "x-delete-confirm": True, diff --git a/tests/unit/test_shortcuts.py b/tests/unit/test_shortcuts.py index 1c14e694..b64fdac5 100644 --- a/tests/unit/test_shortcuts.py +++ b/tests/unit/test_shortcuts.py @@ -466,10 +466,10 @@ def test_spec_type_invalid(self): def test_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=Request) - with pytest.warns(DeprecationWarning): - result = validate_request(request, spec=spec_v31) + result = validate_request(request, spec=spec_v31) - assert result == mock_unmarshal.return_value + with pytest.warns(DeprecationWarning): + assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request) @mock.patch( @@ -538,12 +538,10 @@ def test_cls_apicall_unmarshaller(self, spec_v31): ) TestAPICallReq.setUp(unmarshal) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec_v31, cls=TestAPICallReq - ) + result = validate_request(request, spec=spec_v31, cls=TestAPICallReq) - assert result == unmarshal + with pytest.warns(DeprecationWarning): + assert result == unmarshal assert TestAPICallReq.unmarshal_calls == [ (request,), ] @@ -588,12 +586,10 @@ def test_cls_webhook_unmarshaller(self, spec_v31): ) TestWebhookReq.setUp(unmarshal) - with pytest.warns(DeprecationWarning): - result = validate_request( - request, spec=spec_v31, cls=TestWebhookReq - ) + result = validate_request(request, spec=spec_v31, cls=TestWebhookReq) - assert result == unmarshal + with pytest.warns(DeprecationWarning): + assert result == unmarshal assert TestWebhookReq.unmarshal_calls == [ (request,), ] @@ -611,10 +607,10 @@ def test_cls_invalid(self, spec_v31): def test_webhook_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=WebhookRequest) - with pytest.warns(DeprecationWarning): - result = validate_request(request, spec=spec_v31) + result = validate_request(request, spec=spec_v31) - assert result == mock_unmarshal.return_value + with pytest.warns(DeprecationWarning): + assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request) def test_webhook_request_validator_not_found(self, spec_v30): @@ -797,10 +793,10 @@ def test_request_response(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=Request) response = mock.Mock(spec=Response) - with pytest.warns(DeprecationWarning): - result = validate_response(request, response, spec=spec_v31) + result = validate_response(request, response, spec=spec_v31) - assert result == mock_unmarshal.return_value + with pytest.warns(DeprecationWarning): + assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request, response) @mock.patch( @@ -876,12 +872,12 @@ def test_cls_apicall_unmarshaller(self, spec_v31): ) TestAPICallReq.setUp(unmarshal) - with pytest.warns(DeprecationWarning): - result = validate_response( - request, response, spec=spec_v31, cls=TestAPICallReq - ) + result = validate_response( + request, response, spec=spec_v31, cls=TestAPICallReq + ) - assert result == unmarshal + with pytest.warns(DeprecationWarning): + assert result == unmarshal assert TestAPICallReq.unmarshal_calls == [ (request, response), ] @@ -897,12 +893,12 @@ def test_cls_webhook_unmarshaller(self, spec_v31): ) TestWebhookReq.setUp(unmarshal) - with pytest.warns(DeprecationWarning): - result = validate_response( - request, response, spec=spec_v31, cls=TestWebhookReq - ) + result = validate_response( + request, response, spec=spec_v31, cls=TestWebhookReq + ) - assert result == unmarshal + with pytest.warns(DeprecationWarning): + assert result == unmarshal assert TestWebhookReq.unmarshal_calls == [ (request, response), ] @@ -930,10 +926,10 @@ def test_webhook_request(self, mock_unmarshal, spec_v31): request = mock.Mock(spec=WebhookRequest) response = mock.Mock(spec=Response) - with pytest.warns(DeprecationWarning): - result = validate_response(request, response, spec=spec_v31) + result = validate_response(request, response, spec=spec_v31) - assert result == mock_unmarshal.return_value + with pytest.warns(DeprecationWarning): + assert result == mock_unmarshal.return_value mock_unmarshal.assert_called_once_with(request, response) @mock.patch(