diff --git a/hef/catalog.py b/hef/catalog.py index 56aac04..0e61c54 100644 --- a/hef/catalog.py +++ b/hef/catalog.py @@ -126,3 +126,20 @@ def append_record(record, path) -> None: path = Path(path) with path.open("a", encoding="utf-8") as fh: fh.write(json.dumps(record_to_dict(record), ensure_ascii=False) + "\n") + + +def index_by_id(records) -> dict: + """Map id -> Record, raising CatalogError on a duplicate id.""" + idx: dict = {} + for r in records: + if r.id in idx: + raise CatalogError(f"duplicate record id: {r.id!r}") + idx[r.id] = r + return idx + + +def validate_catalog(records) -> None: + """Validate every record AND cross-record invariants (currently: unique ids).""" + for r in records: + validate(r) + index_by_id(records) # raises on duplicate id diff --git a/tests/test_catalog_integrity.py b/tests/test_catalog_integrity.py new file mode 100644 index 0000000..c12c5a3 --- /dev/null +++ b/tests/test_catalog_integrity.py @@ -0,0 +1,48 @@ +import pytest + +from hef.catalog import Record, validate_catalog, index_by_id, CatalogError + + +def make_record(**o): + base = dict( + id="a", + title="t", + source_url="u", + source_archive="nasa", + license="public_domain", + mode="video", + left=0, + right=0, + dark=0, + light=0, + duration_s=1, + file_path="p", + ) + base.update(o) + return Record(**base) + + +def test_validate_catalog_accepts_unique_ids(): + validate_catalog([make_record(id="a"), make_record(id="b")]) # no raise + + +def test_validate_catalog_rejects_duplicate_id(): + with pytest.raises(CatalogError) as e: + validate_catalog([make_record(id="dup"), make_record(id="dup")]) + assert "dup" in str(e.value) + + +def test_validate_catalog_validates_each_record(): + with pytest.raises(CatalogError): + validate_catalog([make_record(left=9)]) + + +def test_index_by_id_round_trips(): + recs = [make_record(id="a"), make_record(id="b")] + idx = index_by_id(recs) + assert idx["a"].id == "a" and idx["b"].id == "b" + + +def test_index_by_id_rejects_duplicates(): + with pytest.raises(CatalogError): + index_by_id([make_record(id="x"), make_record(id="x")])