Skip to content

Commit b7a9df6

Browse files
committed
add normalizer option
1 parent bc555f5 commit b7a9df6

11 files changed

Lines changed: 399 additions & 20 deletions

File tree

bin/configs/python-lazyImports.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ nameMappings:
1414
modelNameMappings:
1515
# The OpenAPI spec ApiResponse conflicts with the internal ApiResponse
1616
ApiResponse: ModelApiResponse
17+
openapiNormalizer:
18+
SIMPLIFY_ONEOF_ANYOF_ENUM: false

samples/openapi3/client/petstore/python-lazyImports/.openapi-generator/FILES

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,4 @@ setup.cfg
260260
setup.py
261261
test-requirements.txt
262262
test/__init__.py
263-
test/test_data_output_format.py
264-
test/test_enum_ref_with_default_value.py
265263
tox.ini
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# DataOutputFormat
2+
3+
4+
## Enum
5+
6+
* `JSON` (value: `'JSON'`)
7+
8+
* `CSV` (value: `'CSV'`)
9+
10+
* `XML` (value: `'XML'`)
11+
12+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
13+
14+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# EnumRefWithDefaultValue
2+
3+
4+
## Properties
5+
6+
Name | Type | Description | Notes
7+
------------ | ------------- | ------------- | -------------
8+
**report_format** | [**DataOutputFormat**](DataOutputFormat.md) | | [optional] [default to DataOutputFormat.JSON]
9+
10+
## Example
11+
12+
```python
13+
from petstore_api.models.enum_ref_with_default_value import EnumRefWithDefaultValue
14+
15+
# TODO update the JSON string below
16+
json = "{}"
17+
# create an instance of EnumRefWithDefaultValue from a JSON string
18+
enum_ref_with_default_value_instance = EnumRefWithDefaultValue.from_json(json)
19+
# print the JSON string representation of the object
20+
print(EnumRefWithDefaultValue.to_json())
21+
22+
# convert the object into a dict
23+
enum_ref_with_default_value_dict = enum_ref_with_default_value_instance.to_dict()
24+
# create an instance of EnumRefWithDefaultValue from a dict
25+
enum_ref_with_default_value_from_dict = EnumRefWithDefaultValue.from_dict(enum_ref_with_default_value_dict)
26+
```
27+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
28+
29+

samples/openapi3/client/petstore/python-lazyImports/docs/OneOfEnumString.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,28 @@
22

33
oneOf enum strings
44

5-
## Enum
5+
## Properties
66

7-
* `A` (value: `'a'`)
7+
Name | Type | Description | Notes
8+
------------ | ------------- | ------------- | -------------
89

9-
* `B` (value: `'b'`)
10+
## Example
1011

11-
* `C` (value: `'c'`)
12+
```python
13+
from petstore_api.models.one_of_enum_string import OneOfEnumString
1214

13-
* `D` (value: `'d'`)
15+
# TODO update the JSON string below
16+
json = "{}"
17+
# create an instance of OneOfEnumString from a JSON string
18+
one_of_enum_string_instance = OneOfEnumString.from_json(json)
19+
# print the JSON string representation of the object
20+
print(OneOfEnumString.to_json())
1421

22+
# convert the object into a dict
23+
one_of_enum_string_dict = one_of_enum_string_instance.to_dict()
24+
# create an instance of OneOfEnumString from a dict
25+
one_of_enum_string_from_dict = OneOfEnumString.from_dict(one_of_enum_string_dict)
26+
```
1527
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
1628

