Skip to content

Commit 1b3add5

Browse files
committed
[FIX] remove hard-coded main module finding at runserver cmd
1 parent 8606545 commit 1b3add5

2 files changed

Lines changed: 35 additions & 4 deletions

File tree

src/fastapi_fastkit/cli.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,20 @@ def deleteproject(ctx: Context, project_name: str) -> None:
819819
print_error(f"Error during project deletion: {e}")
820820

821821

822+
def _derive_app_module(project_dir: str, main_path: str) -> str:
823+
"""Convert a discovered ``main.py`` path into a uvicorn ``module:attr``.
824+
825+
Templates can place ``main.py`` anywhere under the project (``main.py``,
826+
``src/main.py``, ``src/app/main.py``, ...). The previous ``"src/"`` /
827+
``""`` heuristic mis-mapped the domain-starter layout (``src/app/main.py``
828+
→ wrongly produced ``src.main:app``); deriving the dotted path from the
829+
actual relative location avoids that drift for any future layout too.
830+
"""
831+
rel_path = os.path.relpath(main_path, project_dir)
832+
module_part = os.path.splitext(rel_path)[0].replace(os.sep, ".")
833+
return f"{module_part}:app"
834+
835+
822836
@fastkit_cli.command()
823837
@click.option(
824838
"--host",
@@ -893,10 +907,7 @@ def runserver(
893907
return
894908

895909
main_path = core_modules["main"]
896-
if "src/" in main_path:
897-
app_module = "src.main:app"
898-
else:
899-
app_module = "main:app"
910+
app_module = _derive_app_module(project_dir, main_path)
900911

901912
if venv_python:
902913
print_info(f"Using Python from virtual environment: {venv_python}")

tests/test_cli_operations/test_cli.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,26 @@ def test_runserver_no_venv_project(self, temp_dir: str) -> None:
646646
assert result.exit_code == 0
647647
assert "Virtual environment not found" in result.output
648648

649+
def test_derive_app_module_handles_all_supported_layouts(self) -> None:
650+
"""Regression: nested layouts like src/app/main.py must map correctly.
651+
652+
``runserver`` previously mapped any ``src/`` main file to
653+
``src.main:app``, which silently mis-targeted the
654+
``fastapi-domain-starter`` layout (``src/app/main.py``).
655+
"""
656+
from fastapi_fastkit.cli import _derive_app_module
657+
658+
proj = "/proj"
659+
assert _derive_app_module(proj, os.path.join(proj, "main.py")) == "main:app"
660+
assert (
661+
_derive_app_module(proj, os.path.join(proj, "src", "main.py"))
662+
== "src.main:app"
663+
)
664+
assert (
665+
_derive_app_module(proj, os.path.join(proj, "src", "app", "main.py"))
666+
== "src.app.main:app"
667+
)
668+
649669
def test_addroute_command(self, temp_dir: str) -> None:
650670
# given
651671
os.chdir(temp_dir)

0 commit comments

Comments
 (0)