"""Tests for the dependency bootstrap. The behaviour that matters: a normal start must not touch the network, a missing library should be installed once, and a failed install must report clearly instead of crashing. """ import os import sys import tempfile SRC = os.path.join( os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src" ) if SRC not in sys.path: sys.path.insert(0, SRC) import pytest # noqa: E402 from rdm_card_reader import bootstrap # noqa: E402 from rdm_card_reader.bootstrap import ( # noqa: E402 _pip_command, ensure_dependencies, install, missing_packages, ) class FakeCompleted: def __init__(self, returncode=0, stdout="", stderr=""): self.returncode = returncode self.stdout = stdout self.stderr = stderr # -- detection -------------------------------------------------------------- def test_nothing_missing_for_installed_packages(): assert missing_packages([("sys", "sys")]) == [] def test_importable_name_is_reported_missing(): result = missing_packages([("definitely_not_a_real_module_xyz", "pkg>=1")]) assert result == [("definitely_not_a_real_module_xyz", "pkg>=1")] # -- pip command ------------------------------------------------------------ def test_pip_command_uses_this_interpreter(): command = _pip_command(["pkg>=1"], wheel_dir=None) assert command[:3] == [sys.executable, "-m", "pip"] assert "pkg>=1" in command def test_pip_command_prefers_local_wheels_when_given(): command = _pip_command(["pkg>=1"], wheel_dir="/opt/wheels") assert "--no-index" in command assert "--find-links" in command assert "/opt/wheels" in command def test_pip_command_adds_break_system_packages_outside_venv(monkeypatch): """Debian's pip refuses to touch system Python without this flag.""" monkeypatch.delenv("VIRTUAL_ENV", raising=False) monkeypatch.setattr(bootstrap, "in_virtualenv", lambda: False) assert "--break-system-packages" in _pip_command(["pkg"], None) def test_pip_command_omits_flag_inside_venv(monkeypatch): monkeypatch.setattr(bootstrap, "in_virtualenv", lambda: True) assert "--break-system-packages" not in _pip_command(["pkg"], None) def test_in_virtualenv_detects_env_var(monkeypatch): monkeypatch.setenv("VIRTUAL_ENV", "/tmp/venv") assert bootstrap.in_virtualenv() is True # -- install ---------------------------------------------------------------- def test_install_reports_success(monkeypatch): monkeypatch.setattr( bootstrap.subprocess, "run", lambda *a, **k: FakeCompleted(0) ) assert install(["pkg"]) is True def test_install_returns_false_on_nonzero_exit(monkeypatch): monkeypatch.setattr( bootstrap.subprocess, "run", lambda *a, **k: FakeCompleted(1, stderr="ERROR: no matching distribution"), ) lines = [] assert install(["pkg"], logger=lines.append) is False assert any("no matching distribution" in line for line in lines) def test_install_survives_timeout(monkeypatch): def boom(*args, **kwargs): raise bootstrap.subprocess.TimeoutExpired(cmd="pip", timeout=1) monkeypatch.setattr(bootstrap.subprocess, "run", boom) assert install(["pkg"]) is False def test_install_survives_pip_being_unrunnable(monkeypatch): def boom(*args, **kwargs): raise OSError("no such file or directory") monkeypatch.setattr(bootstrap.subprocess, "run", boom) assert install(["pkg"]) is False # -- ensure_dependencies ---------------------------------------------------- def test_no_install_when_everything_present(monkeypatch): """A normal start must not shell out to pip at all.""" called = [] monkeypatch.setattr(bootstrap, "missing_packages", lambda packages=None: []) monkeypatch.setattr(bootstrap, "install", lambda *a, **k: called.append(1)) assert ensure_dependencies() is True assert called == [] def test_installs_when_missing(monkeypatch): state = {"installed": False} monkeypatch.setattr( bootstrap, "missing_packages", lambda packages=None: [] if state["installed"] else [("rdm6300", "rdm6300>=0.1.1")], ) def fake_install(requirements, wheel_dir=None, logger=None, timeout=300): state["installed"] = True return True monkeypatch.setattr(bootstrap, "install", fake_install) assert ensure_dependencies() is True def test_reports_failure_when_still_missing(monkeypatch): monkeypatch.setattr( bootstrap, "missing_packages", lambda packages=None: [("rdm6300", "rdm6300>=0.1.1")], ) monkeypatch.setattr(bootstrap, "install", lambda *a, **k: False) lines = [] assert ensure_dependencies(logger=lines.append) is False assert any("Install manually with" in line for line in lines) def test_no_install_flag_reports_manual_hint(monkeypatch): monkeypatch.setattr( bootstrap, "missing_packages", lambda packages=None: [("rdm6300", "rdm6300>=0.1.1")], ) called = [] monkeypatch.setattr(bootstrap, "install", lambda *a, **k: called.append(1)) lines = [] assert ensure_dependencies(auto_install=False, logger=lines.append) is False assert called == [] # never shelled out assert any("disabled" in line for line in lines) def test_wheel_dir_is_passed_through(monkeypatch): """An explicit --wheel-dir that covers everything is used as given.""" seen = {} monkeypatch.setattr( bootstrap, "missing_packages", lambda packages=None: [] if seen.get("done") else [("x", "x>=1")], ) def fake_install(requirements, wheel_dir=None, logger=None, timeout=300): seen["wheel_dir"] = wheel_dir seen["done"] = True return True monkeypatch.setattr(bootstrap, "install", fake_install) with tempfile.TemporaryDirectory() as folder: open(os.path.join(folder, "x-1.0-py3-none-any.whl"), "wb").close() ensure_dependencies(wheel_dir=folder) assert seen["wheel_dir"] == folder def test_incomplete_explicit_wheel_dir_is_flagged(monkeypatch): """An unusable --wheel-dir should be called out, not silently ignored.""" seen = {} monkeypatch.setattr( bootstrap, "missing_packages", lambda packages=None: [] if seen.get("done") else [("x", "x>=1")], ) def fake_install(requirements, wheel_dir=None, logger=None, timeout=300): seen["done"] = True return True monkeypatch.setattr(bootstrap, "install", fake_install) lines = [] with tempfile.TemporaryDirectory() as folder: ensure_dependencies(wheel_dir=folder, logger=lines.append) assert any("you gave is incomplete" in line for line in lines)