#!/usr/bin/env python3 """ Download and save fixture data for the sample locations. Run from the project root directory: python tests/capture_fixtures.py This makes real HTTP requests to WDQS and the Wikidata API and uses the local PostGIS database. The output is saved to tests/fixtures/ and is used by test_examples.py so those tests run without any network access. Re-run this script whenever the expected results change (e.g. after an OSM or Wikidata edit that affects a sample location). """ import json import sys from pathlib import Path from unittest.mock import patch sys.path.insert(0, str(Path(__file__).parent.parent)) import geocode.wikidata as wikidata_module from geocode import samples from lookup import app, lat_lon_to_wikidata FIXTURES_DIR = Path(__file__).parent / "fixtures" def capture_sample(i: int, lat: float, lon: float, name: str) -> None: """Capture and save fixture data for one sample location.""" wdqs_calls: dict[str, list] = {} api_calls: dict[str, dict] = {} # Hold references to the real functions before patching. real_wdqs = wikidata_module.wdqs real_api_call = wikidata_module.api_call def recording_wdqs(query: str) -> list: result = real_wdqs(query) wdqs_calls[query] = result return result def recording_api_call(params: dict) -> dict: key = json.dumps(params, sort_keys=True) result = real_api_call(params) api_calls[key] = result return result with patch("geocode.wikidata.wdqs", side_effect=recording_wdqs), patch( "geocode.wikidata.api_call", side_effect=recording_api_call ): reply = lat_lon_to_wikidata(lat, lon) result = reply["result"] commons_cat = result.get("commons_cat") fixture: dict = { "lat": lat, "lon": lon, "name": name, "wdqs": wdqs_calls, "api": api_calls, "expected_wikidata": result.get("wikidata"), "expected_commons_cat": commons_cat["title"] if isinstance(commons_cat, dict) else None, } fixture_path = FIXTURES_DIR / f"sample_{i:02d}.json" fixture_path.write_text(json.dumps(fixture, indent=2, ensure_ascii=False)) qid = fixture["expected_wikidata"] or "none" cat = fixture["expected_commons_cat"] or "no commons cat" print(f" [{i:02d}] {name}: {qid} / {cat}") def main() -> None: """Capture fixtures for all samples.""" FIXTURES_DIR.mkdir(exist_ok=True) indices = None if len(sys.argv) > 1: # Allow passing specific indices on the command line, e.g.: # python tests/capture_fixtures.py 0 5 12 indices = {int(a) for a in sys.argv[1:]} print(f"Capturing fixtures for {len(samples)} samples...") with app.app_context(): for i, (lat, lon, name) in enumerate(samples): if indices and i not in indices: continue print(f"[{i:02d}/{len(samples) - 1}] {name} ({lat}, {lon})") capture_sample(i, lat, lon, name) print(f"\nDone. Fixtures saved to {FIXTURES_DIR}/") if __name__ == "__main__": main()