[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)) {
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()) {

View File

@ -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:

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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]

View File

@ -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