"""Shared plumbing for the two stub-fixture generators. Both write into the same cache dirs, so they must agree on XML escaping (a title containing & or " must not produce malformed XML) and on the provenance-marker text the upload guard depends on. """ from __future__ import annotations from pathlib import Path from bggpipe.config import STUB_CACHE_MARKER_NAME, STUB_DATA_MARKER_NAME FIXTURE_CACHE = Path("tests/fixtures/bgg_cache") CACHE_MARKER_TEXT = ( "This cache contains hand-written stub XML, not real BGG " "responses. Data resolved from it must not be uploaded.\n" ) DATA_MARKER_TEXT = ( "The CSVs in this directory were resolved from hand-written stub " "fixtures, not real BGG data — version_ids are SYNTHETIC. The " "upload stage refuses to run while this file exists. Delete it " "only after re-resolving against real recorded fixtures " "(BGG_API_TOKEN + scripts/record_fixtures.py + resolve --force).\n" ) def esc(text: str) -> str: """Minimal XML attribute/text escaping for hand-built fixture strings.""" return str(text).replace("&", "&").replace("<", "<").replace('"', """) def write_cache_marker(target: Path) -> None: (target / STUB_CACHE_MARKER_NAME).write_text(CACHE_MARKER_TEXT) def write_data_marker(data_dir: Path = Path("data")) -> None: data_dir.mkdir(parents=True, exist_ok=True) (data_dir / STUB_DATA_MARKER_NAME).write_text(DATA_MARKER_TEXT)