diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 3dd6d410..b947ea0d 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -3828,7 +3828,9 @@ def generate_gap_analysis( gap_report = build_emulator_gap_report(profiles, coverages, db, data_names) report_all = gap_report - src_totals: dict[str, int] = {"bios": 0, "data": 0, "large_file": 0, "missing": 0} + src_totals: dict[str, int] = { + "bios": 0, "data": 0, "large_file": 0, "bundled": 0, "missing": 0, + } total_undeclared = 0 emulator_gaps = [] @@ -3836,8 +3838,8 @@ def generate_gap_analysis( if data["gaps"] == 0: continue total_undeclared += data["gaps"] - for key in src_totals: - src_totals[key] += data.get(f"gap_{key}", 0) + for key, count in _gap_sources(data).items(): + src_totals[key] += count emulator_gaps.append((emu_name, data)) @@ -3855,9 +3857,10 @@ def generate_gap_analysis( "## Core complement", "", f"Files loaded by emulators but not declared by any platform. " - f"{total_undeclared:,} files across {len(emulator_gaps)} emulators, " + f"{total_undeclared:,} files across {_count(len(emulator_gaps), 'emulator')}, " f"{total_available:,} available ({pct_available}), " - f"{src_totals['missing']} to source.", + f"{src_totals['bundled']:,} installed with their emulator, " + f"{src_totals['missing']:,} to source.", "", "This counts every profiled emulator, including those no platform " "ships yet, so it reaches past what the pack tables above measure: " @@ -3873,17 +3876,20 @@ def generate_gap_analysis( f"| data/ | {src_totals['data']} | Data directories (buildbot, GitHub) |", f"| release | {src_totals['large_file']} " "| GitHub release assets (large files) |", + f"| bundled | {src_totals['bundled']} " + "| Installed with the emulator's own package, not collected |", f"| missing | {src_totals['missing']} | Not available, needs sourcing |", "", "### Per emulator", "", - "| Emulator | Undeclared | bios | data | release | Missing |", - "|----------|----------:|-----:|-----:|--------:|--------:|", + "| Emulator | Undeclared | bios | data | release | Bundled | Missing |", + "|----------|----------:|-----:|-----:|--------:|--------:|--------:|", ]) for emu_name, data in sorted(emulator_gaps, key=lambda x: -x[1]["gaps"]): display = data["emulator"] - m = data.get("gap_missing", 0) + sources = _gap_sources(data) + m = sources["missing"] missing_str = ( f'{m}' if m > 0 @@ -3892,9 +3898,10 @@ def generate_gap_analysis( lines.append( f"| [{display}](emulators/{emu_name}.md) " f"| {data['gaps']} " - f"| {data.get('gap_bios', 0)} " - f"| {data.get('gap_data', 0)} " - f"| {data.get('gap_large_file', 0)} " + f"| {sources['bios']} " + f"| {sources['data']} " + f"| {sources['large_file']} " + f"| {sources['bundled']} " f"| {missing_str} |" ) lines.append("") @@ -4056,6 +4063,23 @@ def _core_scope_note(config: dict, profiles: dict) -> str: return f" (all libretro, plus {_count(others, 'other core')})" +def _gap_sources(data: dict) -> dict[str, int]: + """Where each undeclared file of one emulator comes from. + + A file the emulator's own package installs is not one to find. The + report's gap_missing counts it, and the gaps page announced 1,356 files + to source where 609 are, with a red badge on emulators that have none. + """ + counts = {"bios": 0, "data": 0, "large_file": 0, "bundled": 0, "missing": 0} + for gap in data.get("gap_details") or []: + source = gap.get("source", "") + if source == "missing" and gap.get("bundled"): + source = "bundled" + if source in counts: + counts[source] += 1 + return counts + + def _render_xref_by_platform( coverages: dict, unique: dict ) -> list[str]: diff --git a/tests/test_site_render.py b/tests/test_site_render.py index 1d1861ff..d551ad1b 100644 --- a/tests/test_site_render.py +++ b/tests/test_site_render.py @@ -111,5 +111,33 @@ class EveryPageAddressesPlatformsAsPeers(unittest.TestCase): self.assertEqual(found, []) +class BundledFilesAreNotToSource(unittest.TestCase): + """The gaps page summed the report's gap_missing, bundled files included: + 1,356 files to source where 609 were, and a red badge of 13 on ZQuest + Classic, whose 13 missing files all come with its own package.""" + + def test_the_summary_and_the_row_count_only_what_must_be_found(self): + import generate_site + + gap = {"required": True, "source_ref": "x", "in_repo": False} + report = {"zq": { + "emulator": "ZQuest Classic", "gaps": 4, "gap_missing": 3, "gap_bios": 1, + "unsourceable": [], + "gap_details": [ + {**gap, "name": "a.dll", "source": "missing", "bundled": True}, + {**gap, "name": "b.dll", "source": "missing", "bundled": True}, + {**gap, "name": "c.bin", "source": "missing"}, + {**gap, "name": "d.bin", "source": "bios", "in_repo": True}, + ], + }} + page = generate_site.generate_gap_analysis( + {"zq": {"emulator": "ZQuest Classic", "files": []}}, {}, + {"files": {}, "indexes": {}}, gap_report=report) + self.assertIn("2 installed with their emulator, 1 to source.", page) + self.assertIn("| missing | 1 | Not available, needs sourcing |", page) + self.assertIn("| [ZQuest Classic](emulators/zq.md) | 4 | 1 | 0 | 0 | 2 | " + '1 |', page) + + if __name__ == "__main__": unittest.main()