1729

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# coding: utf-8
2+
3+
"""
4+
OpenAPI Petstore
5+
6+
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
7+
8+
The version of the OpenAPI document: 1.0.0
9+
Generated by OpenAPI Generator (https://openapi-generator.tech)
10+
11+
Do not edit the class manually.
12+
""" # noqa: E501
13+
14+
15+
from __future__ import annotations
16+
import json
17+
from enum import Enum
18+
from typing_extensions import Self
19+
20+
21+
class DataOutputFormat(str, Enum):
22+
"""
23+
DataOutputFormat
24+
"""
25+
26+
"""
27+
allowed enum values
28+
"""
29+
JSON = 'JSON'
30+
CSV = 'CSV'
31+
XML = 'XML'
32+
33+
@classmethod
34+
def from_json(cls, json_str: str) -> Self:
35+
"""Create an instance of DataOutputFormat from a JSON string"""
36+
return cls(json.loads(json_str))
37+
38+
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# coding: utf-8
2+
3+
"""
4+
OpenAPI Petstore
5+
6+
This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
7+
8+
The version of the OpenAPI document: 1.0.0
9+
Generated by OpenAPI Generator (https://openapi-generator.tech)
10+
11+
Do not edit the class manually.
12+
""" # noqa: E501
13+
14+
15+
from __future__ import annotations
16+
import pprint
17+
import re # noqa: F401
18+
import json
19+
20+
from pydantic import BaseModel, ConfigDict
21+
from typing import Any, ClassVar, Dict, List, Optional
22+
from petstore_api.models.data_output_format import DataOutputFormat
23+
from typing import Optional, Set
24+
from typing_extensions import Self
25+
26+
class EnumRefWithDefaultValue(BaseModel):
27+
"""
28+
EnumRefWithDefaultValue
29+
""" # noqa: E501
30+
report_format: Optional[DataOutputFormat] = DataOutputFormat.JSON
31+
additional_properties: Dict[str, Any] = {}
32+
__properties: ClassVar[List[str]] = ["report_format"]
33+
34+
model_config = ConfigDict(
35+
populate_by_name=True,
36+
validate_assignment=True,
37+
protected_namespaces=(),
38+
)
39+
40+
41+
def to_str(self) -> str:
42+
"""Returns the string representation of the model using alias"""
43+
return pprint.pformat(self.model_dump(by_alias=True))
44+
45+
def to_json(self) -> str:
46+
"""Returns the JSON representation of the model using alias"""
47+
# TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
48+
return json.dumps(self.to_dict())
49+
50+
@classmethod
51+
def from_json(cls, json_str: str) -> Optional[Self]:
52+
"""Create an instance of EnumRefWithDefaultValue from a JSON string"""
53+
return cls.from_dict(json.loads(json_str))
54+
55+
def to_dict(self) -> Dict[str, Any]:
56+
"""Return the dictionary representation of the model using alias.
57+
58+
This has the following differences from calling pydantic's
59+
`self.model_dump(by_alias=True)`:
60+
61+
* `None` is only added to the output dict for nullable fields that
62+
were set at model initialization. Other fields with value `None`
63+
are ignored.
64+
* Fields in `self.additional_properties` are added to the output dict.
65+
"""
66+
excluded_fields: Set[str] = set([
67+
"additional_properties",
68+
])
69+
70+
_dict = self.model_dump(
71+
by_alias=True,
72+
exclude=excluded_fields,
73+
exclude_none=True,
74+
)
75+
# puts key-value pairs in additional_properties in the top level
76+
if self.additional_properties is not None:
77+
for _key, _value in self.additional_properties.items():
78+
_dict[_key] = _value
79+
80+
return _dict
81+
82+
@classmethod
83+
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
84+
"""Create an instance of EnumRefWithDefaultValue from a dict"""
85+
if obj is None:
86+
return None
87+
88+
if not isinstance(obj, dict):
89+
return cls.model_validate(obj)
90+
91+
_obj = cls.model_validate({
92+
"report_format": obj.get("report_format") if obj.get("report_format") is not None else DataOutputFormat.JSON
93+
})
94+
# store additional fields in additional_properties
95+
for _key in obj.keys():
96+
if _key not in cls.__properties:
97+
_obj.additional_properties[_key] = obj.get(_key)
98+
99+
return _obj
100+
101+

samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/one_of_enum_string.py

Lines changed: 110 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,26 +14,124 @@
1414

1515
from __future__ import annotations
1616
import json
17-
from enum import Enum
18-
from typing_extensions import Self
17+
import pprint
18+
from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator
19+
from typing import Any, List, Optional
20+
from petstore_api.models.enum_string1 import EnumString1
21+
from petstore_api.models.enum_string2 import EnumString2
22+
from pydantic import StrictStr, Field
23+
from typing import Union, List, Set, Optional, Dict
24+
from typing_extensions import Literal, Self
1925

26+
ONEOFENUMSTRING_ONE_OF_SCHEMAS = ["EnumString1", "EnumString2"]
2027

21-
class OneOfEnumString(str, Enum):
28+
class OneOfEnumString(BaseModel):
2229
"""
2330
oneOf enum strings
2431
"""
32+
# data type: EnumString1
33+
oneof_schema_1_validator: Optional[EnumString1] = None
34+
# data type: EnumString2
35+
oneof_schema_2_validator: Optional[EnumString2] = None
36+
actual_instance: Optional[Union[EnumString1, EnumString2]] = None
37+
one_of_schemas: Set[str] = { "EnumString1", "EnumString2" }
2538

