diff --git a/modules/openapi-generator/src/main/resources/python-prior/api_client.mustache b/modules/openapi-generator/src/main/resources/python-prior/api_client.mustache index f11b14d6d4d..410fa822c60 100644 --- a/modules/openapi-generator/src/main/resources/python-prior/api_client.mustache +++ b/modules/openapi-generator/src/main/resources/python-prior/api_client.mustache @@ -298,8 +298,10 @@ class ApiClient(object): return obj.isoformat() elif isinstance(obj, ModelSimple): return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, list): return [cls.sanitize_for_serialization(item) for item in obj] + elif isinstance(obj, tuple): + return tuple(cls.sanitize_for_serialization(item) for item in obj) if isinstance(obj, dict): return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} raise ApiValueError( diff --git a/samples/client/petstore/python-prior/petstore_api/api_client.py b/samples/client/petstore/python-prior/petstore_api/api_client.py index be6a8924910..3c9e7a5f68d 100644 --- a/samples/client/petstore/python-prior/petstore_api/api_client.py +++ b/samples/client/petstore/python-prior/petstore_api/api_client.py @@ -286,8 +286,10 @@ class ApiClient(object): return obj.isoformat() elif isinstance(obj, ModelSimple): return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, list): return [cls.sanitize_for_serialization(item) for item in obj] + elif isinstance(obj, tuple): + return tuple(cls.sanitize_for_serialization(item) for item in obj) if isinstance(obj, dict): return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} raise ApiValueError( diff --git a/samples/client/petstore/python-prior_disallowAdditionalPropertiesIfNotPresent/petstore_api/api_client.py b/samples/client/petstore/python-prior_disallowAdditionalPropertiesIfNotPresent/petstore_api/api_client.py index be6a8924910..3c9e7a5f68d 100644 --- a/samples/client/petstore/python-prior_disallowAdditionalPropertiesIfNotPresent/petstore_api/api_client.py +++ b/samples/client/petstore/python-prior_disallowAdditionalPropertiesIfNotPresent/petstore_api/api_client.py @@ -286,8 +286,10 @@ class ApiClient(object): return obj.isoformat() elif isinstance(obj, ModelSimple): return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, list): return [cls.sanitize_for_serialization(item) for item in obj] + elif isinstance(obj, tuple): + return tuple(cls.sanitize_for_serialization(item) for item in obj) if isinstance(obj, dict): return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} raise ApiValueError( diff --git a/samples/openapi3/client/extensions/x-auth-id-alias/python-prior/x_auth_id_alias/api_client.py b/samples/openapi3/client/extensions/x-auth-id-alias/python-prior/x_auth_id_alias/api_client.py index e6c0b2e0602..2a0b4462521 100644 --- a/samples/openapi3/client/extensions/x-auth-id-alias/python-prior/x_auth_id_alias/api_client.py +++ b/samples/openapi3/client/extensions/x-auth-id-alias/python-prior/x_auth_id_alias/api_client.py @@ -286,8 +286,10 @@ class ApiClient(object): return obj.isoformat() elif isinstance(obj, ModelSimple): return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, list): return [cls.sanitize_for_serialization(item) for item in obj] + elif isinstance(obj, tuple): + return tuple(cls.sanitize_for_serialization(item) for item in obj) if isinstance(obj, dict): return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} raise ApiValueError( diff --git a/samples/openapi3/client/petstore/python-prior/petstore_api/api_client.py b/samples/openapi3/client/petstore/python-prior/petstore_api/api_client.py index c14f1d0f1bc..ad9920c602a 100644 --- a/samples/openapi3/client/petstore/python-prior/petstore_api/api_client.py +++ b/samples/openapi3/client/petstore/python-prior/petstore_api/api_client.py @@ -286,8 +286,10 @@ class ApiClient(object): return obj.isoformat() elif isinstance(obj, ModelSimple): return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): + elif isinstance(obj, list): return [cls.sanitize_for_serialization(item) for item in obj] + elif isinstance(obj, tuple): + return tuple(cls.sanitize_for_serialization(item) for item in obj) if isinstance(obj, dict): return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} raise ApiValueError( diff --git a/samples/openapi3/client/petstore/python-prior/tests_manual/test_fake_api.py b/samples/openapi3/client/petstore/python-prior/tests_manual/test_fake_api.py index 12e391238e6..36a515d49c9 100644 --- a/samples/openapi3/client/petstore/python-prior/tests_manual/test_fake_api.py +++ b/samples/openapi3/client/petstore/python-prior/tests_manual/test_fake_api.py @@ -14,8 +14,11 @@ from collections import namedtuple import os import json import unittest +from pathlib import Path from unittest.mock import patch +from urllib3.request import RequestMethods + import petstore_api from petstore_api.api.fake_api import FakeApi # noqa: E501 from petstore_api.rest import RESTClientObject, RESTResponse @@ -490,6 +493,48 @@ class TestFakeApi(unittest.TestCase): finally: file.close() + def test_upload_with_mime_type(self): + """Upload a file, while setting a MIME type for that file. + + Verify that: + + * ``post_params`` may contain a three-tuple in the form ``(file_name, file_handle, + file_mime_type)`` + * This three-tuple is passed to urllib3 as a tuple, without being converted to a list. + + See: + + * https://github.com/OpenAPITools/openapi-generator/issues/14012 + * https://urllib3.readthedocs.io/en/stable/reference/urllib3.request.html + """ + file_path = Path(__file__, "..", "..", "testfiles", "1px_pic1.png").resolve() + file_mime_type = "image/png" + with patch.object(RequestMethods, 'request') as request: + with open(file_path, mode="rb") as file_handle: + request.return_value.status = 200 + resp = self.api.api_client.call_api( + resource_path="/fake/uploadFile", + method="POST", + header_params={"Content-Type": "multipart/form-data"}, + post_params={"file": (file_path.name, file_handle, file_mime_type)}, + ) + + # a single multipart/form-data POST call was made, with a single form field + request.assert_called_once() + fields = request.call_args.kwargs['fields'] + self.assertEqual(len(fields), 1, fields) + field = fields[0] + + # it is in the form (form_field_name, (filename, filedata, mimetype)) + self.assertEqual(field[0], "file") + self.assertEqual(field[1][0], file_path.name) + with open(file_path, mode="rb") as file_handle: + self.assertEqual(field[1][1], file_handle.read()) + self.assertEqual(field[1][2], file_mime_type) + + # the form field value wasn't cast to a list + self.assertIsInstance(fields[0][1], tuple) + def test_download_attachment(self): """Ensures that file deserialization works"""