diff --git a/modules/openapi-generator/src/main/resources/python/model_utils.mustache b/modules/openapi-generator/src/main/resources/python/model_utils.mustache index 9c299d4b3ef..07b77a99d18 100644 --- a/modules/openapi-generator/src/main/resources/python/model_utils.mustache +++ b/modules/openapi-generator/src/main/resources/python/model_utils.mustache @@ -1211,10 +1211,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientCodegenTest.java index f7e949e5f27..45c784f40ed 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/python/PythonLegacyClientCodegenTest.java @@ -18,7 +18,6 @@ package org.openapitools.codegen.python; import com.google.common.collect.Sets; -import com.sun.org.apache.xpath.internal.operations.Bool; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.*; diff --git a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml index fa3500df0a1..41a16b1011b 100644 --- a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing-with-http-signature.yaml @@ -1008,6 +1008,26 @@ paths: application/json: schema: $ref: '#/components/schemas/ArrayOfEnums' + /fake/refs/enum-test: + post: + tags: + - fake + summary: Object contains enum properties and array properties containing enums + operationId: EnumTest + requestBody: + description: Input object + content: + application/json: + schema: + $ref: '#/components/schemas/Enum_Test' + required: false + responses: + 200: + description: Got object containing enums + content: + application/json: + schema: + $ref: '#/components/schemas/Enum_Test' /fake/additional-properties-with-array-of-enums: get: tags: @@ -1671,6 +1691,12 @@ components: $ref: '#/components/schemas/IntegerEnumWithDefaultValue' IntegerEnumOneValue: $ref: '#/components/schemas/IntegerEnumOneValue' + InlineArrayOfStrEnum: + type: array + items: + $ref: '#/components/schemas/StringEnum' + ArrayOfStrEnum: + $ref: '#/components/schemas/ArrayOfEnums' AdditionalPropertiesClass: type: object properties: diff --git a/samples/client/petstore/python/petstore_api/model_utils.py b/samples/client/petstore/python/petstore_api/model_utils.py index 7afcb68f615..ae554710670 100644 --- a/samples/client/petstore/python/petstore_api/model_utils.py +++ b/samples/client/petstore/python/petstore_api/model_utils.py @@ -1493,10 +1493,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], diff --git a/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py b/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py index 2533abbc717..3276615fd49 100644 --- a/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py +++ b/samples/openapi3/client/extensions/x-auth-id-alias/python/x_auth_id_alias/model_utils.py @@ -1493,10 +1493,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], diff --git a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py index f0a4962ad53..7edd9487c37 100644 --- a/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py +++ b/samples/openapi3/client/features/dynamic-servers/python/dynamic_servers/model_utils.py @@ -1493,10 +1493,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], diff --git a/samples/openapi3/client/petstore/python/README.md b/samples/openapi3/client/petstore/python/README.md index 9f9fb246b27..b7e1090f034 100644 --- a/samples/openapi3/client/petstore/python/README.md +++ b/samples/openapi3/client/petstore/python/README.md @@ -88,6 +88,7 @@ Class | Method | HTTP request | Description *FakeApi* | [**array_of_enums**](docs/FakeApi.md#array_of_enums) | **POST** /fake/refs/array-of-enums | Array of Enums *FakeApi* | [**boolean**](docs/FakeApi.md#boolean) | **POST** /fake/refs/boolean | *FakeApi* | [**composed_one_of_number_with_validations**](docs/FakeApi.md#composed_one_of_number_with_validations) | **POST** /fake/refs/composed_one_of_number_with_validations | +*FakeApi* | [**enum_test**](docs/FakeApi.md#enum_test) | **POST** /fake/refs/enum-test | Object contains enum properties and array properties containing enums *FakeApi* | [**fake_health_get**](docs/FakeApi.md#fake_health_get) | **GET** /fake/health | Health check endpoint *FakeApi* | [**mammal**](docs/FakeApi.md#mammal) | **POST** /fake/refs/mammal | *FakeApi* | [**number_with_validations**](docs/FakeApi.md#number_with_validations) | **POST** /fake/refs/number | diff --git a/samples/openapi3/client/petstore/python/docs/EnumTest.md b/samples/openapi3/client/petstore/python/docs/EnumTest.md index 70969239ca2..706c1ebf0ec 100644 --- a/samples/openapi3/client/petstore/python/docs/EnumTest.md +++ b/samples/openapi3/client/petstore/python/docs/EnumTest.md @@ -12,6 +12,8 @@ Name | Type | Description | Notes **string_enum_with_default_value** | [**StringEnumWithDefaultValue**](StringEnumWithDefaultValue.md) | | [optional] **integer_enum_with_default_value** | [**IntegerEnumWithDefaultValue**](IntegerEnumWithDefaultValue.md) | | [optional] **integer_enum_one_value** | [**IntegerEnumOneValue**](IntegerEnumOneValue.md) | | [optional] +**inline_array_of_str_enum** | [**[StringEnum]**](StringEnum.md) | | [optional] +**array_of_str_enum** | [**ArrayOfEnums**](ArrayOfEnums.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/samples/openapi3/client/petstore/python/docs/FakeApi.md b/samples/openapi3/client/petstore/python/docs/FakeApi.md index 164d7f9f8b4..ae713e6ee67 100644 --- a/samples/openapi3/client/petstore/python/docs/FakeApi.md +++ b/samples/openapi3/client/petstore/python/docs/FakeApi.md @@ -9,6 +9,7 @@ Method | HTTP request | Description [**array_of_enums**](FakeApi.md#array_of_enums) | **POST** /fake/refs/array-of-enums | Array of Enums [**boolean**](FakeApi.md#boolean) | **POST** /fake/refs/boolean | [**composed_one_of_number_with_validations**](FakeApi.md#composed_one_of_number_with_validations) | **POST** /fake/refs/composed_one_of_number_with_validations | +[**enum_test**](FakeApi.md#enum_test) | **POST** /fake/refs/enum-test | Object contains enum properties and array properties containing enums [**fake_health_get**](FakeApi.md#fake_health_get) | **GET** /fake/health | Health check endpoint [**mammal**](FakeApi.md#mammal) | **POST** /fake/refs/mammal | [**number_with_validations**](FakeApi.md#number_with_validations) | **POST** /fake/refs/number | @@ -346,6 +347,84 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **enum_test** +> EnumTest enum_test() + +Object contains enum properties and array properties containing enums + +### Example + +```python +import time +import petstore_api +from petstore_api.api import fake_api +from petstore_api.model.enum_test import EnumTest +from pprint import pprint +# Defining the host is optional and defaults to http://petstore.swagger.io:80/v2 +# See configuration.py for a list of all supported configuration parameters. +configuration = petstore_api.Configuration( + host = "http://petstore.swagger.io:80/v2" +) + + +# Enter a context with an instance of the API client +with petstore_api.ApiClient() as api_client: + # Create an instance of the API class + api_instance = fake_api.FakeApi(api_client) + enum_test = EnumTest( + enum_string="UPPER", + enum_string_required="UPPER", + enum_integer=1, + enum_number=1.1, + string_enum=StringEnum("placed"), + integer_enum=IntegerEnum(0), + string_enum_with_default_value=StringEnumWithDefaultValue("placed"), + integer_enum_with_default_value=IntegerEnumWithDefaultValue(0), + integer_enum_one_value=IntegerEnumOneValue(0), + inline_array_of_str_enum=[ + StringEnum("placed"), + ], + array_of_str_enum=ArrayOfEnums([ + StringEnum("placed"), + ]), + ) # EnumTest | Input object (optional) + + # example passing only required values which don't have defaults set + # and optional values + try: + # Object contains enum properties and array properties containing enums + api_response = api_instance.enum_test(enum_test=enum_test) + pprint(api_response) + except petstore_api.ApiException as e: + print("Exception when calling FakeApi->enum_test: %s\n" % e) +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **enum_test** | [**EnumTest**](EnumTest.md)| Input object | [optional] + +### Return type + +[**EnumTest**](EnumTest.md) + +### Authorization + +No authorization required + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | Got object containing enums | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **fake_health_get** > HealthCheckResult fake_health_get() diff --git a/samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py b/samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py index 4ce055c011b..d6fc4b80b4d 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py +++ b/samples/openapi3/client/petstore/python/petstore_api/api/fake_api.py @@ -26,6 +26,7 @@ from petstore_api.model.animal_farm import AnimalFarm from petstore_api.model.array_of_enums import ArrayOfEnums from petstore_api.model.client import Client from petstore_api.model.composed_one_of_number_with_validations import ComposedOneOfNumberWithValidations +from petstore_api.model.enum_test import EnumTest from petstore_api.model.file_schema_test_class import FileSchemaTestClass from petstore_api.model.health_check_result import HealthCheckResult from petstore_api.model.mammal import Mammal @@ -605,6 +606,117 @@ class FakeApi(object): callable=__composed_one_of_number_with_validations ) + def __enum_test( + self, + **kwargs + ): + """Object contains enum properties and array properties containing enums # noqa: E501 + + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + + >>> thread = api.enum_test(async_req=True) + >>> result = thread.get() + + + Keyword Args: + enum_test (EnumTest): Input object. [optional] + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (float/tuple): timeout setting for this request. If one + number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously + + Returns: + EnumTest + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') + return self.call_with_http_info(**kwargs) + + self.enum_test = Endpoint( + settings={ + 'response_type': (EnumTest,), + 'auth': [], + 'endpoint_path': '/fake/refs/enum-test', + 'operation_id': 'enum_test', + 'http_method': 'POST', + 'servers': None, + }, + params_map={ + 'all': [ + 'enum_test', + ], + 'required': [], + 'nullable': [ + ], + 'enum': [ + ], + 'validation': [ + ] + }, + root_map={ + 'validations': { + }, + 'allowed_values': { + }, + 'openapi_types': { + 'enum_test': + (EnumTest,), + }, + 'attribute_map': { + }, + 'location_map': { + 'enum_test': 'body', + }, + 'collection_format_map': { + } + }, + headers_map={ + 'accept': [ + 'application/json' + ], + 'content_type': [ + 'application/json' + ] + }, + api_client=api_client, + callable=__enum_test + ) + def __fake_health_get( self, **kwargs diff --git a/samples/openapi3/client/petstore/python/petstore_api/model/enum_test.py b/samples/openapi3/client/petstore/python/petstore_api/model/enum_test.py index efe4955e573..f6062dd87bd 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/model/enum_test.py +++ b/samples/openapi3/client/petstore/python/petstore_api/model/enum_test.py @@ -29,11 +29,13 @@ from petstore_api.model_utils import ( # noqa: F401 ) def lazy_import(): + from petstore_api.model.array_of_enums import ArrayOfEnums from petstore_api.model.integer_enum import IntegerEnum from petstore_api.model.integer_enum_one_value import IntegerEnumOneValue from petstore_api.model.integer_enum_with_default_value import IntegerEnumWithDefaultValue from petstore_api.model.string_enum import StringEnum from petstore_api.model.string_enum_with_default_value import StringEnumWithDefaultValue + globals()['ArrayOfEnums'] = ArrayOfEnums globals()['IntegerEnum'] = IntegerEnum globals()['IntegerEnumOneValue'] = IntegerEnumOneValue globals()['IntegerEnumWithDefaultValue'] = IntegerEnumWithDefaultValue @@ -114,6 +116,8 @@ class EnumTest(ModelNormal): 'string_enum_with_default_value': (StringEnumWithDefaultValue,), # noqa: E501 'integer_enum_with_default_value': (IntegerEnumWithDefaultValue,), # noqa: E501 'integer_enum_one_value': (IntegerEnumOneValue,), # noqa: E501 + 'inline_array_of_str_enum': ([StringEnum],), # noqa: E501 + 'array_of_str_enum': (ArrayOfEnums,), # noqa: E501 } @cached_property @@ -131,6 +135,8 @@ class EnumTest(ModelNormal): 'string_enum_with_default_value': 'StringEnumWithDefaultValue', # noqa: E501 'integer_enum_with_default_value': 'IntegerEnumWithDefaultValue', # noqa: E501 'integer_enum_one_value': 'IntegerEnumOneValue', # noqa: E501 + 'inline_array_of_str_enum': 'InlineArrayOfStrEnum', # noqa: E501 + 'array_of_str_enum': 'ArrayOfStrEnum', # noqa: E501 } _composed_schemas = {} @@ -190,6 +196,8 @@ class EnumTest(ModelNormal): string_enum_with_default_value (StringEnumWithDefaultValue): [optional] # noqa: E501 integer_enum_with_default_value (IntegerEnumWithDefaultValue): [optional] # noqa: E501 integer_enum_one_value (IntegerEnumOneValue): [optional] # noqa: E501 + inline_array_of_str_enum ([StringEnum]): [optional] # noqa: E501 + array_of_str_enum (ArrayOfEnums): [optional] # noqa: E501 """ _check_type = kwargs.pop('_check_type', True) diff --git a/samples/openapi3/client/petstore/python/petstore_api/model_utils.py b/samples/openapi3/client/petstore/python/petstore_api/model_utils.py index 7afcb68f615..ae554710670 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/model_utils.py +++ b/samples/openapi3/client/petstore/python/petstore_api/model_utils.py @@ -1493,10 +1493,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], diff --git a/samples/openapi3/client/petstore/python/tests_manual/test_enum_test.py b/samples/openapi3/client/petstore/python/tests_manual/test_enum_test.py new file mode 100644 index 00000000000..3f56fd960d3 --- /dev/null +++ b/samples/openapi3/client/petstore/python/tests_manual/test_enum_test.py @@ -0,0 +1,46 @@ +# coding: utf-8 + +""" + OpenAPI Petstore + + This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ # noqa: E501 + + The version of the OpenAPI document: 1.0.0 + Generated by: https://openapi-generator.tech +""" + + +import sys +import unittest + +import petstore_api +from petstore_api.model.enum_test import EnumTest +from petstore_api.model.string_enum import StringEnum +from petstore_api.model.array_of_enums import ArrayOfEnums + + +class TestEnumTest(unittest.TestCase): + """EnumTest unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testEnumTest(self): + """Test EnumTest""" + # inline array of enums + model = EnumTest( + enum_string_required='lower', + inline_array_of_str_enum=[StringEnum('approved')] + ) + # refed array of enums + model = EnumTest( + enum_string_required='lower', + array_of_str_enum=ArrayOfEnums([StringEnum('approved')]) + ) + + +if __name__ == '__main__': + unittest.main() 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 6efc3c4bc0e..52e39fb2fbc 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 @@ -119,6 +119,52 @@ class TestFakeApi(unittest.TestCase): """ pass + def test_enum_test(self): + """Test case for enum_test + + Object contains enum properties and array properties containing enums + """ + from petstore_api.model.enum_test import EnumTest + from petstore_api.model.string_enum import StringEnum + from petstore_api.model.array_of_enums import ArrayOfEnums + + endpoint = self.api.enum_test + assert endpoint.openapi_types['enum_test'] == (EnumTest,) + assert endpoint.settings['response_type'] == (EnumTest,) + + # serialization + deserialization works w/ inline array + with patch.object(RESTClientObject, 'request') as mock_method: + body = EnumTest( + enum_string_required='lower', + inline_array_of_str_enum=[StringEnum('approved')] + ) + json_value = {'enum_string_required': 'lower', 'InlineArrayOfStrEnum': ['approved']} + mock_method.return_value = self.mock_response(json_value) + + response = endpoint(enum_test=body) + self.assert_request_called_with( + mock_method, 'http://petstore.swagger.io:80/v2/fake/refs/enum-test', json_value) + + assert isinstance(response, EnumTest) + assert response == body + + # serialization + deserialization works w/ refed array + with patch.object(RESTClientObject, 'request') as mock_method: + body = EnumTest( + enum_string_required='lower', + array_of_str_enum=ArrayOfEnums([StringEnum('approved')]) + ) + json_value = {'enum_string_required': 'lower', 'ArrayOfStrEnum': ['approved']} + mock_method.return_value = self.mock_response(json_value) + + response = endpoint(enum_test=body) + self.assert_request_called_with( + mock_method, 'http://petstore.swagger.io:80/v2/fake/refs/enum-test', json_value) + + assert isinstance(response, EnumTest) + assert response == body + + def test_array_of_enums(self): """Test case for array_of_enums