Initializare dupa curatare folder
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
"""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, no_deps=False):
|
||||
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, no_deps=False):
|
||||
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, no_deps=False):
|
||||
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)
|
||||
Reference in New Issue
Block a user