"""Cache danych: znormalizowany arkusz zapisany jako Parquet. POZIOM 2 cache — największy zysk wydajności. Parsowanie .xlsx jest wolne (dziesiątki–setki ms na duży plik). Po pierwszym wczytaniu zapisujemy znormalizowaną ramkę jako Parquet (kolumnowy, kompresowany), kluczowaną odciskiem pliku. Kolejne odczyty ładują Parquet — zwykle 10–100x szybciej niż .xlsx i bez ponownego wykrywania nagłówka. Plik Parquet jest też naturalnym formatem pośrednim przy migracji do SQL. """ from __future__ import annotations from pathlib import Path import pandas as pd class FrameCache: def __init__(self, cache_dir: Path) -> None: self.dir = cache_dir / "frames" self.dir.mkdir(parents=True, exist_ok=True) def _path(self, fp: str, sheet: str) -> Path: safe = fp.replace(":", "_") + "__" + str(sheet).replace("/", "_") return self.dir / f"{safe}.parquet" def get(self, fp: str, sheet: str) -> pd.DataFrame | None: p = self._path(fp, sheet) if p.exists(): return pd.read_parquet(p) return None def put(self, fp: str, sheet: str, frame: pd.DataFrame) -> None: # astype(str) na kolumnach object zapewnia stabilny zapis Parquet frame.to_parquet(self._path(fp, sheet), index=False)