From 7726bf013e991f9c3d0a90d544da886a9728e15d Mon Sep 17 00:00:00 2001 From: Lee Elenbaas Date: Mon, 6 Feb 2023 17:42:20 +0200 Subject: [PATCH 1/3] Add response data into the template data --- openapi_python_client/parser/responses.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openapi_python_client/parser/responses.py b/openapi_python_client/parser/responses.py index e1f2cb49a..34f5ae1f9 100644 --- a/openapi_python_client/parser/responses.py +++ b/openapi_python_client/parser/responses.py @@ -19,6 +19,7 @@ class Response: status_code: HTTPStatus prop: Property source: str + data: object def _source_by_content_type(content_type: str) -> Optional[str]: @@ -107,4 +108,4 @@ def response_from_data( if isinstance(prop, PropertyError): return prop, schemas - return Response(status_code=status_code, prop=prop, source=source), schemas + return Response(status_code=status_code, prop=prop, source=source, data=data), schemas From 2c15f42975ccb26be42c7f0d85bfab59442b0832 Mon Sep 17 00:00:00 2001 From: Lee Elenbaas Date: Sun, 28 May 2023 15:23:08 +0300 Subject: [PATCH 2/3] Handle empty response as None data --- openapi_python_client/parser/responses.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openapi_python_client/parser/responses.py b/openapi_python_client/parser/responses.py index 34f5ae1f9..7fbab4540 100644 --- a/openapi_python_client/parser/responses.py +++ b/openapi_python_client/parser/responses.py @@ -40,6 +40,7 @@ def empty_response( ) -> Response: """Return an untyped response, for when no response type is defined""" return Response( + data=None, status_code=status_code, prop=AnyProperty( name=response_name, From 4ac8c55553c2b4de1d9ba34d1febd5d875fd9b26 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Fri, 5 Jan 2024 16:54:16 -0700 Subject: [PATCH 3/3] Update tests, add types, document changes --- ...enapi_data_attribute_to_response_object.md | 10 ++++ openapi_python_client/parser/responses.py | 15 +++--- tests/test_parser/test_openapi.py | 49 ------------------- tests/test_parser/test_responses.py | 12 ++++- 4 files changed, 27 insertions(+), 59 deletions(-) create mode 100644 .changeset/add_original_openapi_data_attribute_to_response_object.md diff --git a/.changeset/add_original_openapi_data_attribute_to_response_object.md b/.changeset/add_original_openapi_data_attribute_to_response_object.md new file mode 100644 index 000000000..61ccf8de5 --- /dev/null +++ b/.changeset/add_original_openapi_data_attribute_to_response_object.md @@ -0,0 +1,10 @@ +--- +default: minor +--- + +# Add original OpenAPI `data` attribute to `Response` object + +PR #767 + +In custom templates, you can now access a `response.data` attribute that contains the original OpenAPI definition of the +response (Response Object or Reference Object). diff --git a/openapi_python_client/parser/responses.py b/openapi_python_client/parser/responses.py index 1106c81c2..3a22deb71 100644 --- a/openapi_python_client/parser/responses.py +++ b/openapi_python_client/parser/responses.py @@ -34,8 +34,7 @@ class Response: status_code: HTTPStatus prop: Property source: _ResponseSource - data: object # Extra data for custom templates - + data: Union[oai.Response, oai.Reference] # Original data which created this response, useful for custom templates def _source_by_content_type(content_type: str) -> Optional[_ResponseSource]: @@ -62,18 +61,18 @@ def empty_response( status_code: HTTPStatus, response_name: str, config: Config, - description: Optional[str], + data: Union[oai.Response, oai.Reference], ) -> Response: """Return an untyped response, for when no response type is defined""" return Response( - data=None, + data=data, status_code=status_code, prop=AnyProperty( name=response_name, default=None, required=True, python_name=PythonIdentifier(value=response_name, prefix=config.field_prefix), - description=description, + description=data.description if isinstance(data, oai.Response) else None, example=None, ), source=NONE_SOURCE, @@ -97,7 +96,7 @@ def response_from_data( status_code=status_code, response_name=response_name, config=config, - description=None, + data=data, ), schemas, ) @@ -109,7 +108,7 @@ def response_from_data( status_code=status_code, response_name=response_name, config=config, - description=data.description, + data=data, ), schemas, ) @@ -131,7 +130,7 @@ def response_from_data( status_code=status_code, response_name=response_name, config=config, - description=data.description, + data=data, ), schemas, ) diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index a92cc7845..d81c57556 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -187,55 +187,6 @@ def test__add_responses_error(self, mocker): ), ] - def test__add_responses(self, mocker, date_time_property_factory, date_property_factory): - from openapi_python_client.parser.openapi import Endpoint, Response - - response_1_data = mocker.MagicMock() - response_2_data = mocker.MagicMock() - data = { - "200": response_1_data, - "404": response_2_data, - } - endpoint = self.make_endpoint() - schemas = mocker.MagicMock() - schemas_1 = mocker.MagicMock() - schemas_2 = mocker.MagicMock() - response_1 = Response( - status_code=200, - source="source", - prop=date_time_property_factory(name="datetime"), - ) - response_2 = Response( - status_code=404, - source="source", - prop=date_property_factory(name="date"), - ) - response_from_data = mocker.patch( - f"{MODULE_NAME}.response_from_data", side_effect=[(response_1, schemas_1), (response_2, schemas_2)] - ) - config = MagicMock() - - endpoint, response_schemas = Endpoint._add_responses( - endpoint=endpoint, data=data, schemas=schemas, config=config - ) - - response_from_data.assert_has_calls( - [ - mocker.call(status_code=200, data=response_1_data, schemas=schemas, parent_name="name", config=config), - mocker.call( - status_code=404, data=response_2_data, schemas=schemas_1, parent_name="name", config=config - ), - ] - ) - assert endpoint.responses == [response_1, response_2] - assert endpoint.relative_imports == { - "from dateutil.parser import isoparse", - "from typing import cast", - "import datetime", - "import_3", - } - assert response_schemas == schemas_2 - def test_add_parameters_handles_no_params(self): from openapi_python_client.parser.openapi import Endpoint, Schemas diff --git a/tests/test_parser/test_responses.py b/tests/test_parser/test_responses.py index c60b23a72..0342112c5 100644 --- a/tests/test_parser/test_responses.py +++ b/tests/test_parser/test_responses.py @@ -11,9 +11,11 @@ def test_response_from_data_no_content(any_property_factory): from openapi_python_client.parser.responses import Response, response_from_data + data = oai.Response.model_construct(description="") + response, schemas = response_from_data( status_code=200, - data=oai.Response.model_construct(description=""), + data=data, schemas=Schemas(), parent_name="parent", config=MagicMock(), @@ -28,15 +30,18 @@ def test_response_from_data_no_content(any_property_factory): description="", ), source=NONE_SOURCE, + data=data, ) def test_response_from_data_reference(any_property_factory): from openapi_python_client.parser.responses import Response, response_from_data + data = oai.Reference.model_construct() + response, schemas = response_from_data( status_code=200, - data=oai.Reference.model_construct(), + data=data, schemas=Schemas(), parent_name="parent", config=MagicMock(), @@ -50,6 +55,7 @@ def test_response_from_data_reference(any_property_factory): required=True, ), source=NONE_SOURCE, + data=data, ) @@ -92,6 +98,7 @@ def test_response_from_data_no_content_schema(any_property_factory): description=data.description, ), source=NONE_SOURCE, + data=data, ) @@ -147,6 +154,7 @@ def test_response_from_data_property(mocker, any_property_factory): status_code=400, prop=prop, source=JSON_SOURCE, + data=data, ) property_from_data.assert_called_once_with( name="response_400",