From c36ef73342782b116aa46106374dae1656ad984a Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Thu, 4 Jun 2026 01:34:20 -0700 Subject: [PATCH] feat: catalog Record dict conversion --- hef/catalog.py | 19 ++++++++++++++++++- tests/test_catalog.py | 23 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hef/catalog.py b/hef/catalog.py index 4f7c142..d4bcc10 100644 --- a/hef/catalog.py +++ b/hef/catalog.py @@ -2,7 +2,7 @@ from __future__ import annotations -from dataclasses import dataclass +from dataclasses import dataclass, asdict, fields from typing import Optional MODES = frozenset({"audio", "video", "av"}) @@ -70,3 +70,20 @@ def validate(record: Record) -> None: raise CatalogError("duration_s must be non-negative") if record.license in ATTRIBUTION_LICENSES and not record.attribution: raise CatalogError(f"license {record.license} requires attribution") + + +def record_to_dict(record: Record) -> dict: + """Convert a Record to a plain dict suitable for JSON serialization.""" + return asdict(record) + + +def record_from_dict(data: dict) -> Record: + """Build a Record from a dict, rejecting unknown or missing fields.""" + known = {f.name for f in fields(Record)} + unknown = set(data) - known + if unknown: + raise CatalogError(f"unknown fields: {sorted(unknown)}") + try: + return Record(**data) + except TypeError as exc: + raise CatalogError(str(exc)) from exc diff --git a/tests/test_catalog.py b/tests/test_catalog.py index ff75108..6ed5f13 100644 --- a/tests/test_catalog.py +++ b/tests/test_catalog.py @@ -69,3 +69,26 @@ def test_empty_id_raises(): def test_negative_duration_raises(): with pytest.raises(CatalogError): validate(make_record(duration_s=-1)) + + +from hef.catalog import record_to_dict, record_from_dict + + +def test_dict_round_trip(): + record = make_record() + restored = record_from_dict(record_to_dict(record)) + assert restored == record + + +def test_record_from_dict_rejects_unknown_field(): + data = record_to_dict(make_record()) + data["bogus"] = 1 + with pytest.raises(CatalogError): + record_from_dict(data) + + +def test_record_from_dict_rejects_missing_required_field(): + data = record_to_dict(make_record()) + del data["title"] + with pytest.raises(CatalogError): + record_from_dict(data)