Skip to content

Commit b44f5b9

Browse files
committed
Sanitize api names
1 parent c457e9f commit b44f5b9

6 files changed

Lines changed: 34 additions & 7 deletions

File tree

.generator/conftest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,8 @@ def undo_operations():
337337
def api(context, api_version, specs, name):
338338
"""Return an API instance."""
339339
assert name in {tag["name"].replace(" ", "") for tag in specs[api_version]["tags"]}
340-
context["api_instance"] = {"name": name}
340+
sanitized_name = name.replace("-", "")
341+
context["api_instance"] = {"name": sanitized_name}
341342

342343

343344
@given(parsers.parse('operation "{name}" enabled'))

.generator/src/generator/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def cli(specs, output):
3636
env.filters["parameters"] = openapi.parameters
3737
env.filters["return_type"] = openapi.return_type
3838
env.filters["safe_snake_case"] = formatter.safe_snake_case
39+
env.filters["class_name"] = formatter.class_name
3940
env.filters["docstring"] = formatter.docstring
4041

4142
env.globals["enumerate"] = enumerate

.generator/src/generator/formatter.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,26 @@ def snake_case(value):
9191
return PATTERN_DOUBLE_UNDERSCORE.sub("_", s1)
9292

9393

94+
def class_name(value):
95+
"""
96+
Convert a string into a valid Python API class name by:
97+
1. Removing all non-alphanumeric characters
98+
2. Appending 'Api' suffix
99+
100+
Args:
101+
value (str): The input string to convert
102+
103+
Returns:
104+
str: A valid Python class name ending in 'Api'
105+
106+
Example:
107+
>>> class_name("On-Call")
108+
'OnCallApi'
109+
"""
110+
value = re.sub(r'[^a-zA-Z0-9]', '', value)
111+
return value + "Api"
112+
113+
94114
def safe_snake_case(value):
95115
for token, replacement in EDGE_CASES.items():
96116
value = value.replace(token, replacement)

.generator/src/generator/templates/api.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ from {{ package }}.model_utils import (
2222
from {{ package }}.{{ version }}.model.{{ model|safe_snake_case }} import {{ model }}
2323
{%- endfor %}
2424

25-
{% set classname = name.replace(" ", "") + "Api" %}
25+
{% set classname = name|class_name %}
2626
class {{ classname }}:
2727
"""
2828
{{ description|docstring|indent(4) }}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{%- for api in apis %}
2-
{%- set classname = api.replace(" ", "") + "Api" %}
2+
{%- set classname = api|class_name %}
33
from {{ package }}.{{ version }}.api.{{ classname|safe_snake_case }} import {{ classname }}
44
{%- endfor %}
55

66

77
__all__ = [
88
{%- for api in apis %}
9-
{%- set classname = api.replace(" ", "") + "Api" %}
9+
{%- set classname = api|class_name %}
1010
"{{ classname }}",
1111
{%- endfor %}
1212
]

tests/conftest.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,19 @@ def client(configuration):
383383
with ApiClient(configuration) as api_client:
384384
yield api_client
385385

386+
def _api_name(value):
387+
value = re.sub(r'[^a-zA-Z0-9]', '', value)
388+
return value + "Api"
389+
390+
386391

387392
@given(parsers.parse('an instance of "{name}" API'))
388393
def api(context, package_name, client, name):
389394
"""Return an API instance."""
390395
module_name = snake_case(name)
391396
package = importlib.import_module(f"{package_name}.api.{module_name}_api")
392397
context["api"] = {
393-
"api": getattr(package, name + "Api")(client),
398+
"api": getattr(package, _api_name(name))(client),
394399
"package": package_name,
395400
"calls": [],
396401
}
@@ -479,7 +484,7 @@ def wrapper(context, undo):
479484

480485
package = importlib.import_module(f"{package_name}.api.{module_name}_api")
481486
with ApiClient(configuration) as client:
482-
api = getattr(package, name + "Api")(client)
487+
api = getattr(package, _api_name(name))(client)
483488
operation_method = getattr(api, operation_name)
484489
params_map = getattr(api, f"_{operation_name}_endpoint").params_map
485490

@@ -565,7 +570,7 @@ def cleanup(api, version, operation_id, response, request, client=client):
565570
undo_name = undo_tag.replace(" ", "")
566571
undo_module_name = snake_case(undo_tag)
567572
undo_package = importlib.import_module(f"{package_name}.api.{undo_module_name}_api")
568-
api = getattr(undo_package, undo_name + "Api")(client)
573+
api = getattr(undo_package, _api_name(undo_tag))(client)
569574

570575
operation_name = snake_case(operation["operationId"])
571576
method = getattr(api, operation_name)

0 commit comments

Comments
 (0)