Skip to content

Commit 72de5bc

Browse files
authored
[Python] Fix the post processing of string enums (#20976)
* fix/ x-enum-varnames in python * make x-enum-varnames examples more clear * make x enum varname usage more explicit * fix tests * trigger tests * trigger tests once again... * fix more tests
1 parent d4d1420 commit 72de5bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+836
-167
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractPythonCodegen.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -958,8 +958,10 @@ private ModelsMap postProcessModelsMap(ModelsMap objs) {
958958
for (Map<String, Object> enumVars : (List<Map<String, Object>>) model.getAllowableValues().get("enumVars")) {
959959
if ((Boolean) enumVars.get("isString")) {
960960
model.vendorExtensions.putIfAbsent("x-py-enum-type", "str");
961-
// update `name`, e.g.
962-
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "str"));
961+
// Do not overwrite the variable name if already set through x-enum-varnames
962+
if (model.vendorExtensions.get("x-enum-varnames") == null) {
963+
enumVars.put("name", toEnumVariableName((String) enumVars.get("value"), "str"));
964+
}
963965
} else {
964966
model.vendorExtensions.putIfAbsent("x-py-enum-type", "int");
965967
// Do not overwrite the variable name if already set through x-enum-varnames

modules/openapi-generator/src/test/resources/3_0/python/petstore-with-fake-endpoints-models-for-testing.yaml

+33-29
Original file line numberDiff line numberDiff line change
@@ -2102,35 +2102,6 @@ components:
21022102
enum:
21032103
- 1.1
21042104
- -1.2
2105-
enum_number_vendor_ext:
2106-
type: integer
2107-
format: int32
2108-
enum:
2109-
- 42
2110-
- 18
2111-
- 56
2112-
x-enum-descriptions:
2113-
- 'Description for 42'
2114-
- 'Description for 18'
2115-
- 'Description for 56'
2116-
x-enum-varnames:
2117-
- FortyTwo
2118-
- Eigtheen
2119-
- FiftySix
2120-
enum_string_vendor_ext:
2121-
type: string
2122-
enum:
2123-
- FOO
2124-
- Bar
2125-
- baz
2126-
x-enum-descriptions:
2127-
- 'Description for FOO'
2128-
- 'Description for Bar'
2129-
- 'Description for baz'
2130-
x-enum-varnames:
2131-
- FOOVar
2132-
- BarVar
2133-
- bazVar
21342105
enum_string_single_member:
21352106
type: string
21362107
enum:
@@ -2148,6 +2119,10 @@ components:
21482119
$ref: '#/components/schemas/OuterEnumDefaultValue'
21492120
outerEnumIntegerDefaultValue:
21502121
$ref: '#/components/schemas/OuterEnumIntegerDefaultValue'
2122+
enumNumberVendorExt:
2123+
$ref: '#/components/schemas/EnumNumberVendorExt'
2124+
enumStringVendorExt:
2125+
$ref: '#/components/schemas/EnumStringVendorExt'
21512126
AdditionalPropertiesClass:
21522127
type: object
21532128
properties:
@@ -2339,6 +2314,35 @@ components:
23392314
- 1
23402315
- 2
23412316
example: 2
2317+
EnumNumberVendorExt:
2318+
type: integer
2319+
format: int32
2320+
enum:
2321+
- 42
2322+
- 18
2323+
- 56
2324+
x-enum-descriptions:
2325+
- 'Description for 42'
2326+
- 'Description for 18'
2327+
- 'Description for 56'
2328+
x-enum-varnames:
2329+
- FortyTwo
2330+
- Eigtheen
2331+
- FiftySix
2332+
EnumStringVendorExt:
2333+
type: string
2334+
enum:
2335+
- FOO
2336+
- Bar
2337+
- baz
2338+
x-enum-descriptions:
2339+
- 'Description for FOO'
2340+
- 'Description for Bar'
2341+
- 'Description for baz'
2342+
x-enum-varnames:
2343+
- FOO_XEnumVarname
2344+
- BarVar_XEnumVarname
2345+
- bazVar_XEnumVarname
23422346
OuterEnumDefaultValue:
23432347
type: string
23442348
enum:

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

+4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ docs/Dog.md
3939
docs/DummyModel.md
4040
docs/EnumArrays.md
4141
docs/EnumClass.md
42+
docs/EnumNumberVendorExt.md
4243
docs/EnumString1.md
4344
docs/EnumString2.md
45+
docs/EnumStringVendorExt.md
4446
docs/EnumTest.md
4547
docs/FakeApi.md
4648
docs/FakeClassnameTags123Api.md
@@ -167,8 +169,10 @@ petstore_api/models/dog.py
167169
petstore_api/models/dummy_model.py
168170
petstore_api/models/enum_arrays.py
169171
petstore_api/models/enum_class.py
172+
petstore_api/models/enum_number_vendor_ext.py
170173
petstore_api/models/enum_string1.py
171174
petstore_api/models/enum_string2.py
175+
petstore_api/models/enum_string_vendor_ext.py
172176
petstore_api/models/enum_test.py
173177
petstore_api/models/feeding.py
174178
petstore_api/models/file.py

samples/openapi3/client/petstore/python-aiohttp/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ Class | Method | HTTP request | Description
185185
- [DummyModel](docs/DummyModel.md)
186186
- [EnumArrays](docs/EnumArrays.md)
187187
- [EnumClass](docs/EnumClass.md)
188+
- [EnumNumberVendorExt](docs/EnumNumberVendorExt.md)
188189
- [EnumString1](docs/EnumString1.md)
189190
- [EnumString2](docs/EnumString2.md)
191+
- [EnumStringVendorExt](docs/EnumStringVendorExt.md)
190192
- [EnumTest](docs/EnumTest.md)
191193
- [Feeding](docs/Feeding.md)
192194
- [File](docs/File.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# EnumNumberVendorExt
2+
3+
4+
## Enum
5+
6+
* `FortyTwo` (value: `42`)
7+
8+
* `Eigtheen` (value: `18`)
9+
10+
* `FiftySix` (value: `56`)
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+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# EnumStringVendorExt
2+
3+
4+
## Enum
5+
6+
* `FOO_XEnumVarname` (value: `'FOO'`)
7+
8+
* `BarVar_XEnumVarname` (value: `'Bar'`)
9+
10+
* `bazVar_XEnumVarname` (value: `'baz'`)
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+

samples/openapi3/client/petstore/python-aiohttp/docs/EnumTest.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ Name | Type | Description | Notes
1010
**enum_integer_default** | **int** | | [optional] [default to 5]
1111
**enum_integer** | **int** | | [optional]
1212
**enum_number** | **float** | | [optional]
13-
**enum_number_vendor_ext** | **int** | | [optional]
14-
**enum_string_vendor_ext** | **str** | | [optional]
1513
**enum_string_single_member** | **str** | | [optional]
1614
**enum_integer_single_member** | **int** | | [optional]
1715
**outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional]
1816
**outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional]
1917
**outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] [default to OuterEnumDefaultValue.PLACED]
2018
**outer_enum_integer_default_value** | [**OuterEnumIntegerDefaultValue**](OuterEnumIntegerDefaultValue.md) | | [optional] [default to OuterEnumIntegerDefaultValue.NUMBER_0]
19+
**enum_number_vendor_ext** | [**EnumNumberVendorExt**](EnumNumberVendorExt.md) | | [optional]
20+
**enum_string_vendor_ext** | [**EnumStringVendorExt**](EnumStringVendorExt.md) | | [optional]
2121

