"""Odcisk pliku = klucz unieważniania cache. Wszystkie warstwy cache są kluczowane odciskiem pliku. Gdy plik Excela się zmieni, zmienia się odcisk -> automatyczny "cache miss" i przebudowa. Domyślnie używamy taniego (mtime + rozmiar); sha256 dostępne, gdy potrzeba pewności co do treści. """ from __future__ import annotations import hashlib import os def fingerprint(path: str, strong: bool = False) -> str: if strong: h = hashlib.sha256() with open(path, "rb") as f: for chunk in iter(lambda: f.read(1024 * 1024), b""): h.update(chunk) return "sha256:" + h.hexdigest()[:16] st = os.stat(path) return f"mt:{int(st.st_mtime)}:{st.st_size}"