diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java index 63dcef5d867..e6c9e36846f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java @@ -693,7 +693,11 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co if (ModelUtils.isArraySchema(p)) { ArraySchema ap = (ArraySchema) p; Schema inner = ap.getItems(); - return getSchemaType(p) + "[" + getTypeDeclaration(inner) + "]"; + String innerDeclaration = getTypeDeclaration(inner); + if (inner.getNullable() != null && inner.getNullable()) { + innerDeclaration = "Optional[" + innerDeclaration + "]"; + } + return getSchemaType(p) + "[" + innerDeclaration + "]"; } else if (ModelUtils.isMapSchema(p)) { Schema inner = ModelUtils.getAdditionalProperties(p); return getSchemaType(p) + "[str, " + getTypeDeclaration(inner) + "]"; @@ -1748,10 +1752,21 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co pt.setType("List"); moduleImports.add("typing", "List"); } - pt.addTypeParam(getType(cp.getItems())); + pt.addTypeParam(collectionItemType(cp.getItems())); return pt; } + private PythonType collectionItemType(CodegenProperty itemCp) { + PythonType itemPt = getType(itemCp); + if (itemCp != null && itemCp.isNullable) { + moduleImports.add("typing", "Optional"); + PythonType opt = new PythonType("Optional"); + opt.addTypeParam(itemPt); + itemPt = opt; + } + return itemPt; + } + private PythonType stringType(IJsonSchemaValidationProperties cp) { if (cp.getHasValidation()) { diff --git a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml index c9eee7da1db..0aa6c1f795b 100644 --- a/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml @@ -1923,6 +1923,12 @@ components: type: string minItems: 0 maxItems: 3 + array_of_nullable_float: + type: array + items: + type: number + format: float + nullable: true array_array_of_integer: type: array items: diff --git a/samples/openapi3/client/petstore/python-aiohttp/docs/ArrayTest.md b/samples/openapi3/client/petstore/python-aiohttp/docs/ArrayTest.md index 97e52ef5d6b..7b964521751 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/docs/ArrayTest.md +++ b/samples/openapi3/client/petstore/python-aiohttp/docs/ArrayTest.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **array_of_string** | **List[str]** | | [optional] +**array_of_nullable_float** | **List[Optional[float]]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] diff --git a/samples/openapi3/client/petstore/python-aiohttp/docs/NullableClass.md b/samples/openapi3/client/petstore/python-aiohttp/docs/NullableClass.md index 93fa80af2ea..9dc167e54e9 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/docs/NullableClass.md +++ b/samples/openapi3/client/petstore/python-aiohttp/docs/NullableClass.md @@ -13,8 +13,8 @@ Name | Type | Description | Notes **date_prop** | **date** | | [optional] **datetime_prop** | **datetime** | | [optional] **array_nullable_prop** | **List[object]** | | [optional] -**array_and_items_nullable_prop** | **List[object]** | | [optional] -**array_items_nullable** | **List[object]** | | [optional] +**array_and_items_nullable_prop** | **List[Optional[object]]** | | [optional] +**array_items_nullable** | **List[Optional[object]]** | | [optional] **object_nullable_prop** | **Dict[str, object]** | | [optional] **object_and_items_nullable_prop** | **Dict[str, object]** | | [optional] **object_items_nullable** | **Dict[str, object]** | | [optional] diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/array_test.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/array_test.py index c1c0bd95404..c5a44501eee 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/array_test.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/array_test.py @@ -29,9 +29,10 @@ class ArrayTest(BaseModel): ArrayTest """ # noqa: E501 array_of_string: Optional[Annotated[List[StrictStr], Field(min_length=0, max_length=3)]] = None + array_of_nullable_float: Optional[List[Optional[float]]] = None array_array_of_integer: Optional[List[List[StrictInt]]] = None array_array_of_model: Optional[List[List[ReadOnlyFirst]]] = None - __properties: ClassVar[List[str]] = ["array_of_string", "array_array_of_integer", "array_array_of_model"] + __properties: ClassVar[List[str]] = ["array_of_string", "array_of_nullable_float", "array_array_of_integer", "array_array_of_model"] model_config = { "populate_by_name": True, @@ -94,6 +95,7 @@ class ArrayTest(BaseModel): _obj = cls.model_validate({ "array_of_string": obj.get("array_of_string"), + "array_of_nullable_float": obj.get("array_of_nullable_float"), "array_array_of_integer": obj.get("array_array_of_integer"), "array_array_of_model": [ [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] diff --git a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/nullable_class.py b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/nullable_class.py index 101f1a96b6a..41e660fc73e 100644 --- a/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/nullable_class.py +++ b/samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/nullable_class.py @@ -35,8 +35,8 @@ class NullableClass(BaseModel): date_prop: Optional[date] = None datetime_prop: Optional[datetime] = None array_nullable_prop: Optional[List[Dict[str, Any]]] = None - array_and_items_nullable_prop: Optional[List[Dict[str, Any]]] = None - array_items_nullable: Optional[List[Dict[str, Any]]] = None + array_and_items_nullable_prop: Optional[List[Optional[Dict[str, Any]]]] = None + array_items_nullable: Optional[List[Optional[Dict[str, Any]]]] = None object_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None object_and_items_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None object_items_nullable: Optional[Dict[str, Dict[str, Any]]] = None diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/ArrayTest.md b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/ArrayTest.md index 0a40fb36d26..d99d1a3c4ae 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/ArrayTest.md +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/docs/ArrayTest.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **array_of_string** | **List[str]** | | [optional] +**array_of_nullable_float** | **List[float]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] diff --git a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/array_test.py b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/array_test.py index 8ec1a1ad67e..206b34dc402 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/array_test.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/array_test.py @@ -27,9 +27,10 @@ class ArrayTest(BaseModel): ArrayTest """ array_of_string: Optional[conlist(StrictStr, max_items=3, min_items=0)] = None + array_of_nullable_float: Optional[conlist(float)] = None array_array_of_integer: Optional[conlist(conlist(StrictInt))] = None array_array_of_model: Optional[conlist(conlist(ReadOnlyFirst))] = None - __properties = ["array_of_string", "array_array_of_integer", "array_array_of_model"] + __properties = ["array_of_string", "array_of_nullable_float", "array_array_of_integer", "array_array_of_model"] class Config: """Pydantic configuration""" @@ -77,6 +78,7 @@ class ArrayTest(BaseModel): _obj = ArrayTest.parse_obj({ "array_of_string": obj.get("array_of_string"), + "array_of_nullable_float": obj.get("array_of_nullable_float"), "array_array_of_integer": obj.get("array_array_of_integer"), "array_array_of_model": [ [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/docs/ArrayTest.md b/samples/openapi3/client/petstore/python-pydantic-v1/docs/ArrayTest.md index 0a40fb36d26..d99d1a3c4ae 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/docs/ArrayTest.md +++ b/samples/openapi3/client/petstore/python-pydantic-v1/docs/ArrayTest.md @@ -5,6 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **array_of_string** | **List[str]** | | [optional] +**array_of_nullable_float** | **List[float]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] diff --git a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/array_test.py b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/array_test.py index 5e266148eb4..399c66702c5 100644 --- a/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/array_test.py +++ b/samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/array_test.py @@ -19,7 +19,7 @@ import json from typing import Any, Dict, List, Optional -from pydantic import BaseModel, StrictInt, StrictStr, conlist +from pydantic import BaseModel, StrictFloat, StrictInt, StrictStr, conlist from petstore_api.models.read_only_first import ReadOnlyFirst class ArrayTest(BaseModel): @@ -27,10 +27,11 @@ class ArrayTest(BaseModel): ArrayTest """ array_of_string: Optional[conlist(StrictStr, max_items=3, min_items=0)] = None + array_of_nullable_float: Optional[conlist(StrictFloat)] = None array_array_of_integer: Optional[conlist(conlist(StrictInt))] = None array_array_of_model: Optional[conlist(conlist(ReadOnlyFirst))] = None additional_properties: Dict[str, Any] = {} - __properties = ["array_of_string", "array_array_of_integer", "array_array_of_model"] + __properties = ["array_of_string", "array_of_nullable_float", "array_array_of_integer", "array_array_of_model"] class Config: """Pydantic configuration""" @@ -84,6 +85,7 @@ class ArrayTest(BaseModel): _obj = ArrayTest.parse_obj({ "array_of_string": obj.get("array_of_string"), + "array_of_nullable_float": obj.get("array_of_nullable_float"), "array_array_of_integer": obj.get("array_array_of_integer"), "array_array_of_model": [ [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] diff --git a/samples/openapi3/client/petstore/python/docs/ArrayTest.md b/samples/openapi3/client/petstore/python/docs/ArrayTest.md index 97e52ef5d6b..7b964521751 100644 --- a/samples/openapi3/client/petstore/python/docs/ArrayTest.md +++ b/samples/openapi3/client/petstore/python/docs/ArrayTest.md @@ -6,6 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **array_of_string** | **List[str]** | | [optional] +**array_of_nullable_float** | **List[Optional[float]]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] diff --git a/samples/openapi3/client/petstore/python/docs/NullableClass.md b/samples/openapi3/client/petstore/python/docs/NullableClass.md index 93fa80af2ea..9dc167e54e9 100644 --- a/samples/openapi3/client/petstore/python/docs/NullableClass.md +++ b/samples/openapi3/client/petstore/python/docs/NullableClass.md @@ -13,8 +13,8 @@ Name | Type | Description | Notes **date_prop** | **date** | | [optional] **datetime_prop** | **datetime** | | [optional] **array_nullable_prop** | **List[object]** | | [optional] -**array_and_items_nullable_prop** | **List[object]** | | [optional] -**array_items_nullable** | **List[object]** | | [optional] +**array_and_items_nullable_prop** | **List[Optional[object]]** | | [optional] +**array_items_nullable** | **List[Optional[object]]** | | [optional] **object_nullable_prop** | **Dict[str, object]** | | [optional] **object_and_items_nullable_prop** | **Dict[str, object]** | | [optional] **object_items_nullable** | **Dict[str, object]** | | [optional] diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/array_test.py b/samples/openapi3/client/petstore/python/petstore_api/models/array_test.py index 01639b8261a..2986612fad5 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/array_test.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/array_test.py @@ -17,7 +17,7 @@ import pprint import re # noqa: F401 import json -from pydantic import BaseModel, Field, StrictInt, StrictStr +from pydantic import BaseModel, Field, StrictFloat, StrictInt, StrictStr from typing import Any, ClassVar, Dict, List, Optional from typing_extensions import Annotated from petstore_api.models.read_only_first import ReadOnlyFirst @@ -29,10 +29,11 @@ class ArrayTest(BaseModel): ArrayTest """ # noqa: E501 array_of_string: Optional[Annotated[List[StrictStr], Field(min_length=0, max_length=3)]] = None + array_of_nullable_float: Optional[List[Optional[StrictFloat]]] = None array_array_of_integer: Optional[List[List[StrictInt]]] = None array_array_of_model: Optional[List[List[ReadOnlyFirst]]] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["array_of_string", "array_array_of_integer", "array_array_of_model"] + __properties: ClassVar[List[str]] = ["array_of_string", "array_of_nullable_float", "array_array_of_integer", "array_array_of_model"] model_config = { "populate_by_name": True, @@ -102,6 +103,7 @@ class ArrayTest(BaseModel): _obj = cls.model_validate({ "array_of_string": obj.get("array_of_string"), + "array_of_nullable_float": obj.get("array_of_nullable_float"), "array_array_of_integer": obj.get("array_array_of_integer"), "array_array_of_model": [ [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] diff --git a/samples/openapi3/client/petstore/python/petstore_api/models/nullable_class.py b/samples/openapi3/client/petstore/python/petstore_api/models/nullable_class.py index 903fa5d037b..5ad5c19a06c 100644 --- a/samples/openapi3/client/petstore/python/petstore_api/models/nullable_class.py +++ b/samples/openapi3/client/petstore/python/petstore_api/models/nullable_class.py @@ -35,8 +35,8 @@ class NullableClass(BaseModel): date_prop: Optional[date] = None datetime_prop: Optional[datetime] = None array_nullable_prop: Optional[List[Dict[str, Any]]] = None - array_and_items_nullable_prop: Optional[List[Dict[str, Any]]] = None - array_items_nullable: Optional[List[Dict[str, Any]]] = None + array_and_items_nullable_prop: Optional[List[Optional[Dict[str, Any]]]] = None + array_items_nullable: Optional[List[Optional[Dict[str, Any]]]] = None object_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None object_and_items_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None object_items_nullable: Optional[Dict[str, Dict[str, Any]]] = None