2222
## Example
2323

samples/openapi3/client/petstore/python-aiohttp/petstore_api/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@
7373
from petstore_api.models.dummy_model import DummyModel
7474
from petstore_api.models.enum_arrays import EnumArrays
7575
from petstore_api.models.enum_class import EnumClass
76+
from petstore_api.models.enum_number_vendor_ext import EnumNumberVendorExt
7677
from petstore_api.models.enum_string1 import EnumString1
7778
from petstore_api.models.enum_string2 import EnumString2
79+
from petstore_api.models.enum_string_vendor_ext import EnumStringVendorExt
7880
from petstore_api.models.enum_test import EnumTest
7981
from petstore_api.models.feeding import Feeding
8082
from petstore_api.models.file import File

samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@
4848
from petstore_api.models.dummy_model import DummyModel
4949
from petstore_api.models.enum_arrays import EnumArrays
5050
from petstore_api.models.enum_class import EnumClass
51+
from petstore_api.models.enum_number_vendor_ext import EnumNumberVendorExt
5152
from petstore_api.models.enum_string1 import EnumString1
5253
from petstore_api.models.enum_string2 import EnumString2
54+
from petstore_api.models.enum_string_vendor_ext import EnumStringVendorExt
5355
from petstore_api.models.enum_test import EnumTest
5456
from petstore_api.models.feeding import Feeding
5557
from petstore_api.models.file import File
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 EnumNumberVendorExt(int, Enum):
22+
"""
23+
EnumNumberVendorExt
24+
"""
25+
26+
"""
27+
allowed enum values
28+
"""
29+
FortyTwo = 42
30+
Eigtheen = 18
31+
FiftySix = 56
32+
33+
@classmethod
34+
def from_json(cls, json_str: str) -> Self:
35+
"""Create an instance of EnumNumberVendorExt from a JSON string"""
36+
return cls(json.loads(json_str))
37+
38+
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 EnumStringVendorExt(str, Enum):
22+
"""
23+
EnumStringVendorExt
24+
"""
25+
26+
"""
27+
allowed enum values
28+
"""
29+
FOO_XEnumVarname = 'FOO'
30+
BarVar_XEnumVarname = 'Bar'
31+
bazVar_XEnumVarname = 'baz'
32+
33+
@classmethod
34+
def from_json(cls, json_str: str) -> Self:
35+
"""Create an instance of EnumStringVendorExt from a JSON string"""
36+
return cls(json.loads(json_str))
37+
38+

samples/openapi3/client/petstore/python-aiohttp/petstore_api/models/enum_test.py

