Skip to content

Commit 67af02c

Browse files
authored
python-pydantic-v1: Keep trailing commas for enum validation tuples (OpenAPITools#19985)
* python-pydantic-v1: Keep trailing commas for tuples when enum has just single member * Update samples * Add test for single member enums * Refactor test name
1 parent 66c7b2f commit 67af02c

File tree

35 files changed

+188
-54
lines changed

35 files changed

+188
-54
lines changed

modules/openapi-generator/src/main/resources/python-fastapi/model_generic.mustache

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
6969
{{/required}}
7070
{{#isArray}}
7171
for i in value:
72-
if i not in ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}):
72+
if i not in ({{#allowableValues}}{{#enumVars}}{{{value}}},{{^-last}} {{/-last}}{{/enumVars}}{{/allowableValues}}):
7373
raise ValueError("each list item must be one of ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})")
7474
{{/isArray}}
7575
{{^isArray}}
76-
if value not in ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}):
76+
if value not in ({{#allowableValues}}{{#enumVars}}{{{value}}},{{^-last}} {{/-last}}{{/enumVars}}{{/allowableValues}}):
7777
raise ValueError("must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})")
7878
{{/isArray}}
7979
return value

modules/openapi-generator/src/main/resources/python-pydantic-v1/model_generic.mustache

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}
7474
{{/required}}
7575
{{#isArray}}
7676
for i in value:
77-
if i not in ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}):
77+
if i not in ({{#allowableValues}}{{#enumVars}}{{{value}}},{{^-last}} {{/-last}}{{/enumVars}}{{/allowableValues}}):
7878
raise ValueError("each list item must be one of ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})")
7979
{{/isArray}}
8080
{{^isArray}}
81-
if value not in ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}):
81+
if value not in ({{#allowableValues}}{{#enumVars}}{{{value}}},{{^-last}} {{/-last}}{{/enumVars}}{{/allowableValues}}):
8282
raise ValueError("must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})")
8383
{{/isArray}}
8484
return value

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

+9
Original file line numberDiff line numberDiff line change
@@ -2124,6 +2124,15 @@ components:
21242124
- FOOVar
21252125
- BarVar
21262126
- bazVar
2127+
enum_string_single_member:
2128+
type: string
2129+
enum:
2130+
- 'abc'
2131+
enum_integer_single_member:
2132+
type: integer
2133+
format: int32
2134+
enum:
2135+
- 100
21272136
outerEnum:
21282137
$ref: '#/components/schemas/OuterEnum'
21292138
outerEnumInteger:

samples/client/echo_api/python-pydantic-v1/openapi_client/models/default_value.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def array_string_enum_default_validate_enum(cls, value):
4444
return value
4545

4646
for i in value:
47-
if i not in ('success', 'failure', 'unclassified'):
47+
if i not in ('success', 'failure', 'unclassified',):
4848
raise ValueError("each list item must be one of ('success', 'failure', 'unclassified')")
4949
return value
5050

samples/client/echo_api/python-pydantic-v1/openapi_client/models/pet.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def status_validate_enum(cls, value):
4242
if value is None:
4343
return value
4444

45-
if value not in ('available', 'pending', 'sold'):
45+
if value not in ('available', 'pending', 'sold',):
4646
raise ValueError("must be one of enum values ('available', 'pending', 'sold')")
4747
return value
4848

samples/client/echo_api/python-pydantic-v1/openapi_client/models/query.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def outcomes_validate_enum(cls, value):
3737
return value
3838

3939
for i in value:
40-
if i not in ('SUCCESS', 'FAILURE', 'SKIPPED'):
40+
if i not in ('SUCCESS', 'FAILURE', 'SKIPPED',):
4141
raise ValueError("each list item must be one of ('SUCCESS', 'FAILURE', 'SKIPPED')")
4242
return value
4343

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

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Name | Type | Description | Notes
1212
**enum_number** | **float** | | [optional]
1313
**enum_number_vendor_ext** | **int** | | [optional]
1414
**enum_string_vendor_ext** | **str** | | [optional]
15+
**enum_string_single_member** | **str** | | [optional]
16+
**enum_integer_single_member** | **int** | | [optional]
1517
**outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional]
1618
**outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional]
1719
**outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional] [default to OuterEnumDefaultValue.PLACED]

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

+25-1
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ class EnumTest(BaseModel):
3737
enum_number: Optional[float] = None
3838
enum_number_vendor_ext: Optional[StrictInt] = None
3939
enum_string_vendor_ext: Optional[StrictStr] = None
40+
enum_string_single_member: Optional[StrictStr] = None
41+
enum_integer_single_member: Optional[StrictInt] = None
4042
outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum")
4143
outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger")
4244
outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=OuterEnumDefaultValue.PLACED, alias="outerEnumDefaultValue")
4345
outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=OuterEnumIntegerDefaultValue.NUMBER_0, alias="outerEnumIntegerDefaultValue")
44-
__properties: ClassVar[List[str]] = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "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"]
4547

4648
@field_validator('enum_string')
4749
def enum_string_validate_enum(cls, value):
@@ -110,6 +112,26 @@ def enum_string_vendor_ext_validate_enum(cls, value):
110112
raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')")
111113
return value
112114

115+
@field_validator('enum_string_single_member')
116+
def enum_string_single_member_validate_enum(cls, value):
117+
"""Validates the enum"""
118+
if value is None:
119+
return value
120+
121+
if value not in set(['abc']):
122+
raise ValueError("must be one of enum values ('abc')")
123+
return value
124+
125+
@field_validator('enum_integer_single_member')
126+
def enum_integer_single_member_validate_enum(cls, value):
127+
"""Validates the enum"""
128+
if value is None:
129+
return value
130+
131+
if value not in set([100]):
132+
raise ValueError("must be one of enum values (100)")
133+
return value
134+
113135
model_config = ConfigDict(
114136
populate_by_name=True,
115137
validate_assignment=True,
@@ -173,6 +195,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
173195
"enum_number": obj.get("enum_number"),
174196
"enum_number_vendor_ext": obj.get("enum_number_vendor_ext"),
175197
"enum_string_vendor_ext": obj.get("enum_string_vendor_ext"),
198+
"enum_string_single_member": obj.get("enum_string_single_member"),
199+
"enum_integer_single_member": obj.get("enum_integer_single_member"),
176200
"outerEnum": obj.get("outerEnum"),
177201
"outerEnumInteger": obj.get("outerEnumInteger"),
178202
"outerEnumDefaultValue": obj.get("outerEnumDefaultValue") if obj.get("outerEnumDefaultValue") is not None else OuterEnumDefaultValue.PLACED,

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

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Name | Type | Description | Notes
1111
**enum_number** | **float** | | [optional]
1212
**enum_number_vendor_ext** | **int** | | [optional]
1313
**enum_string_vendor_ext** | **str** | | [optional]
14+
**enum_string_single_member** | **str** | | [optional]
15+
**enum_integer_single_member** | **int** | | [optional]
1416
**outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional]
1517
**outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional]
1618
**outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional]

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/bathing.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ class Bathing(BaseModel):
3333
@validator('task_name')
3434
def task_name_validate_enum(cls, value):
3535
"""Validates the enum"""
36-
if value not in ('cleaning_deep'):
36+
if value not in ('cleaning_deep',):
3737
raise ValueError("must be one of enum values ('cleaning_deep')")
3838
return value
3939

