pocket-confidant / seed_data.py
LocutusofArgo
feat: make the Space publishable without binary db
0fbe3a4
Raw
History Blame Contribute Delete
3.8 kB
"""Seed the Space's journal DB with the demo entries.
The Space prefers a pre-built SQLite snapshot when one is present, but it can
also fall back to the JSON-backed demo seed from `engine.store`. That keeps the
Space publishable without checking a large binary DB into the Hugging Face repo.
Idempotent: if the user's home DB already has entries, seeding is skipped.
"""
from __future__ import annotations
import os
import shutil
import time
from pathlib import Path
# Resolve paths relative to this file. On the Space, all files land at /app/,
# so the prebuilt DB is a sibling of seed_data.py. In dev, we also try the
# repo root.
_SPACE_DIR = Path(__file__).resolve().parent
DEFAULT_DB_SIBLING = _SPACE_DIR / "data" / "journal_preloaded.db"
DEFAULT_DB_REPOROOT = _SPACE_DIR.parent / "data" / "journal_preloaded.db"
def _resolve_prebuilt_db() -> Path | None:
if DEFAULT_DB_SIBLING.exists():
return DEFAULT_DB_SIBLING
if DEFAULT_DB_REPOROOT.exists():
return DEFAULT_DB_REPOROOT
return None
def seed_journal(target_db_path: str | os.PathLike) -> int:
"""Copy the pre-built journal DB to the user's home directory.
Idempotent: if the target DB already has entries, this is a no-op.
Returns the number of entries in the target DB after seeding.
"""
target = Path(target_db_path)
target.parent.mkdir(parents=True, exist_ok=True)
# Check if the target already has entries (idempotent)
if target.exists():
try:
import sqlite3
conn = sqlite3.connect(str(target))
existing = conn.execute("SELECT COUNT(*) FROM entries").fetchone()[0]
conn.close()
if existing >= 1:
print(f"[seed_data] target DB already has {existing} entries; skipping copy")
return existing
except Exception as exc:
print(f"[seed_data] could not check target DB: {exc}")
prebuilt = _resolve_prebuilt_db()
if prebuilt is None:
print("[seed_data] no prebuilt DB found; seeding from JSON demo data")
try:
from engine.store import seed_demo_data
except Exception as exc:
print(f"[seed_data] could not import JSON seed helper: {exc}")
return 0
t0 = time.time()
n = seed_demo_data(target)
elapsed = time.time() - t0
print(f"[seed_data] seeded {n} entries from JSON in {elapsed:.2f}s")
return n
print(f"[seed_data] copying prebuilt DB: {prebuilt} -> {target}")
t0 = time.time()
shutil.copy2(str(prebuilt), str(target))
elapsed = time.time() - t0
# Count entries
import sqlite3
conn = sqlite3.connect(str(target))
n = conn.execute("SELECT COUNT(*) FROM entries").fetchone()[0]
conn.close()
print(f"[seed_data] seeded {n} entries in {elapsed:.2f}s (file copy)")
return n
# --------------------------------------------------------------------------- #
# Sync seed_journal signature for backward-compat with calls that pass `store`
# --------------------------------------------------------------------------- #
def seed_journal_compat(store=None, json_path=None, max_entries=50):
"""Backward-compat wrapper for the old seed_journal(store, ...) API.
Tries to use the prebuilt DB; falls back to no-op if not present.
"""
if store is not None:
try:
db_path = store.db_path
except AttributeError:
return 0
return seed_journal(db_path)
return 0
if __name__ == "__main__":
# Smoke test: copy the prebuilt DB to a temp location and count.
import sys
target = sys.argv[1] if len(sys.argv) > 1 else str(Path.home() / ".pocket-confidant" / "journal.db")
n = seed_journal(target)
print(f"OK: {n} entries at {target}")