mindXtrain / tests /test_hf_extension.py
Gregory-L's picture
v1.0.4 — close the limitations 1.0.3 listed, and correct the ones it overstated
74da4f7 verified
Raw History Blame Contribute Delete
6.54 kB
"""Units for the Hugging Face extension and its CLI surface.
`huggingface_hub` is an optional extra, so the missing-dependency path is asserted by FORCING
its absence (`sys.modules[name] = None` makes `import` raise) rather than by trusting the
ambient environment. It was trusted once: these tests passed on a bare install and inverted
silently the moment the `ui` extra arrived, because gradio depends on huggingface-hub.
Everything else runs against stubs: no token, no network, no Hub.
"""
from __future__ import annotations
import sys
from typing import Any
import pytest
from typer.testing import CliRunner
from mindxtrain.cli.main import app
from mindxtrain.hf import extension as ext
runner = CliRunner()
@pytest.fixture(autouse=True)
def no_ambient_token(monkeypatch: pytest.MonkeyPatch) -> None:
"""A developer's real HF_TOKEN must not change what these tests assert."""
for name in ext._HF_ENV:
monkeypatch.delenv(name, raising=False)
@pytest.fixture
def hub_absent(monkeypatch: pytest.MonkeyPatch) -> None:
"""Force `import huggingface_hub` to fail, whatever is installed.
A `None` entry in `sys.modules` makes the import raise ImportError, so the
not-installed contract is testable on a machine where the extra IS installed.
"""
monkeypatch.setitem(sys.modules, "huggingface_hub", None)
# --- token resolution --------------------------------------------------------------------
def test_explicit_token_beats_the_environment(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("HF_TOKEN", "from-env")
assert ext._token("explicit") == "explicit"
def test_environment_names_are_tried_in_order(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("HUGGINGFACEHUB_API_TOKEN", "third")
assert ext._token() == "third"
monkeypatch.setenv("HF_TOKEN", "first")
assert ext._token() == "first"
def test_no_token_anywhere_is_none() -> None:
assert ext._token() is None
# --- the optional dependency is reported, never raised -----------------------------------
def test_missing_dependency_is_a_result_not_an_exception(hub_absent: None) -> None:
"""A missing optional extra is reported as a result; it must never raise at the caller."""
api, err = ext._api("a-token")
assert api is None
assert err["ok"] is False
assert "--extra hf" in err["reason"] # the extra that actually installs it
def test_pull_base_reports_the_missing_dependency(hub_absent: None) -> None:
out = ext.pull_base("HuggingFaceTB/SmolLM2-135M")
assert out["ok"] is False and "huggingface_hub" in out["reason"]
def test_no_token_names_the_variables_to_set(monkeypatch: pytest.MonkeyPatch) -> None:
"""With the library present but no token, the error must say which env vars are read."""
monkeypatch.setattr(ext, "_api", ext._api) # keep the real function
fake_hub = type("m", (), {"HfApi": lambda **kw: None})
monkeypatch.setitem(__import__("sys").modules, "huggingface_hub", fake_hub)
api, err = ext._api()
assert api is None
assert "HF_TOKEN" in err["reason"]
# --- tree_paths: the RepoFolder trap -----------------------------------------------------
# The filter matches on the CLASS NAME, so these stubs must carry the Hub's exact names —
# `tree_paths` deliberately avoids importing the optional type just to check it.
class RepoFile:
def __init__(self, path: str) -> None:
self.path = path
class RepoFolder:
def __init__(self, path: str) -> None:
self.path = path
def test_tree_paths_skips_folders() -> None:
"""Folders and files both carry `.path`; counting folders as files corrupts any scan."""
api = type("A", (), {"list_repo_tree": lambda self, r, **kw: [
RepoFile("gen1/adapter.safetensors"), RepoFolder("gen1"), RepoFile("README.md"),
]})()
assert ext.tree_paths(api, "PYTHAI/x") == ["gen1/adapter.safetensors", "README.md"]
def test_tree_paths_on_a_tree_of_only_folders_is_empty() -> None:
"""The bug this guards: a scan reporting "nothing on the Hub" while the repo is full."""
api = type("A", (), {"list_repo_tree": lambda self, r, **kw: [RepoFolder("gen1"), RepoFolder("gen2")]})()
assert ext.tree_paths(api, "PYTHAI/x") == []
# --- guards that must not need a network -------------------------------------------------
def test_warm_refuses_a_config_without_a_model(tmp_path) -> None: # type: ignore[no-untyped-def]
cfg = tmp_path / "run.yaml"
cfg.write_text("train:\n epochs: 1\n", encoding="utf-8")
out = ext.warm(cfg)
assert out["ok"] is False
assert "model.name" in out["reason"] or "huggingface_hub" in out["reason"]
def test_publish_refuses_a_missing_run_dir(tmp_path) -> None: # type: ignore[no-untyped-def]
out = ext.publish_generation(tmp_path / "nope", "PYTHAI/x")
assert out["ok"] is False and "no run dir" in out["reason"]
# --- the CLI surface ---------------------------------------------------------------------
def test_hf_is_registered_as_a_command_group() -> None:
result = runner.invoke(app, ["--help"])
assert "hf" in result.stdout
def test_every_hf_verb_is_reachable() -> None:
result = runner.invoke(app, ["hf", "--help"])
for verb in ("whoami", "pull", "warm", "publish", "lineage", "dataset", "space"):
assert verb in result.stdout
def test_failure_exits_nonzero_so_a_script_can_branch(hub_absent: None) -> None:
"""The ascent loop warms a base and checks $? — an `ok:false` that exits 0 would be a trap."""
result = runner.invoke(app, ["hf", "whoami"])
assert result.exit_code == 1
assert "huggingface_hub" in result.stdout
def test_success_exits_zero_and_prints_the_result(monkeypatch: pytest.MonkeyPatch) -> None:
import mindxtrain.hf as hf_pkg
monkeypatch.setattr(hf_pkg, "account", lambda tok=None: {"ok": True, "name": "Gregory-L",
"can_write": ["PYTHAI"]})
result = runner.invoke(app, ["hf", "whoami"])
assert result.exit_code == 0
assert "Gregory-L" in result.stdout
def test_token_option_is_passed_through(monkeypatch: pytest.MonkeyPatch) -> None:
seen: dict[str, Any] = {}
import mindxtrain.hf as hf_pkg
def fake_account(tok=None): # type: ignore[no-untyped-def]
seen["token"] = tok
return {"ok": True}
monkeypatch.setattr(hf_pkg, "account", fake_account)
assert runner.invoke(app, ["hf", "whoami", "--token", "abc"]).exit_code == 0
assert seen["token"] == "abc"