fix: coerce numeric hashes to strings

This commit is contained in:
Abdessamad Derraz committed 2026-08-07 15:30:37 +02:00
1 parent fe41c237a2
commit 587aadde08
4 files changed
+70 -2

No files matched your search

+1 -1
View File
@@ -602,7 +602,7 @@ files:
size: 16384
sha1: a3d9e5be091b98de39a046ab167fb7632d053682
md5: b3c450c36a88b491281d18fdf3e94ab0
crc32: 70295038
crc32: "70295038"
note: "Plus/4 Kernal NTSC Rev 5 (default NTSC). Embedded in core."
source_ref: "vice/src/plus4/plus4rom.h:37"
+24
View File
@@ -768,11 +768,35 @@ def load_emulator_profiles(
continue
if skip_aliases and profile.get("type") == "alias":
continue
_normalize_hash_fields(profile)
profiles[f.stem] = profile
_emulator_profiles_cache[cache_key] = profiles
return profiles
_HASH_FIELDS = ("crc32", "md5", "sha1", "sha256")
def _normalize_hash_fields(node: object) -> None:
"""Coerce hash values to str in place.
YAML types unquoted digit-only hashes (e.g. crc32: 70295038) as int,
which breaks string comparisons and formatting downstream.
"""
if isinstance(node, dict):
for key, val in node.items():
if key in _HASH_FIELDS:
if isinstance(val, int):
node[key] = str(val)
elif isinstance(val, list):
node[key] = [str(v) if isinstance(v, int) else v for v in val]
else:
_normalize_hash_fields(val)
elif isinstance(node, list):
for item in node:
_normalize_hash_fields(item)
def unique_emulator_profiles(profiles: dict[str, dict]) -> dict[str, dict]:
"""Profiles counting as distinct emulators (aliases and tests excluded)."""
return {
+1 -1
View File
@@ -96,7 +96,7 @@ class Exporter(BaseExporter):
rom_parts.append(f"size {size}")
crc = fe.get("crc32", "")
if crc:
rom_parts.append(f"crc {crc.upper()}")
rom_parts.append(f"crc {str(crc).upper()}")
md5 = fe.get("md5", "")
if isinstance(md5, list):
md5 = md5[0] if md5 else ""
+44
View File
@@ -935,6 +935,22 @@ class TestE2E(unittest.TestCase):
profiles = load_emulator_profiles(self.emulators_dir)
self.assertNotIn("test_alias", profiles)
def test_42b_profile_hash_fields_load_as_str(self):
"""Unquoted digit-only hashes must load as strings, not YAML ints."""
with tempfile.TemporaryDirectory() as tmp:
Path(tmp, "numcrc.yml").write_text(
"emulator: NumCRC\n"
"type: libretro\n"
"files:\n"
" - name: kernal.bin\n"
" crc32: 70295038\n"
" md5: [12345678901234567890123456789012]\n"
)
profiles = load_emulator_profiles(tmp)
entry = profiles["numcrc"]["files"][0]
self.assertEqual(entry["crc32"], "70295038")
self.assertEqual(entry["md5"], ["12345678901234567890123456789012"])
def test_43_cross_ref_data_dir_does_not_suppress_files(self):
config = load_platform_config("test_md5", self.platforms_dir)
profiles = load_emulator_profiles(self.emulators_dir)
@@ -3842,6 +3858,34 @@ class TestE2E(unittest.TestCase):
self.assertIn("retroarch", exporters)
self.assertIs(exporters["retroarch"], SystemDatExporter)
def test_systemdat_exporter_numeric_crc(self):
"""Digit-only crc32 typed as int by YAML must not break the export."""
from exporter.systemdat_exporter import Exporter as SystemDatExporter
truth = {
"platform": "retroarch",
"systems": {
"commodore-plus4": {
"files": [
{
"name": "kernal-318005-05.bin",
"path": "kernal-318005-05.bin",
"size": 16384,
"crc32": 70295038,
"required": False,
},
],
},
},
}
out_path = os.path.join(self.root, "System_numeric.dat")
SystemDatExporter().export(truth, out_path, scraped_data={"systems": {}})
with open(out_path) as fh:
content = fh.read()
self.assertIn("crc 70295038", content)
# ---------------------------------------------------------------
# Full truth + diff integration test
# ---------------------------------------------------------------