From 2ffd5c356246221035ef3032fc90c284a7587e76 Mon Sep 17 00:00:00 2001 From: kayqueGovetri Date: Wed, 17 Jun 2026 18:30:22 -0300 Subject: [PATCH 1/4] feat: add get app name in pyproject.toml --- .../commands/deploy/archive.py | 32 ++++++- tests/test_cli_deploy.py | 85 +++++++++++++++++++ 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy/archive.py b/src/fastapi_cloud_cli/commands/deploy/archive.py index 795dcf01..7a8cc7b6 100644 --- a/src/fastapi_cloud_cli/commands/deploy/archive.py +++ b/src/fastapi_cloud_cli/commands/deploy/archive.py @@ -8,7 +8,9 @@ from pydantic import AfterValidator logger = logging.getLogger(__name__) - +import sys +if sys.version_info >= (3, 11): + import tomllib def validate_app_directory(v: str | None) -> str | None: if v is None: @@ -42,9 +44,35 @@ def validate_app_directory(v: str | None) -> str | None: AppDirectory = Annotated[str | None, AfterValidator(validate_app_directory)] +def _project_name_from_pyproject(path: Path) -> str: + if sys.version_info < (3, 11): + return "" + + if not path.exists(): + return "" + + try: + with path.open("rb") as f: + data = tomllib.load(f) + + project_name = data.get("project", {}).get("name") + if project_name: + return str(project_name) + + poetry_name = data.get("tool", {}).get("poetry", {}).get("name") + if poetry_name: + return str(poetry_name) + + except Exception: + return "" + + return "" def _get_app_name(path: Path) -> str: - # TODO: use pyproject.toml to get the app name + pyproject_path = path / "pyproject.toml" + name = _project_name_from_pyproject(pyproject_path) + if name: + return name return path.name diff --git a/tests/test_cli_deploy.py b/tests/test_cli_deploy.py index 1dbf4a55..52e8bd77 100644 --- a/tests/test_cli_deploy.py +++ b/tests/test_cli_deploy.py @@ -4,6 +4,7 @@ import string from datetime import timedelta from pathlib import Path +import sys from typing import TypedDict from unittest.mock import patch @@ -20,6 +21,7 @@ from fastapi_cloud_cli.cli import app from fastapi_cloud_cli.config import Settings from fastapi_cloud_cli.utils.api import StreamLogError, TooManyRetriesError +from fastapi_cloud_cli.commands.deploy.archive import _project_name_from_pyproject from tests.conftest import ConfiguredApp from tests.utils import Keys, build_logs_response, changing_dir, create_jwt_token @@ -2494,3 +2496,86 @@ def test_invalid_large_file_threshold( assert result.exit_code == 2 assert "Invalid value for '--large-file-threshold'" in result.output + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_project_name_from_pyproject_project_section(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[project] +name = "my-app" +""", + encoding="utf-8", + ) + + result = _project_name_from_pyproject(pyproject) + + assert result == "my-app" + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_project_name_from_pyproject_poetry_section(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[tool.poetry] +name = "my-poetry-app" +""", + encoding="utf-8", + ) + + result = _project_name_from_pyproject(pyproject) + + assert result == "my-poetry-app" + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_project_name_from_pyproject_missing_file(tmp_path: Path) -> None: + pyproject = tmp_path / "missing.toml" + + result = _project_name_from_pyproject(pyproject) + + assert result == "" + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_project_name_from_pyproject_missing_name(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[project] +version = "0.1.0" +""", + encoding="utf-8", + ) + + result = _project_name_from_pyproject(pyproject) + + assert result == "" + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_project_name_from_pyproject_invalid_toml(tmp_path: Path) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[project +name = "invalid" +""", + encoding="utf-8", + ) + + result = _project_name_from_pyproject(pyproject) + + assert result == "" \ No newline at end of file From d327eebb05631d9e7d545173cd0cd94676ebe616 Mon Sep 17 00:00:00 2001 From: kayqueGovetri Date: Wed, 17 Jun 2026 18:35:29 -0300 Subject: [PATCH 2/4] style: run ruff check --- src/fastapi_cloud_cli/commands/deploy/archive.py | 6 +++++- tests/test_cli_deploy.py | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy/archive.py b/src/fastapi_cloud_cli/commands/deploy/archive.py index 7a8cc7b6..23946bea 100644 --- a/src/fastapi_cloud_cli/commands/deploy/archive.py +++ b/src/fastapi_cloud_cli/commands/deploy/archive.py @@ -9,8 +9,10 @@ logger = logging.getLogger(__name__) import sys + if sys.version_info >= (3, 11): - import tomllib + import tomllib # type: ignore[import-not-found] + def validate_app_directory(v: str | None) -> str | None: if v is None: @@ -44,6 +46,7 @@ def validate_app_directory(v: str | None) -> str | None: AppDirectory = Annotated[str | None, AfterValidator(validate_app_directory)] + def _project_name_from_pyproject(path: Path) -> str: if sys.version_info < (3, 11): return "" @@ -68,6 +71,7 @@ def _project_name_from_pyproject(path: Path) -> str: return "" + def _get_app_name(path: Path) -> str: pyproject_path = path / "pyproject.toml" name = _project_name_from_pyproject(pyproject_path) diff --git a/tests/test_cli_deploy.py b/tests/test_cli_deploy.py index 52e8bd77..19346d0e 100644 --- a/tests/test_cli_deploy.py +++ b/tests/test_cli_deploy.py @@ -2497,6 +2497,7 @@ def test_invalid_large_file_threshold( assert result.exit_code == 2 assert "Invalid value for '--large-file-threshold'" in result.output + @pytest.mark.skipif( sys.version_info < (3, 11), reason="tomllib is only available on Python 3.11+", @@ -2515,6 +2516,7 @@ def test_project_name_from_pyproject_project_section(tmp_path: Path) -> None: assert result == "my-app" + @pytest.mark.skipif( sys.version_info < (3, 11), reason="tomllib is only available on Python 3.11+", @@ -2533,6 +2535,7 @@ def test_project_name_from_pyproject_poetry_section(tmp_path: Path) -> None: assert result == "my-poetry-app" + @pytest.mark.skipif( sys.version_info < (3, 11), reason="tomllib is only available on Python 3.11+", @@ -2544,6 +2547,7 @@ def test_project_name_from_pyproject_missing_file(tmp_path: Path) -> None: assert result == "" + @pytest.mark.skipif( sys.version_info < (3, 11), reason="tomllib is only available on Python 3.11+", @@ -2562,6 +2566,7 @@ def test_project_name_from_pyproject_missing_name(tmp_path: Path) -> None: assert result == "" + @pytest.mark.skipif( sys.version_info < (3, 11), reason="tomllib is only available on Python 3.11+", @@ -2578,4 +2583,4 @@ def test_project_name_from_pyproject_invalid_toml(tmp_path: Path) -> None: result = _project_name_from_pyproject(pyproject) - assert result == "" \ No newline at end of file + assert result == "" From 9537b6eb45e0625c51c0c627896497139e7eb8be Mon Sep 17 00:00:00 2001 From: kayqueGovetri Date: Wed, 17 Jun 2026 18:46:10 -0300 Subject: [PATCH 3/4] style: run mypy --- src/fastapi_cloud_cli/commands/deploy/archive.py | 12 +++++++----- tests/test_cli_deploy.py | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy/archive.py b/src/fastapi_cloud_cli/commands/deploy/archive.py index 23946bea..d67c884c 100644 --- a/src/fastapi_cloud_cli/commands/deploy/archive.py +++ b/src/fastapi_cloud_cli/commands/deploy/archive.py @@ -1,3 +1,4 @@ +import importlib import logging import re from pathlib import Path, PurePosixPath @@ -8,10 +9,6 @@ from pydantic import AfterValidator logger = logging.getLogger(__name__) -import sys - -if sys.version_info >= (3, 11): - import tomllib # type: ignore[import-not-found] def validate_app_directory(v: str | None) -> str | None: @@ -48,7 +45,12 @@ def validate_app_directory(v: str | None) -> str | None: def _project_name_from_pyproject(path: Path) -> str: - if sys.version_info < (3, 11): + try: + tomllib = importlib.import_module("tomllib") + except ImportError: + return "" + + if tomllib is None: return "" if not path.exists(): diff --git a/tests/test_cli_deploy.py b/tests/test_cli_deploy.py index 19346d0e..f0f4b335 100644 --- a/tests/test_cli_deploy.py +++ b/tests/test_cli_deploy.py @@ -2,9 +2,9 @@ import random import re import string +import sys from datetime import timedelta from pathlib import Path -import sys from typing import TypedDict from unittest.mock import patch @@ -19,9 +19,9 @@ from typer.testing import CliRunner from fastapi_cloud_cli.cli import app +from fastapi_cloud_cli.commands.deploy.archive import _project_name_from_pyproject from fastapi_cloud_cli.config import Settings from fastapi_cloud_cli.utils.api import StreamLogError, TooManyRetriesError -from fastapi_cloud_cli.commands.deploy.archive import _project_name_from_pyproject from tests.conftest import ConfiguredApp from tests.utils import Keys, build_logs_response, changing_dir, create_jwt_token From 5acef8246ed93d11588f30d7afc0b14296ba1e15 Mon Sep 17 00:00:00 2001 From: kayqueGovetri Date: Wed, 17 Jun 2026 18:55:04 -0300 Subject: [PATCH 4/4] test: adding new test to project_name_from_py_project --- .../commands/deploy/archive.py | 3 -- tests/test_archive.py | 28 ++++++++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/fastapi_cloud_cli/commands/deploy/archive.py b/src/fastapi_cloud_cli/commands/deploy/archive.py index d67c884c..a102e53f 100644 --- a/src/fastapi_cloud_cli/commands/deploy/archive.py +++ b/src/fastapi_cloud_cli/commands/deploy/archive.py @@ -50,9 +50,6 @@ def _project_name_from_pyproject(path: Path) -> str: except ImportError: return "" - if tomllib is None: - return "" - if not path.exists(): return "" diff --git a/tests/test_archive.py b/tests/test_archive.py index cbb8ec58..b87b279a 100644 --- a/tests/test_archive.py +++ b/tests/test_archive.py @@ -1,9 +1,10 @@ +import sys from pathlib import Path import fastar import pytest -from fastapi_cloud_cli.commands.deploy.archive import archive +from fastapi_cloud_cli.commands.deploy.archive import _get_app_name, archive @pytest.fixture @@ -163,3 +164,28 @@ def test_archive_includes_hidden_files_but_excludes_env( dst_path / ".config", dst_path / ".config" / "settings.json", } + + +def test_get_app_name_uses_directory_name_when_pyproject_is_missing( + tmp_path: Path, +) -> None: + assert _get_app_name(tmp_path) == tmp_path.name + + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="tomllib is only available on Python 3.11+", +) +def test_get_app_name_uses_project_name_from_pyproject( + tmp_path: Path, +) -> None: + pyproject = tmp_path / "pyproject.toml" + pyproject.write_text( + """ +[project] +name = "my-app" +""", + encoding="utf-8", + ) + + assert _get_app_name(tmp_path) == "my-app"