fix: Annotate free-form object as dict in Python (#17082)

This commit is contained in:
Robert Schweizer
2023-11-18 03:46:01 +01:00
committed by GitHub
parent 0098d56a6a
commit 5e7f2f274c
6 changed files with 34 additions and 31 deletions

View File

@@ -2024,16 +2024,6 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
return new PythonType(cp.getDataType());
}
private PythonType freeFormType(IJsonSchemaValidationProperties cp) {
typingImports.add("Dict");
typingImports.add("Any");
typingImports.add("Union");
PythonType pt = new PythonType("Union");
pt.addTypeParam(new PythonType("str"));
pt.addTypeParam(new PythonType("Any"));
return pt;
}
private PythonType modelType(IJsonSchemaValidationProperties cp) {
// add model prefix
hasModelsToImport = true;
@@ -2056,7 +2046,7 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
if (cp.getIsArray()) {
return arrayType(cp);
} else if (cp.getIsMap()) {
} else if (cp.getIsMap() || cp.getIsFreeFormObject()) {
return mapType(cp);
} else if (cp.getIsString()) {
return stringType(cp);
@@ -2076,8 +2066,6 @@ public abstract class AbstractPythonCodegen extends DefaultCodegen implements Co
return dateType(cp);
} else if (cp.getIsUuid()) {
return uuidType(cp);
} else if (cp.getIsFreeFormObject()) { // type: object
return freeFormType(cp);
}
return null;

View File

@@ -18,7 +18,7 @@ import re # noqa: F401
import json
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing import Any, ClassVar, Dict, List, Optional
from pydantic import BaseModel
from pydantic import Field
try:
@@ -30,7 +30,7 @@ class InnerDictWithProperty(BaseModel):
"""
InnerDictWithProperty
""" # noqa: E501
a_property: Optional[Union[str, Any]] = Field(default=None, alias="aProperty")
a_property: Optional[Dict[str, Any]] = Field(default=None, alias="aProperty")
__properties: ClassVar[List[str]] = ["aProperty"]
model_config = {

View File

@@ -18,7 +18,7 @@ import re # noqa: F401
import json
from datetime import date, datetime
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing import Any, ClassVar, Dict, List, Optional
from pydantic import BaseModel, StrictBool, StrictInt, StrictStr
try:
from typing import Self
@@ -36,12 +36,12 @@ class NullableClass(BaseModel):
string_prop: Optional[StrictStr] = None
date_prop: Optional[date] = None
datetime_prop: Optional[datetime] = None
array_nullable_prop: Optional[List[Union[str, Any]]] = None
array_and_items_nullable_prop: Optional[List[Union[str, Any]]] = None
array_items_nullable: Optional[List[Union[str, Any]]] = None
object_nullable_prop: Optional[Dict[str, Union[str, Any]]] = None
object_and_items_nullable_prop: Optional[Dict[str, Union[str, Any]]] = None
object_items_nullable: Optional[Dict[str, Union[str, Any]]] = 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
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
additional_properties: Dict[str, Any] = {}
__properties: ClassVar[List[str]] = ["required_integer_prop", "integer_prop", "number_prop", "boolean_prop", "string_prop", "date_prop", "datetime_prop", "array_nullable_prop", "array_and_items_nullable_prop", "array_items_nullable", "object_nullable_prop", "object_and_items_nullable_prop", "object_items_nullable"]

View File

@@ -18,7 +18,7 @@ import re # noqa: F401
import json
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing import Any, ClassVar, Dict, List, Optional
from pydantic import BaseModel
from pydantic import Field
try:
@@ -30,7 +30,7 @@ class InnerDictWithProperty(BaseModel):
"""
InnerDictWithProperty
""" # noqa: E501
a_property: Optional[Union[str, Any]] = Field(default=None, alias="aProperty")
a_property: Optional[Dict[str, Any]] = Field(default=None, alias="aProperty")
additional_properties: Dict[str, Any] = {}
__properties: ClassVar[List[str]] = ["aProperty"]

View File

@@ -18,7 +18,7 @@ import re # noqa: F401
import json
from datetime import date, datetime
from typing import Any, ClassVar, Dict, List, Optional, Union
from typing import Any, ClassVar, Dict, List, Optional
from pydantic import BaseModel, StrictBool, StrictFloat, StrictInt, StrictStr
try:
from typing import Self
@@ -36,12 +36,12 @@ class NullableClass(BaseModel):
string_prop: Optional[StrictStr] = None
date_prop: Optional[date] = None
datetime_prop: Optional[datetime] = None
array_nullable_prop: Optional[List[Union[str, Any]]] = None
array_and_items_nullable_prop: Optional[List[Union[str, Any]]] = None
array_items_nullable: Optional[List[Union[str, Any]]] = None
object_nullable_prop: Optional[Dict[str, Union[str, Any]]] = None
object_and_items_nullable_prop: Optional[Dict[str, Union[str, Any]]] = None
object_items_nullable: Optional[Dict[str, Union[str, Any]]] = 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
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
additional_properties: Dict[str, Any] = {}
__properties: ClassVar[List[str]] = ["required_integer_prop", "integer_prop", "number_prop", "boolean_prop", "string_prop", "date_prop", "datetime_prop", "array_nullable_prop", "array_and_items_nullable_prop", "array_items_nullable", "object_nullable_prop", "object_and_items_nullable_prop", "object_items_nullable"]

View File

@@ -8,8 +8,10 @@ import time
import unittest
from pydantic import ValidationError
import pytest
import petstore_api
from petstore_api import InnerDictWithProperty
class ModelTests(unittest.TestCase):
@@ -508,6 +510,19 @@ class ModelTests(unittest.TestCase):
self.assertFalse(b is None)
self.assertEqual(b.optional_dict["key"].a_property["a"], "b")
def test_freeform_object(self):
# Allows dict[str, Any] and is nullable
a = InnerDictWithProperty.from_dict({"aProperty": {"a": 12}})
a = InnerDictWithProperty.from_dict({"aProperty": None})
# Allows no other values
with pytest.raises(ValidationError):
a = InnerDictWithProperty.from_dict({"aProperty": {123: 45}})
with pytest.raises(ValidationError):
a = InnerDictWithProperty.from_dict({"aProperty": "abc"})
with pytest.raises(ValidationError):
a = InnerDictWithProperty.from_dict({"aProperty": 12})
def test_object_with_dict_of_dict_of_object(self):
# for https://github.com/OpenAPITools/openapi-generator/issues/15135
d = {"optionalDict": {"a": {"b": {"aProperty": "value"}}}}