fix: an install pins every installed package with a constraints file, so a new package's dependencies cannot move one that is already here; an unreadable package list installs nothing

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
digital-garbage
2026-10-10 16:15:29 +03:00
co-authored by Claude Haiku 5.5
parent 78a418812b
commit 599cb2c0c3
2 changed files with 49 additions and 5 deletions
+29 -3
View File
@@ -229,7 +229,7 @@ def test_a_missing_requirement_is_installed_by_its_whole_line_so_a_pin_or_url_su
monkeypatch.setattr(update, "_installed_version", lambda n: "1.0" if n == "numpy" else None)
ran = []
monkeypatch.setattr(update.subprocess, "run", lambda cmd, **k: ran.append(cmd) or subprocess.CompletedProcess(cmd, 0, "", ""))
monkeypatch.setattr(update, "_pip_freeze", lambda: {})
monkeypatch.setattr(update, "_pip_freeze", lambda: {"numpy": "1.26.4"})
assert update.install_requirements()["ok"]
assert [c[-1] for c in ran] == ["zz_absent_pkg>=3.8,<3.9", "zz_model @ https://example.com/zz_model.whl"]
@@ -244,7 +244,7 @@ def test_one_package_that_cannot_install_does_not_stop_the_others(repo, monkeypa
return subprocess.CompletedProcess(cmd, 1 if "zz_bad_url" in cmd[-1] else 0, "", "404 not found")
monkeypatch.setattr(update.subprocess, "run", fake_run)
monkeypatch.setattr(update, "_pip_freeze", lambda: {})
monkeypatch.setattr(update, "_pip_freeze", lambda: {"numpy": "1.26.4"})
out = update.install_requirements()
assert ran == ["zz_bad_url @ https://example.com/missing.whl", "zz_good_pkg"], "the second still installs"
assert out["ok"] is False and "zz_bad_url" in out["detail"] and "404 not found" in out["detail"]
@@ -269,6 +269,32 @@ def test_a_spacy_model_that_does_not_load_is_downloaded_on_the_switch(repo, monk
ran = []
monkeypatch.setattr(update, "_spacy_model_loads", lambda: bool(ran) and ran[-1] == ["spacy", "download", "en_core_web_sm"])
monkeypatch.setattr(update.subprocess, "run", lambda cmd, **k: ran.append(cmd[-3:]) or subprocess.CompletedProcess(cmd, 0, "", ""))
monkeypatch.setattr(update, "_pip_freeze", lambda: {})
monkeypatch.setattr(update, "_pip_freeze", lambda: {"numpy": "1.26.4"})
assert update.install_requirements()["ok"]
assert ran[-1] == ["spacy", "download", "en_core_web_sm"]
def test_an_install_pins_every_installed_package_so_nothing_already_here_moves(repo, monkeypatch):
(repo / "requirements.txt").write_text("zz_new_pkg\n")
monkeypatch.setattr(update, "_installed_version", lambda n: None)
seen = {}
def fake_run(cmd, **k):
if "-c" in cmd:
seen["constraints"] = open(cmd[cmd.index("-c") + 1]).read()
return subprocess.CompletedProcess(cmd, 0, "", "")
monkeypatch.setattr(update.subprocess, "run", fake_run)
monkeypatch.setattr(update, "_pip_freeze", lambda: {"numpy": "1.26.4", "torch": "2.9.0"})
assert update.install_requirements()["ok"]
assert "numpy==1.26.4" in seen["constraints"] and "torch==2.9.0" in seen["constraints"]
def test_an_unreadable_installed_list_installs_nothing(repo, monkeypatch):
(repo / "requirements.txt").write_text("zz_new_pkg\n")
monkeypatch.setattr(update, "_installed_version", lambda n: None)
ran = []
monkeypatch.setattr(update.subprocess, "run", lambda cmd, **k: ran.append(cmd) or subprocess.CompletedProcess(cmd, 0, "", ""))
monkeypatch.setattr(update, "_pip_freeze", lambda: {})
out = update.install_requirements()
assert out["ok"] is False and ran == []
+20 -2
View File
@@ -12,10 +12,12 @@ feature: no module can announce the thing that updates every module.
"""
from __future__ import annotations
import os
import re
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
@@ -426,9 +428,25 @@ def install_requirements(timeout: int = 900) -> dict:
# stop every other one from installing too. Dependencies are resolved normally: a new package
# with nothing under it is not installed, it is broken. The freeze diff says whether anything
# already present moved as a result.
if not before:
return {"ran": False, "ok": False,
"detail": "Could not read the installed packages, so nothing is installed (an install could move them). "
f"Run it yourself: {sys.executable} -m pip install <the missing packages>"}
# Constraints: every installed package stays at its version, so a new package's dependencies can be added
# but never bump one that is already here. A dependency that needs a newer one fails, and says so.
constraints = tempfile.NamedTemporaryFile("w", suffix=".txt", delete=False, encoding="utf-8")
try:
constraints.write("\n".join(f"{n}=={v}" for n, v in before.items()) + "\n")
constraints.close()
return _install_each(status, constraints.name, before, floor_note, timeout, model_broken)
finally:
os.unlink(constraints.name)
def _install_each(status, constraints_path, before, floor_note, timeout, model_broken):
failed, done = [], []
for line in status.get("install", []):
cmd = [sys.executable, "-m", "pip", "install", "--disable-pip-version-check", line]
cmd = [sys.executable, "-m", "pip", "install", "--disable-pip-version-check", "-c", constraints_path, line]
try:
proc = subprocess.run(cmd, cwd=REPO_ROOT, capture_output=True, text=True, timeout=timeout)
except subprocess.TimeoutExpired:
@@ -442,7 +460,7 @@ def install_requirements(timeout: int = 900) -> dict:
else:
done.append(line)
if model_broken:
cmd = [sys.executable, "-m", "spacy", "download", "en_core_web_sm"]
cmd = [sys.executable, "-m", "spacy", "download", "en_core_web_sm"] # the model is data, not a dependency: no constraints
try:
proc = subprocess.run(cmd, cwd=REPO_ROOT, capture_output=True, text=True, timeout=timeout)
if proc.returncode != 0 or not _spacy_model_loads():