Files
wildminder-ComfyUI-KEEP/tests/test_package_metadata.py
T
WildAi fcbfcce3a6 plan(P3): address review findings
Five review findings of the P3 phase, each fixed at its root:

1. (medium) The P3.7 metadata test imported `tomllib` at module level: the
   **3.10 CI job** (the declared `requires-python >=3.10` minimum) died
   during collection, so the registry-metadata assertions never ran on 3.10.
   The parser import is now guarded (`tomllib` -> `tomli`, the package the
   3.10 job installs); without any parser the module *skips* instead of
   dying. `pyproject.toml` gained the test extra
   `tomli>=2.0; python_version < '3.11'`.
   Proof: a 3.10 simulation (the stdlib `tomllib` refused for the test
   module, `tomli` on sys.path) -> 6 passed; the control without `tomli`
   -> 6 skipped (no collection error).

2. (medium) The P3.5 "primary-root-first multi-root" resolution was not
   wired into the production load path: `resolve_model_file` (the only
   `get_full_path_or_raise` caller) was used by tests only, so a weight in
   a secondary model root was downloaded into the primary root again.
   `src/keep_paths.py` now has `find_model_file()` (the multi-root lookup
   through `folder_paths.get_full_path_or_raise`) and `resolve_model_root()`
   (the root the weights really live in); `load_file_from_url_comfy()` - the
   production path of `src/keep_model_loader.py:107` - uses the lookup, and
   the facelib root follows the weights (the facelib helper builds its
   paths from a single root). New tests prove that the production path
   uses a weight of an extra model root and that the primary root wins.
   The `models_dir` grep guard is no longer a blanket exemption: only the
   registration in `src/keep_paths.py` may use the attribute.

3. (low) `[tool.comfy].Icon` was an empty string and the test only checked
   that the key exists. The preview asset **is** committed
   (`git cat-file -s HEAD:assets/keep-preview.png` -> 93279 bytes); only the
   working copy was missing (an uncommitted local deletion, restored from
   HEAD - no asset change is in this commit). The key now points at
   `assets/keep-preview.png` and the test asserts that the value is not
   empty and names a file that is really in the repository.

4. (low) `tests/test_package_entrypoint.py` hard-coded the V1 state and
   would have gone red (not xfail) when P4.4 flips the root `__init__.py`
   to `comfy_entrypoint`. The assertions now follow the entry point that is
   really there: exactly **one** mapping style (V1 XOR V3). The mocked
   smoke test of `tests/test_package_import.py` got the same treatment; the
   headless variant is P4.4's job (its test list names it).

5. (low) The plan's §3 rule ("`comfy.*` imports inside `src/` are lazy
   (function-level) so the pack imports without a ComfyUI server") was
   violated and unguarded. The `comfy` imports of `src/keep_model_loader.py`
   and `src/keep_processor.py` are function-level now; the vendored facelib
   helper (which imports `comfy` itself) is imported lazily through a module
   `__getattr__` (PEP 562), so `loader.FaceRestoreHelper` still resolves to
   the vendored class. Structure **guard (f)** (`tests/test_structure.py`)
   forbids a module-level `comfy`/`comfy_api` import in `src/**` (with the
   self-test the guards file demands), and the new
   `tests/test_lazy_imports.py` proves at runtime that the engines import
   while every `comfy` import is blocked.

Gate after the commit:
  python.exe -m pytest -q tests -m "unit or mock_integration"
    -> 153 passed, 1 skipped, 5 deselected, 3 xfailed
  COMFYUI_ROOT=C:/_Dev/ComfyUI_dev/ComfyUI-source/ComfyUI python.exe
    -m pytest -q tests -m "unit or mock_integration or headless"
    -> 158 passed, 1 skipped, 3 xfailed

Details: docs/2026-10-23-p3-review-findings.md
2026-10-23 20:34:51 +03:00

121 lines
4.1 KiB
Python

