Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion src/fastapi_cloud_cli/commands/deploy/archive.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import importlib
import logging
import re
from pathlib import Path, PurePosixPath
Expand Down Expand Up @@ -43,8 +44,38 @@ 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:
try:
tomllib = importlib.import_module("tomllib")
except ImportError:
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


Expand Down
28 changes: 27 additions & 1 deletion tests/test_archive.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"
90 changes: 90 additions & 0 deletions tests/test_cli_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import random
import re
import string
import sys
from datetime import timedelta
from pathlib import Path
from typing import TypedDict
Expand All @@ -18,6 +19,7 @@
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 tests.conftest import ConfiguredApp
Expand Down Expand Up @@ -2494,3 +2496,91 @@ 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 == ""
Loading