[Python] Handle nullable list items (#17594)

* fix nullable elements

* update type info in docs

* update examples
This commit is contained in:
Huan-Cheng Chang 2024-01-13 04:29:22 +01:00 committed by GitHub
parent c6efe8810d
commit 968c6dc418
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 49 additions and 16 deletions

View File

@ -693,7 +693,11 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
if (ModelUtils.isArraySchema(p)) { if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p; ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems(); 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)) { } else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p); Schema inner = ModelUtils.getAdditionalProperties(p);
return getSchemaType(p) + "[str, " + getTypeDeclaration(inner) + "]"; return getSchemaType(p) + "[str, " + getTypeDeclaration(inner) + "]";
@ -1748,10 +1752,21 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
pt.setType("List"); pt.setType("List");
moduleImports.add("typing", "List"); moduleImports.add("typing", "List");
} }
pt.addTypeParam(getType(cp.getItems())); pt.addTypeParam(collectionItemType(cp.getItems()));
return pt; 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) { private PythonType stringType(IJsonSchemaValidationProperties cp) {
if (cp.getHasValidation()) { if (cp.getHasValidation()) {

View File

@ -1923,6 +1923,12 @@ components:
type: string type: string
minItems: 0 minItems: 0
maxItems: 3 maxItems: 3
array_of_nullable_float:
type: array
items:
type: number
format: float
nullable: true
array_array_of_integer: array_array_of_integer:
type: array type: array
items: items:

View File

@ -6,6 +6,7 @@
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**array_of_string** | **List[str]** | | [optional] **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_integer** | **List[List[int]]** | | [optional]
**array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional]

View File

@ -13,8 +13,8 @@ Name | Type | Description | Notes
**date_prop** | **date** | | [optional] **date_prop** | **date** | | [optional]
**datetime_prop** | **datetime** | | [optional] **datetime_prop** | **datetime** | | [optional]
**array_nullable_prop** | **List[object]** | | [optional] **array_nullable_prop** | **List[object]** | | [optional]
**array_and_items_nullable_prop** | **List[object]** | | [optional] **array_and_items_nullable_prop** | **List[Optional[object]]** | | [optional]
**array_items_nullable** | **List[object]** | | [optional] **array_items_nullable** | **List[Optional[object]]** | | [optional]
**object_nullable_prop** | **Dict[str, object]** | | [optional] **object_nullable_prop** | **Dict[str, object]** | | [optional]
**object_and_items_nullable_prop** | **Dict[str, object]** | | [optional] **object_and_items_nullable_prop** | **Dict[str, object]** | | [optional]
**object_items_nullable** | **Dict[str, object]** | | [optional] **object_items_nullable** | **Dict[str, object]** | | [optional]

View File

@ -29,9 +29,10 @@ class ArrayTest(BaseModel):
ArrayTest ArrayTest
""" # noqa: E501 """ # noqa: E501
array_of_string: Optional[Annotated[List[StrictStr], Field(min_length=0, max_length=3)]] = None 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_integer: Optional[List[List[StrictInt]]] = None
array_array_of_model: Optional[List[List[ReadOnlyFirst]]] = 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 = { model_config = {
"populate_by_name": True, "populate_by_name": True,
@ -94,6 +95,7 @@ class ArrayTest(BaseModel):
_obj = cls.model_validate({ _obj = cls.model_validate({
"array_of_string": obj.get("array_of_string"), "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_integer": obj.get("array_array_of_integer"),
"array_array_of_model": [ "array_array_of_model": [
[ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item]

View File

@ -35,8 +35,8 @@ class NullableClass(BaseModel):
date_prop: Optional[date] = None date_prop: Optional[date] = None
datetime_prop: Optional[datetime] = None datetime_prop: Optional[datetime] = None
array_nullable_prop: Optional[List[Dict[str, Any]]] = None array_nullable_prop: Optional[List[Dict[str, Any]]] = None
array_and_items_nullable_prop: Optional[List[Dict[str, Any]]] = None array_and_items_nullable_prop: Optional[List[Optional[Dict[str, Any]]]] = None
array_items_nullable: Optional[List[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_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None
object_and_items_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 object_items_nullable: Optional[Dict[str, Dict[str, Any]]] = None

View File

@ -5,6 +5,7 @@
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**array_of_string** | **List[str]** | | [optional] **array_of_string** | **List[str]** | | [optional]
**array_of_nullable_float** | **List[float]** | | [optional]
**array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional]
**array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional]

View File

@ -27,9 +27,10 @@ class ArrayTest(BaseModel):
ArrayTest ArrayTest
""" """
array_of_string: Optional[conlist(StrictStr, max_items=3, min_items=0)] = None 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_integer: Optional[conlist(conlist(StrictInt))] = None
array_array_of_model: Optional[conlist(conlist(ReadOnlyFirst))] = 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: class Config:
"""Pydantic configuration""" """Pydantic configuration"""
@ -77,6 +78,7 @@ class ArrayTest(BaseModel):
_obj = ArrayTest.parse_obj({ _obj = ArrayTest.parse_obj({
"array_of_string": obj.get("array_of_string"), "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_integer": obj.get("array_array_of_integer"),
"array_array_of_model": [ "array_array_of_model": [
[ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item]

View File

@ -5,6 +5,7 @@
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**array_of_string** | **List[str]** | | [optional] **array_of_string** | **List[str]** | | [optional]
**array_of_nullable_float** | **List[float]** | | [optional]
**array_array_of_integer** | **List[List[int]]** | | [optional] **array_array_of_integer** | **List[List[int]]** | | [optional]
**array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional]

View File

@ -19,7 +19,7 @@ import json
from typing import Any, Dict, List, Optional 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 from petstore_api.models.read_only_first import ReadOnlyFirst
class ArrayTest(BaseModel): class ArrayTest(BaseModel):
@ -27,10 +27,11 @@ class ArrayTest(BaseModel):
ArrayTest ArrayTest
""" """
array_of_string: Optional[conlist(StrictStr, max_items=3, min_items=0)] = None 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_integer: Optional[conlist(conlist(StrictInt))] = None
array_array_of_model: Optional[conlist(conlist(ReadOnlyFirst))] = None array_array_of_model: Optional[conlist(conlist(ReadOnlyFirst))] = None
additional_properties: Dict[str, Any] = {} 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: class Config:
"""Pydantic configuration""" """Pydantic configuration"""
@ -84,6 +85,7 @@ class ArrayTest(BaseModel):
_obj = ArrayTest.parse_obj({ _obj = ArrayTest.parse_obj({
"array_of_string": obj.get("array_of_string"), "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_integer": obj.get("array_array_of_integer"),
"array_array_of_model": [ "array_array_of_model": [
[ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item]

View File

@ -6,6 +6,7 @@
Name | Type | Description | Notes Name | Type | Description | Notes
------------ | ------------- | ------------- | ------------- ------------ | ------------- | ------------- | -------------
**array_of_string** | **List[str]** | | [optional] **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_integer** | **List[List[int]]** | | [optional]
**array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional] **array_array_of_model** | **List[List[ReadOnlyFirst]]** | | [optional]

View File

@ -13,8 +13,8 @@ Name | Type | Description | Notes
**date_prop** | **date** | | [optional] **date_prop** | **date** | | [optional]
**datetime_prop** | **datetime** | | [optional] **datetime_prop** | **datetime** | | [optional]
**array_nullable_prop** | **List[object]** | | [optional] **array_nullable_prop** | **List[object]** | | [optional]
**array_and_items_nullable_prop** | **List[object]** | | [optional] **array_and_items_nullable_prop** | **List[Optional[object]]** | | [optional]
**array_items_nullable** | **List[object]** | | [optional] **array_items_nullable** | **List[Optional[object]]** | | [optional]
**object_nullable_prop** | **Dict[str, object]** | | [optional] **object_nullable_prop** | **Dict[str, object]** | | [optional]
**object_and_items_nullable_prop** | **Dict[str, object]** | | [optional] **object_and_items_nullable_prop** | **Dict[str, object]** | | [optional]
**object_items_nullable** | **Dict[str, object]** | | [optional] **object_items_nullable** | **Dict[str, object]** | | [optional]

View File

@ -17,7 +17,7 @@ import pprint
import re # noqa: F401 import re # noqa: F401
import json 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 import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated from typing_extensions import Annotated
from petstore_api.models.read_only_first import ReadOnlyFirst from petstore_api.models.read_only_first import ReadOnlyFirst
@ -29,10 +29,11 @@ class ArrayTest(BaseModel):
ArrayTest ArrayTest
""" # noqa: E501 """ # noqa: E501
array_of_string: Optional[Annotated[List[StrictStr], Field(min_length=0, max_length=3)]] = None 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_integer: Optional[List[List[StrictInt]]] = None
array_array_of_model: Optional[List[List[ReadOnlyFirst]]] = None array_array_of_model: Optional[List[List[ReadOnlyFirst]]] = None
additional_properties: Dict[str, Any] = {} 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 = { model_config = {
"populate_by_name": True, "populate_by_name": True,
@ -102,6 +103,7 @@ class ArrayTest(BaseModel):
_obj = cls.model_validate({ _obj = cls.model_validate({
"array_of_string": obj.get("array_of_string"), "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_integer": obj.get("array_array_of_integer"),
"array_array_of_model": [ "array_array_of_model": [
[ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item] [ReadOnlyFirst.from_dict(_inner_item) for _inner_item in _item]

View File

@ -35,8 +35,8 @@ class NullableClass(BaseModel):
date_prop: Optional[date] = None date_prop: Optional[date] = None
datetime_prop: Optional[datetime] = None datetime_prop: Optional[datetime] = None
array_nullable_prop: Optional[List[Dict[str, Any]]] = None array_nullable_prop: Optional[List[Dict[str, Any]]] = None
array_and_items_nullable_prop: Optional[List[Dict[str, Any]]] = None array_and_items_nullable_prop: Optional[List[Optional[Dict[str, Any]]]] = None
array_items_nullable: Optional[List[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_nullable_prop: Optional[Dict[str, Dict[str, Any]]] = None
object_and_items_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 object_items_nullable: Optional[Dict[str, Dict[str, Any]]] = None