From 7d2c393118687562d6acd9564e4253d5166f92ea Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 6 Nov 2026 03:53:26 +0100 Subject: [PATCH] fix: provenance gaps read held names by index profile_needs decided held-ness from each record's own name. np2pi's KANJI2.ROM, held as the PC-88 n88knj2.rom, was listed missing and paired with a Fujitsu dump. It now reads by_name as verify does, and an unsourceable entry is not held by a homonym, which lists xm7's KANJI.ROM. --- scripts/provenance_report.py | 10 +++++++++- tests/test_provenance.py | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/scripts/provenance_report.py b/scripts/provenance_report.py index 77d217143..a54c1b0a6 100644 --- a/scripts/provenance_report.py +++ b/scripts/provenance_report.py @@ -80,11 +80,17 @@ def profile_needs(profiles: dict, db: dict) -> dict: (_crc_key(str(f.get("crc32", "")).lower()), f.get("size")) for f in files.values() if f.get("crc32") } + # Held under its own name or under an alias the database indexes, as + # the resolver and verify read it: np2pi's KANJI2.ROM is the PC-88 + # n88knj2.rom, and its own name alone listed it missing. sizes_by_name: dict[str, set[int]] = {} for record in files.values(): sizes_by_name.setdefault(str(record.get("name", "")).casefold(), set()).add( record.get("size") ) + for alias, sha1s in indexes.get("by_name", {}).items(): + held = sizes_by_name.setdefault(str(alias).casefold(), set()) + held.update(files[sha1].get("size") for sha1 in sha1s if sha1 in files) by_hash: dict[tuple, list[dict]] = {} by_name: dict[str, list[tuple[dict, dict]]] = {} @@ -117,7 +123,9 @@ def profile_needs(profiles: dict, db: dict) -> dict: if all(entry.get(k) is None for k in ("size", "min_size", "max_size")): continue names = [name, *(entry.get("aliases") or [])] - if any( + # An unsourceable entry is not held by a homonym: xm7's + # KANJI2.ROM is the Fujitsu font, the held one the PC-88's. + if not entry.get("unsourceable") and any( _fits(held, entry) for alias in names for held in sizes_by_name.get(str(alias).casefold(), ()) diff --git a/tests/test_provenance.py b/tests/test_provenance.py index a1ed98574..d76d3a9b4 100644 --- a/tests/test_provenance.py +++ b/tests/test_provenance.py @@ -417,6 +417,29 @@ class TestProvenanceReport(unittest.TestCase): ) +class HeldUnderAnAlias(unittest.TestCase): + """profile_needs read held names from each record's own name: np2pi's + KANJI2.ROM, which the database holds as the PC-88 n88knj2.rom, was + listed missing and paired with the Fujitsu FM77AV40SX dump.""" + + DB = { + "files": {"a" * 40: {"name": "n88knj2.rom", "size": 131072}}, + "indexes": {"by_name": {"KANJI2.ROM": ["a" * 40], "n88knj2.rom": ["a" * 40]}}, + } + + def _needs(self, **fields): + from scripts.provenance_report import profile_needs + + entry = {"name": "KANJI2.ROM", "size": 131072, **fields} + return profile_needs({"emu": {"files": [entry]}}, self.DB)["by_name"] + + def test_an_alias_the_database_indexes_is_held(self): + self.assertEqual(self._needs(), {}) + + def test_an_unsourceable_entry_is_not_held_by_a_homonym(self): + self.assertIn("kanji2.rom", self._needs(unsourceable="another machine's font")) + + class TestProvenancePage(unittest.TestCase): def _page(self, extra_entries=None, provenance=True): db = {