"""P3.7 - the registry metadata of the pack.
``pyproject.toml`` is the metadata the ComfyUI Registry reads. The test
parses it with ``tomllib`` (the standard library since Python 3.11) and
asserts that the metadata is complete and that the dependency list is the
true runtime set of P2.6 (``requirements.txt``).
The parser import is **guarded**: the pack supports Python 3.10
(``requires-python = ">=3.10"``), where ``tomllib`` does not exist. The
3.10 CI job installs ``tomli`` (the same parser under its old name), so the
metadata is asserted on 3.10 as well - the module never dies during
collection.
"""
from __future__ import annotations
from pathlib import Path
import pytest
try: # Python 3.11+
import tomllib
except ModuleNotFoundError: # Python 3.10 - the CI job installs ``tomli``
try:
import tomli as tomllib # type: ignore[no-redef]
except ModuleNotFoundError: # no TOML parser at all
tomllib = None # type: ignore[assignment]
REPO_ROOT = Path(__file__).resolve().parent.parent
PYPROJECT = REPO_ROOT / "pyproject.toml"
REQUIREMENTS = REPO_ROOT / "requirements.txt"
#: The metadata of the pack (P3.7).
EXPECTED_VERSION = "2.0.0"
EXPECTED_REQUIRES_PYTHON = ">=3.10"
EXPECTED_COMFY = {
"PublisherId": "wildai",
"DisplayName": "KEEP",
"requires-comfyui": ">=0.28.0",
}
#: The preview asset of the registry entry (P3.7 - the ``Icon`` key).
EXPECTED_ICON = "assets/keep-preview.png"
@pytest.fixture(scope="module")
def pyproject() -> dict:
assert PYPROJECT.is_file(), f"missing {PYPROJECT}"
if tomllib is None:
pytest.skip(
"no TOML parser available - install ``tomli`` on Python 3.10 "
"(the CI job does)"
)
with PYPROJECT.open("rb") as handle:
return tomllib.load(handle)
def _requirement_entries() -> set[str]:
return {
line.strip()
for line in REQUIREMENTS.read_text(encoding="utf-8").splitlines()
if line.strip() and not line.strip().startswith("#")
}
@pytest.mark.unit
def test_the_pyproject_parses(pyproject):
"""The metadata is parseable (tomllib on Python 3.11+, tomli on 3.10)."""
assert "project" in pyproject
assert pyproject["project"]["name"] == "ComfyUI-KEEP"
@pytest.mark.unit
def test_the_version_is_the_release_version(pyproject):
"""The pack is version ``2.0.0``."""
assert pyproject["project"]["version"] == EXPECTED_VERSION
@pytest.mark.unit
def test_the_python_requirement_is_declared(pyproject):
"""The pack supports Python 3.10 and newer."""
assert pyproject["project"]["requires-python"] == EXPECTED_REQUIRES_PYTHON
@pytest.mark.unit
def test_the_comfy_metadata_is_complete(pyproject):
"""Every ``[tool.comfy]`` key of the registry is present."""
comfy = pyproject.get("tool", {}).get("comfy")
assert comfy is not None, "pyproject.toml has no [tool.comfy] table"
for key, value in EXPECTED_COMFY.items():
assert key in comfy, f"[tool.comfy] has no {key}"
assert comfy[key] == value, f"[tool.comfy].{key}: {comfy[key]!r} != {value!r}"
assert "Icon" in comfy, "[tool.comfy] has no Icon"
@pytest.mark.unit
def test_the_icon_points_at_the_preview_asset(pyproject):
"""The ``Icon`` is not an empty string - it points at the preview asset.
An empty ``Icon`` passes the "the key exists" check above, but the
registry entry has no preview then: the value must name a file that is
really in the repository.
"""
comfy = pyproject.get("tool", {}).get("comfy") or {}
icon = comfy.get("Icon", "")
assert isinstance(icon, str) and icon.strip(), (
f"[tool.comfy].Icon is empty - the registry entry would have no preview"
)
assert icon == EXPECTED_ICON, icon
asset = REPO_ROOT / icon
assert asset.is_file(), f"the icon {icon!r} is not in the repository"
@pytest.mark.unit
def test_the_dependencies_are_the_true_runtime_set(pyproject):
"""The declared dependencies are exactly the ones of ``requirements.txt``."""
declared = set(pyproject["project"]["dependencies"])
assert declared == _requirement_entries(), sorted(
declared ^ _requirement_entries()
)