diff --git a/src/openapi_python_generator/language_converters/python/service_generator.py b/src/openapi_python_generator/language_converters/python/service_generator.py index caca9bd..5888731 100644 --- a/src/openapi_python_generator/language_converters/python/service_generator.py +++ b/src/openapi_python_generator/language_converters/python/service_generator.py @@ -428,17 +428,18 @@ def generate_service_operation( services = [] service_ops = [] for path_name, path in paths.items(): + clean_path_name = clean_up_path_name(path_name) for http_operation in HTTP_OPERATIONS: op = path.__getattribute__(http_operation) if op is None: continue if library_config.include_sync: - sync_so = generate_service_operation(op, path_name, False) + sync_so = generate_service_operation(op, clean_path_name, False) service_ops.append(sync_so) if library_config.include_async: - async_so = generate_service_operation(op, path_name, True) + async_so = generate_service_operation(op, clean_path_name, True) service_ops.append(async_so) # Ensure every operation has a tag; fallback to "default" for untagged operations @@ -489,3 +490,11 @@ def generate_service_operation( ) return services + + +def clean_up_path_name(path_name: str) -> str: + # Clean up path name: only replace dashes inside curly brackets for f-string compatibility, keep other dashes + def _replace_bracket_dashes(match): + return "{" + match.group(1).replace("-", "_") + "}" + + return re.sub(r"\{([^}/]+)\}", _replace_bracket_dashes, path_name) diff --git a/tests/regression/test_issue_117.py b/tests/regression/test_issue_117.py new file mode 100644 index 0000000..1dd0372 --- /dev/null +++ b/tests/regression/test_issue_117.py @@ -0,0 +1,36 @@ +import pytest +from click.testing import CliRunner + +from openapi_python_generator.common import HTTPLibrary, library_config_dict +from openapi_python_generator.generate_data import generate_data +from tests.conftest import test_data_folder +from tests.conftest import test_result_path + + +@pytest.fixture +def runner() -> CliRunner: + """Fixture for invoking command-line interfaces.""" + return CliRunner() + + +@pytest.mark.parametrize( + "library", + [HTTPLibrary.httpx, HTTPLibrary.aiohttp, HTTPLibrary.requests], +) +def test_issue_117(runner: CliRunner, model_data_with_cleanup, library) -> None: + """ + https://github.com/MarcoMuellner/openapi-python-generator/issues/117 + """ + generate_data(test_data_folder / "issue_117.json", test_result_path, library) + + if library_config_dict[library].include_sync: + assert (test_result_path / "services" / "default_service.py").exists() + assert (test_result_path / "services" / "default_service.py").read_text().find( + 'path = f"/bar-boz/{foo_bar}"' + ) != -1 + + if library_config_dict[library].include_async: + assert (test_result_path / "services" / "async_default_service.py").exists() + assert ( + test_result_path / "services" / "async_default_service.py" + ).read_text().find('path = f"/bar-boz/{foo_bar}"') != -1 diff --git a/tests/test_data/issue_117.json b/tests/test_data/issue_117.json new file mode 100644 index 0000000..aee9c89 --- /dev/null +++ b/tests/test_data/issue_117.json @@ -0,0 +1,29 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "New Specs", + "version": "1.0.0" + }, + "paths": { + + "/bar-boz/{foo-bar}": { + "get": { + + "parameters": [ + { + "name": "foo-bar", + "in": "path", + "description": "Buzz.", + "required": true, + "schema": { + "type": "string" + } + } + ] + } + } + }, + "components": { + "schemas": {} + } +} \ No newline at end of file