26-
"""
27-
allowed enum values
28-
"""
29-
A = 'a'
30-
B = 'b'
31-
C = 'c'
32-
D = 'd'
39+
model_config = ConfigDict(
40+
validate_assignment=True,
41+
protected_namespaces=(),
42+
)
43+
44+
45+
def __init__(self, *args, **kwargs) -> None:
46+
if args:
47+
if len(args) > 1:
48+
raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
49+
if kwargs:
50+
raise ValueError("If a position argument is used, keyword arguments cannot be used.")
51+
super().__init__(actual_instance=args[0])
52+
else:
53+
super().__init__(**kwargs)
54+
55+
@field_validator('actual_instance')
56+
def actual_instance_must_validate_oneof(cls, v):
57+
instance = OneOfEnumString.model_construct()
58+
error_messages = []
59+
match = 0
60+
# validate data type: EnumString1
61+
if not isinstance(v, EnumString1):
62+
error_messages.append(f"Error! Input type `{type(v)}` is not `EnumString1`")
63+
else:
64+
match += 1
65+
# validate data type: EnumString2
66+
if not isinstance(v, EnumString2):
67+
error_messages.append(f"Error! Input type `{type(v)}` is not `EnumString2`")
68+
else:
69+
match += 1
70+
if match > 1:
71+
# more than 1 match
72+
raise ValueError("Multiple matches found when setting `actual_instance` in OneOfEnumString with oneOf schemas: EnumString1, EnumString2. Details: " + ", ".join(error_messages))
73+
elif match == 0:
74+
# no match
75+
raise ValueError("No match found when setting `actual_instance` in OneOfEnumString with oneOf schemas: EnumString1, EnumString2. Details: " + ", ".join(error_messages))
76+
else:
77+
return v
78+
79+
@classmethod
80+
def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
81+
return cls.from_json(json.dumps(obj))
3382

3483
@classmethod
3584
def from_json(cls, json_str: str) -> Self:
36-
"""Create an instance of OneOfEnumString from a JSON string"""
37-
return cls(json.loads(json_str))
85+
"""Returns the object represented by the json string"""
86+
instance = cls.model_construct()
87+
error_messages = []
88+
match = 0
89+
90+
# deserialize data into EnumString1
91+
try:
92+
instance.actual_instance = EnumString1.from_json(json_str)
93+
match += 1
94+
except (ValidationError, ValueError) as e:
95+
error_messages.append(str(e))
96+
# deserialize data into EnumString2
97+
try:
98+
instance.actual_instance = EnumString2.from_json(json_str)
99+
match += 1
100+
except (ValidationError, ValueError) as e:
101+
error_messages.append(str(e))
102+
103+
if match > 1:
104+
# more than 1 match
105+
raise ValueError("Multiple matches found when deserializing the JSON string into OneOfEnumString with oneOf schemas: EnumString1, EnumString2. Details: " + ", ".join(error_messages))
106+
elif match == 0:
107+
# no match
108+
raise ValueError("No match found when deserializing the JSON string into OneOfEnumString with oneOf schemas: EnumString1, EnumString2. Details: " + ", ".join(error_messages))
109+
else:
110+
return instance
111+
112+
def to_json(self) -> str:
113+
"""Returns the JSON representation of the actual instance"""
114+
if self.actual_instance is None:
115+
return "null"
116+
117+
if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json):
118+
return self.actual_instance.to_json()
119+
else:
120+
return json.dumps(self.actual_instance)
121+
122+
def to_dict(self) -> Optional[Union[Dict[str, Any], EnumString1, EnumString2]]:
123+
"""Returns the dict representation of the actual instance"""
124+
if self.actual_instance is None:
125+
return None
126+
127+
if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict):
128+
return self.actual_instance.to_dict()
129+
else:
130+
# primitive type
131+
return self.actual_instance
132+
133+
def to_str(self) -> str:
134+
"""Returns the string representation of the actual instance"""
135+
return pprint.pformat(self.model_dump())
38136

39137

samples/openapi3/client/petstore/python-lazyImports/petstore_api/models/with_nested_one_of.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ def to_dict(self) -> Dict[str, Any]:
7878
# override the default output from pydantic by calling `to_dict()` of nested_pig
7979
if self.nested_pig:
8080
_dict['nested_pig'] = self.nested_pig.to_dict()
81+
# override the default output from pydantic by calling `to_dict()` of nested_oneof_enum_string
82+
if self.nested_oneof_enum_string:
83+
_dict['nested_oneof_enum_string'] = self.nested_oneof_enum_string.to_dict()
8184
# puts key-value pairs in additional_properties in the top level
8285
if self.additional_properties is not None:
8386
for _key, _value in self.additional_properties.items():
@@ -97,7 +100,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
97100
_obj = cls.model_validate({
98101
"size": obj.get("size"),
99102
"nested_pig": Pig.from_dict(obj["nested_pig"]) if obj.get("nested_pig") is not None else None,
100-
"nested_oneof_enum_string": obj.get("nested_oneof_enum_string")
103+
"nested_oneof_enum_string": OneOfEnumString.from_dict(obj["nested_oneof_enum_string"]) if obj.get("nested_oneof_enum_string") is not None else None
101104
})
102105
# store additional fields in additional_properties
103106
for _key in obj.keys():

0 commit comments

Comments
 (0)