4040
@validator('function_name')
4141
def function_name_validate_enum(cls, value):
4242
"""Validates the enum"""
43-
if value not in ('care_nourish'):
43+
if value not in ('care_nourish',):
4444
raise ValueError("must be one of enum values ('care_nourish')")
4545
return value
4646

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/enum_arrays.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def just_symbol_validate_enum(cls, value):
3535
if value is None:
3636
return value
3737

38-
if value not in ('>=', '$'):
38+
if value not in ('>=', '$',):
3939
raise ValueError("must be one of enum values ('>=', '$')")
4040
return value
4141

@@ -46,7 +46,7 @@ def array_enum_validate_enum(cls, value):
4646
return value
4747

4848
for i in value:
49-
if i not in ('fish', 'crab'):
49+
if i not in ('fish', 'crab',):
5050
raise ValueError("each list item must be one of ('fish', 'crab')")
5151
return value
5252

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

+32-8
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,28 @@ class EnumTest(BaseModel):
3636
enum_number: Optional[float] = None
3737
enum_number_vendor_ext: Optional[StrictInt] = None
3838
enum_string_vendor_ext: Optional[StrictStr] = None
39+
enum_string_single_member: Optional[StrictStr] = None
40+
enum_integer_single_member: Optional[StrictInt] = None
3941
outer_enum: Optional[OuterEnum] = Field(default=None, alias="outerEnum")
4042
outer_enum_integer: Optional[OuterEnumInteger] = Field(default=None, alias="outerEnumInteger")
4143
outer_enum_default_value: Optional[OuterEnumDefaultValue] = Field(default=None, alias="outerEnumDefaultValue")
4244
outer_enum_integer_default_value: Optional[OuterEnumIntegerDefaultValue] = Field(default=None, alias="outerEnumIntegerDefaultValue")
43-
__properties = ["enum_string", "enum_string_required", "enum_integer_default", "enum_integer", "enum_number", "enum_number_vendor_ext", "enum_string_vendor_ext", "outerEnum", "outerEnumInteger", "outerEnumDefaultValue", "outerEnumIntegerDefaultValue"]
45+
__properties = ["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"]
4446

