From 2cafeb1d332c270b286f07293671752f4a5f89ef Mon Sep 17 00:00:00 2001 From: Abdessamad Derraz <3028866+Abdess@users.noreply.github.com> Date: Tue, 6 Oct 2026 04:30:11 +0200 Subject: [PATCH] fix: key the casefold index on its source dict --- scripts/common.py | 16 ++++++++++------ tests/test_casefold_cache.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 tests/test_casefold_cache.py diff --git a/scripts/common.py b/scripts/common.py index ef8ade3b..dfab57ce 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -35,19 +35,23 @@ def load_database(db_path: str) -> dict: -_casefold_index_cache: dict[int, dict[str, list[str]]] = {} +# One slot: the dict it was built from, its size then, and the folded view. +# Keyed by id() alone, a database freed and replaced by another at the same +# address got the old index back, and the case-insensitive step answered from +# a collection that no longer existed. +_casefold_index_cache: list[tuple[dict, int, dict[str, list[str]]]] = [] def _casefold_name_index(by_name: dict) -> dict[str, list[str]]: """Build (and cache) a casefolded view of the by_name index.""" - key = id(by_name) - cached = _casefold_index_cache.get(key) - if cached is not None: - return cached + if _casefold_index_cache: + source, size, folded = _casefold_index_cache[0] + if source is by_name and size == len(by_name): + return folded folded: dict[str, list[str]] = {} for name, sha1s in by_name.items(): folded.setdefault(name.casefold(), []).extend(sha1s) - _casefold_index_cache[key] = folded + _casefold_index_cache[:] = [(by_name, len(by_name), folded)] return folded diff --git a/tests/test_casefold_cache.py b/tests/test_casefold_cache.py new file mode 100644 index 00000000..efb55069 --- /dev/null +++ b/tests/test_casefold_cache.py @@ -0,0 +1,30 @@ +"""The case-insensitive name index answers for the database it was asked about.""" + +from __future__ import annotations + +import sys +import unittest +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(REPO_ROOT / "scripts")) + +from common import _casefold_name_index # noqa: E402 + + +class CasefoldIndexFollowsItsSource(unittest.TestCase): + def test_a_new_dict_gets_its_own_index(self): + first = {"BIOS.ROM": ["a"]} + self.assertEqual(_casefold_name_index(first)["bios.rom"], ["a"]) + second = {"Bios.Rom": ["b"]} + self.assertEqual(_casefold_name_index(second)["bios.rom"], ["b"]) + + def test_a_grown_dict_is_reindexed(self): + index = {"A.BIN": ["a"]} + _casefold_name_index(index) + index["B.BIN"] = ["b"] + self.assertIn("b.bin", _casefold_name_index(index)) + + +if __name__ == "__main__": + unittest.main()