diff --git a/lib/api.py b/lib/api.py index e83a98f..63562f7 100644 --- a/lib/api.py +++ b/lib/api.py @@ -62,10 +62,6 @@ app.request_class = _LargeZimRequest from .netsyms_api import netsyms_bp app.register_blueprint(netsyms_bp) -# ── Wiki-enrich Blueprint (extraction #5 prep — HTTP wrapper over wiki_index) ── -from .wiki_enrich_api import wiki_enrich_bp -app.register_blueprint(wiki_enrich_bp) - # ── Wiki-rewrite Blueprint (extraction #5 prep — HTTP wrapper over rewrite_wiki_link) ── from .wiki_rewrite_api import wiki_rewrite_bp app.register_blueprint(wiki_rewrite_bp) diff --git a/lib/place_detail.py b/lib/place_detail.py deleted file mode 100644 index 6f6f1ba..0000000 --- a/lib/place_detail.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Wiki-index lookup for place enrichment. - -Provides lookup_wiki_index(wikidata_id, name, country_code) — a pure read of the -local wiki_index.db, used by the /api/wiki-enrich endpoint (navi-places -HTTP-fetches wiki enrichment instead of reading the 2.1 GB DB directly). -""" -import os -import sqlite3 - -from .utils import setup_logging - -logger = setup_logging('recon.place_detail') - - -# ── Wiki Index enrichment ─────────────────────────────────────────────── - -_wiki_index_conn = None - -def _get_wiki_index_db(): - global _wiki_index_conn - if _wiki_index_conn is not None: - return _wiki_index_conn - - db_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data", "wiki_index.db") - if not os.path.exists(db_path): - logger.debug(f"wiki_index.db not found at {db_path}") - return None - - _wiki_index_conn = sqlite3.connect(db_path, check_same_thread=False) - _wiki_index_conn.row_factory = sqlite3.Row - logger.info(f"Wiki index DB ready at {db_path}") - return _wiki_index_conn - - -def lookup_wiki_index(wikidata_id=None, name=None, country_code=None): - """Standalone wiki_index lookup, extracted for the /api/wiki-enrich endpoint - (extraction #5: navi-places HTTP-fetches wiki enrichment instead of reading - the 2.1 GB wiki_index.db directly). - - Mirrors the lookup that `_enrich_with_wiki_index` performs in-process: - by wikidata_id first, then a name + country_code fallback. Returns a dict of - wiki enrichment fields (only those present), or None if there is no match or - the wiki_index DB is unavailable. Pure DB read — no feature-flag gating - (callers decide whether to call) and never raises. - - NOTE: additive only — `_enrich_with_wiki_index` is intentionally left - untouched here; it can be DRY-refactored to delegate to this in a later PR. - """ - db = _get_wiki_index_db() - if not db: - return None - - try: - cur = db.cursor() - row = None - - if wikidata_id: - wid = wikidata_id - if isinstance(wid, str) and wid.startswith("http"): - wid = wid.split("/")[-1] - cur.execute( - "SELECT summary, wiki_population, wikipedia_title, wikivoyage_title FROM wiki_places WHERE wikidata_id = ?", - (wid,) - ) - row = cur.fetchone() - - if not row and name and country_code: - cur.execute( - "SELECT summary, wiki_population, wikipedia_title, wikivoyage_title FROM wiki_places WHERE place_name = ? AND country_code = ? LIMIT 1", - (name, country_code.lower()) - ) - row = cur.fetchone() - - if not row: - return None - - out = {} - if row["summary"]: - out["wiki_summary"] = row["summary"] - if row["wiki_population"]: - try: - out["wiki_population"] = int(row["wiki_population"]) - except (ValueError, TypeError): - out["wiki_population"] = row["wiki_population"] - if row["wikipedia_title"]: - title = row["wikipedia_title"].replace(" ", "_") - out["wiki_url"] = f"https://en.wikipedia.org/wiki/{title}" - if row["wikivoyage_title"]: - title = row["wikivoyage_title"].replace(" ", "_") - out["wikivoyage_url"] = f"https://en.wikivoyage.org/wiki/{title}" - - return out or None - - except Exception as e: - logger.debug(f"wiki_index lookup error: {e}") - return None diff --git a/lib/wiki_enrich_api.py b/lib/wiki_enrich_api.py deleted file mode 100644 index ff0f9c7..0000000 --- a/lib/wiki_enrich_api.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Wiki-enrich API — read-only HTTP wrapper over the wiki_index lookup. - -Extraction #5 prep: lets the (future) navi-places service fetch wiki enrichment -over HTTP instead of reading recon's 2.1 GB data/wiki_index.db directly. Additive -only — does not change place_detail's in-process `_enrich_with_wiki_index` path. - - GET /api/wiki-enrich?wikidata= (primary key) - GET /api/wiki-enrich?name=&country= (fallback key) - -Public (no auth), matching /api/place/*. 400 if no usable key; 404 on no match. -""" -from flask import Blueprint, request, jsonify - -from .place_detail import lookup_wiki_index - -wiki_enrich_bp = Blueprint('wiki_enrich', __name__) - - -@wiki_enrich_bp.route('/api/wiki-enrich') -def api_wiki_enrich(): - wikidata = (request.args.get('wikidata') or '').strip() or None - name = (request.args.get('name') or '').strip() or None - country = (request.args.get('country') or '').strip() or None - - if not wikidata and not (name and country): - return jsonify({'error': 'provide ?wikidata= or ?name=&country='}), 400 - - result = lookup_wiki_index(wikidata_id=wikidata, name=name, country_code=country) - if result is None: - return jsonify({'error': 'no wiki match'}), 404 - return jsonify(result) diff --git a/lib/wiki_enrich_api_test.py b/lib/wiki_enrich_api_test.py deleted file mode 100644 index 681e5cb..0000000 --- a/lib/wiki_enrich_api_test.py +++ /dev/null @@ -1,77 +0,0 @@ -"""Tests for the /api/wiki-enrich endpoint (extraction #5 prep). - -Plain-assert style (matching the other lib *_test.py; recon's venv has no -pytest). Builds a minimal Flask app with only wiki_enrich_bp registered (avoids -importing the full recon app) and points place_detail's lazy wiki_index -connection at an in-memory fixture DB. Run with pytest, or directly: - python -m lib.wiki_enrich_api_test -""" -import sqlite3 - -from flask import Flask - -from lib import place_detail -from lib.wiki_enrich_api import wiki_enrich_bp - - -def _client(): - """Fresh in-memory wiki_index fixture + a minimal app with just the route.""" - conn = sqlite3.connect(":memory:", check_same_thread=False) - conn.row_factory = sqlite3.Row - conn.execute( - "CREATE TABLE wiki_places (wikidata_id TEXT, place_name TEXT, country_code TEXT, " - "summary TEXT, wiki_population TEXT, wikipedia_title TEXT, wikivoyage_title TEXT)" - ) - conn.execute( - "INSERT INTO wiki_places VALUES (?,?,?,?,?,?,?)", - ("Q830149", "Filer", "us", "A city in Idaho.", "2508", "Filer, Idaho", "Filer"), - ) - conn.commit() - # Point the lazy module-level connection at the fixture so - # _get_wiki_index_db()/lookup_wiki_index() use it (bypasses the file path). - place_detail._wiki_index_conn = conn - app = Flask(__name__) - app.register_blueprint(wiki_enrich_bp) - return app.test_client() - - -def test_wiki_enrich_hit_by_wikidata(): - resp = _client().get("/api/wiki-enrich?wikidata=Q830149") - assert resp.status_code == 200, resp.status_code - d = resp.get_json() - assert d["wiki_summary"] == "A city in Idaho." - assert d["wiki_population"] == 2508 # cast to int - assert d["wiki_url"] == "https://en.wikipedia.org/wiki/Filer,_Idaho" - assert d["wikivoyage_url"] == "https://en.wikivoyage.org/wiki/Filer" - - -def test_wiki_enrich_no_match_404(): - resp = _client().get("/api/wiki-enrich?wikidata=Q9999999") - assert resp.status_code == 404, resp.status_code - - -def test_wiki_enrich_name_country_fallback(): - resp = _client().get("/api/wiki-enrich?name=Filer&country=US") - assert resp.status_code == 200, resp.status_code - assert resp.get_json()["wiki_summary"] == "A city in Idaho." - - -def test_wiki_enrich_no_key_400(): - c = _client() - assert c.get("/api/wiki-enrich").status_code == 400 - # name without country is not a usable key - assert c.get("/api/wiki-enrich?name=Filer").status_code == 400 - - -if __name__ == "__main__": - failures = 0 - for _name, _fn in sorted(globals().items()): - if _name.startswith("test_") and callable(_fn): - try: - _fn() - print(f"PASS {_name}") - except Exception as exc: # noqa: BLE001 - failures += 1 - print(f"FAIL {_name}: {exc!r}") - print("OK" if failures == 0 else f"{failures} FAILED") - raise SystemExit(1 if failures else 0)