4547
@validator('enum_string')
4648
def enum_string_validate_enum(cls, value):
4749
"""Validates the enum"""
4850
if value is None:
4951
return value
5052

51-
if value not in ('UPPER', 'lower', ''):
53+
if value not in ('UPPER', 'lower', '',):
5254
raise ValueError("must be one of enum values ('UPPER', 'lower', '')")
5355
return value
5456

5557
@validator('enum_string_required')
5658
def enum_string_required_validate_enum(cls, value):
5759
"""Validates the enum"""
58-
if value not in ('UPPER', 'lower', ''):
60+
if value not in ('UPPER', 'lower', '',):
5961
raise ValueError("must be one of enum values ('UPPER', 'lower', '')")
6062
return value
6163

@@ -65,7 +67,7 @@ def enum_integer_default_validate_enum(cls, value):
6567
if value is None:
6668
return value
6769

68-
if value not in (1, 5, 14):
70+
if value not in (1, 5, 14,):
6971
raise ValueError("must be one of enum values (1, 5, 14)")
7072
return value
7173

@@ -75,7 +77,7 @@ def enum_integer_validate_enum(cls, value):
7577
if value is None:
7678
return value
7779

78-
if value not in (1, -1):
80+
if value not in (1, -1,):
7981
raise ValueError("must be one of enum values (1, -1)")
8082
return value
8183

@@ -85,7 +87,7 @@ def enum_number_validate_enum(cls, value):
8587
if value is None:
8688
return value
8789

88-
if value not in (1.1, -1.2):
90+
if value not in (1.1, -1.2,):
8991
raise ValueError("must be one of enum values (1.1, -1.2)")
9092
return value
9193

@@ -95,7 +97,7 @@ def enum_number_vendor_ext_validate_enum(cls, value):
9597
if value is None:
9698
return value
9799

98-
if value not in (42, 18, 56):
100+
if value not in (42, 18, 56,):
99101
raise ValueError("must be one of enum values (42, 18, 56)")
100102
return value
101103

@@ -105,10 +107,30 @@ def enum_string_vendor_ext_validate_enum(cls, value):
105107
if value is None:
106108
return value
107109

108-
if value not in ('FOO', 'Bar', 'baz'):
110+
if value not in ('FOO', 'Bar', 'baz',):
109111
raise ValueError("must be one of enum values ('FOO', 'Bar', 'baz')")
110112
return value
111113

114+
@validator('enum_string_single_member')
115+
def enum_string_single_member_validate_enum(cls, value):
116+
"""Validates the enum"""
117+
if value is None:
118+
return value
119+
120+
if value not in ('abc',):
121+
raise ValueError("must be one of enum values ('abc')")
122+
return value
123+
124+
@validator('enum_integer_single_member')
125+
def enum_integer_single_member_validate_enum(cls, value):
126+
"""Validates the enum"""
127+
if value is None:
128+
return value
129+
130+
if value not in (100,):
131+
raise ValueError("must be one of enum values (100)")
132+
return value
133+
112134
class Config:
113135
"""Pydantic configuration"""
114136
allow_population_by_field_name = True
@@ -157,6 +179,8 @@ def from_dict(cls, obj: dict) -> EnumTest:
157179
"enum_number": obj.get("enum_number"),
158180
"enum_number_vendor_ext": obj.get("enum_number_vendor_ext"),
159181
"enum_string_vendor_ext": obj.get("enum_string_vendor_ext"),
182+
"enum_string_single_member": obj.get("enum_string_single_member"),
183+
"enum_integer_single_member": obj.get("enum_integer_single_member"),
160184
"outer_enum": obj.get("outerEnum"),
161185
"outer_enum_integer": obj.get("outerEnumInteger"),
162186
"outer_enum_default_value": obj.get("outerEnumDefaultValue"),

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/feeding.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ class Feeding(BaseModel):
3333
@validator('task_name')
3434
def task_name_validate_enum(cls, value):
3535
"""Validates the enum"""
36-
if value not in ('cleaning'):
36+
if value not in ('cleaning',):
3737
raise ValueError("must be one of enum values ('cleaning')")
3838
return value
3939

