From be2daab00cabc526e12754d749723fbf98b705b9 Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Fri, 9 Oct 2026 22:45:57 +0200 Subject: [PATCH] fix: judge the gap report on the flat declared set --- scripts/cross_reference.py | 30 +++++++++++++++++++--- tests/test_declared_names.py | 49 ++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 tests/test_declared_names.py diff --git a/scripts/cross_reference.py b/scripts/cross_reference.py index 02be2fd8..488ad8e4 100644 --- a/scripts/cross_reference.py +++ b/scripts/cross_reference.py @@ -70,6 +70,25 @@ def load_platform_files( return declared, platform_data_dirs +def declared_names(platforms_dir: str, platforms: list[str] | None, db: dict) -> set[str]: + """Every name the platforms declare, under every spelling the database knows. + + The report judged "undeclared" per normalized system id, which does not + bring bk and elektronika-bk, or nintendo-sgb and nintendo-super-game-boy, + together: 646 entries whose exact name a platform declares were counted + undeclared, while verify and the site read one flat set. + """ + from common import expand_platform_declared_names + + names: set[str] = set() + for platform_name in platforms or list_registered_platforms( + platforms_dir, include_archived=True + ): + config = load_platform_config(platform_name, platforms_dir) + names.update(expand_platform_declared_names(config, db)) + return names + + def _build_supplemental_index( data_root: str = "data", bios_root: str = "bios" ) -> set[str]: @@ -135,6 +154,7 @@ def _resolve_source( by_path_suffix: dict | None = None, file_entry: dict | None = None, db_files: dict | None = None, + bios_dir: str | None = None, ) -> str | None: """Return the source category for a file, or None if not found. @@ -177,7 +197,7 @@ def _resolve_source( return "bios" # bios/ under the canonical MAME set name, as resolve_local_file does: # a renamed archive is held once, under the name the dedup kept. - canonical = get_mame_clone_map().get(fname) + canonical = get_mame_clone_map(bios_dir).get(fname) if canonical and canonical != fname: if canonical in by_name and _name_hit(canonical): return "bios" @@ -269,6 +289,7 @@ def entry_source(f: dict, index: dict) -> str | None: continue source = _resolve_source( candidate, by_name, by_name_lower, data_names, by_path_suffix, f, db_files, + index.get("bios_dir"), ) if source is not None: return source @@ -513,6 +534,7 @@ def cross_reference( "db_files": db_files, "data_names": data_names, "all_declared": all_declared, + "bios_dir": db.get("bios_dir"), } for emu_name, profile in profiles.items(): _cross_reference_profile( @@ -611,13 +633,13 @@ def main(): print("No emulator profiles found.", file=sys.stderr) return - declared, plat_data_dirs = load_platform_files( - args.platforms_dir, [args.platform] if args.platform else None - ) + selected = [args.platform] if args.platform else None + declared, plat_data_dirs = load_platform_files(args.platforms_dir, selected) db = load_database(args.db) data_names = _build_supplemental_index() report = cross_reference( profiles, declared, db, plat_data_dirs, data_names, + all_declared=declared_names(args.platforms_dir, selected, db), standalone_cores=standalone_cores, ) diff --git a/tests/test_declared_names.py b/tests/test_declared_names.py new file mode 100644 index 00000000..6eeba15e --- /dev/null +++ b/tests/test_declared_names.py @@ -0,0 +1,49 @@ +"""The command line report judges "undeclared" on the flat declared set. + +Per normalized system id, bk and elektronika-bk never met, nor nintendo-sgb +and nintendo-super-game-boy: 646 entries whose exact name a platform +declares were counted undeclared, while verify and the site read one flat +set, enriched with every spelling the database knows. +""" + +from __future__ import annotations + +import sys +import unittest +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parent.parent +sys.path.insert(0, str(REPO_ROOT / "scripts")) + +from common import load_database, load_emulator_profiles # noqa: E402 +from cross_reference import ( # noqa: E402 + _build_supplemental_index, + cross_reference, + declared_names, + load_platform_files, +) + + +class FlatDeclaredSet(unittest.TestCase): + def test_a_name_declared_under_another_system_id_is_not_a_gap(self): + if not (REPO_ROOT / "database.json").is_file(): + self.skipTest("no database.json") + db = load_database(str(REPO_ROOT / "database.json")) + platforms = str(REPO_ROOT / "platforms") + profiles = {k: v for k, v in load_emulator_profiles(str(REPO_ROOT / "emulators")).items() if k == "bk"} + if not profiles: + self.skipTest("no bk profile") + declared, data_dirs = load_platform_files(platforms, ["batocera"]) + names = _build_supplemental_index() + per_system = cross_reference(profiles, declared, db, data_dirs, names) + flat = cross_reference( + profiles, declared, db, data_dirs, names, + all_declared=declared_names(platforms, ["batocera"], db), + ) + gaps = {g["name"] for g in flat["bk"]["gap_details"]} + self.assertNotIn("MONIT10.ROM", gaps) + self.assertLess(flat["bk"]["gaps"], per_system["bk"]["gaps"]) + + +if __name__ == "__main__": + unittest.main()