Skip to content

Commit 3eae20d

Browse files
Add support for x-enumNames extension (#2653)
* Add x-enumNames support for OpenAPI schemas and update related parsing logic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 2df42fb commit 3eae20d

4 files changed

Lines changed: 96 additions & 4 deletions

File tree

src/datamodel_code_generator/parser/jsonschema.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,8 @@ def validate_null_type(cls, value: Any) -> Any: # noqa: N805
333333
required: list[str] = [] # noqa: RUF012
334334
ref: Optional[str] = Field(default=None, alias="$ref") # noqa: UP045
335335
nullable: Optional[bool] = False # noqa: UP045
336-
x_enum_varnames: list[str] = Field(default=[], alias="x-enum-varnames")
336+
x_enum_varnames: list[str] = Field(default_factory=list, alias="x-enum-varnames")
337+
x_enum_names: list[str] = Field(default_factory=list, alias="x-enumNames")
337338
description: Optional[str] = None # noqa: UP045
338339
title: Optional[str] = None # noqa: UP045
339340
example: Any = None
@@ -2390,14 +2391,16 @@ def parse_enum(
23902391

23912392
exclude_field_names: set[str] = set()
23922393

2394+
enum_names = obj.x_enum_varnames or obj.x_enum_names
2395+
23932396
for i, enum_part in enumerate(enum_times):
23942397
if obj.type == "string" or isinstance(enum_part, str):
23952398
default = f"'{enum_part.translate(escape_characters)}'" if isinstance(enum_part, str) else enum_part
2396-
field_name = obj.x_enum_varnames[i] if obj.x_enum_varnames else str(enum_part)
2399+
field_name = enum_names[i] if enum_names and i < len(enum_names) and enum_names[i] else str(enum_part)
23972400
else:
23982401
default = enum_part
2399-
if obj.x_enum_varnames:
2400-
field_name = obj.x_enum_varnames[i]
2402+
if enum_names and i < len(enum_names) and enum_names[i]:
2403+
field_name = enum_names[i]
24012404
elif isinstance(enum_part, dict):
24022405
field_name = self._get_field_name_from_dict_enum(enum_part, i)
24032406
else:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# generated by datamodel-codegen:
2+
# filename: x_enum_names.yaml
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from enum import Enum, IntEnum
8+
9+
10+
class CustomerColor(IntEnum):
11+
BloodOrange = 1
12+
Sunflower = 2
13+
LightGreen = 3
14+
SkyBlue = 4
15+
Purple = 5
16+
17+
18+
class StringStatus(Enum):
19+
Pending = 'pending'
20+
Active = 'active'
21+
Closed = 'closed'
22+
23+
24+
class PriorityTest(IntEnum):
25+
VarnameOne = 1
26+
VarnameTwo = 2
27+
28+
29+
class ShortNames(IntEnum):
30+
First = 1
31+
Second = 2
32+
integer_3 = 3
33+
integer_4 = 4
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
openapi: 3.0.0
2+
info:
3+
title: Test x-enumNames
4+
version: 1.0.0
5+
paths: {}
6+
components:
7+
schemas:
8+
# Integer enum with x-enumNames
9+
CustomerColor:
10+
type: integer
11+
enum: [1, 2, 3, 4, 5]
12+
x-enumNames:
13+
- BloodOrange
14+
- Sunflower
15+
- LightGreen
16+
- SkyBlue
17+
- Purple
18+
19+
# String enum with x-enumNames
20+
StringStatus:
21+
type: string
22+
enum: ['pending', 'active', 'closed']
23+
x-enumNames:
24+
- Pending
25+
- Active
26+
- Closed
27+
28+
# x-enum-varnames takes priority over x-enumNames
29+
PriorityTest:
30+
type: integer
31+
enum: [1, 2]
32+
x-enum-varnames:
33+
- VarnameOne
34+
- VarnameTwo
35+
x-enumNames:
36+
- EnumNameOne
37+
- EnumNameTwo
38+
39+
# x-enumNames shorter than enum (graceful fallback)
40+
ShortNames:
41+
type: integer
42+
enum: [1, 2, 3, 4]
43+
x-enumNames:
44+
- First
45+
- Second

tests/main/openapi/test_main_openapi.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,3 +3463,14 @@ def test_main_nested_package_enum_default(output_dir: Path) -> None:
34633463
"--set-default-enum-member",
34643464
],
34653465
)
3466+
3467+
3468+
def test_main_openapi_x_enum_names(output_file: Path) -> None:
3469+
"""Test OpenAPI generation with x-enumNames extension (NSwag/NJsonSchema style)."""
3470+
run_main_and_assert(
3471+
input_path=OPEN_API_DATA_PATH / "x_enum_names.yaml",
3472+
output_path=output_file,
3473+
input_file_type="openapi",
3474+
assert_func=assert_file_content,
3475+
expected_file="x_enum_names.py",
3476+
)

0 commit comments

Comments
 (0)