fix: emulator region report reads the pack drop set

This commit is contained in:
Abdessamad Derraz committed 2026-10-05 21:43:32 +02:00
1 parent 012bf2fec2
commit 3177a57103
4 files changed
+71 -45

No files matched your search

+4 -19
View File
@@ -1283,25 +1283,9 @@ def generate_emulator_pack(
zip_path = os.path.join(output_dir, zip_name)
os.makedirs(output_dir, exist_ok=True)
# One group per system (or explicit variant_group) inside each profile.
# Multi-system cores such as O2EM therefore retain a fallback BIOS for
# every system instead of letting one matching system empty another.
region_drops: set[str] = set()
if regions:
region_index = region_mod.build_region_index(dict(selected))
region_groups: dict[str, list[tuple[str, str]]] = {}
for emu_name, profile in sorted(selected):
structure = profile.get("pack_structure")
for fe in filter_files_by_mode(profile.get("files", []), standalone):
dest = _resolve_destination(fe, structure, standalone)
if dest:
group_id = _emulator_region_group(emu_name, profile, fe)
region_groups.setdefault(group_id, []).append(
(dest, fe.get("name", ""))
)
region_drops = region_mod.resolve_region_drops(
region_groups, region_index, regions
)
region_drops: set[str] = (
emulator_region_drops(selected, standalone, regions) if regions else set()
)
total_files = 0
missing_files = []
@@ -3436,6 +3420,7 @@ from packextras import ( # noqa: E402,F401
_collect_emulator_extras,
_extra_system_ids,
platform_region_groups,
emulator_region_drops,
_emulator_region_group,
)
+28
View File
@@ -600,6 +600,34 @@ def platform_region_groups(
groups.setdefault(group_id, []).append((dest, name))
return groups, extra_dests
def emulator_region_drops(
selected: list[tuple[str, dict]], standalone: bool, regions: list[str]
) -> set[str]:
"""Destinations an emulator-mode `--region` withdraws.
One group per system (or explicit variant_group) inside each profile, so
a multi-system core such as O2EM keeps a fallback BIOS for every system
instead of letting one matching system empty another. The emulator pack
and `verify --emulator` both read this, keyed by pack destination.
"""
import region as region_mod
from packpaths import _resolve_destination
from validation import filter_files_by_mode
region_index = region_mod.build_region_index(dict(selected))
region_groups: dict[str, list[tuple[str, str]]] = {}
for emu_name, profile in sorted(selected):
structure = profile.get("pack_structure")
for fe in filter_files_by_mode(profile.get("files", []), standalone):
dest = _resolve_destination(fe, structure, standalone)
if dest:
group_id = _emulator_region_group(emu_name, profile, fe)
region_groups.setdefault(group_id, []).append(
(dest, fe.get("name", ""))
)
return region_mod.resolve_region_drops(region_groups, region_index, regions)
def _emulator_region_group(emu_name: str, profile: dict, file_entry: dict) -> str:
"""Stable group ID for regional alternatives within an emulator profile."""
variant = file_entry.get("variant_group")
+8 -15
View File
@@ -1242,7 +1242,7 @@ def verify_emulator(
"""Verify files for specific emulator profiles.
A region priority list narrows the report the same way a pack built with the
same list would be narrowed. One group per profile, as in generate_pack.
same list would be narrowed, through the emulator pack's own drop set.
"""
load_emulator_profiles(emulators_dir)
zip_contents = build_zip_contents_index(db)
@@ -1265,22 +1265,12 @@ def verify_emulator(
dest_to_name: dict[str, str] = {}
data_dir_notices: list[str] = []
# The emulator pack withdraws these; the report withdraws the same.
region_drops: set[str] = set()
if regions:
import region as region_mod
from packextras import emulator_region_drops
region_index = region_mod.build_region_index(dict(selected))
region_groups: dict[str, list[tuple[str, str]]] = {}
for emu_name, profile in selected:
members = region_groups.setdefault(emu_name, [])
for fe in filter_files_by_mode(profile.get("files", []), standalone):
nm = fe.get("name", "")
key = fe.get("path") or nm
if key:
members.append((key, nm))
region_drops = region_mod.resolve_region_drops(
region_groups, region_index, regions
)
region_drops = emulator_region_drops(selected, standalone, regions)
for emu_name, profile in selected:
files = expand_directory_entries(
@@ -1289,10 +1279,13 @@ def verify_emulator(
standalone,
)
if region_drops:
from packpaths import _resolve_destination
structure = profile.get("pack_structure")
files = [
fe
for fe in files
if (fe.get("path") or fe.get("name", "")) not in region_drops
if _resolve_destination(fe, structure, standalone) not in region_drops
]
# Check data directories (only notice if not cached)
+31 -11
View File
@@ -551,18 +551,38 @@ class TestReportAndBuilderNarrowTogether(unittest.TestCase):
tmp.cleanup()
def test_one_grouping_pass_serves_both_sides(self):
"""A second hand-rolled grouping is how the two drifted apart."""
"""A second hand-rolled grouping is how the two drifted apart.
Every module is read, not only the two that once held a copy: the
builder was split into several modules and a grouping can move with
it. packextras.py holds the two shared passes, platform and emulator.
"""
scripts = Path(__file__).resolve().parent.parent / "scripts"
hand_rolled = 0
for name in ("generate_pack.py", "verify.py"):
for line in (scripts / name).read_text().splitlines():
if "region_groups.setdefault(" in line:
hand_rolled += 1
self.assertLessEqual(
hand_rolled, 2,
"platform region grouping belongs to platform_region_groups; "
"the only other pass is the per-emulator pack shape",
)
for path in sorted(scripts.rglob("*.py")):
if path.name == "packextras.py":
continue
with self.subTest(module=path.name):
self.assertNotIn(
"region_groups.setdefault(", path.read_text(encoding="utf-8"),
"region grouping belongs to packextras: platform_region_groups "
"or emulator_region_drops",
)
def test_emulator_report_keeps_what_the_emulator_pack_keeps(self):
"""O2EM: --region us left the Videopac BIOSes in the pack, not in the report."""
repo = Path(__file__).resolve().parent.parent
if not (repo / "emulators" / "o2em.yml").is_file():
self.skipTest("no o2em profile")
from verify import verify_emulator
from common import load_database
db = load_database(str(repo / "database.json"))
full = verify_emulator(["o2em"], str(repo / "emulators"), db)
narrowed = verify_emulator(["o2em"], str(repo / "emulators"), db, regions=["north-america"])
names = {d["name"] for d in narrowed["details"]}
for kept in ("c52.bin", "g7400.bin", "jopac.bin"):
self.assertIn(kept, names, "a system with no candidate in the region falls back")
self.assertEqual(full["total_files"], narrowed["total_files"])
if __name__ == "__main__":