open-navigator / packages /hosting /tests /test_huggingface_publisher.py
jcbowyer's picture
Clean HuggingFace deployment without binary files
e59d91d
Raw
History Blame Contribute Delete
4.1 kB
"""Unit tests for the hosting.huggingface library (no network calls)."""
from __future__ import annotations
import pandas as pd
import pytest
from hosting.huggingface import HFConfig, HFConfigError, dataset_name_from_stem
from hosting.huggingface import datasets as ds
from hosting.huggingface import spaces
from hosting.huggingface.publisher import DatasetPublisher, UploadResult, summarize
# -- config ------------------------------------------------------------
def test_config_dataset_repo_id():
cfg = HFConfig(token="t", organization="Org", dataset_prefix="one")
assert cfg.dataset_repo_id("bills") == "Org/one-bills"
assert cfg.dataset_prefix_repo("meetings") == "Org/one-meetings"
def test_require_token_raises_when_missing():
with pytest.raises(HFConfigError):
HFConfig(token=None).require_token()
# -- name simplification ----------------------------------------------
@pytest.mark.parametrize(
"stem,expected",
[
("bills_bills", "bills"),
("bills_bill_actions", "bill-actions"),
("nonprofits_organizations", "nonprofits-organizations"),
("events_documents", "event-documents"),
("some_other_table", "some-other-table"),
],
)
def test_dataset_name_from_stem(stem, expected):
assert dataset_name_from_stem(stem) == expected
# -- split name derivation for state splits ---------------------------
def test_split_name_for_strips_state_and_family_prefix():
assert ds._split_name_for("nonprofits_organizations_AL", "AL") == "organizations"
assert ds._split_name_for("jurisdictions_directory_TX", "TX") == "directory"
# -- registries are well-formed ---------------------------------------
def test_registries_use_parquet_filenames():
for table in (ds.MEETING_TABLES, ds.CONTACTS_TABLES, ds.NONPROFIT_TABLES):
assert all(fname.endswith(".parquet") for fname in table.values())
assert "AL" in ds.US_STATES and "DC" in ds.US_STATES
# -- summarize ---------------------------------------------------------
def test_summarize_counts_ok_and_failed():
results = [
UploadResult(repo_id="a", url="u", records=10),
UploadResult(repo_id="b", url="u", error="boom"),
]
ok, failed, total = summarize(results)
assert (ok, failed, total) == (1, 1, 10)
# -- publisher wiring (mock HF, no network) ---------------------------
class _FakeDataset:
def __init__(self, df):
self.df = df
@classmethod
def from_pandas(cls, df):
return cls(df)
def push_to_hub(self, **kwargs): # noqa: D401 - records the call
_FakeDataset.last_call = kwargs
def _make_publisher(monkeypatch):
pub = DatasetPublisher.__new__(DatasetPublisher)
pub.config = HFConfig(token="t", organization="Org", dataset_prefix="one")
pub.token = "t"
pub.api = object()
monkeypatch.setattr(pub, "ensure_repo", lambda *a, **k: None)
return pub
def test_publish_dataframe_pushes_with_split(monkeypatch):
import hosting.huggingface.publisher as pub_mod
monkeypatch.setitem(__import__("sys").modules, "datasets", type("M", (), {"Dataset": _FakeDataset}))
pub = _make_publisher(monkeypatch)
df = pd.DataFrame({"x": [1, 2, 3]})
result = pub.publish_dataframe(df, "Org/one-bills", split="train")
assert result.ok
assert result.records == 3
assert _FakeDataset.last_call["repo_id"] == "Org/one-bills"
assert _FakeDataset.last_call["split"] == "train"
def test_publish_parquet_missing_file_returns_error(monkeypatch, tmp_path):
pub = _make_publisher(monkeypatch)
result = pub.publish_parquet(tmp_path / "nope.parquet", "Org/one-x")
assert not result.ok
assert result.error == "File not found"
# -- spaces dry-run counting ------------------------------------------
def test_space_dry_run_counts_files(tmp_path):
(tmp_path / "keep.txt").write_text("a")
(tmp_path / "node_modules").mkdir()
(tmp_path / "node_modules" / "x.js").write_text("b")
count = spaces.SpaceDeployer._count_uploadable(
tmp_path, spaces.DEFAULT_IGNORE_PATTERNS
)
assert count == 1