Skip to content

Commit 797b76f

Browse files
committed
Don't depend on stringcase (closes openapi-generators#369)
Let's reimplement what we need here so that we don't depend on stringcase anymore (see openapi-generators#369 for rationale). I've added a few test cases for stuff I've seen break along the way.
1 parent f3aa0b0 commit 797b76f

File tree

5 files changed

+23
-27
lines changed

5 files changed

+23
-27
lines changed

mypy.ini

-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ strict_equality = True
88
[mypy-importlib_metadata]
99
ignore_missing_imports = True
1010

11-
[mypy-stringcase]
12-
ignore_missing_imports = True
13-
1411
[mypy-typer]
1512
ignore_missing_imports = True
1613

openapi_python_client/utils.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import builtins
22
import re
33
from keyword import iskeyword
4+
from typing import List
45

5-
import stringcase
6+
delimiters = " _-"
67

78

89
def sanitize(value: str) -> str:
9-
""" Removes every character that isn't 0-9, A-Z, a-z, ' ', -, or _ """
10-
return re.sub(r"[^\w _\-]+", "", value)
10+
""" Removes every character that isn't 0-9, A-Z, a-z, or a known delimiter """
11+
return re.sub(rf"[^\w{delimiters}]+", "", value)
12+
13+
14+
def split_words(value: str) -> List[str]:
15+
""" Split a string on non-capital letters and known delimiters """
16+
value = " ".join(re.split("([A-Z]?[a-z0-9]+)", value))
17+
return re.findall(rf"[^{delimiters}]+", value)
1118

1219

1320
def fix_keywords(value: str) -> str:
@@ -25,22 +32,23 @@ def fix_reserved_words(value: str) -> str:
2532
return value
2633

2734

28-
def group_title(value: str) -> str:
29-
value = re.sub(r"([A-Z]{2,})([A-Z][a-z]|[ \-_]|$)", lambda m: m.group(1).title() + m.group(2), value.strip())
30-
value = re.sub(r"(^|[ _-])([A-Z])", lambda m: m.group(1) + m.group(2).lower(), value)
31-
return value
32-
33-
3435
def snake_case(value: str) -> str:
35-
return fix_keywords(stringcase.snakecase(group_title(sanitize(value))))
36+
words = split_words(sanitize(value))
37+
value = "_".join(words).lower()
38+
return fix_keywords(value)
3639

3740

3841
def pascal_case(value: str) -> str:
39-
return fix_keywords(stringcase.pascalcase(sanitize(value.replace(" ", ""))))
42+
words = split_words(sanitize(value))
43+
words = [word.capitalize() if not word.isupper() else word for word in words]
44+
value = "".join(words)
45+
return fix_keywords(value)
4046

4147

4248
def kebab_case(value: str) -> str:
43-
return fix_keywords(stringcase.spinalcase(group_title(sanitize(value))))
49+
words = split_words(sanitize(value))
50+
value = "-".join(words).lower()
51+
return fix_keywords(value)
4452

4553

4654
def remove_string_escapes(value: str) -> str:

poetry.lock

-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ include = ["CHANGELOG.md", "openapi_python_client/py.typed"]
2121
[tool.poetry.dependencies]
2222
python = "^3.6"
2323
jinja2 = "^2.11.1"
24-
stringcase = "^1.2.0"
2524
typer = "^0.3"
2625
colorama = {version = "^0.4.3", markers = "sys_platform == 'win32'"}
2726
shellingham = "^1.3.2"

tests/test_utils.py

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ def test_snake_case_from_pascal_with_acronyms():
1212
assert utils.snake_case("HTTPResponse") == "http_response"
1313
assert utils.snake_case("APIClientHTTPResponse") == "api_client_http_response"
1414
assert utils.snake_case("OAuthClientHTTPResponse") == "o_auth_client_http_response"
15+
assert utils.snake_case("S3Config") == "s3_config"
1516

1617

1718
def test_snake_case_from_pascal():
@@ -20,6 +21,7 @@ def test_snake_case_from_pascal():
2021

2122
def test_snake_case_from_camel():
2223
assert utils.snake_case("httpResponseLowerCamel") == "http_response_lower_camel"
24+
assert utils.snake_case("connectionID") == "connection_id"
2325

2426

2527
def test_kebab_case():
@@ -59,6 +61,7 @@ def test_to_valid_python_identifier():
5961
("snake_case", "SnakeCase"),
6062
("TLAClass", "TLAClass"),
6163
("Title Case", "TitleCase"),
64+
("s3_config", "S3Config"),
6265
],
6366
)
6467
def test_pascalcase(before, after):

0 commit comments

Comments
 (0)