+8-26
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
2121
from typing import Any, ClassVar, Dict, List, Optional
22+
from petstore_api.models.enum_number_vendor_ext import EnumNumberVendorExt
23+
from petstore_api.models.enum_string_vendor_ext import EnumStringVendorExt
2224
from petstore_api.models.outer_enum import OuterEnum
2325
from petstore_api.models.outer_enum_default_value import OuterEnumDefaultValue
2426
from petstore_api.models.outer_enum_integer import OuterEnumInteger
@@ -35,15 +37,15 @@ class EnumTest(BaseModel):
3537
enum_integer_default: Optional[StrictInt] = 5
3638
enum_integer: Optional[StrictInt] = None
3739
enum_number: Optional[float] = None
38-
enum_number_vendor_ext: Optional[StrictInt] = None
39-
enum_string_vendor_ext: Optional[StrictStr] = None
4040
enum_string_single_member: Optional[StrictStr] = None
4141
enum_integer_single_member: Optional[StrictInt] = None
4242
outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum")
4343
outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger")
4444
outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=OuterEnumDefaultValue.PLACED, alias="outerEnumDefaultValue")
4545
outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=OuterEnumIntegerDefaultValue.NUMBER_0, alias="outerEnumIntegerDefaultValue")
46-
__properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "enum_string_single_member", "enum_integer_single_member", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"]
46+
enum_number_vendor_ext: Optional[EnumNumberVendorExt] = Field(default=None, alias="enumNumberVendorExt")
47+
enum_string_vendor_ext: Optional[EnumStringVendorExt] = Field(default=None, alias="enumStringVendorExt")
48+
__properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_string_single_member", "enum_integer_single_member", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue", "enumNumberVendorExt", "enumStringVendorExt"]
4749

4850
@field_validator('enum_string')
4951
def enum_string_validate_enum(cls, value):
@@ -92,26 +94,6 @@ def enum_number_validate_enum(cls, value):
9294
raise ValueError("must be one of enum values (1.1, -1.2)")
9395
return value
9496

95-
@field_validator('enum_number_vendor_ext')
96-
def enum_number_vendor_ext_validate_enum(cls, value):
97-
"""Validates the enum"""
98-
if value is None:
99-
return value
100-
101-
if value not in set([42, 18, 56]):
102-
raise ValueError("must be one of enum values (42, 18, 56)")
103-
return value
104-
105-
@field_validator('enum_string_vendor_ext')
106-
def enum_string_vendor_ext_validate_enum(cls, value):
107-
"""Validates the enum"""
108-
if value is None:
109-
return value
110-
111-
if value not in set(['FOO', 'Bar', 'baz']):
112-
raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')")
113-
return value
114-
11597
@field_validator('enum_string_single_member')
11698
def enum_string_single_member_validate_enum(cls, value):
11799
"""Validates the enum"""
@@ -193,14 +175,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
193175
"enum_integer_default": obj.get("enum_integer_default") if obj.get("enum_integer_default") is not None else 5,
194176
"enum_integer": obj.get("enum_integer"),
195177
"enum_number": obj.get("enum_number"),
196-
"enum_number_vendor_ext": obj.get("enum_number_vendor_ext"),
197-
"enum_string_vendor_ext": obj.get("enum_string_vendor_ext"),
198178
"enum_string_single_member": obj.get("enum_string_single_member"),
199179
"enum_integer_single_member": obj.get("enum_integer_single_member"),
200180
"outerEnum": obj.get("outerEnum"),
201181
"outerEnumInteger": obj.get("outerEnumInteger"),
202182
"outerEnumDefaultValue": obj.get("outerEnumDefaultValue") if obj.get("outerEnumDefaultValue") is not None else OuterEnumDefaultValue.PLACED,
203-
"outerEnumIntegerDefaultValue": obj.get("outerEnumIntegerDefaultValue") if obj.get("outerEnumIntegerDefaultValue") is not None else OuterEnumIntegerDefaultValue.NUMBER_0
183+
"outerEnumIntegerDefaultValue": obj.get("outerEnumIntegerDefaultValue") if obj.get("outerEnumIntegerDefaultValue") is not None else OuterEnumIntegerDefaultValue.NUMBER_0,
184+
"enumNumberVendorExt": obj.get("enumNumberVendorExt"),
185+
"enumStringVendorExt": obj.get("enumStringVendorExt")
204186
})
205187
return _obj
206188

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
import unittest
16+
17+
from petstore_api.models.enum_number_vendor_ext import EnumNumberVendorExt
18+
19+
class TestEnumNumberVendorExt(unittest.TestCase):
20+
"""EnumNumberVendorExt unit test stubs"""
21+
22+
def setUp(self):
23+
pass
24+
25+
def tearDown(self):
26+
pass
27+
28+
def testEnumNumberVendorExt(self):
29+
"""Test EnumNumberVendorExt"""
30+
# inst = EnumNumberVendorExt()
31+
32+
if __name__ == '__main__':
33+
unittest.main()

0 commit comments

Comments
 (0)