Skip to content

Commit 0ca0d78

Browse files
committed
Allow case sensitive enum values
1 parent f741d81 commit 0ca0d78

File tree

6 files changed

+53
-16
lines changed

6 files changed

+53
-16
lines changed

openapi_python_client/config.py

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class Config(BaseModel):
3535
]
3636
field_prefix: str = "field_"
3737
http_timeout: int = 5
38+
case_sensitive_enums: bool = False
3839

3940
@staticmethod
4041
def load_from_path(path: Path) -> "Config":

openapi_python_client/parser/properties/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def build_enum_property(
404404
),
405405
schemas,
406406
)
407-
values = EnumProperty.values_from_list(value_list)
407+
values = EnumProperty.values_from_list(value_list, case_sensitive_enums=config.case_sensitive_enums)
408408

409409
if class_info.name in schemas.classes_by_name:
410410
existing = schemas.classes_by_name[class_info.name]

openapi_python_client/parser/properties/enum_property.py

+16-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__all__ = ["EnumProperty"]
22

3-
from typing import Any, ClassVar, Dict, List, Optional, Set, Type, Union, cast
3+
from typing import Any, ClassVar, Dict, Optional, Sequence, Set, Type, Union
44

55
import attr
66

@@ -50,24 +50,30 @@ def get_imports(self, *, prefix: str) -> Set[str]:
5050
return imports
5151

5252
@staticmethod
53-
def values_from_list(values: Union[List[str], List[int]]) -> Dict[str, ValueType]:
53+
def values_from_list(
54+
values: Union[Sequence[str], Sequence[int]], case_sensitive_enums: bool = False
55+
) -> Dict[str, ValueType]:
5456
"""Convert a list of values into dict of {name: value}, where value can sometimes be None"""
5557
output: Dict[str, ValueType] = {}
5658

57-
for i, value in enumerate(values):
58-
value = cast(Union[str, int], value)
59+
for value in values:
5960
if isinstance(value, int):
6061
if value < 0:
6162
output[f"VALUE_NEGATIVE_{-value}"] = value
6263
else:
6364
output[f"VALUE_{value}"] = value
6465
continue
65-
if value and value[0].isalpha():
66-
key = value.upper()
66+
67+
if case_sensitive_enums:
68+
sanitized_key = utils.case_insensitive_snake_case(value)
6769
else:
68-
key = f"VALUE_{i}"
69-
if key in output:
70-
raise ValueError(f"Duplicate key {key} in Enum")
71-
sanitized_key = utils.snake_case(key).upper()
70+
sanitized_key = utils.snake_case(value.lower()).upper()
71+
if not value or not value[0].isalpha():
72+
sanitized_key = f"LITERAL_{sanitized_key}"
73+
74+
if sanitized_key in output:
75+
raise ValueError(f"Duplicate key {sanitized_key} in Enum")
76+
7277
output[sanitized_key] = utils.remove_string_escapes(value)
78+
7379
return output

openapi_python_client/utils.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,19 @@ def fix_reserved_words(value: str) -> str:
6666
return value
6767

6868

69+
def case_insensitive_snake_case(value: str) -> str:
70+
"""Converts to snake_case, but preserves capitalization of acronyms"""
71+
words = split_words(sanitize(value))
72+
value = "_".join(words)
73+
74+
return value
75+
76+
6977
def snake_case(value: str) -> str:
7078
"""Converts to snake_case"""
71-
words = split_words(sanitize(value))
72-
return "_".join(words).lower()
79+
value = case_insensitive_snake_case(value).lower()
80+
81+
return value
7382

7483

7584
def pascal_case(value: str) -> str:

tests/test_config.py

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def test_load_from_path(tmp_path: Path, filename, dump, relative):
3737
"project_name_override": "project-name",
3838
"package_name_override": "package_name",
3939
"package_version_override": "package_version",
40+
"case_sensitive_enums": True,
4041
}
4142
yml_file.write_text(dump(data))
4243

@@ -47,3 +48,4 @@ def test_load_from_path(tmp_path: Path, filename, dump, relative):
4748
assert config.project_name_override == "project-name"
4849
assert config.package_name_override == "package_name"
4950
assert config.package_version_override == "package_version"
51+
assert config.case_sensitive_enums == True

tests/test_parser/test_properties/test_init.py

+22-3
Original file line numberDiff line numberDiff line change
@@ -383,13 +383,32 @@ def test_values_from_list(self):
383383

384384
assert result == {
385385
"ABC": "abc",
386-
"VALUE_1": "123",
386+
"LITERAL_123": "123",
387387
"A23": "a23",
388-
"VALUE_3": "1bc",
388+
"LITERAL_1BC": "1bc",
389389
"VALUE_4": 4,
390390
"VALUE_NEGATIVE_3": -3,
391391
"A_THING_WITH_SPACES": "a Thing WIth spaces",
392-
"VALUE_7": "",
392+
"LITERAL_": "",
393+
}
394+
395+
def test_values_from_list_with_case_sesitive(self):
396+
from openapi_python_client.parser.properties import EnumProperty
397+
398+
data = ["abc", "Abc", "123", "a23", "1bc", 4, -3, "a Thing WIth spaces", ""]
399+
400+
result = EnumProperty.values_from_list(data, case_sensitive_enums=True)
401+
402+
assert result == {
403+
"abc": "abc",
404+
"Abc": "Abc",
405+
"LITERAL_123": "123",
406+
"a23": "a23",
407+
"LITERAL_1bc": "1bc",
408+
"VALUE_4": 4,
409+
"VALUE_NEGATIVE_3": -3,
410+
"a_Thing_W_Ith_spaces": "a Thing WIth spaces",
411+
"LITERAL_": "",
393412
}
394413

395414
def test_values_from_list_duplicate(self):

0 commit comments

Comments
 (0)