mirror of
https://github.com/zvx-echo6/recon.git
synced 2026-06-10 08:54:34 +02:00
decouple: remove /api/wiki-enrich + wiki_index read path (migrated to navi-places)
PR-B of decouple #4-READ. navi-places now reads its own wiki_index.db directly (navi-backend a8f9520, deployed + verified: Horseshoe Falls enrichment served from /var/lib/navi-backend/wiki_index.db; admin-info dropped the recon-wiki-enrich dependency). recon's endpoint is edge-unreachable-unused, safe to remove. - DELETE lib/wiki_enrich_api.py (the /api/wiki-enrich blueprint). - DELETE lib/place_detail.py (97-line survivor: lookup_wiki_index + _get_wiki_index_db) — its only consumer was wiki_enrich_api.py (verified zero non-test code consumers). Fully orphaned. - DELETE lib/wiki_enrich_api_test.py (tests the deleted endpoint). - api.py: drop the wiki_enrich_bp import + register_blueprint. Untouched (separate decouple): /api/wiki-rewrite (wiki_rewrite_api.py + wiki_rewrite.py), still navi-consumed. /opt/recon/data/wiki_index.db left in place (data; now a harmless dead file). Internal localhost migration — no nginx. Flag (doc follow-up, not fixed): deployment_config.py:10 + wiki_rewrite_api.py:6 both have stale in-prose references to the deleted place_detail. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
21c0f11eff
commit
ac99723e51
4 changed files with 0 additions and 209 deletions
|
|
@ -62,10 +62,6 @@ app.request_class = _LargeZimRequest
|
||||||
from .netsyms_api import netsyms_bp
|
from .netsyms_api import netsyms_bp
|
||||||
app.register_blueprint(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) ──
|
# ── Wiki-rewrite Blueprint (extraction #5 prep — HTTP wrapper over rewrite_wiki_link) ──
|
||||||
from .wiki_rewrite_api import wiki_rewrite_bp
|
from .wiki_rewrite_api import wiki_rewrite_bp
|
||||||
app.register_blueprint(wiki_rewrite_bp)
|
app.register_blueprint(wiki_rewrite_bp)
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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=<Qid> (primary key)
|
|
||||||
GET /api/wiki-enrich?name=<name>&country=<cc> (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=<id> or ?name=<name>&country=<cc>'}), 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)
|
|
||||||
|
|
@ -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)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue