diff --git a/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/tests/__init__.py b/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/tests/__init__.py index dcb864fe9..28a4f10c1 100644 --- a/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/tests/__init__.py +++ b/end_to_end_tests/custom-templates-golden-record/my_test_api_client/api/tests/__init__.py @@ -19,6 +19,7 @@ token_with_cookie_auth_token_with_cookie_get, unsupported_content_tests_unsupported_content_get, upload_file_tests_upload_post, + upload_multiple_files_tests_upload_post, ) @@ -72,6 +73,13 @@ def upload_file_tests_upload_post(cls) -> types.ModuleType: """ return upload_file_tests_upload_post + @classmethod + def upload_multiple_files_tests_upload_post(cls) -> types.ModuleType: + """ + Upload several files in the same request + """ + return upload_multiple_files_tests_upload_post + @classmethod def json_body_tests_json_body_post(cls) -> types.ModuleType: """ 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 new file mode 100644 index 000000000..e5e42d546 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_multiple_files_tests_upload_post.py @@ -0,0 +1,126 @@ +from typing import Any, Dict, List, Optional, Union + +import httpx + +from ...client import Client +from ...models.http_validation_error import HTTPValidationError +from ...types import UNSET, File, Response, Unset + + +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() + cookies: Dict[str, Any] = client.get_cookies() + + if keep_alive is not UNSET: + headers["keep-alive"] = keep_alive + + multipart_multipart_data = [] + for multipart_data_item_data in multipart_data: + multipart_data_item = multipart_data_item_data.to_tuple() + + multipart_multipart_data.append(multipart_data_item) + + return { + "url": url, + "headers": headers, + "cookies": cookies, + "timeout": client.get_timeout(), + "files": multipart_multipart_data, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, HTTPValidationError]]: + if response.status_code == 200: + response_200 = response.json() + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[Any, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + multipart_data: List[File], + keep_alive: Union[Unset, bool] = UNSET, +) -> Response[Union[Any, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + multipart_data: List[File], + keep_alive: Union[Unset, bool] = UNSET, +) -> Optional[Union[Any, HTTPValidationError]]: + """Upload several files in the same request""" + + return sync_detailed( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + multipart_data: List[File], + keep_alive: Union[Unset, bool] = UNSET, +) -> Response[Union[Any, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + multipart_data: List[File], + keep_alive: Union[Unset, bool] = UNSET, +) -> Optional[Union[Any, HTTPValidationError]]: + """Upload several files in the same request""" + + return ( + await asyncio_detailed( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + ).parsed diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index 3724f428c..5e8c2cbe8 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -269,6 +269,61 @@ } } }, + "/tests/upload/multiple": { + "post": { + "tags": [ + "tests" + ], + "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" + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, "/tests/json_body": { "post": { "tags": [ 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 b955ad40a..44dac097e 100644 --- a/openapi_python_client/templates/property_templates/list_property.py.jinja +++ b/openapi_python_client/templates/property_templates/list_property.py.jinja @@ -17,7 +17,7 @@ for {{ inner_source }} in (_{{ property.python_name }} or []): {% endif %} {% endmacro %} -{% macro _transform(property, source, destination, stringify) %} +{% macro _transform(property, source, destination, stringify, transform_method) %} {% set inner_property = property.inner_property %} {% if stringify %} {% set stringified_destination = destination %} @@ -28,7 +28,7 @@ for {{ inner_source }} in (_{{ property.python_name }} or []): {{ destination }} = [] for {{ inner_source }} in {{ source }}: {% from "property_templates/" + inner_property.template import transform %} - {{ transform(inner_property, inner_source, inner_property.python_name) | indent(4) }} + {{ transform(inner_property, inner_source, inner_property.python_name, transform_method) | indent(4) }} {{ destination }}.append({{ inner_property.python_name }}) {% else %} {{ destination }} = {{ source }} @@ -40,7 +40,7 @@ for {{ inner_source }} in {{ source }}: {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, list){% endmacro %} -{% macro transform(property, source, destination, declare_type=True, stringify=False) %} +{% macro transform(property, source, destination, declare_type=True, stringify=False, transform_method="to_dict") %} {% set inner_property = property.inner_property %} {% if stringify %} {% set type_string = "Union[Unset, Tuple[None, str, str]]" %} @@ -52,9 +52,9 @@ for {{ inner_source }} in {{ source }}: if {{ source }} is None: {{ destination }} = None else: - {{ _transform(property, source, destination, stringify) | indent(4) }} + {{ _transform(property, source, destination, stringify, transform_method) | indent(4) }} {% else %} -{{ _transform(property, source, destination, stringify) }} +{{ _transform(property, source, destination, stringify, transform_method) }} {% endif %} {% else %} {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET @@ -63,11 +63,15 @@ if not isinstance({{ source }}, Unset): if {{ source }} is None: {{ destination }} = None else: - {{ _transform(property, source, destination, stringify) | indent(8)}} + {{ _transform(property, source, destination, stringify, transform_method) | indent(8)}} {% else %} - {{ _transform(property, source, destination, stringify) | indent(4)}} + {{ _transform(property, source, destination, stringify, transform_method) | indent(4)}} {% endif %} {% endif %} {% endmacro %} + +{% macro transform_multipart(property, source, destination) %} +{{ transform(property, source, destination, transform_method="to_multipart") }} +{% endmacro %}