"""Перезапись golden-снимков разбора ОСВ и форм и diff изменившихся (design D-10). Из каталога `api/`: `ENV_FILE=.env.test .venv/bin/python scripts/golden_update.py [--check]` (то же — `make golden-update`, из корня репозитория). Файлы — `fixtures/osv/**` включая `synthetic/`; снимки — в `fixtures/golden/expected_osv_parse/` (зеркало `osv/`); файлы форм — `fixtures/statements-xlsx/**` (включая `synthetic/`), снимки — в `fixtures/golden/expected_statement_parse/`. Без флага снимки перезаписываются, для изменившихся печатается unified diff; `--check` только сравнивает (код возврата 1, если снимки расходятся с разбором). Снимки части, для которой нет исходного каталога (`osv/synthetic` отсутствует или пуст, нет реальных файлов), не удаляются. Снимок — регрессия, а не оракул: перед коммитом в репозиторий fixtures просмотрите diff (`git -C ../fixtures diff`) и убедитесь, что каждое изменение — следствие намеренной правки парсера. """ import argparse import sys from collections.abc import Sequence from pathlib import Path API_ROOT = Path(__file__).resolve().parents[1] sys.path[:0] = [str(API_ROOT), str(API_ROOT / "tests")] from fixtures_helpers import ( # noqa: E402 fixtures_skip_reason, osv_dkb_golden_files, osv_fixture_files, resolve_fixtures_dir, statement_files, statement_synthetic_files, synthetic_files, ) from golden_helpers import sync_snapshots # noqa: E402 from src.parser import get_parser # noqa: E402 EXIT_OK = 0 EXIT_DIFFERS = 1 EXIT_NO_FIXTURES = 3 def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Golden-снимки разбора ОСВ: перезапись + diff, либо --check") parser.add_argument("--check", action="store_true", help="только сравнить снимки с разбором, ничего не писать") options = parser.parse_args(argv) reason = fixtures_skip_reason() if reason is not None: print(reason, file=sys.stderr) return EXIT_NO_FIXTURES root = resolve_fixtures_dir() files = [ *osv_fixture_files(root), *osv_dkb_golden_files(root), *synthetic_files(root), *statement_files(root), *statement_synthetic_files(root), ] report = sync_snapshots(root, files, get_parser(), write=not options.check) for diff in report.diffs: sys.stdout.write(diff if diff.endswith("\n") else diff + "\n") mode = "режим --check, ничего не записано" if options.check else "снимки записаны" print( f"файлов: {len(files)}; без изменений: {report.unchanged}; новых: {len(report.created)}; " f"изменено: {len(report.changed)}; лишних снимков: {len(report.orphans)}; сохранено без исходного каталога: " f"{len(report.protected)} ({mode})", file=sys.stderr, ) for orphan in report.orphans: print(f"лишний снимок{'' if options.check else ' удалён'}: {orphan}", file=sys.stderr) for kept in report.protected: print(f"снимок сохранён (нет исходного каталога): {kept}", file=sys.stderr) return EXIT_DIFFERS if options.check and report.differs else EXIT_OK if __name__ == "__main__": reconfigure = getattr(sys.stdout, "reconfigure", None) if reconfigure is not None: reconfigure(encoding="utf-8") raise SystemExit(main())