From e8484c71606e193bc1d767e4636e1ad77389936c Mon Sep 17 00:00:00 2001 From: John Sorial Date: Mon, 20 Dec 2021 13:59:23 +0100 Subject: [PATCH 1/9] fix: _get_kwargs bool headers are now converted to strings --- openapi_python_client/__init__.py | 11 +++++++++-- .../templates/endpoint_macros.py.jinja | 6 +++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index 608af8dce..5f11e3dc3 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -267,7 +267,9 @@ def _build_api(self) -> None: encoding=self.file_encoding, ) - endpoint_template = self.env.get_template("endpoint_module.py.jinja") + endpoint_template = self.env.get_template( + "endpoint_module.py.jinja", globals={"isbool": lambda obj: obj.get_base_type_string() == "bool"} + ) for tag, collection in endpoint_collections_by_tag.items(): tag_dir = api_dir / tag tag_dir.mkdir() @@ -281,7 +283,12 @@ def _build_api(self) -> None: for endpoint in collection.endpoints: module_path = tag_dir / f"{utils.PythonIdentifier(endpoint.name, self.config.field_prefix)}.py" - module_path.write_text(endpoint_template.render(endpoint=endpoint), encoding=self.file_encoding) + module_path.write_text( + endpoint_template.render( + endpoint=endpoint, + ), + encoding=self.file_encoding, + ) def _get_project_for_url_or_path( # pylint: disable=too-many-arguments diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index 36c65d7e2..bf294b1c0 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -5,7 +5,11 @@ headers["{{ parameter.name | kebabcase}}"] = {{ parameter.python_name }} {% else %} if {{ parameter.python_name }} is not UNSET: - headers["{{ parameter.name | kebabcase}}"] = {{ parameter.python_name }} + headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} + str({{ parameter.python_name }}) + {% else %} + {{ parameter.python_name}} + {% endif %} {% endif %} {% endfor %} {% endif %} From 9d47d0180856b667ce987a268fa15adcb903d06a Mon Sep 17 00:00:00 2001 From: John Sorial Date: Tue, 4 Jan 2022 21:04:07 +0100 Subject: [PATCH 2/9] Fixed for required boolean header --- openapi_python_client/templates/endpoint_macros.py.jinja | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index bf294b1c0..d7af8bf02 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -2,7 +2,11 @@ {% if endpoint.header_parameters %} {% for parameter in endpoint.header_parameters.values() %} {% if parameter.required %} -headers["{{ parameter.name | kebabcase}}"] = {{ parameter.python_name }} +headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} + str({{ parameter.python_name }}) + {% else %} + {{ parameter.python_name}} + {% endif %} {% else %} if {{ parameter.python_name }} is not UNSET: headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} From 24a1af28e1562c4fcd8a57fdc1b603829d7aafad Mon Sep 17 00:00:00 2001 From: John Sorial Date: Tue, 4 Jan 2022 21:10:26 +0100 Subject: [PATCH 3/9] Fixed GoldenRecord to accept the new str(bool) header --- .../api/tests/upload_file_tests_upload_post.py | 2 +- .../api/tests/upload_multiple_files_tests_upload_post.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index a3f4d03c7..128a30145 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -20,7 +20,7 @@ def _get_kwargs( cookies: Dict[str, Any] = client.get_cookies() if keep_alive is not UNSET: - headers["keep-alive"] = keep_alive + headers["keep-alive"] = str(keep_alive) multipart_multipart_data = multipart_data.to_multipart() diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 553bc619a..724bc0bce 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -19,7 +19,7 @@ def _get_kwargs( cookies: Dict[str, Any] = client.get_cookies() if keep_alive is not UNSET: - headers["keep-alive"] = keep_alive + headers["keep-alive"] = str(keep_alive) multipart_multipart_data = [] for multipart_data_item_data in multipart_data: From bb3fc395566e80558692890b2fd7559d5cb9dce4 Mon Sep 17 00:00:00 2001 From: John Sorial Date: Tue, 11 Jan 2022 21:16:35 +0100 Subject: [PATCH 4/9] Boolean Headers are now lowercase --- .../api/tests/upload_file_tests_upload_post.py | 2 +- .../api/tests/upload_multiple_files_tests_upload_post.py | 2 +- openapi_python_client/templates/endpoint_macros.py.jinja | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index 128a30145..1f3e26273 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -20,7 +20,7 @@ def _get_kwargs( cookies: Dict[str, Any] = client.get_cookies() if keep_alive is not UNSET: - headers["keep-alive"] = str(keep_alive) + headers["keep-alive"] = str(keep_alive).lower() multipart_multipart_data = multipart_data.to_multipart() diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 724bc0bce..4f87a4b5d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -19,7 +19,7 @@ def _get_kwargs( cookies: Dict[str, Any] = client.get_cookies() if keep_alive is not UNSET: - headers["keep-alive"] = str(keep_alive) + headers["keep-alive"] = str(keep_alive).lower() multipart_multipart_data = [] for multipart_data_item_data in multipart_data: diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index d7af8bf02..451ed1a51 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -3,14 +3,14 @@ {% for parameter in endpoint.header_parameters.values() %} {% if parameter.required %} headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} - str({{ parameter.python_name }}) + str({{ parameter.python_name }}).lower() {% else %} {{ parameter.python_name}} {% endif %} {% else %} if {{ parameter.python_name }} is not UNSET: headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} - str({{ parameter.python_name }}) + str({{ parameter.python_name }}).lower() {% else %} {{ parameter.python_name}} {% endif %} From c1e88825eec2409da32198df25779b8d6f0dd118 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 17 Jan 2022 15:32:45 -0700 Subject: [PATCH 5/9] fix: Explicitly transform allowed header properties and omit disallowed types. --- .../api/location/__init__.py | 6 +- .../api/default/get_common_parameters.py | 8 +- .../api/default/post_common_parameters.py | 8 +- .../api/location/get_location_header_types.py | 117 ++++++++++++++++++ .../get_location_query_optionality.py | 17 +-- ...lete_common_parameters_overriding_param.py | 8 +- .../get_common_parameters_overriding_param.py | 8 +- .../get_same_name_multiple_locations_param.py | 10 +- .../parameters/multiple_path_parameters.py | 2 +- .../api/tag1/get_tag_with_number.py | 2 +- .../api/tests/defaults_tests_defaults_post.py | 42 ++++--- .../api/tests/get_basic_list_of_booleans.py | 2 +- .../api/tests/get_basic_list_of_floats.py | 2 +- .../api/tests/get_basic_list_of_integers.py | 2 +- .../api/tests/get_basic_list_of_strings.py | 2 +- .../api/tests/get_user_list.py | 17 +-- .../api/tests/int_enum_tests_int_enum_post.py | 13 +- .../tests/json_body_tests_json_body_post.py | 7 +- .../no_response_tests_no_response_get.py | 2 +- .../octet_stream_tests_octet_stream_get.py | 2 +- .../api/tests/post_form_data.py | 2 +- .../api/tests/post_tests_json_body_string.py | 2 +- .../api/tests/test_inline_objects.py | 2 +- ..._with_cookie_auth_token_with_cookie_get.py | 2 +- ...d_content_tests_unsupported_content_get.py | 2 +- .../tests/upload_file_tests_upload_post.py | 25 +--- ...upload_multiple_files_tests_upload_post.py | 25 +--- .../my_test_api_client/api/true_/false_.py | 8 +- .../my_test_api_client/models/a_model.py | 9 +- .../body_upload_file_tests_upload_post.py | 8 +- .../models/model_with_any_json_properties.py | 1 + .../models/model_with_union_property.py | 1 + .../model_with_union_property_inlined.py | 1 + end_to_end_tests/openapi.json | 67 ++++++---- .../api/body/post_body_multipart.py | 2 +- .../post_body_multipart_multipart_data.py | 8 +- .../test_body/test_post_body_multipart.py | 7 +- openapi_python_client/__init__.py | 2 +- .../parser/properties/__init__.py | 18 +-- .../parser/properties/property.py | 2 +- .../templates/endpoint_macros.py.jinja | 76 +++++------- .../templates/endpoint_module.py.jinja | 8 +- .../templates/model.py.jinja | 35 +++--- .../property_templates/any_property.py.jinja | 7 -- .../boolean_property.py.jinja | 3 + .../float_property.py.jinja | 3 + .../property_templates/helpers.jinja | 18 +++ .../property_templates/int_property.py.jinja | 3 + .../property_templates/list_property.py.jinja | 12 +- .../union_property.py.jinja | 32 +++-- pyproject.toml | 5 +- 51 files changed, 412 insertions(+), 261 deletions(-) create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py create mode 100644 openapi_python_client/templates/property_templates/boolean_property.py.jinja create mode 100644 openapi_python_client/templates/property_templates/float_property.py.jinja create mode 100644 openapi_python_client/templates/property_templates/helpers.jinja create mode 100644 openapi_python_client/templates/property_templates/int_property.py.jinja diff --git a/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/location/__init__.py b/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/location/__init__.py index b7e42ea57..b85aa074d 100644 --- a/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/location/__init__.py +++ b/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/location/__init__.py @@ -2,10 +2,14 @@ import types -from . import get_location_query_optionality +from . import get_location_header_types, get_location_query_optionality class LocationEndpoints: @classmethod def get_location_query_optionality(cls) -> types.ModuleType: return get_location_query_optionality + + @classmethod + def get_location_header_types(cls) -> types.ModuleType: + return get_location_header_types diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py index 83747a10f..68c3bdf76 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/get_common_parameters.py @@ -13,12 +13,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/common_parameters".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - params: Dict[str, Any] = { - "common": common, - } + params: Dict[str, Any] = {} + params["common"] = common + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py index 214fa80a2..4041c7079 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/default/post_common_parameters.py @@ -13,12 +13,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/common_parameters".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - params: Dict[str, Any] = { - "common": common, - } + params: Dict[str, Any] = {} + params["common"] = common + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py new file mode 100644 index 000000000..1edce3582 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_header_types.py @@ -0,0 +1,117 @@ +from typing import Any, Dict, Union + +import httpx + +from ...client import Client +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + client: Client, + boolean_header: Union[Unset, bool] = UNSET, + string_header: Union[Unset, str] = UNSET, + number_header: Union[Unset, float] = UNSET, + integer_header: Union[Unset, int] = UNSET, +) -> Dict[str, Any]: + url = "{}/location/header/types".format(client.base_url) + + headers: Dict[str, str] = client.get_headers() + cookies: Dict[str, Any] = client.get_cookies() + + if not isinstance(boolean_header, Unset): + headers["Boolean-Header"] = "true" if boolean_header else "false" + + if not isinstance(string_header, Unset): + headers["String-Header"] = string_header + + if not isinstance(number_header, Unset): + headers["Number-Header"] = str(number_header) + + if not isinstance(integer_header, Unset): + headers["Integer-Header"] = str(integer_header) + + return { + "method": "get", + "url": url, + "headers": headers, + "cookies": cookies, + "timeout": client.get_timeout(), + } + + +def _build_response(*, response: httpx.Response) -> Response[Any]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=None, + ) + + +def sync_detailed( + *, + client: Client, + boolean_header: Union[Unset, bool] = UNSET, + string_header: Union[Unset, str] = UNSET, + number_header: Union[Unset, float] = UNSET, + integer_header: Union[Unset, int] = UNSET, +) -> Response[Any]: + """ + Args: + boolean_header (Union[Unset, bool]): + string_header (Union[Unset, str]): + number_header (Union[Unset, float]): + integer_header (Union[Unset, int]): + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ) + + response = httpx.request( + verify=client.verify_ssl, + **kwargs, + ) + + return _build_response(response=response) + + +async def asyncio_detailed( + *, + client: Client, + boolean_header: Union[Unset, bool] = UNSET, + string_header: Union[Unset, str] = UNSET, + number_header: Union[Unset, float] = UNSET, + integer_header: Union[Unset, int] = UNSET, +) -> Response[Any]: + """ + Args: + boolean_header (Union[Unset, bool]): + string_header (Union[Unset, str]): + number_header (Union[Unset, float]): + integer_header (Union[Unset, int]): + + Returns: + Response[Any] + """ + + kwargs = _get_kwargs( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ) + + async with httpx.AsyncClient(verify=client.verify_ssl) as _client: + response = await _client.request(**kwargs) + + return _build_response(response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py index 46f8d43f6..9838c2881 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/location/get_location_query_optionality.py @@ -17,29 +17,32 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/location/query/optionality".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() + params: Dict[str, Any] = {} json_not_null_required = not_null_required.isoformat() + params["not_null_required"] = json_not_null_required + json_null_required: Union[Unset, None, str] = UNSET if not isinstance(null_required, Unset): json_null_required = null_required.isoformat() if null_required else None + params["null_required"] = json_null_required + json_null_not_required: Union[Unset, None, str] = UNSET if not isinstance(null_not_required, Unset): json_null_not_required = null_not_required.isoformat() if null_not_required else None + params["null_not_required"] = json_null_not_required + json_not_null_not_required: Union[Unset, None, str] = UNSET if not isinstance(not_null_not_required, Unset): json_not_null_not_required = not_null_not_required.isoformat() if not_null_not_required else None - params: Dict[str, Any] = { - "not_null_required": json_not_null_required, - "null_required": json_null_required, - "null_not_required": json_null_not_required, - "not_null_not_required": json_not_null_not_required, - } + params["not_null_not_required"] = json_not_null_not_required + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py index fa4be9a72..a9fdf4d89 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/delete_common_parameters_overriding_param.py @@ -14,12 +14,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/common_parameters_overriding/{param}".format(client.base_url, param=param_path) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - params: Dict[str, Any] = { - "param": param_query, - } + params: Dict[str, Any] = {} + params["param"] = param_query + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py index b16f8b66a..9965f6926 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_common_parameters_overriding_param.py @@ -14,12 +14,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/common_parameters_overriding/{param}".format(client.base_url, param=param_path) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - params: Dict[str, Any] = { - "param": param_query, - } + params: Dict[str, Any] = {} + params["param"] = param_query + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py index 5a6edc00c..ea985c15d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/get_same_name_multiple_locations_param.py @@ -16,18 +16,18 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/same-name-multiple-locations/{param}".format(client.base_url, param=param_path) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - if param_header is not UNSET: + if not isinstance(param_header, Unset): headers["param"] = param_header if param_cookie is not UNSET: cookies["param"] = param_cookie - params: Dict[str, Any] = { - "param": param_query, - } + params: Dict[str, Any] = {} + params["param"] = param_query + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py index d4c65b6e4..ea47dfaa8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/parameters/multiple_path_parameters.py @@ -18,7 +18,7 @@ def _get_kwargs( client.base_url, param4=param4, param2=param2, param1=param1, param3=param3 ) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py index cf3d857ef..d50631c94 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tag1/get_tag_with_number.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tag_with_number".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index 6e45eaf74..6bcd59c8c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -1,5 +1,5 @@ import datetime -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Union, cast import httpx from dateutil.parser import isoparse @@ -28,23 +28,39 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/defaults".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() + params: Dict[str, Any] = {} + params["string_prop"] = string_prop + json_date_prop = date_prop.isoformat() + params["date_prop"] = json_date_prop + + params["float_prop"] = float_prop + + params["int_prop"] = int_prop + + params["boolean_prop"] = boolean_prop + json_list_prop = [] for list_prop_item_data in list_prop: list_prop_item = list_prop_item_data.value json_list_prop.append(list_prop_item) + params["list_prop"] = json_list_prop + json_union_prop = union_prop + params["union_prop"] = json_union_prop + json_union_prop_with_ref: Union[None, Unset, float, str] if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif union_prop_with_ref is None: json_union_prop_with_ref = None + elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): @@ -53,25 +69,20 @@ def _get_kwargs( else: json_union_prop_with_ref = union_prop_with_ref + params["union_prop_with_ref"] = json_union_prop_with_ref + json_enum_prop = enum_prop.value + params["enum_prop"] = json_enum_prop + json_model_prop = model_prop.to_dict() + params.update(json_model_prop) + json_required_model_prop = required_model_prop.to_dict() - params: Dict[str, Any] = { - "string_prop": string_prop, - "date_prop": json_date_prop, - "float_prop": float_prop, - "int_prop": int_prop, - "boolean_prop": boolean_prop, - "list_prop": json_list_prop, - "union_prop": json_union_prop, - "union_prop_with_ref": json_union_prop_with_ref, - "enum_prop": json_enum_prop, - } - params.update(json_model_prop) params.update(json_required_model_prop) + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { @@ -86,8 +97,7 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == 200: - response_200 = response.json() - + response_200 = cast(Any, response.json()) return response_200 if response.status_code == 422: response_422 = HTTPValidationError.from_dict(response.json()) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py index 2b0759b55..bddce1d9a 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/basic_lists/booleans".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py index 7ee7fad18..083fc498e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/basic_lists/floats".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py index 70a50f0bf..21b9f4c4f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/basic_lists/integers".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py index 5d1719414..7fb6a52d6 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/basic_lists/strings".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index 65f6f75bd..29dd706e8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -21,15 +21,18 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() + params: Dict[str, Any] = {} json_an_enum_value = [] for an_enum_value_item_data in an_enum_value: an_enum_value_item = an_enum_value_item_data.value json_an_enum_value.append(an_enum_value_item) + params["an_enum_value"] = json_an_enum_value + json_an_enum_value_with_null = [] for an_enum_value_with_null_item_data in an_enum_value_with_null: an_enum_value_with_null_item = ( @@ -38,19 +41,19 @@ def _get_kwargs( json_an_enum_value_with_null.append(an_enum_value_with_null_item) + params["an_enum_value_with_null"] = json_an_enum_value_with_null + json_an_enum_value_with_only_null = an_enum_value_with_only_null + params["an_enum_value_with_only_null"] = json_an_enum_value_with_only_null + if isinstance(some_date, datetime.date): json_some_date = some_date.isoformat() else: json_some_date = some_date.isoformat() - params: Dict[str, Any] = { - "an_enum_value": json_an_enum_value, - "an_enum_value_with_null": json_an_enum_value_with_null, - "an_enum_value_with_only_null": json_an_enum_value_with_only_null, - "some_date": json_some_date, - } + params["some_date"] = json_some_date + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py index f268f1004..a18f9cfef 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional, Union, cast import httpx @@ -15,14 +15,14 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/int_enum".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() + params: Dict[str, Any] = {} json_int_enum = int_enum.value - params: Dict[str, Any] = { - "int_enum": json_int_enum, - } + params["int_enum"] = json_int_enum + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { @@ -37,8 +37,7 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == 200: - response_200 = response.json() - + response_200 = cast(Any, response.json()) return response_200 if response.status_code == 422: response_422 = HTTPValidationError.from_dict(response.json()) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py index f0d5533d2..5dfe0a79c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional, Union, cast import httpx @@ -15,7 +15,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/json_body".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() json_json_body = json_body.to_dict() @@ -32,8 +32,7 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == 200: - response_200 = response.json() - + response_200 = cast(Any, response.json()) return response_200 if response.status_code == 422: response_422 = HTTPValidationError.from_dict(response.json()) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py index 969d01b0c..d30f9e651 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/no_response".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py index 50fcaf6de..cefaeabbb 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py @@ -13,7 +13,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/octet_stream".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py index 9721364a7..7ccca1a85 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_form_data.py @@ -14,7 +14,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/post_form_data".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py index 86a5bb096..290cba783 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/post_tests_json_body_string.py @@ -14,7 +14,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/json_body/string".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() json_json_body = json_body diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py index e91401f98..64ae9b210 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py @@ -15,7 +15,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/inline_objects".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() json_json_body = json_body.to_dict() diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py index 01a0cd2f5..337ad0603 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/token_with_cookie_auth_token_with_cookie_get.py @@ -13,7 +13,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/auth/token_with_cookie".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() cookies["MyToken"] = my_token diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py index 9d404f41f..e2dc56a7b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py @@ -12,7 +12,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/tests/unsupported_content".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py index 310b7bf43..d939f04fe 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -1,27 +1,23 @@ -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional, Union, cast import httpx from ...client import Client from ...models.body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost from ...models.http_validation_error import HTTPValidationError -from ...types import UNSET, Response, Unset +from ...types import Response def _get_kwargs( *, client: Client, multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, ) -> Dict[str, Any]: url = "{}/tests/upload".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - if keep_alive is not UNSET: - headers["keep-alive"] = str(keep_alive).lower() - multipart_multipart_data = multipart_data.to_multipart() return { @@ -36,8 +32,7 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == 200: - response_200 = response.json() - + response_200 = cast(Any, response.json()) return response_200 if response.status_code == 422: response_422 = HTTPValidationError.from_dict(response.json()) @@ -59,14 +54,12 @@ def sync_detailed( *, client: Client, multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, ) -> Response[Union[Any, HTTPValidationError]]: """Upload File Upload a file Args: - keep_alive (Union[Unset, bool]): multipart_data (BodyUploadFileTestsUploadPost): Returns: @@ -76,7 +69,6 @@ def sync_detailed( kwargs = _get_kwargs( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) response = httpx.request( @@ -91,14 +83,12 @@ def sync( *, client: Client, multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload File Upload a file Args: - keep_alive (Union[Unset, bool]): multipart_data (BodyUploadFileTestsUploadPost): Returns: @@ -108,7 +98,6 @@ def sync( return sync_detailed( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ).parsed @@ -116,14 +105,12 @@ async def asyncio_detailed( *, client: Client, multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, ) -> Response[Union[Any, HTTPValidationError]]: """Upload File Upload a file Args: - keep_alive (Union[Unset, bool]): multipart_data (BodyUploadFileTestsUploadPost): Returns: @@ -133,7 +120,6 @@ async def asyncio_detailed( kwargs = _get_kwargs( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) async with httpx.AsyncClient(verify=client.verify_ssl) as _client: @@ -146,14 +132,12 @@ async def asyncio( *, client: Client, multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload File Upload a file Args: - keep_alive (Union[Unset, bool]): multipart_data (BodyUploadFileTestsUploadPost): Returns: @@ -164,6 +148,5 @@ async def asyncio( await asyncio_detailed( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py index 2cae2bdff..c278f408b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -1,26 +1,22 @@ -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional, Union, cast import httpx from ...client import Client from ...models.http_validation_error import HTTPValidationError -from ...types import UNSET, File, Response, Unset +from ...types import File, Response def _get_kwargs( *, client: Client, multipart_data: List[File], - keep_alive: Union[Unset, bool] = UNSET, ) -> Dict[str, Any]: url = "{}/tests/upload/multiple".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - if keep_alive is not UNSET: - headers["keep-alive"] = str(keep_alive).lower() - multipart_multipart_data = [] for multipart_data_item_data in multipart_data: multipart_data_item = multipart_data_item_data.to_tuple() @@ -39,8 +35,7 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: if response.status_code == 200: - response_200 = response.json() - + response_200 = cast(Any, response.json()) return response_200 if response.status_code == 422: response_422 = HTTPValidationError.from_dict(response.json()) @@ -62,14 +57,12 @@ def sync_detailed( *, client: Client, multipart_data: List[File], - keep_alive: Union[Unset, bool] = UNSET, ) -> Response[Union[Any, HTTPValidationError]]: """Upload multiple files Upload several files in the same request Args: - keep_alive (Union[Unset, bool]): multipart_data (List[File]): Returns: @@ -79,7 +72,6 @@ def sync_detailed( kwargs = _get_kwargs( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) response = httpx.request( @@ -94,14 +86,12 @@ def sync( *, client: Client, multipart_data: List[File], - keep_alive: Union[Unset, bool] = UNSET, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload multiple files Upload several files in the same request Args: - keep_alive (Union[Unset, bool]): multipart_data (List[File]): Returns: @@ -111,7 +101,6 @@ def sync( return sync_detailed( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ).parsed @@ -119,14 +108,12 @@ async def asyncio_detailed( *, client: Client, multipart_data: List[File], - keep_alive: Union[Unset, bool] = UNSET, ) -> Response[Union[Any, HTTPValidationError]]: """Upload multiple files Upload several files in the same request Args: - keep_alive (Union[Unset, bool]): multipart_data (List[File]): Returns: @@ -136,7 +123,6 @@ async def asyncio_detailed( kwargs = _get_kwargs( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) async with httpx.AsyncClient(verify=client.verify_ssl) as _client: @@ -149,14 +135,12 @@ async def asyncio( *, client: Client, multipart_data: List[File], - keep_alive: Union[Unset, bool] = UNSET, ) -> Optional[Union[Any, HTTPValidationError]]: """Upload multiple files Upload several files in the same request Args: - keep_alive (Union[Unset, bool]): multipart_data (List[File]): Returns: @@ -167,6 +151,5 @@ async def asyncio( await asyncio_detailed( client=client, multipart_data=multipart_data, - keep_alive=keep_alive, ) ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py index ef6040283..2007bd6bd 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/true_/false_.py @@ -13,12 +13,12 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/naming/keywords".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() - params: Dict[str, Any] = { - "import": import_, - } + params: Dict[str, Any] = {} + params["import"] = import_ + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} return { diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 48cd1ca77..d52001229 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -79,6 +79,7 @@ def to_dict(self) -> Dict[str, Any]: a_date = self.a_date.isoformat() required_not_nullable = self.required_not_nullable + if isinstance(self.one_of_models, FreeFormModel): one_of_models = self.one_of_models.to_dict() @@ -91,7 +92,6 @@ def to_dict(self) -> Dict[str, Any]: model = self.model.to_dict() any_value = self.any_value - an_optional_allof_enum: Union[Unset, str] = UNSET if not isinstance(self.an_optional_allof_enum, Unset): an_optional_allof_enum = self.an_optional_allof_enum.value @@ -120,6 +120,7 @@ def to_dict(self) -> Dict[str, Any]: nullable_one_of_models: Union[Dict[str, Any], None] if self.nullable_one_of_models is None: nullable_one_of_models = None + elif isinstance(self.nullable_one_of_models, FreeFormModel): nullable_one_of_models = self.nullable_one_of_models.to_dict() @@ -129,6 +130,7 @@ def to_dict(self) -> Dict[str, Any]: not_required_one_of_models: Union[Dict[str, Any], Unset] if isinstance(self.not_required_one_of_models, Unset): not_required_one_of_models = UNSET + elif isinstance(self.not_required_one_of_models, FreeFormModel): not_required_one_of_models = UNSET if not isinstance(self.not_required_one_of_models, Unset): @@ -144,6 +146,7 @@ def to_dict(self) -> Dict[str, Any]: not_required_nullable_one_of_models = UNSET elif self.not_required_nullable_one_of_models is None: not_required_nullable_one_of_models = None + elif isinstance(self.not_required_nullable_one_of_models, FreeFormModel): not_required_nullable_one_of_models = UNSET if not isinstance(self.not_required_nullable_one_of_models, Unset): @@ -255,9 +258,7 @@ def _parse_one_of_models(data: object) -> Union[Any, FreeFormModel, ModelWithUni return one_of_models_type_1 except: # noqa: E722 pass - one_of_models_type_2 = data - - return one_of_models_type_2 + return cast(Union[Any, FreeFormModel, ModelWithUnionProperty], data) one_of_models = _parse_one_of_models(d.pop("one_of_models")) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py index 9db6d85f8..85bd57118 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py @@ -109,10 +109,14 @@ def to_multipart(self) -> Dict[str, Any]: some_optional_file = self.some_optional_file.to_tuple() some_string = ( - self.some_string if self.some_string is UNSET else (None, str(self.some_string).encode(), "text/plain") + self.some_string + if isinstance(self.some_string, Unset) + else (None, str(self.some_string).encode(), "text/plain") ) some_number = ( - self.some_number if self.some_number is UNSET else (None, str(self.some_number).encode(), "text/plain") + self.some_number + if isinstance(self.some_number, Unset) + else (None, str(self.some_number).encode(), "text/plain") ) some_array: Union[Unset, Tuple[None, bytes, str]] = UNSET if not isinstance(self.some_array, Unset): diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py index 08a016dd8..af82eb24f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py @@ -21,6 +21,7 @@ def to_dict(self) -> Dict[str, Any]: field_dict: Dict[str, Any] = {} for prop_name, prop in self.additional_properties.items(): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalPropertyType0): field_dict[prop_name] = prop.to_dict() diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 9afb3cdde..e1fd0cf5b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -22,6 +22,7 @@ def to_dict(self) -> Dict[str, Any]: a_property: Union[Unset, int, str] if isinstance(self.a_property, Unset): a_property = UNSET + elif isinstance(self.a_property, AnEnum): a_property = UNSET if not isinstance(self.a_property, Unset): diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py index e8537d13d..e89861520 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property_inlined.py @@ -22,6 +22,7 @@ def to_dict(self) -> Dict[str, Any]: fruit: Union[Dict[str, Any], Unset] if isinstance(self.fruit, Unset): fruit = UNSET + elif isinstance(self.fruit, ModelWithUnionPropertyInlinedFruitType0): fruit = UNSET if not isinstance(self.fruit, Unset): diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index ef1e9d392..4131446a9 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -250,17 +250,7 @@ "summary": "Upload File", "description": "Upload a file ", "operationId": "upload_file_tests_upload_post", - "parameters": [ - { - "required": false, - "schema": { - "title": "Keep-Alive", - "type": "boolean" - }, - "name": "keep-alive", - "in": "header" - } - ], + "parameters": [], "requestBody": { "content": { "multipart/form-data": { @@ -301,17 +291,7 @@ "summary": "Upload multiple files", "description": "Upload several files in the same request", "operationId": "upload_multiple_files_tests_upload_post", - "parameters": [ - { - "required": false, - "schema": { - "title": "Keep-Alive", - "type": "boolean" - }, - "name": "keep-alive", - "in": "header" - } - ], + "parameters": [], "requestBody": { "content": { "multipart/form-data": { @@ -1000,6 +980,49 @@ "responses": {} } }, + "/location/header/types": { + "description": "Test the valid types to send in headers.", + "get": { + "tags": [ + "location" + ], + "parameters": [ + { + "required": false, + "schema": { + "type": "boolean" + }, + "name": "Boolean-Header", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "string" + }, + "name": "String-Header", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "number" + }, + "name": "Number-Header", + "in": "header" + }, + { + "required": false, + "schema": { + "type": "integer" + }, + "name": "Integer-Header", + "in": "header" + } + ], + "responses": {} + } + }, "/naming/keywords": { "description": "Ensure that Python keywords are renamed properly.", "get": { diff --git a/integration-tests/integration_tests/api/body/post_body_multipart.py b/integration-tests/integration_tests/api/body/post_body_multipart.py index 206b7bc13..b582d9bfc 100644 --- a/integration-tests/integration_tests/api/body/post_body_multipart.py +++ b/integration-tests/integration_tests/api/body/post_body_multipart.py @@ -16,7 +16,7 @@ def _get_kwargs( ) -> Dict[str, Any]: url = "{}/body/multipart".format(client.base_url) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() multipart_multipart_data = multipart_data.to_multipart() diff --git a/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py b/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py index 0766a3a83..1c7f6f651 100644 --- a/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py +++ b/integration-tests/integration_tests/models/post_body_multipart_multipart_data.py @@ -43,11 +43,15 @@ def to_dict(self) -> Dict[str, Any]: return field_dict def to_multipart(self) -> Dict[str, Any]: - a_string = self.a_string if self.a_string is UNSET else (None, str(self.a_string).encode(), "text/plain") + a_string = ( + self.a_string if isinstance(self.a_string, Unset) else (None, str(self.a_string).encode(), "text/plain") + ) file = self.file.to_tuple() description = ( - self.description if self.description is UNSET else (None, str(self.description).encode(), "text/plain") + self.description + if isinstance(self.description, Unset) + else (None, str(self.description).encode(), "text/plain") ) field_dict: Dict[str, Any] = {} diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index b5e453ab6..eaf9083a3 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -1,12 +1,13 @@ from io import BytesIO -from integration_tests import Client from integration_tests.api.body import post_body_multipart -from integration_tests.models import PostBodyMultipartMultipartData, PostBodyMultipartResponse200 +from integration_tests.client import Client +from integration_tests.models.post_body_multipart_multipart_data import PostBodyMultipartMultipartData +from integration_tests.models.post_body_multipart_response_200 import PostBodyMultipartResponse200 from integration_tests.types import File -def test(): +def test() -> None: client = Client("http://localhost:3000") a_string = "a test string" diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index 8f7caa1fa..417f6c7ab 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -73,7 +73,7 @@ def __init__( ) else: loader = package_loader - self.env: Environment = Environment(loader=loader, trim_blocks=True, lstrip_blocks=True) + self.env: Environment = Environment(loader=loader, trim_blocks=True, lstrip_blocks=True, extensions=['jinja2.ext.loopcontrols']) self.project_name: str = config.project_name_override or f"{utils.kebab_case(openapi.title).lower()}-client" self.project_dir: Path = Path.cwd() diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index d6e1457c0..8922c17a9 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -31,7 +31,6 @@ class AnyProperty(Property): _type_string: ClassVar[str] = "Any" _json_type_string: ClassVar[str] = "Any" - template: ClassVar[Optional[str]] = "any_property.py.jinja" @attr.s(auto_attribs=True, frozen=True) @@ -124,6 +123,7 @@ class FloatProperty(Property): _type_string: ClassVar[str] = "float" _json_type_string: ClassVar[str] = "float" + template: ClassVar[str] = "float_property.py.jinja" @attr.s(auto_attribs=True, frozen=True) @@ -132,6 +132,7 @@ class IntProperty(Property): _type_string: ClassVar[str] = "int" _json_type_string: ClassVar[str] = "int" + template: ClassVar[str] = "int_property.py.jinja" @attr.s(auto_attribs=True, frozen=True) @@ -140,6 +141,7 @@ class BooleanProperty(Property): _type_string: ClassVar[str] = "bool" _json_type_string: ClassVar[str] = "bool" + template: ClassVar[str] = "boolean_property.py.jinja" InnerProp = TypeVar("InnerProp", bound=Property) @@ -182,12 +184,6 @@ class UnionProperty(Property): inner_properties: List[Property] template: ClassVar[str] = "union_property.py.jinja" - has_properties_without_templates: bool = attr.ib(init=False) - - def __attrs_post_init__(self) -> None: - object.__setattr__( - self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) - ) def _get_inner_type_strings(self, json: bool = False) -> Set[str]: return {p.get_type_string(no_optional=True, json=json) for p in self.inner_properties} @@ -249,14 +245,6 @@ def get_imports(self, *, prefix: str) -> Set[str]: imports.add("from typing import cast, Union") return imports - def inner_properties_with_template(self) -> Iterator[Property]: - """ - Get all the properties that make up this `Union`. - - Called by the union property macros to aid in construction / deserialization. - """ - return (prop for prop in self.inner_properties if prop.template) - def _string_based_property( name: str, required: bool, data: oai.Schema, config: Config diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 5b7f9ead9..e072fa2cb 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -33,7 +33,7 @@ class Property: description: Optional[str] = attr.ib() example: Optional[str] = attr.ib() - template: ClassVar[Optional[str]] = None + template: ClassVar[str] = "any_property.py.jinja" json_is_dict: ClassVar[bool] = False def set_python_name(self, new_name: str, config: Config) -> None: diff --git a/openapi_python_client/templates/endpoint_macros.py.jinja b/openapi_python_client/templates/endpoint_macros.py.jinja index 451ed1a51..d90cd6242 100644 --- a/openapi_python_client/templates/endpoint_macros.py.jinja +++ b/openapi_python_client/templates/endpoint_macros.py.jinja @@ -1,20 +1,16 @@ +{% from "property_templates/helpers.jinja" import guarded_statement %} + {% macro header_params(endpoint) %} {% if endpoint.header_parameters %} {% for parameter in endpoint.header_parameters.values() %} - {% if parameter.required %} -headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} - str({{ parameter.python_name }}).lower() - {% else %} - {{ parameter.python_name}} - {% endif %} + {% set destination = 'headers["' + parameter.name + '"]' %} + {% import "property_templates/" + parameter.template as param_template %} + {% if param_template.transform_header %} + {% set statement = param_template.transform_header(parameter, parameter.python_name, destination) %} {% else %} -if {{ parameter.python_name }} is not UNSET: - headers["{{ parameter.name | kebabcase}}"] = {% if isbool(parameter) %} - str({{ parameter.python_name }}).lower() - {% else %} - {{ parameter.python_name}} - {% endif %} + {% set statement = destination + " = " + parameter.python_name %} {% endif %} +{{ guarded_statement(parameter, parameter.python_name, statement) }} {% endfor %} {% endif %} {% endmacro %} @@ -35,35 +31,23 @@ if {{ parameter.python_name }} is not UNSET: {% macro query_params(endpoint) %} {% if endpoint.query_parameters %} - {% for property in endpoint.query_parameters.values() %} +params: Dict[str, Any] = {} +{% for property in endpoint.query_parameters.values() %} + {% set destination = property.python_name %} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.transform %} {% set destination = "json_" + property.python_name %} - {% if property.template %} - {% from "property_templates/" + property.template import transform %} -{{ transform(property, property.python_name, destination) }} - {% endif %} - {% endfor %} -params: Dict[str, Any] = { - {% for property in endpoint.query_parameters.values() %} - {% if not property.json_is_dict %} - {% if property.template %} - "{{ property.name }}": {{ "json_" + property.python_name }}, - {% else %} - "{{ property.name }}": {{ property.python_name }}, - {% endif %} - {% endif %} - {% endfor %} -} - {% for property in endpoint.query_parameters.values() %} - {% if property.json_is_dict %} - {% set property_name = "json_" + property.python_name %} - {% if property.required and not property.nullable %} -params.update({{ property_name }}) - {% else %} -if {% if not property.required %}not isinstance({{ property_name }}, Unset){% endif %}{% if not property.required and property.nullable %} and {% endif %}{% if property.nullable %}{{ property_name }} is not None{% endif %}: - params.update({{ property_name }}) - {% endif %} - {% endif %} - {% endfor %} +{{ prop_template.transform(property, property.python_name, destination) }} + {% endif %} + {%- if not property.json_is_dict %} +params["{{ property.name }}"] = {{ destination }} + {% else %} +{{ guarded_statement(property, destination, "params.update(" + destination + ")") }} + {% endif %} + + +{% endfor %} + params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% endif %} {% endmacro %} @@ -72,9 +56,9 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% if endpoint.json_body %} {% set property = endpoint.json_body %} {% set destination = "json_" + property.python_name %} - {% if property.template %} - {% from "property_templates/" + property.template import transform %} -{{ transform(property, property.python_name, destination) }} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.transform %} +{{ prop_template.transform(property, property.python_name, destination) }} {% else %} {{ destination }} = {{ property.python_name }} {% endif %} @@ -85,9 +69,9 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None} {% if endpoint.multipart_body %} {% set property = endpoint.multipart_body %} {% set destination = "multipart_" + property.python_name %} - {% if property.template %} - {% from "property_templates/" + property.template import transform_multipart %} -{{ transform_multipart(property, property.python_name, destination) }} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.transform_multipart %} +{{ prop_template.transform_multipart(property, property.python_name, destination) }} {% endif %} {% endif %} {% endmacro %} diff --git a/openapi_python_client/templates/endpoint_module.py.jinja b/openapi_python_client/templates/endpoint_module.py.jinja index ff3d499c1..e87738fa9 100644 --- a/openapi_python_client/templates/endpoint_module.py.jinja +++ b/openapi_python_client/templates/endpoint_module.py.jinja @@ -25,7 +25,7 @@ def _get_kwargs( {%- endfor -%} ) - headers: Dict[str, Any] = client.get_headers() + headers: Dict[str, str] = client.get_headers() cookies: Dict[str, Any] = client.get_cookies() {{ header_params(endpoint) | indent(4) }} @@ -61,9 +61,9 @@ def _get_kwargs( def _parse_response(*, response: httpx.Response) -> Optional[{{ return_string }}]: {% for response in endpoint.responses %} if response.status_code == {{ response.status_code }}: - {% if response.prop.template %} - {% from "property_templates/" + response.prop.template import construct %} - {{ construct(response.prop, response.source) | indent(8) }} + {% import "property_templates/" + response.prop.template as prop_template %} + {% if prop_template.construct %} + {{ prop_template.construct(response.prop, response.source) | indent(8) }} {% else %} {{ response.prop.python_name }} = cast({{ response.prop.get_type_string() }}, {{ response.source }}) {% endif %} diff --git a/openapi_python_client/templates/model.py.jinja b/openapi_python_client/templates/model.py.jinja index 6f65fb5fa..07f929d66 100644 --- a/openapi_python_client/templates/model.py.jinja +++ b/openapi_python_client/templates/model.py.jinja @@ -66,12 +66,11 @@ class {{ class_name }}: {% macro _to_dict(multipart=False) %} {% for property in model.required_properties + model.optional_properties %} -{% if property.template %} -{% from "property_templates/" + property.template import transform %} -{# Stopped here #} -{{ transform(property, "self." + property.python_name, property.python_name, multipart=multipart) }} +{% import "property_templates/" + property.template as prop_template %} +{% if prop_template.transform %} +{{ prop_template.transform(property, "self." + property.python_name, property.python_name, multipart=multipart) }} {% elif multipart %} -{{ property.python_name }} = self.{{ property.python_name }} if self.{{ property.python_name }} is UNSET else (None, str(self.{{ property.python_name }}).encode(), "text/plain") +{{ property.python_name }} = self.{{ property.python_name }} if isinstance(self.{{ property.python_name }}, Unset) else (None, str(self.{{ property.python_name }}).encode(), "text/plain") {% else %} {{ property.python_name }} = self.{{ property.python_name }} {% endif %} @@ -79,10 +78,14 @@ class {{ class_name }}: field_dict: Dict[str, Any] = {} {% if model.additional_properties %} -{% if model.additional_properties.template %} -{% from "property_templates/" + model.additional_properties.template import transform %} +{% if model.additional_properties.template %}{# Can be a bool instead of an object #} + {% import "property_templates/" + model.additional_properties.template as prop_template %} +{% else %} + {% set prop_template = None %} +{% endif %} +{% if prop_template and prop_template.transform %} for prop_name, prop in self.additional_properties.items(): - {{ transform(model.additional_properties, "prop", "field_dict[prop_name]", multipart=multipart) | indent(4) }} + {{ prop_template.transform(model.additional_properties, "prop", "field_dict[prop_name]", multipart=multipart) | indent(4) }} {% elif multipart %} field_dict.update({ key: (None, str(value).encode(), "text/plain") @@ -126,9 +129,9 @@ return field_dict {% else %} {% set property_source = 'd.pop("' + property.name + '", UNSET)' %} {% endif %} - {% if property.template %} - {% from "property_templates/" + property.template import construct %} - {{ construct(property, property_source) | indent(8) }} + {% import "property_templates/" + property.template as prop_template %} + {% if prop_template.construct %} + {{ prop_template.construct(property, property_source) | indent(8) }} {% else %} {{ property.python_name }} = {{ property_source }} {% endif %} @@ -141,11 +144,15 @@ return field_dict ) {% if model.additional_properties %} - {% if model.additional_properties.template %} - {% from "property_templates/" + model.additional_properties.template import construct %} + {% if model.additional_properties.template %}{# Can be a bool instead of an object #} + {% import "property_templates/" + model.additional_properties.template as prop_template %} + {% else %} + {% set prop_template = None %} + {% endif %} + {% if prop_template and prop_template.construct %} additional_properties = {} for prop_name, prop_dict in d.items(): - {{ construct(model.additional_properties, "prop_dict") | indent(12) }} + {{ prop_template.construct(model.additional_properties, "prop_dict") | indent(12) }} additional_properties[prop_name] = {{ model.additional_properties.python_name }} {{ module_name }}.additional_properties = additional_properties diff --git a/openapi_python_client/templates/property_templates/any_property.py.jinja b/openapi_python_client/templates/property_templates/any_property.py.jinja index f2019e4c5..e69de29bb 100644 --- a/openapi_python_client/templates/property_templates/any_property.py.jinja +++ b/openapi_python_client/templates/property_templates/any_property.py.jinja @@ -1,7 +0,0 @@ -{% macro construct(property, source, initial_value="None") %} -{{ property.python_name }} = {{ source }} -{% endmacro %} - -{% macro transform(property, source, destination, declare_type=True, multipart=False) %} -{{ destination }} = {{ source }} -{% endmacro %} diff --git a/openapi_python_client/templates/property_templates/boolean_property.py.jinja b/openapi_python_client/templates/property_templates/boolean_property.py.jinja new file mode 100644 index 000000000..a63639bc5 --- /dev/null +++ b/openapi_python_client/templates/property_templates/boolean_property.py.jinja @@ -0,0 +1,3 @@ +{% macro transform_header(property, source, destination) %} +{{ destination }} = "true" if {{ source }} else "false" +{% endmacro %} diff --git a/openapi_python_client/templates/property_templates/float_property.py.jinja b/openapi_python_client/templates/property_templates/float_property.py.jinja new file mode 100644 index 000000000..f66f991ee --- /dev/null +++ b/openapi_python_client/templates/property_templates/float_property.py.jinja @@ -0,0 +1,3 @@ +{% macro transform_header(property, source, destination) %} +{{ destination }} = str({{ source }}) +{% endmacro %} diff --git a/openapi_python_client/templates/property_templates/helpers.jinja b/openapi_python_client/templates/property_templates/helpers.jinja new file mode 100644 index 000000000..33c753df5 --- /dev/null +++ b/openapi_python_client/templates/property_templates/helpers.jinja @@ -0,0 +1,18 @@ +{% macro guarded_statement(property, source, statement) %} +{# If the property can be UNSET or None, this macro returns the provided statement guarded by an if which will check + for those invalid values. Otherwise, it returns the statement unmodified. #} +{% if property.required and not property.nullable %} +{{ statement }} +{% else %} + {% if property.nullable and not property.required %} +if not isinstance({{ source }}, Unset) and {{ source }} is not None: + {{ statement }} + {% elif property.nullable %} +if {{ source }} is not None: + {{ statement }} + {% else %} +if not isinstance({{ source }}, Unset): + {{ statement }} + {% endif %} +{% endif %} +{% endmacro %} diff --git a/openapi_python_client/templates/property_templates/int_property.py.jinja b/openapi_python_client/templates/property_templates/int_property.py.jinja new file mode 100644 index 000000000..f66f991ee --- /dev/null +++ b/openapi_python_client/templates/property_templates/int_property.py.jinja @@ -0,0 +1,3 @@ +{% macro transform_header(property, source, destination) %} +{{ destination }} = str({{ source }}) +{% endmacro %} diff --git a/openapi_python_client/templates/property_templates/list_property.py.jinja b/openapi_python_client/templates/property_templates/list_property.py.jinja index 9c7187837..9686f6930 100644 --- a/openapi_python_client/templates/property_templates/list_property.py.jinja +++ b/openapi_python_client/templates/property_templates/list_property.py.jinja @@ -1,6 +1,7 @@ {% macro construct(property, source, initial_value="[]") %} {% set inner_property = property.inner_property %} -{% if inner_property.template %} +{% import "property_templates/" + inner_property.template as inner_template %} +{% if inner_template.construct %} {% set inner_source = inner_property.python_name + "_data" %} {{ property.python_name }} = {{ initial_value }} _{{ property.python_name }} = {{ source }} @@ -9,8 +10,7 @@ for {{ inner_source }} in (_{{ property.python_name }}): {% else %} for {{ inner_source }} in (_{{ property.python_name }} or []): {% endif %} - {% from "property_templates/" + inner_property.template import construct %} - {{ construct(inner_property, inner_source) | indent(4) }} + {{ inner_template.construct(inner_property, inner_source) | indent(4) }} {{ property.python_name }}.append({{ inner_property.python_name }}) {% else %} {{ property.python_name }} = cast({{ property.get_type_string(no_optional=True) }}, {{ source }}) @@ -23,12 +23,12 @@ for {{ inner_source }} in (_{{ property.python_name }} or []): {% set multipart_destination = destination %} {% set destination = "_temp_" + destination %} {% endif %} -{% if inner_property.template %} +{% import "property_templates/" + inner_property.template as inner_template %} +{% if inner_template.transform %} {% set inner_source = inner_property.python_name + "_data" %} {{ destination }} = [] for {{ inner_source }} in {{ source }}: - {% from "property_templates/" + inner_property.template import transform %} - {{ transform(inner_property, inner_source, inner_property.python_name, transform_method) | indent(4) }} + {{ inner_template.transform(inner_property, inner_source, inner_property.python_name, transform_method) | indent(4) }} {{ destination }}.append({{ inner_property.python_name }}) {% else %} {{ destination }} = {{ source }} diff --git a/openapi_python_client/templates/property_templates/union_property.py.jinja b/openapi_python_client/templates/property_templates/union_property.py.jinja index 807137c08..8a7d506d6 100644 --- a/openapi_python_client/templates/property_templates/union_property.py.jinja +++ b/openapi_python_client/templates/property_templates/union_property.py.jinja @@ -8,9 +8,14 @@ def _parse_{{ property.python_name }}(data: object) -> {{ property.get_type_stri if isinstance(data, Unset): return data {% endif %} - {% for inner_property in property.inner_properties_with_template() %} + {% set ns = namespace(contains_unmodified_properties = false) %} + {% for inner_property in property.inner_properties %} {% import "property_templates/" + inner_property.template as inner_template %} - {% if inner_template.check_type_for_construct and (not loop.last or property.has_properties_without_templates) %} + {% if not inner_template.construct %} + {% set ns.contains_unmodified_properties = true %} + {% continue %} + {% endif %} + {% if inner_template.check_type_for_construct and (not loop.last or ns.contains_unmodified_properties) %} try: if not {{ inner_template.check_type_for_construct(inner_property, "data") }}: raise TypeError() @@ -27,8 +32,7 @@ def _parse_{{ property.python_name }}(data: object) -> {{ property.get_type_stri return {{ inner_property.python_name }} {% endif %} {% endfor %} - {% if property.has_properties_without_templates %} - {# Doesn't really matter what we cast it to as this type will be erased, so cast to one of the options #} + {% if ns.contains_unmodified_properties %} return cast({{ property.get_type_string() }}, data) {% endif %} @@ -52,21 +56,29 @@ elif {{ source }} is None: {% endif %} {{ destination }} = None {% endif %} -{% for inner_property in property.inner_properties_with_template() %} + +{% set ns = namespace(contains_properties_without_transform = false, contains_modified_properties = not property.required) %} +{% for inner_property in property.inner_properties %} + {% import "property_templates/" + inner_property.template as inner_template %} + {% if not inner_template.transform %} + {% set ns.contains_properties_without_transform = true %} + {% continue %} + {% else %} + {% set ns.contains_modified_properties = true %} + {% endif %} {% if loop.first and property.required and not property.nullable %}{# No if UNSET or if None statement before this #} if isinstance({{ source }}, {{ inner_property.get_instance_type_string() }}): - {% elif not loop.last or property.has_properties_without_templates %} + {% elif not loop.last or ns.contains_properties_without_transform %} elif isinstance({{ source }}, {{ inner_property.get_instance_type_string() }}): {% else %} else: {% endif %} - {% from "property_templates/" + inner_property.template import transform %} - {{ transform(inner_property, source, destination, declare_type=False, multipart=multipart) | indent(4) }} + {{ inner_template.transform(inner_property, source, destination, declare_type=False, multipart=multipart) | indent(4) }} {% endfor %} -{% if property.has_properties_without_templates and (property.inner_properties_with_template() | any or not property.required)%} +{% if ns.contains_properties_without_transform and ns.contains_modified_properties %} else: {{ destination }} = {{ source }} -{% elif property.has_properties_without_templates %} +{% elif ns.contains_properties_without_transform %} {{ destination }} = {{ source }} {% endif %} diff --git a/pyproject.toml b/pyproject.toml index 01aa43116..dd9bd566c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,7 +75,10 @@ task regen\ && task e2e\ """ regen_e2e = "python -m end_to_end_tests.regen_golden_record" -regen_integration = "openapi-python-client update --url https://raw.githubusercontent.com/openapi-generators/openapi-test-server/main/openapi.json --config integration-tests-config.yaml" +regen_integration = """ +openapi-python-client update --url https://raw.githubusercontent.com/openapi-generators/openapi-test-server/main/openapi.json --config integration-tests-config.yaml\ +&& mypy integration-tests --strict +""" docs = "typer openapi_python_client/cli.py utils docs > usage.md" [tool.black] From 92521254dd006cf612f31628984fc13cd82eaca9 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 17 Jan 2022 15:37:36 -0700 Subject: [PATCH 6/9] style: Black and isort --- openapi_python_client/__init__.py | 4 +++- openapi_python_client/parser/properties/__init__.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openapi_python_client/__init__.py b/openapi_python_client/__init__.py index 417f6c7ab..b1dde1611 100644 --- a/openapi_python_client/__init__.py +++ b/openapi_python_client/__init__.py @@ -73,7 +73,9 @@ def __init__( ) else: loader = package_loader - self.env: Environment = Environment(loader=loader, trim_blocks=True, lstrip_blocks=True, extensions=['jinja2.ext.loopcontrols']) + self.env: Environment = Environment( + loader=loader, trim_blocks=True, lstrip_blocks=True, extensions=["jinja2.ext.loopcontrols"] + ) self.project_name: str = config.project_name_override or f"{utils.kebab_case(openapi.title).lower()}-client" self.project_dir: Path = Path.cwd() diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 8922c17a9..54d5d5a8c 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -10,7 +10,7 @@ ] from itertools import chain -from typing import Any, ClassVar, Dict, Generic, Iterable, Iterator, List, Optional, Set, Tuple, TypeVar, Union +from typing import Any, ClassVar, Dict, Generic, Iterable, List, Optional, Set, Tuple, TypeVar, Union import attr From 3d916b88e8cf54b9abd7072a241676dc1b47e630 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 17 Jan 2022 18:49:48 -0700 Subject: [PATCH 7/9] feat: Alert users when they have requested a header type which is not allowed --- openapi_python_client/parser/openapi.py | 10 +++-- .../parser/properties/__init__.py | 24 ++++++++++ .../parser/properties/property.py | 15 +++++++ tests/test_parser/test_openapi.py | 44 +++++++++++++++---- 4 files changed, 81 insertions(+), 12 deletions(-) diff --git a/openapi_python_client/parser/openapi.py b/openapi_python_client/parser/openapi.py index 359d6022c..a013551c5 100644 --- a/openapi_python_client/parser/openapi.py +++ b/openapi_python_client/parser/openapi.py @@ -287,9 +287,6 @@ def add_parameters( if isinstance(param, oai.Reference) or param.param_schema is None: continue - if param.param_in == oai.ParameterLocation.PATH and not param.required: - return ParseError(data=param, detail="Path parameter must be required"), schemas - unique_param = (param.name, param.param_in) if unique_param in unique_parameters: duplication_detail = ( @@ -300,7 +297,7 @@ def add_parameters( return ParseError(data=data, detail=duplication_detail), schemas unique_parameters.add(unique_param) - prop, schemas = property_from_data( + prop, new_schemas = property_from_data( name=param.name, required=param.required, data=param.param_schema, @@ -310,6 +307,11 @@ def add_parameters( ) if isinstance(prop, ParseError): return ParseError(detail=f"cannot parse parameter of endpoint {endpoint.name}", data=prop.data), schemas + location_error = prop.validate_location(param.param_in) + if location_error is not None: + location_error.data = param + return location_error, schemas + schemas = new_schemas if prop.name in parameters_by_location[param.param_in]: # This parameter was defined in the Operation, so ignore the PathItem definition continue diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 54d5d5a8c..5920987af 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -49,6 +49,12 @@ class StringProperty(Property): pattern: Optional[str] = None _type_string: ClassVar[str] = "str" _json_type_string: ClassVar[str] = "str" + _allowed_locations: ClassVar[Set[oai.ParameterLocation]] = { + oai.ParameterLocation.QUERY, + oai.ParameterLocation.PATH, + oai.ParameterLocation.COOKIE, + oai.ParameterLocation.HEADER, + } @attr.s(auto_attribs=True, frozen=True) @@ -123,6 +129,12 @@ class FloatProperty(Property): _type_string: ClassVar[str] = "float" _json_type_string: ClassVar[str] = "float" + _allowed_locations: ClassVar[Set[oai.ParameterLocation]] = { + oai.ParameterLocation.QUERY, + oai.ParameterLocation.PATH, + oai.ParameterLocation.COOKIE, + oai.ParameterLocation.HEADER, + } template: ClassVar[str] = "float_property.py.jinja" @@ -132,6 +144,12 @@ class IntProperty(Property): _type_string: ClassVar[str] = "int" _json_type_string: ClassVar[str] = "int" + _allowed_locations: ClassVar[Set[oai.ParameterLocation]] = { + oai.ParameterLocation.QUERY, + oai.ParameterLocation.PATH, + oai.ParameterLocation.COOKIE, + oai.ParameterLocation.HEADER, + } template: ClassVar[str] = "int_property.py.jinja" @@ -141,6 +159,12 @@ class BooleanProperty(Property): _type_string: ClassVar[str] = "bool" _json_type_string: ClassVar[str] = "bool" + _allowed_locations: ClassVar[Set[oai.ParameterLocation]] = { + oai.ParameterLocation.QUERY, + oai.ParameterLocation.PATH, + oai.ParameterLocation.COOKIE, + oai.ParameterLocation.HEADER, + } template: ClassVar[str] = "boolean_property.py.jinja" diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index e072fa2cb..bcedfc3d9 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -5,7 +5,9 @@ import attr from ... import Config +from ... import schema as oai from ...utils import PythonIdentifier +from ..errors import ParseError @attr.s(auto_attribs=True, frozen=True) @@ -28,6 +30,11 @@ class Property: nullable: bool _type_string: ClassVar[str] = "" _json_type_string: ClassVar[str] = "" # Type of the property after JSON serialization + _allowed_locations: ClassVar[Set[oai.ParameterLocation]] = { + oai.ParameterLocation.QUERY, + oai.ParameterLocation.PATH, + oai.ParameterLocation.COOKIE, + } default: Optional[str] = attr.ib() python_name: PythonIdentifier description: Optional[str] = attr.ib() @@ -36,6 +43,14 @@ class Property: template: ClassVar[str] = "any_property.py.jinja" json_is_dict: ClassVar[bool] = False + def validate_location(self, location: oai.ParameterLocation) -> Optional[ParseError]: + """Returns an error if this type of property is not allowed in the given location""" + if location not in self._allowed_locations: + return ParseError(detail=f"{self.get_type_string()} is not allowed in {location}") + if location == oai.ParameterLocation.PATH and not self.required: + return ParseError(detail="Path parameter must be required") + return None + def set_python_name(self, new_name: str, config: Config) -> None: """Mutates this Property to set a new python_name. diff --git a/tests/test_parser/test_openapi.py b/tests/test_parser/test_openapi.py index 53d96596a..3b8d1c672 100644 --- a/tests/test_parser/test_openapi.py +++ b/tests/test_parser/test_openapi.py @@ -507,9 +507,38 @@ def test_add_parameters_parse_error(self, mocker): ) assert result == ( ParseError(data=parse_error.data, detail=f"cannot parse parameter of endpoint {endpoint.name}"), - property_schemas, + initial_schemas, ) + @pytest.mark.parametrize( + "data_type, allowed", + [ + (oai.DataType.STRING, True), + (oai.DataType.INTEGER, True), + (oai.DataType.NUMBER, True), + (oai.DataType.BOOLEAN, True), + (oai.DataType.ARRAY, False), + (oai.DataType.OBJECT, False), + ], + ) + def test_add_parameters_header_types(self, data_type, allowed): + from openapi_python_client.parser.openapi import Endpoint + + endpoint = self.make_endpoint() + initial_schemas = Schemas() + param = oai.Parameter.construct( + name="test", required=True, param_schema=oai.Schema(type=data_type), param_in=oai.ParameterLocation.HEADER + ) + config = Config() + + result = Endpoint.add_parameters( + endpoint=endpoint, data=oai.Operation.construct(parameters=[param]), schemas=initial_schemas, config=config + ) + if allowed: + assert isinstance(result[0], Endpoint) + else: + assert isinstance(result[0], ParseError) + def test__add_parameters_parse_error_on_non_required_path_param(self): endpoint = self.make_endpoint() param = oai.Parameter.construct( @@ -534,13 +563,12 @@ def test_validation_error_when_location_not_supported(self, mocker): def test__add_parameters_with_location_postfix_conflict1(self, mocker, property_factory): """Checks when the PythonIdentifier of new parameter already used.""" from openapi_python_client.parser.openapi import Endpoint - from openapi_python_client.parser.properties import Property endpoint = self.make_endpoint() - path_prop_conflicted = property_factory(name="prop_name_path", required=False, nullable=False, default=None) - query_prop = property_factory(name="prop_name", required=False, nullable=False, default=None) - path_prop = property_factory(name="prop_name", required=False, nullable=False, default=None) + path_prop_conflicted = property_factory(name="prop_name_path", required=True, nullable=False, default=None) + query_prop = property_factory(name="prop_name", required=True, nullable=False, default=None) + path_prop = property_factory(name="prop_name", required=True, nullable=False, default=None) schemas_1 = mocker.MagicMock() schemas_2 = mocker.MagicMock() @@ -582,9 +610,9 @@ def test__add_parameters_with_location_postfix_conflict2(self, mocker, property_ from openapi_python_client.parser.openapi import Endpoint endpoint = self.make_endpoint() - path_prop_conflicted = property_factory(name="prop_name_path", required=False, nullable=False, default=None) - path_prop = property_factory(name="prop_name", required=False, nullable=False, default=None) - query_prop = property_factory(name="prop_name", required=False, nullable=False, default=None) + path_prop_conflicted = property_factory(name="prop_name_path", required=True, nullable=False, default=None) + path_prop = property_factory(name="prop_name", required=True, nullable=False, default=None) + query_prop = property_factory(name="prop_name", required=True, nullable=False, default=None) schemas_1 = mocker.MagicMock() schemas_2 = mocker.MagicMock() schemas_3 = mocker.MagicMock() From d9db0922ee877f900869b2c3bf4226191aee7fc4 Mon Sep 17 00:00:00 2001 From: Dylan Anthony Date: Mon, 17 Jan 2022 19:47:48 -0700 Subject: [PATCH 8/9] ci: Add integration tests for headers. --- .../api/parameters/__init__.py | 0 .../api/parameters/post_parameters_header.py | 185 ++++++++++++++++++ .../integration_tests/models/__init__.py | 1 + .../post_parameters_header_response_200.py | 78 ++++++++ integration-tests/tests/conftest.py | 7 + .../test_body/test_post_body_multipart.py | 4 +- .../test_post_parameters_header.py | 29 +++ 7 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 integration-tests/integration_tests/api/parameters/__init__.py create mode 100644 integration-tests/integration_tests/api/parameters/post_parameters_header.py create mode 100644 integration-tests/integration_tests/models/post_parameters_header_response_200.py create mode 100644 integration-tests/tests/conftest.py create mode 100644 integration-tests/tests/test_api/test_parameters/test_post_parameters_header.py diff --git a/integration-tests/integration_tests/api/parameters/__init__.py b/integration-tests/integration_tests/api/parameters/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/integration-tests/integration_tests/api/parameters/post_parameters_header.py b/integration-tests/integration_tests/api/parameters/post_parameters_header.py new file mode 100644 index 000000000..1d12d6f8b --- /dev/null +++ b/integration-tests/integration_tests/api/parameters/post_parameters_header.py @@ -0,0 +1,185 @@ +from typing import Any, Dict, Optional, Union + +import httpx + +from ...client import Client +from ...models.post_parameters_header_response_200 import PostParametersHeaderResponse200 +from ...models.public_error import PublicError +from ...types import Response + + +def _get_kwargs( + *, + client: Client, + boolean_header: bool, + string_header: str, + number_header: float, + integer_header: int, +) -> Dict[str, Any]: + url = "{}/parameters/header".format(client.base_url) + + headers: Dict[str, str] = client.get_headers() + cookies: Dict[str, Any] = client.get_cookies() + + headers["Boolean-Header"] = "true" if boolean_header else "false" + + headers["String-Header"] = string_header + + headers["Number-Header"] = str(number_header) + + headers["Integer-Header"] = str(integer_header) + + return { + "method": "post", + "url": url, + "headers": headers, + "cookies": cookies, + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[PostParametersHeaderResponse200, PublicError]]: + if response.status_code == 200: + response_200 = PostParametersHeaderResponse200.from_dict(response.json()) + + return response_200 + if response.status_code == 400: + response_400 = PublicError.from_dict(response.json()) + + return response_400 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[PostParametersHeaderResponse200, PublicError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + boolean_header: bool, + string_header: str, + number_header: float, + integer_header: int, +) -> Response[Union[PostParametersHeaderResponse200, PublicError]]: + """ + Args: + boolean_header (bool): + string_header (str): + number_header (float): + integer_header (int): + + Returns: + Response[Union[PostParametersHeaderResponse200, PublicError]] + """ + + kwargs = _get_kwargs( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ) + + response = httpx.request( + verify=client.verify_ssl, + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + boolean_header: bool, + string_header: str, + number_header: float, + integer_header: int, +) -> Optional[Union[PostParametersHeaderResponse200, PublicError]]: + """ + Args: + boolean_header (bool): + string_header (str): + number_header (float): + integer_header (int): + + Returns: + Response[Union[PostParametersHeaderResponse200, PublicError]] + """ + + return sync_detailed( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + boolean_header: bool, + string_header: str, + number_header: float, + integer_header: int, +) -> Response[Union[PostParametersHeaderResponse200, PublicError]]: + """ + Args: + boolean_header (bool): + string_header (str): + number_header (float): + integer_header (int): + + Returns: + Response[Union[PostParametersHeaderResponse200, PublicError]] + """ + + kwargs = _get_kwargs( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ) + + async with httpx.AsyncClient(verify=client.verify_ssl) as _client: + response = await _client.request(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + boolean_header: bool, + string_header: str, + number_header: float, + integer_header: int, +) -> Optional[Union[PostParametersHeaderResponse200, PublicError]]: + """ + Args: + boolean_header (bool): + string_header (str): + number_header (float): + integer_header (int): + + Returns: + Response[Union[PostParametersHeaderResponse200, PublicError]] + """ + + return ( + await asyncio_detailed( + client=client, + boolean_header=boolean_header, + string_header=string_header, + number_header=number_header, + integer_header=integer_header, + ) + ).parsed diff --git a/integration-tests/integration_tests/models/__init__.py b/integration-tests/integration_tests/models/__init__.py index 22998f371..a8044ede4 100644 --- a/integration-tests/integration_tests/models/__init__.py +++ b/integration-tests/integration_tests/models/__init__.py @@ -2,5 +2,6 @@ from .post_body_multipart_multipart_data import PostBodyMultipartMultipartData from .post_body_multipart_response_200 import PostBodyMultipartResponse200 +from .post_parameters_header_response_200 import PostParametersHeaderResponse200 from .problem import Problem from .public_error import PublicError diff --git a/integration-tests/integration_tests/models/post_parameters_header_response_200.py b/integration-tests/integration_tests/models/post_parameters_header_response_200.py new file mode 100644 index 000000000..772ffad3e --- /dev/null +++ b/integration-tests/integration_tests/models/post_parameters_header_response_200.py @@ -0,0 +1,78 @@ +from typing import Any, Dict, List, Type, TypeVar + +import attr + +T = TypeVar("T", bound="PostParametersHeaderResponse200") + + +@attr.s(auto_attribs=True) +class PostParametersHeaderResponse200: + """ + Attributes: + boolean (bool): Echo of the 'Boolean-Header' input parameter from the header. + string (str): Echo of the 'String-Header' input parameter from the header. + number (float): Echo of the 'Number-Header' input parameter from the header. + integer (int): Echo of the 'Integer-Header' input parameter from the header. + """ + + boolean: bool + string: str + number: float + integer: int + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + boolean = self.boolean + string = self.string + number = self.number + integer = self.integer + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "boolean": boolean, + "string": string, + "number": number, + "integer": integer, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + boolean = d.pop("boolean") + + string = d.pop("string") + + number = d.pop("number") + + integer = d.pop("integer") + + post_parameters_header_response_200 = cls( + boolean=boolean, + string=string, + number=number, + integer=integer, + ) + + post_parameters_header_response_200.additional_properties = d + return post_parameters_header_response_200 + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/integration-tests/tests/conftest.py b/integration-tests/tests/conftest.py new file mode 100644 index 000000000..aebbecfc5 --- /dev/null +++ b/integration-tests/tests/conftest.py @@ -0,0 +1,7 @@ +import pytest +from integration_tests.client import Client + + +@pytest.fixture(scope="session") +def client() -> Client: + return Client("http://localhost:3000") diff --git a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py index eaf9083a3..5ff6cbcf6 100644 --- a/integration-tests/tests/test_api/test_body/test_post_body_multipart.py +++ b/integration-tests/tests/test_api/test_body/test_post_body_multipart.py @@ -7,9 +7,7 @@ from integration_tests.types import File -def test() -> None: - client = Client("http://localhost:3000") - +def test(client: Client) -> None: a_string = "a test string" payload = b"some file content" file_name = "cool_stuff.txt" diff --git a/integration-tests/tests/test_api/test_parameters/test_post_parameters_header.py b/integration-tests/tests/test_api/test_parameters/test_post_parameters_header.py new file mode 100644 index 000000000..39f87d00d --- /dev/null +++ b/integration-tests/tests/test_api/test_parameters/test_post_parameters_header.py @@ -0,0 +1,29 @@ +from integration_tests.api.parameters.post_parameters_header import sync_detailed +from integration_tests.client import Client +from integration_tests.models.post_parameters_header_response_200 import PostParametersHeaderResponse200 + + +def test(client: Client) -> None: + string_header = "a test string" + integer_header = 1 + number_header = 1.1 + boolean_header = True + + response = sync_detailed( + client=client, + boolean_header=boolean_header, + string_header=string_header, + integer_header=integer_header, + number_header=number_header, + ) + + parsed = response.parsed + assert parsed is not None, f"{response.status_code}: {response.content}" + assert isinstance( + parsed, + PostParametersHeaderResponse200, + ), parsed + assert parsed.string == string_header + assert parsed.integer == integer_header + assert parsed.number == number_header + assert parsed.boolean == boolean_header From 6718ebdf036ed1ecadef35ef0f7365f2f05c091d Mon Sep 17 00:00:00 2001 From: dbanty Date: Tue, 18 Jan 2022 02:51:05 +0000 Subject: [PATCH 9/9] chore: Regenerate Integration Client --- integration-tests/tests/conftest.py | 1 + 1 file changed, 1 insertion(+) diff --git a/integration-tests/tests/conftest.py b/integration-tests/tests/conftest.py index aebbecfc5..9cdd679fa 100644 --- a/integration-tests/tests/conftest.py +++ b/integration-tests/tests/conftest.py @@ -1,4 +1,5 @@ import pytest + from integration_tests.client import Client