Files
app/backend/tests/flow/test_modules.py
T
stroblmeandClaude Opus 5 60d7ec81c0 Rename the import package app to fluksio
A wheel whose top-level module is `app` collides with anything else in a
user's venv, so the package that is about to be published takes the name
it is published under. Only the Python package moves; the repo, the
Docker WORKDIR and the compose project keep theirs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-21 21:48:05 +02:00

78 lines
2.4 KiB
Python

"""The venv node code imports from is built and kept in step with a manifest."""
import shutil
import subprocess
from pathlib import Path
import pytest
from fluksio.flow import modules
from fluksio.flow.store import FlowStore
pytestmark = pytest.mark.skipif(
shutil.which("uv") is None, reason="module management needs uv"
)
@pytest.fixture
def venv(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
directory = tmp_path / "user-venv"
monkeypatch.setattr(modules, "VENV_DIR", directory)
return directory
def test_an_empty_manifest_gives_a_venv_of_its_own(venv: Path, tmp_path: Path):
store = FlowStore(tmp_path / "flows")
store.write_requirements("")
modules.sync("")
assert Path(modules.venv_python()).exists()
assert modules.venv_python().startswith(str(venv))
information = modules.info(store)
assert information.applied is True
assert information.python_version
def test_a_manifest_already_applied_is_not_installed_again(
venv: Path, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
):
store = FlowStore(tmp_path / "flows")
store.write_requirements("")
modules.sync("")
marker = (venv / ".applied").read_text()
# Recorded rather than refused: reconcile swallows what it fails on, so an
# exception raised in here would never reach the test.
calls: list[object] = []
monkeypatch.setattr(subprocess, "run", lambda *args, **kwargs: calls.append(args))
modules.reconcile(store)
assert calls == []
assert (venv / ".applied").read_text() == marker
def test_a_missing_uv_is_a_failed_apply_rather_than_a_crash(
venv: Path, monkeypatch: pytest.MonkeyPatch
):
def no_uv(*args: object, **kwargs: object) -> None:
raise FileNotFoundError(2, "No such file or directory: 'uv'")
monkeypatch.setattr(subprocess, "run", no_uv)
ok, output = modules.sync("")
# The route turns this into a 400 with the output; an exception would be a
# 500 with nothing in it.
assert ok is False
assert "uv could not run" in output
def test_a_manifest_that_does_not_resolve_leaves_the_venv_alone(venv: Path):
modules.sync("")
ok, output = modules.sync("fluksio-no-such-package-anywhere==9.9.9")
assert ok is False
assert output
# The marker still describes the manifest that actually installed.
assert (venv / ".applied").read_text() == modules._digest("")