fix: a requirement that cannot install no longer blocks the others; comfy-kitchen's sol_attn floor (0.2.32) is in requirements, so an older version is reported on update
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
7aa571000a
commit
7a809ae7d2
@@ -231,7 +231,24 @@ def test_a_missing_requirement_is_installed_by_its_whole_line_so_a_pin_or_url_su
|
||||
monkeypatch.setattr(update.subprocess, "run", lambda cmd, **k: ran.append(cmd) or subprocess.CompletedProcess(cmd, 0, "", ""))
|
||||
monkeypatch.setattr(update, "_pip_freeze", lambda: {})
|
||||
assert update.install_requirements()["ok"]
|
||||
assert ran[0][-2:] == ["zz_absent_pkg>=3.8,<3.9", "zz_model @ https://example.com/zz_model.whl"]
|
||||
assert [c[-1] for c in ran] == ["zz_absent_pkg>=3.8,<3.9", "zz_model @ https://example.com/zz_model.whl"]
|
||||
|
||||
|
||||
def test_one_package_that_cannot_install_does_not_stop_the_others(repo, monkeypatch):
|
||||
(repo / "requirements.txt").write_text("zz_bad_url @ https://example.com/missing.whl\nzz_good_pkg\n")
|
||||
monkeypatch.setattr(update, "_installed_version", lambda n: None)
|
||||
ran = []
|
||||
|
||||
def fake_run(cmd, **k):
|
||||
ran.append(cmd[-1])
|
||||
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: {})
|
||||
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"]
|
||||
assert "zz_good_pkg" not in out["detail"].split("Could not install:")[1].split("\n")[0]
|
||||
|
||||
|
||||
def test_a_branch_switch_installs_what_is_missing_even_when_the_requirements_file_did_not_change(repo, monkeypatch):
|
||||
|
||||
+28
-23
@@ -405,35 +405,40 @@ def install_requirements(timeout: int = 900) -> dict:
|
||||
+ (f"\n\n{floor_note}" if floor_note else ""))}
|
||||
|
||||
before = _pip_freeze()
|
||||
# Only the absent ones, by name — never `-r requirements.txt`, which would upgrade
|
||||
# anything below its floor. Dependencies are resolved normally: a new package with
|
||||
# nothing under it is not installed, it is broken. The freeze diff below is what says
|
||||
# whether anything already present moved as a result.
|
||||
cmd = [sys.executable, "-m", "pip", "install", "--disable-pip-version-check",
|
||||
*status["install"]]
|
||||
try:
|
||||
proc = subprocess.run(cmd, cwd=REPO_ROOT, capture_output=True, text=True,
|
||||
timeout=timeout)
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"ran": True, "ok": False,
|
||||
"detail": f"pip did not finish within {timeout}s — run it yourself: "
|
||||
f"pip install {' '.join(status['install'])}"}
|
||||
except OSError as e:
|
||||
return {"ran": True, "ok": False, "detail": f"could not run pip: {e}"}
|
||||
if proc.returncode != 0:
|
||||
tail = ((proc.stderr or proc.stdout or "").strip() or "pip failed")[-800:]
|
||||
return {"ran": True, "ok": False,
|
||||
"detail": f"pip install failed — run it yourself:\n"
|
||||
f" {sys.executable} -m pip install "
|
||||
f"{' '.join(status['install'])}\n\n{tail}"}
|
||||
# One pip call per absent requirement, never `-r requirements.txt` (that would upgrade anything
|
||||
# below its floor). Separate calls, because one call is all-or-nothing: a single package that
|
||||
# cannot install (a model URL that is unreachable, a wheel missing for this Python) used to
|
||||
# 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.
|
||||
failed, done = [], []
|
||||
for line in status["install"]:
|
||||
cmd = [sys.executable, "-m", "pip", "install", "--disable-pip-version-check", line]
|
||||
try:
|
||||
proc = subprocess.run(cmd, cwd=REPO_ROOT, capture_output=True, text=True, timeout=timeout)
|
||||
except subprocess.TimeoutExpired:
|
||||
failed.append((line, f"pip did not finish within {timeout}s"))
|
||||
continue
|
||||
except OSError as e:
|
||||
failed.append((line, f"could not run pip: {e}"))
|
||||
continue
|
||||
if proc.returncode != 0:
|
||||
failed.append((line, ((proc.stderr or proc.stdout or "").strip() or "pip failed")[-400:]))
|
||||
else:
|
||||
done.append(line)
|
||||
changed = _pip_diff(before, _pip_freeze())
|
||||
if changed:
|
||||
print("[FunPack update] pip changed these packages: " + ", ".join(changed))
|
||||
if failed:
|
||||
return {"ran": True, "ok": False, "changed": changed,
|
||||
"detail": ("Could not install: " + ", ".join(line for line, _ in failed) + ".\n"
|
||||
+ "\n".join(f"{line}:\n{tail}" for line, tail in failed)
|
||||
+ "\n\nTo do it yourself:\n"
|
||||
+ "\n".join(f" {sys.executable} -m pip install {line}" for line, _ in failed))}
|
||||
return {"ran": True, "ok": True, "changed": changed,
|
||||
"detail": (f"Installed missing: {', '.join(status['missing'])}\n"
|
||||
+ (("Changed: " + ", ".join(changed) + "\n") if changed else "")
|
||||
+ (f"\n{floor_note}\n" if floor_note else "")
|
||||
+ (proc.stdout or "").strip()[-800:])}
|
||||
+ (f"\n{floor_note}\n" if floor_note else ""))}
|
||||
|
||||
|
||||
def _pip_freeze() -> dict:
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Version floors ONLY where FunPack needs one, and never a bare upgrade of
|
||||
# anything the rest of ComfyUI compiles against.
|
||||
#
|
||||
# SLA's sol-attn method needs comfy_kitchen's compiled sol_attn kernel, first in 0.2.32. A lower
|
||||
# version is reported on update, never upgraded automatically: it is compiled against torch.
|
||||
comfy-kitchen>=0.2.32
|
||||
|
||||
# Reads .gguf containers in the FunPack loaders. Pure python + numpy; it does
|
||||
# not pull CUDA or any model. Without it a .gguf needs the ComfyUI-GGUF node
|
||||
# pack instead.
|
||||
|
||||
Reference in New Issue
Block a user