#!/usr/bin/env python """Regenerate the committed report fixtures from the real reports in `raw/`. uv run python scripts/anonymize_reports.py # rewrite fixtures uv run python scripts/anonymize_reports.py --check # fail if they are out of date uv run python scripts/anonymize_reports.py --report # show what would be removed `tests/fixtures/reports/raw/` is gitignored and holds the originals; everything one level up is committed and must be clean. The transformation is deterministic (see `fintracker.sources.reports.anonymize`), so running this twice is a no-op and a reviewer can reproduce any fixture from the original. """ from __future__ import annotations import argparse import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) from fintracker.sources.reports.anonymize import ( anonymize, anonymize_filename, collect_secrets, ) FIXTURES = Path(__file__).resolve().parent.parent / "tests" / "fixtures" / "reports" RAW = FIXTURES / "raw" def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--check", action="store_true", help="exit 1 if a fixture is stale") parser.add_argument("--report", action="store_true", help="print what was found") args = parser.parse_args() if not RAW.exists(): print(f"нет {RAW} — положите туда реальные отчёты", file=sys.stderr) return 1 sources = [p for p in sorted(RAW.rglob("*")) if p.is_file() and not p.name.startswith(".")] # One secret set for the whole corpus: a Snowball note quotes the Sber agreement number, # so a per-file scrub would leak what another file names. secrets = collect_secrets((p.read_bytes(), p.name) for p in sources) if args.report: for original, substitute in secrets.replacements.items(): print(f"{original!r} -> {substitute!r}") stale: list[str] = [] written = 0 for source in sources: data = source.read_bytes() clean, _ = anonymize(data, source.name, secrets) relative = source.relative_to(RAW) target = FIXTURES / relative.parent / anonymize_filename(source.name, secrets) if args.report: continue # --report only inspects; it must never touch a fixture if target.exists() and target.read_bytes() == clean: continue if args.check: stale.append(str(target.relative_to(FIXTURES))) continue target.parent.mkdir(parents=True, exist_ok=True) target.write_bytes(clean) written += 1 print(f"{relative} -> {target.relative_to(FIXTURES)}") if stale: print("фикстуры устарели, перегенерируйте: " + ", ".join(stale), file=sys.stderr) return 1 if not args.check and not args.report: print(f"обновлено файлов: {written}") return 0 if __name__ == "__main__": raise SystemExit(main())