diff --git a/modules/openapi-generator/src/main/resources/python/api_client.handlebars b/modules/openapi-generator/src/main/resources/python/api_client.handlebars index 81426853056..4379c88b823 100644 --- a/modules/openapi-generator/src/main/resources/python/api_client.handlebars +++ b/modules/openapi-generator/src/main/resources/python/api_client.handlebars @@ -1399,24 +1399,24 @@ class RequestBody(StyleFormSerializer, JSONDetector): def __multipart_json_item(self, key: str, value: Schema) -> RequestField: json_value = self.__json_encoder.default(value) - return RequestField(name=key, data=json.dumps(json_value), headers={'Content-Type': 'application/json'}) + request_field = RequestField(name=key, data=json.dumps(json_value)) + request_field.make_multipart(content_type='application/json') + return request_field def __multipart_form_item(self, key: str, value: Schema) -> RequestField: if isinstance(value, str): - return RequestField(name=key, data=str(value), headers={'Content-Type': 'text/plain'}) + request_field = RequestField(name=key, data=str(value)) + request_field.make_multipart(content_type='text/plain') elif isinstance(value, bytes): - return RequestField(name=key, data=value, headers={'Content-Type': 'application/octet-stream'}) + request_field = RequestField(name=key, data=value) + request_field.make_multipart(content_type='application/octet-stream') elif isinstance(value, FileIO): - request_field = RequestField( - name=key, - data=value.read(), - filename=os.path.basename(value.name), - headers={'Content-Type': 'application/octet-stream'} - ) + # TODO use content.encoding to limit allowed content types if they are present + request_field = RequestField.from_tuples(key, (os.path.basename(value.name), value.read())) value.close() - return request_field else: - return self.__multipart_json_item(key=key, value=value) + request_field = self.__multipart_json_item(key=key, value=value) + return request_field def __serialize_multipart_form_data( self, in_data: Schema @@ -1506,4 +1506,4 @@ class RequestBody(StyleFormSerializer, JSONDetector): return self.__serialize_application_x_www_form_data(cast_in_data) elif content_type == 'application/octet-stream': return self.__serialize_application_octet_stream(cast_in_data) - raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) + raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) \ No newline at end of file diff --git a/samples/openapi3/client/3_0_3_unit_test/python/unit_test_api/api_client.py b/samples/openapi3/client/3_0_3_unit_test/python/unit_test_api/api_client.py index 6fa884fc7d8..102e967cf7b 100644 --- a/samples/openapi3/client/3_0_3_unit_test/python/unit_test_api/api_client.py +++ b/samples/openapi3/client/3_0_3_unit_test/python/unit_test_api/api_client.py @@ -1389,24 +1389,24 @@ class RequestBody(StyleFormSerializer, JSONDetector): def __multipart_json_item(self, key: str, value: Schema) -> RequestField: json_value = self.__json_encoder.default(value) - return RequestField(name=key, data=json.dumps(json_value), headers={'Content-Type': 'application/json'}) + request_field = RequestField(name=key, data=json.dumps(json_value)) + request_field.make_multipart(content_type='application/json') + return request_field def __multipart_form_item(self, key: str, value: Schema) -> RequestField: if isinstance(value, str): - return RequestField(name=key, data=str(value), headers={'Content-Type': 'text/plain'}) + request_field = RequestField(name=key, data=str(value)) + request_field.make_multipart(content_type='text/plain') elif isinstance(value, bytes): - return RequestField(name=key, data=value, headers={'Content-Type': 'application/octet-stream'}) + request_field = RequestField(name=key, data=value) + request_field.make_multipart(content_type='application/octet-stream') elif isinstance(value, FileIO): - request_field = RequestField( - name=key, - data=value.read(), - filename=os.path.basename(value.name), - headers={'Content-Type': 'application/octet-stream'} - ) + # TODO use content.encoding to limit allowed content types if they are present + request_field = RequestField.from_tuples(key, (os.path.basename(value.name), value.read())) value.close() - return request_field else: - return self.__multipart_json_item(key=key, value=value) + request_field = self.__multipart_json_item(key=key, value=value) + return request_field def __serialize_multipart_form_data( self, in_data: Schema @@ -1496,4 +1496,4 @@ class RequestBody(StyleFormSerializer, JSONDetector): return self.__serialize_application_x_www_form_data(cast_in_data) elif content_type == 'application/octet-stream': return self.__serialize_application_octet_stream(cast_in_data) - raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) + raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) \ No newline at end of file diff --git a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/api_client.py b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/api_client.py index d52c3115dd0..6d9c2d44e6a 100644 --- a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/api_client.py +++ b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/api_client.py @@ -1389,24 +1389,24 @@ class RequestBody(StyleFormSerializer, JSONDetector): def __multipart_json_item(self, key: str, value: Schema) -> RequestField: json_value = self.__json_encoder.default(value) - return RequestField(name=key, data=json.dumps(json_value), headers={'Content-Type': 'application/json'}) + request_field = RequestField(name=key, data=json.dumps(json_value)) + request_field.make_multipart(content_type='application/json') + return request_field def __multipart_form_item(self, key: str, value: Schema) -> RequestField: if isinstance(value, str): - return RequestField(name=key, data=str(value), headers={'Content-Type': 'text/plain'}) + request_field = RequestField(name=key, data=str(value)) + request_field.make_multipart(content_type='text/plain') elif isinstance(value, bytes): - return RequestField(name=key, data=value, headers={'Content-Type': 'application/octet-stream'}) + request_field = RequestField(name=key, data=value) + request_field.make_multipart(content_type='application/octet-stream') elif isinstance(value, FileIO): - request_field = RequestField( - name=key, - data=value.read(), - filename=os.path.basename(value.name), - headers={'Content-Type': 'application/octet-stream'} - ) + # TODO use content.encoding to limit allowed content types if they are present + request_field = RequestField.from_tuples(key, (os.path.basename(value.name), value.read())) value.close() - return request_field else: - return self.__multipart_json_item(key=key, value=value) + request_field = self.__multipart_json_item(key=key, value=value) + return request_field def __serialize_multipart_form_data( self, in_data: Schema @@ -1496,4 +1496,4 @@ class RequestBody(StyleFormSerializer, JSONDetector): return self.__serialize_application_x_www_form_data(cast_in_data) elif content_type == 'application/octet-stream': return self.__serialize_application_octet_stream(cast_in_data) - raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) + raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/python/petstore_api/api_client.py b/samples/openapi3/client/petstore/python/petstore_api/api_client.py index 9ee9ff13f68..163013facda 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/api_client.py +++ b/samples/openapi3/client/petstore/python/petstore_api/api_client.py @@ -1398,24 +1398,24 @@ class RequestBody(StyleFormSerializer, JSONDetector): def __multipart_json_item(self, key: str, value: Schema) -> RequestField: json_value = self.__json_encoder.default(value) - return RequestField(name=key, data=json.dumps(json_value), headers={'Content-Type': 'application/json'}) + request_field = RequestField(name=key, data=json.dumps(json_value)) + request_field.make_multipart(content_type='application/json') + return request_field def __multipart_form_item(self, key: str, value: Schema) -> RequestField: if isinstance(value, str): - return RequestField(name=key, data=str(value), headers={'Content-Type': 'text/plain'}) + request_field = RequestField(name=key, data=str(value)) + request_field.make_multipart(content_type='text/plain') elif isinstance(value, bytes): - return RequestField(name=key, data=value, headers={'Content-Type': 'application/octet-stream'}) + request_field = RequestField(name=key, data=value) + request_field.make_multipart(content_type='application/octet-stream') elif isinstance(value, FileIO): - request_field = RequestField( - name=key, - data=value.read(), - filename=os.path.basename(value.name), - headers={'Content-Type': 'application/octet-stream'} - ) + # TODO use content.encoding to limit allowed content types if they are present + request_field = RequestField.from_tuples(key, (os.path.basename(value.name), value.read())) value.close() - return request_field else: - return self.__multipart_json_item(key=key, value=value) + request_field = self.__multipart_json_item(key=key, value=value) + return request_field def __serialize_multipart_form_data( self, in_data: Schema @@ -1505,4 +1505,4 @@ class RequestBody(StyleFormSerializer, JSONDetector): return self.__serialize_application_x_www_form_data(cast_in_data) elif content_type == 'application/octet-stream': return self.__serialize_application_octet_stream(cast_in_data) - raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) + raise NotImplementedError('Serialization has not yet been implemented for {}'.format(content_type)) \ No newline at end of file diff --git a/samples/openapi3/client/petstore/python/tests_manual/test_fake_api.py b/samples/openapi3/client/petstore/python/tests_manual/test_fake_api.py index 5bf64cee445..12c108871d6 100644 --- a/samples/openapi3/client/petstore/python/tests_manual/test_fake_api.py +++ b/samples/openapi3/client/petstore/python/tests_manual/test_fake_api.py @@ -35,8 +35,7 @@ class MIMEFormdata(nonmultipart.MIMENonMultipart): class TestFakeApi(ApiTestMixin): """FakeApi unit test stubs""" configuration = petstore_api.Configuration() - api_client = api_client.ApiClient(configuration=configuration) - api = FakeApi(api_client=api_client) + api = FakeApi(api_client=api_client.ApiClient(configuration=configuration)) def test_array_model(self): from petstore_api.model import animal_farm, animal @@ -469,7 +468,11 @@ class TestFakeApi(ApiTestMixin): name='file', data=file_bytes, filename=file_name, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Location': None, + 'Content-Type': 'image/png', + "Content-Disposition": "form-data; name=\"file\"; filename=\"1px_pic1.png\"" + } ), ), content_type='multipart/form-data' @@ -493,7 +496,11 @@ class TestFakeApi(ApiTestMixin): api_client.RequestField( name='file', data=file_bytes, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Type': 'application/octet-stream', + "Content-Disposition": "form-data; name=\"file\"", + "Content-Location": None + } ), ), content_type='multipart/form-data' @@ -548,13 +555,22 @@ class TestFakeApi(ApiTestMixin): name='files', data=file_bytes, filename=file_name, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Type': 'image/png', + "Content-Disposition": "form-data; name=\"files\"; filename=\"1px_pic1.png\"", + "Content-Location": None + } ), api_client.RequestField( name='files', data=file_bytes, filename=file_name, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Type': 'image/png', + "Content-Disposition": "form-data; name=\"files\"; filename=\"1px_pic1.png\"", + "Content-Location": None + + } ), ), content_type='multipart/form-data' @@ -579,12 +595,20 @@ class TestFakeApi(ApiTestMixin): api_client.RequestField( name='files', data=file_bytes, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Type': 'application/octet-stream', + "Content-Disposition": "form-data; name=\"files\"", + "Content-Location": None + } ), api_client.RequestField( name='files', data=file_bytes, - headers={'Content-Type': 'application/octet-stream'} + headers={ + 'Content-Type': 'application/octet-stream', + "Content-Disposition": "form-data; name=\"files\"", + "Content-Location": None + } ), ), content_type='multipart/form-data' @@ -657,11 +681,15 @@ class TestFakeApi(ApiTestMixin): accept_content_type=content_type, content_type=content_type, fields=( - api_client.RequestField( - name='someProp', - data=single_char_str, - headers={'Content-Type': 'text/plain'} - ), + api_client.RequestField( + name='someProp', + data=single_char_str, + headers={ + 'Content-Type': 'text/plain', + "Content-Disposition": "form-data; name=\"someProp\"", + "Content-Location": None + } + ), ), ) self.assertEqual(api_response.body, {'someProp': single_char_str}) @@ -764,32 +792,6 @@ class TestFakeApi(ApiTestMixin): assert isinstance(api_response.body, schemas.Unset) assert isinstance(api_response.headers, schemas.Unset) - def test_x_www_form_urlencoded(self): - with patch.object(urllib3.PoolManager, 'request') as mock_request: - from urllib3._collections import HTTPHeaderDict - from petstore_api.apis.tags import pet_api - - pet_id = dict(petId=2345) - pet_values = dict( - name='mister furball award', - status='happy, fuzzy, and bouncy' - ) - mock_request.return_value = self.response("") - - api_instance = pet_api.PetApi(self.api_client) - api_instance.update_pet_with_form(path_params=pet_id, body=pet_values) - mock_request.assert_called_with( - 'POST', - 'http://petstore.swagger.io:80/v2/pet/2345', - body='name=mister%20furball%20award&status=happy%2C%20fuzzy%2C%20and%20bouncy', - fields={}, - encode_multipart=False, - preload_content=True, - timeout=None, - headers=HTTPHeaderDict({'User-Agent': self.user_agent, - 'Content-Type': 'application/x-www-form-urlencoded'}) - ) - def test_json_patch(self): with patch.object(urllib3.PoolManager, 'request') as mock_request: from petstore_api.model import json_patch_request @@ -829,4 +831,4 @@ class TestFakeApi(ApiTestMixin): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file diff --git a/samples/openapi3/client/petstore/python/tests_manual/test_paths/test_pet_pet_id/test_post.py b/samples/openapi3/client/petstore/python/tests_manual/test_paths/test_pet_pet_id/test_post.py new file mode 100644 index 00000000000..2a18e055ee0 --- /dev/null +++ b/samples/openapi3/client/petstore/python/tests_manual/test_paths/test_pet_pet_id/test_post.py @@ -0,0 +1,60 @@ +# coding: utf-8 + +""" + + + Generated by: https://openapi-generator.tech +""" + +import unittest +from unittest.mock import patch + +import urllib3 + +import petstore_api +from petstore_api.paths.pet_pet_id import post +from petstore_api import configuration, schemas, api_client + +from ... import ApiTestMixin + + +class TestPetPetId(ApiTestMixin, unittest.TestCase): + """ + PetPetId unit test stubs + Updates a pet in the store with form data # noqa: E501 + """ + + def test_post(self): + used_api_client = api_client.ApiClient() + api = post.ApiForpost(api_client=used_api_client) + + with patch.object(urllib3.PoolManager, 'request') as mock_request: + path_params = {'petId': 2345} + body = { + 'name': 'mister furball award', + 'status': 'happy, fuzzy, and bouncy' + } + mock_request.return_value = self.response("") + + api_response = api.post(path_params=path_params, body=body) + mock_request.assert_called_with( + 'POST', + 'http://petstore.swagger.io:80/v2/pet/2345', + body='name=mister%20furball%20award&status=happy%2C%20fuzzy%2C%20and%20bouncy', + fields={}, + encode_multipart=False, + preload_content=True, + timeout=None, + headers={ + 'User-Agent': self.user_agent, + 'Content-Type': 'application/x-www-form-urlencoded' + } + ) + assert isinstance(api_response.response, urllib3.HTTPResponse) + assert isinstance(api_response.body, schemas.Unset) + assert isinstance(api_response.headers, schemas.Unset) + assert api_response.response.status == 200 + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/samples/openapi3/client/petstore/python/tests_manual/test_request_body.py b/samples/openapi3/client/petstore/python/tests_manual/test_request_body.py index c1f78880e96..3e8d687e619 100644 --- a/samples/openapi3/client/petstore/python/tests_manual/test_request_body.py +++ b/samples/openapi3/client/petstore/python/tests_manual/test_request_body.py @@ -71,21 +71,53 @@ class TestParameter(unittest.TestCase): dict( fields=( api_client.RequestField( - name='some_null', data='null', headers={'Content-Type': 'application/json'}), + name='some_null', data='null', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_null\"", + "Content-Location": None + }), api_client.RequestField( - name='some_bool', data='true', headers={'Content-Type': 'application/json'}), + name='some_bool', data='true', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_bool\"", + "Content-Location": None + }), api_client.RequestField( - name='some_str', data='a', headers={'Content-Type': 'text/plain'}), + name='some_str', data='a', headers={ + 'Content-Type': 'text/plain', + "Content-Disposition": "form-data; name=\"some_str\"", + "Content-Location": None + }), api_client.RequestField( - name='some_int', data='1', headers={'Content-Type': 'application/json'}), + name='some_int', data='1', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_int\"", + "Content-Location": None + }), api_client.RequestField( - name='some_float', data='3.14', headers={'Content-Type': 'application/json'}), + name='some_float', data='3.14', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_float\"", + "Content-Location": None + }), api_client.RequestField( - name='some_list', data='[]', headers={'Content-Type': 'application/json'}), + name='some_list', data='[]', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_list\"", + "Content-Location": None + }), api_client.RequestField( - name='some_dict', data='{}', headers={'Content-Type': 'application/json'}), + name='some_dict', data='{}', headers={ + 'Content-Type': 'application/json', + "Content-Disposition": "form-data; name=\"some_dict\"", + "Content-Location": None + }), api_client.RequestField( - name='some_bytes', data=b'abc', headers={'Content-Type': 'application/octet-stream'}) + name='some_bytes', data=b'abc', headers={ + 'Content-Type': 'application/octet-stream', + "Content-Disposition": "form-data; name=\"some_bytes\"", + "Content-Location": None + }) ) ) ) @@ -110,7 +142,7 @@ class TestParameter(unittest.TestCase): def test_application_x_www_form_urlencoded_serialization(self): payload = dict( some_null=None, - some_str='hi, spacether!', + some_str='hi there', some_int=1, some_float=3.14, some_list=[], @@ -123,7 +155,7 @@ class TestParameter(unittest.TestCase): serialization = request_body.serialize(payload, content_type) self.assertEqual( serialization, - dict(body='some_str=hi%2C%20spacether%21&some_int=1&some_float=3.14') + dict(body='some_str=hi%20there&some_int=1&some_float=3.14') ) serialization = request_body.serialize({}, content_type) @@ -144,4 +176,4 @@ class TestParameter(unittest.TestCase): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file