From a0672d44597cb8c7c5374460bfdd3c9ed47a4abb Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Wed, 21 Oct 2026 05:05:50 +0200 Subject: [PATCH] refactor: derive the spelling index from its table The index of other system spellings was rebuilt only when the page table changed length, so a table of the same size kept the previous links. The builder now returns its table and set_system_page_map installs it with the index derived from it. --- scripts/generate_site.py | 27 ++++++++++++++----------- scripts/siterender.py | 35 +++++++++++++++++++++------------ tests/test_site_system_links.py | 35 +++++++++++++++++++++------------ 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 3e75caea..85fa0465 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -143,13 +143,13 @@ def _system_folder( return None -def _build_system_page_map_from_data( +def _system_pages_from_data( manufacturers: dict, coverages: dict, db: dict, profiles: dict | None = None, -) -> None: - """Build system_id -> (manufacturer_slug, console_name) mapping. +) -> dict[str, tuple[str, str]]: + """The system_id -> (manufacturer_slug, console_name) table. Uses platform file paths to trace system_id -> bios directory -> manufacturer page. """ @@ -187,10 +187,11 @@ def _build_system_page_map_from_data( console_norm[key] = entry # Map system_id -> (manufacturer, console) via platform file entries + pages: dict[str, tuple[str, str]] = {} for cov in coverages.values(): config = cov["config"] for sys_id, system in config.get("systems", {}).items(): - if sys_id in _system_page_map: + if sys_id in pages: continue # Strategy 1: the folder holding the files the system declares, # found by content, and most votes win. A bare name stands in only @@ -198,18 +199,18 @@ def _build_system_page_map_from_data( place = _system_folder(system.get("files", []), db, name_consoles) if place is not None: mfr, console = place - _system_page_map[sys_id] = (mfr.lower().replace(" ", "-"), console) + pages[sys_id] = (mfr.lower().replace(" ", "-"), console) continue # Strategy 2: fuzzy match system_id against console directory names if sys_id in console_norm: - _system_page_map[sys_id] = console_norm[sys_id] + pages[sys_id] = console_norm[sys_id] else: # Try partial match: "nintendo-wii" matches "Wii" under "Nintendo" parts = sys_id.split("-") for i in range(len(parts)): suffix = "-".join(parts[i:]) if suffix in console_norm: - _system_page_map[sys_id] = console_norm[suffix] + pages[sys_id] = console_norm[suffix] break # Systems only emulator profiles name (sega-naomi, commodore-pet): placed @@ -218,7 +219,7 @@ def _build_system_page_map_from_data( for profile in (profiles or {}).values(): systems = [str(sid) for sid in profile.get("systems") or []] for sys_id in systems: - if sys_id in _system_page_map: + if sys_id in pages: continue files = [ entry for entry in profile.get("files") or [] @@ -228,9 +229,10 @@ def _build_system_page_map_from_data( place = _system_folder(files, db, name_consoles) if place is not None: mfr, console = place - _system_page_map[sys_id] = (mfr.lower().replace(" ", "-"), console) + pages[sys_id] = (mfr.lower().replace(" ", "-"), console) elif sys_id in console_norm: - _system_page_map[sys_id] = console_norm[sys_id] + pages[sys_id] = console_norm[sys_id] + return pages @@ -4833,7 +4835,9 @@ def _generate(args: argparse.Namespace) -> None: # Build system_id -> manufacturer page map (needed by all generators) print("Building system cross-reference map...") manufacturers = _group_by_manufacturer(db) - _build_system_page_map_from_data(manufacturers, coverages, db, profiles) + set_system_page_map( + _system_pages_from_data(manufacturers, coverages, db, profiles) + ) print(f" {len(_system_page_map)} system IDs mapped to pages") export_reports = load_export_reports() @@ -5129,6 +5133,7 @@ from siterender import ( # noqa: E402,F401 _slugify_anchor, _system_page_map, _system_link, + set_system_page_map, _platform_link, _emulator_link, _fmt_size, diff --git a/scripts/siterender.py b/scripts/siterender.py index 1b17b85b..81d3a04b 100644 --- a/scripts/siterender.py +++ b/scripts/siterender.py @@ -161,8 +161,27 @@ def _slugify_anchor(text: str) -> str: slug = slug.strip("-") return slug -_norm_page_cache: dict[str, tuple[str, str] | None] = {} -_norm_page_size = -1 +_norm_page_map: dict[str, tuple[str, str] | None] = {} + + +def set_system_page_map(mapping: dict[str, tuple[str, str]]) -> None: + """Install the system id -> page table every link on the site reads. + + The table replaces the previous one, and the index of other spellings is + derived from it here. Kept anywhere else, it outlived a table of the same + size and linked to the pages of the previous one. + """ + from common import _norm_system_id + + _system_page_map.clear() + _system_page_map.update(mapping) + _norm_page_map.clear() + for known, page in _system_page_map.items(): + key = _norm_system_id(known) + if _norm_page_map.get(key, page) != page: + _norm_page_map[key] = None + else: + _norm_page_map[key] = page def _page_by_norm(sys_id: str) -> tuple[str, str] | None: @@ -172,19 +191,9 @@ def _page_by_norm(sys_id: str) -> tuple[str, str] | None: keyed by the platforms' spellings: 2,431 of 4,195 cards had no link. A spelling two pages share leads nowhere rather than to either. """ - global _norm_page_size from common import _norm_system_id - if _norm_page_size != len(_system_page_map): - _norm_page_cache.clear() - for known, page in _system_page_map.items(): - key = _norm_system_id(known) - if _norm_page_cache.get(key, page) != page: - _norm_page_cache[key] = None - else: - _norm_page_cache[key] = page - _norm_page_size = len(_system_page_map) - return _norm_page_cache.get(_norm_system_id(sys_id)) + return _norm_page_map.get(_norm_system_id(sys_id)) def _system_link(sys_id: str, prefix: str = "") -> str: diff --git a/tests/test_site_system_links.py b/tests/test_site_system_links.py index c4433ed6..61e9d4be 100644 --- a/tests/test_site_system_links.py +++ b/tests/test_site_system_links.py @@ -69,31 +69,40 @@ class OtherSpellingsOfOneSystem(unittest.TestCase): self.assertEqual(gs._system_emulators("sega-mega-drive", index), ["genesis_plus_gx"]) self.assertEqual(gs._system_emulators("nintendo-snes", index), []) + def _install(self, mapping: dict) -> None: + import siterender + + saved = dict(siterender._system_page_map) + self.addCleanup(siterender.set_system_page_map, saved) + siterender.set_system_page_map(mapping) + def test_a_profile_spelling_links_to_the_platform_page(self): import siterender - saved = dict(siterender._system_page_map) - self.addCleanup(lambda: (siterender._system_page_map.clear(), - siterender._system_page_map.update(saved))) - siterender._system_page_map.clear() - siterender._system_page_map["sega-mega-drive"] = ("sega", "Mega Drive") + self._install({"sega-mega-drive": ("sega", "Mega Drive")}) self.assertIn("systems/sega.md#mega-drive", siterender._system_link("sega-megadrive")) - siterender._system_page_map["megadrive"] = ("other", "Elsewhere") + self._install({"sega-mega-drive": ("sega", "Mega Drive"), + "megadrive": ("other", "Elsewhere")}) self.assertEqual(siterender._system_link("sega-megadrive"), "sega-megadrive") - def test_a_system_only_profiles_name_is_placed_by_their_files(self): + def test_a_table_of_the_same_size_replaces_the_other_spellings(self): + """The index of other spellings was kept while the table kept its + length, so a second table of one entry linked to the first one's page.""" import siterender - saved = dict(siterender._system_page_map) - self.addCleanup(lambda: (siterender._system_page_map.clear(), - siterender._system_page_map.update(saved))) - siterender._system_page_map.clear() + self._install({"sega-mega-drive": ("sega", "Mega Drive")}) + self.assertIn("systems/sega.md#", siterender._system_link("sega-megadrive")) + self._install({"sega-mega-drive": ("other", "Elsewhere")}) + self.assertEqual(siterender._system_link("sega-megadrive"), + "[sega-megadrive](systems/other.md#elsewhere)") + + def test_a_system_only_profiles_name_is_placed_by_their_files(self): manufacturers = {"Commodore": {"PET": [{"name": "basic4.bin"}]}} profiles = {"vice_xpet": {"systems": ["commodore-pet"], "files": [{"name": "basic4.bin"}]}} - gs._build_system_page_map_from_data( + pages = gs._system_pages_from_data( manufacturers, {}, {"files": {}, "indexes": {}}, profiles) - self.assertEqual(siterender._system_page_map["commodore-pet"], ("commodore", "PET")) + self.assertEqual(pages["commodore-pet"], ("commodore", "PET")) class ACopyIsOnItsOwnFoldersPage(unittest.TestCase):