diff --git a/scripts/generate_site.py b/scripts/generate_site.py index 4dde50897..c5206c4f0 100644 --- a/scripts/generate_site.py +++ b/scripts/generate_site.py @@ -6443,13 +6443,6 @@ def _region_order() -> dict[str, int]: return {region: index for index, region in enumerate(ordered)} -_REGION_WORDS = {"uk": "UK", "asia-ntsc": "Asia (NTSC)", "asia-pal": "Asia (PAL)"} - - -def _region_word(region: str) -> str: - return _REGION_WORDS.get(region) or region.replace("-", " ").title() - - def _reading_pairs(sha1: str, consumers: FileConsumers) -> list[tuple[str, dict]]: """The profile entries that read a file, each with its emulator.""" files_of = getattr(consumers, "emulator_files", {}) @@ -7031,7 +7024,7 @@ def _group_start(group: _StartGroup, first_below: bool) -> list[tuple[str, str]] else: regional[(*same, region)] = regional.pop(same) - out = [(", ".join(_region_word(r) for r in regions), regional[regions]) + out = [(", ".join(_region_words(r) for r in regions), regional[regions]) for regions in sorted(regional, key=lambda rs: (order.get(rs[0], len(order)), rs))] # A name a region line gives already is no "also", and one only # emulators no region line answers reads is an "instead": armsx1 reads diff --git a/tests/test_site_render.py b/tests/test_site_render.py index 2ad8e6788..0236dc2bd 100644 --- a/tests/test_site_render.py +++ b/tests/test_site_render.py @@ -429,3 +429,28 @@ class TheSearchSkipsLinkLists(unittest.TestCase): if __name__ == "__main__": unittest.main() + + +class OneDefinitionPerName(unittest.TestCase): + """generate_site defined _REGION_WORDS twice: the second table replaced + the first at import, and _region_word, written beside the first, never + read it.""" + + def test_no_module_name_is_bound_twice(self): + import ast + + for path in sorted((REPO_ROOT / "scripts").glob("*site*.py")): + seen: dict[str, int] = {} + for node in ast.parse(path.read_text(encoding="utf-8")).body: + if isinstance(node, (ast.FunctionDef, ast.ClassDef)): + names = [node.name] + elif isinstance(node, ast.Assign): + names = [t.id for t in node.targets if isinstance(t, ast.Name)] + elif isinstance(node, ast.AnnAssign) and isinstance(node.target, ast.Name): + names = [node.target.id] + else: + continue + for name in names: + self.assertNotIn(name, seen, f"{path.name}:{node.lineno} binds {name} " + f"again, first at line {seen.get(name)}") + seen[name] = node.lineno