From bfd50e5add3cbe404f6228897e3fb0ddbe4d78bc Mon Sep 17 00:00:00 2001 From: Maxime Toussaint Date: Wed, 17 Sep 2025 08:39:50 -0400 Subject: [PATCH 1/2] Issue-117: Fix dashes in brackets of path for f-strings --- .../python/service_generator.py | 13 +++++-- tests/regression/test_issue_117.py | 36 +++++++++++++++++++ tests/test_data/issue_117.json | 29 +++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/regression/test_issue_117.py create mode 100644 tests/test_data/issue_117.json 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..b4f890c --- /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"/{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"/{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..61e8b8f --- /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": { + + "/{foo-bar}": { + "get": { + + "parameters": [ + { + "name": "foo-bar", + "in": "path", + "description": "Buzz.", + "required": true, + "schema": { + "type": "string" + } + } + ] + } + } + }, + "components": { + "schemas": {} + } +} \ No newline at end of file From fbdb10fb5e1f18fbeb541fc76cfc4154fbfb5063 Mon Sep 17 00:00:00 2001 From: Maxime Toussaint Date: Wed, 17 Sep 2025 10:33:56 -0400 Subject: [PATCH 2/2] Improve test --- tests/regression/test_issue_117.py | 4 ++-- tests/test_data/issue_117.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regression/test_issue_117.py b/tests/regression/test_issue_117.py index b4f890c..1dd0372 100644 --- a/tests/regression/test_issue_117.py +++ b/tests/regression/test_issue_117.py @@ -26,11 +26,11 @@ def test_issue_117(runner: CliRunner, model_data_with_cleanup, library) -> None: 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"/{foo_bar}"' + '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"/{foo_bar}"') != -1 + ).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 index 61e8b8f..aee9c89 100644 --- a/tests/test_data/issue_117.json +++ b/tests/test_data/issue_117.json @@ -6,7 +6,7 @@ }, "paths": { - "/{foo-bar}": { + "/bar-boz/{foo-bar}": { "get": { "parameters": [