4040
@validator('function_name')
4141
def function_name_validate_enum(cls, value):
4242
"""Validates the enum"""
43-
if value not in ('care_nourish'):
43+
if value not in ('care_nourish',):
4444
raise ValueError("must be one of enum values ('care_nourish')")
4545
return value
4646

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/map_test.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def map_of_enum_string_validate_enum(cls, value):
3737
if value is None:
3838
return value
3939

40-
if value not in ('UPPER', 'lower'):
40+
if value not in ('UPPER', 'lower',):
4141
raise ValueError("must be one of enum values ('UPPER', 'lower')")
4242
return value
4343

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/order.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def status_validate_enum(cls, value):
3939
if value is None:
4040
return value
4141

42-
if value not in ('placed', 'approved', 'delivered'):
42+
if value not in ('placed', 'approved', 'delivered',):
4343
raise ValueError("must be one of enum values ('placed', 'approved', 'delivered')")
4444
return value
4545

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/pet.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def status_validate_enum(cls, value):
4141
if value is None:
4242
return value
4343

44-
if value not in ('available', 'pending', 'sold'):
44+
if value not in ('available', 'pending', 'sold',):
4545
raise ValueError("must be one of enum values ('available', 'pending', 'sold')")
4646
return value
4747

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/poop_cleaning.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ class PoopCleaning(BaseModel):
3333
@validator('task_name')
3434
def task_name_validate_enum(cls, value):
3535
"""Validates the enum"""
36-
if value not in ('cleaning'):
36+
if value not in ('cleaning',):
3737
raise ValueError("must be one of enum values ('cleaning')")
3838
return value
3939

4040
@validator('function_name')
4141
def function_name_validate_enum(cls, value):
4242
"""Validates the enum"""
43-
if value not in ('care'):
43+
if value not in ('care',):
4444
raise ValueError("must be one of enum values ('care')")
4545
return value
4646

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/special_name.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def var_schema_validate_enum(cls, value):
3737
if value is None:
3838
return value
3939

40-
if value not in ('available', 'pending', 'sold'):
40+
if value not in ('available', 'pending', 'sold',):
4141
raise ValueError("must be one of enum values ('available', 'pending', 'sold')")
4242
return value
4343

samples/openapi3/client/petstore/python-pydantic-v1-aiohttp/petstore_api/models/test_model_with_enum_default.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_inline_defined_enum_with_default_validate_enum(cls, value):
4040
if value is None:
4141
return value
4242

43-
if value not in ('A', 'B', 'C'):
43+
if value not in ('A', 'B', 'C',):
4444
raise ValueError("must be one of enum values ('A', 'B', 'C')")
4545
return value
4646

samples/openapi3/client/petstore/python-pydantic-v1/docs/EnumTest.md

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Name | Type | Description | Notes
1111
**enum_number** | **float** | | [optional]
1212
**enum_number_vendor_ext** | **int** | | [optional]
1313
**enum_string_vendor_ext** | **str** | | [optional]
14+
**enum_string_single_member** | **str** | | [optional]
15+
**enum_integer_single_member** | **int** | | [optional]
1416
**outer_enum** | [**OuterEnum**](OuterEnum.md) | | [optional]
1517
**outer_enum_integer** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional]
1618
**outer_enum_default_value** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional]

samples/openapi3/client/petstore/python-pydantic-v1/petstore_api/models/bathing.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ class Bathing(BaseModel):
3434
@validator('task_name')
3535
def task_name_validate_enum(cls, value):
3636
"""Validates the enum"""
37-
if value not in ('cleaning_deep'):
37+
if value not in ('cleaning_deep',):
3838
raise ValueError("must be one of enum values ('cleaning_deep')")
3939
return value
4040

4141
@validator('function_name')
4242
def function_name_validate_enum(cls, value):
4343
"""Validates the enum"""
44-
if value not in ('care_nourish'):
44+
if value not in ('care_nourish',):
4545
raise ValueError("must be one of enum values ('care_nourish')")
4646
return value
4747

0 commit comments

Comments
 (0)