From 9c46f7471d610fd50256584759e6388d892b406c Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 10 Nov 2026 02:25:27 +0100 Subject: [PATCH] fix: write a shared list without a YAML anchor The amiberry and hatarib extractors give a search record and its copy record one list object, and PyYAML wrote it as &id001 and *id001. platforms/retrobat.yml, batocera.yml and knulli.yml carried such anchors. The platform dumper now writes every list out, and the two files the RetroBat scrape does not rewrite are dumped again through it: their content is unchanged. --- platforms/batocera.yml | 50 +++++++++++++++++++++++++++++---- platforms/knulli.yml | 50 +++++++++++++++++++++++++++++---- platforms/retrobat.yml | 8 ++++-- scripts/scraper/base_scraper.py | 7 +++++ tests/test_scraper_contract.py | 15 ++++++++++ 5 files changed, 118 insertions(+), 12 deletions(-) diff --git a/platforms/batocera.yml b/platforms/batocera.yml index 99023f988..fccda9985 100644 --- a/platforms/batocera.yml +++ b/platforms/batocera.yml @@ -6498,7 +6498,7 @@ launchers: - "tos102{L}.img" - "tos100{L}.img" expands: - L: &id001 + L: - us - uk - de @@ -6525,7 +6525,17 @@ launchers: - "tos162{L}.img" - "tos106{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine ste --tos @@ -6542,7 +6552,17 @@ launchers: - "tos206{L}.img" - "tos205{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine megaste --tos @@ -6558,7 +6578,17 @@ launchers: - "etos512{L}.img" - "tos306{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine tt --tos @@ -6576,7 +6606,17 @@ launchers: - "tos402{L}.img" - "tos400{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine falcon --tos diff --git a/platforms/knulli.yml b/platforms/knulli.yml index 8d17ac162..2bbbad334 100644 --- a/platforms/knulli.yml +++ b/platforms/knulli.yml @@ -5349,7 +5349,7 @@ launchers: - "tos102{L}.img" - "tos100{L}.img" expands: - L: &id001 + L: - us - uk - de @@ -5376,7 +5376,17 @@ launchers: - "tos162{L}.img" - "tos106{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine ste --tos @@ -5393,7 +5403,17 @@ launchers: - "tos206{L}.img" - "tos205{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine megaste --tos @@ -5409,7 +5429,17 @@ launchers: - "etos512{L}.img" - "tos306{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine tt --tos @@ -5427,7 +5457,17 @@ launchers: - "tos402{L}.img" - "tos400{L}.img" expands: - L: *id001 + L: + - us + - uk + - de + - es + - fr + - it + - nl + - ru + - se + - '' case_insensitive: false search_dir: /userdata/bios passes_to: --machine falcon --tos diff --git a/platforms/retrobat.yml b/platforms/retrobat.yml index f9653d9e3..a05769063 100644 --- a/platforms/retrobat.yml +++ b/platforms/retrobat.yml @@ -4594,7 +4594,7 @@ launchers: - emulator: hatarib build: libretro kind: core_option - names: &id001 + names: - tos206.img - tos106.img - tos104.img @@ -4609,7 +4609,11 @@ launchers: - emulator: hatarib build: libretro kind: copies - names: *id001 + names: + - tos206.img + - tos106.img + - tos104.img + - tos102.img case_insensitive: true search_dir: bios/hatari/tos passes_to: bios/hatarib/ diff --git a/scripts/scraper/base_scraper.py b/scripts/scraper/base_scraper.py index 183ccd856..bbd8dc220 100644 --- a/scripts/scraper/base_scraper.py +++ b/scripts/scraper/base_scraper.py @@ -345,8 +345,15 @@ class _PlatformDumper(yaml.SafeDumper): Names such as "7800 BIOS (E).rom" or "Bandai - WonderSwan: x" are plain text, and a bare "01" would be read back as an integer. + + Two records sharing one list are written out twice, never as an anchor + and its alias: RetroBat's amiberry search and copy records share their + name list, and the platform file turned into &id001 and *id001. """ + def ignore_aliases(self, data: object) -> bool: + return True + def _quoted_str(dumper: yaml.SafeDumper, data: str) -> yaml.ScalarNode: style = None diff --git a/tests/test_scraper_contract.py b/tests/test_scraper_contract.py index a7555649d..aab7692ca 100644 --- a/tests/test_scraper_contract.py +++ b/tests/test_scraper_contract.py @@ -1119,5 +1119,20 @@ class EmptyScrapeWritesNothing(unittest.TestCase): scraper.module_ids(archive) +class PlatformFileHasNoAnchors(unittest.TestCase): + def test_a_shared_list_is_written_twice(self): + """RetroBat's amiberry search and copy records share one name list: + the platform file read back the same, but held &id001 and *id001.""" + import yaml + + from scraper.base_scraper import _PlatformDumper + + names = ["kick34005.A500", "amiga-os-130.rom"] + text = yaml.dump([{"names": names}, {"names": names}], Dumper=_PlatformDumper) + self.assertNotIn("&id", text) + self.assertNotIn("*id", text) + self.assertEqual(yaml.safe_load(text), [{"names": names}, {"names": names}]) + + if __name__ == "__main__": unittest.main()