Files
parentcalendar/main.py
T

71 lines
2.9 KiB
Python

"""ParentCalendar.
Usage:
python main.py start the server (settings: see .env.example)
python main.py backup <destination> copy the database (SQLite online backup) and the photos
"""
import logging
import os
import shutil
import sqlite3
import sys
from datetime import datetime
from pathlib import Path
from parentcalendar import config, db
def backup(destination):
dest = Path(destination)
dest.mkdir(parents=True, exist_ok=True)
target = dest / f"parentcalendar-{datetime.now():%Y%m%d-%H%M%S}.db"
src, out = db.connect(), sqlite3.connect(target)
try:
src.backup(out) # consistent copy even while the server is writing
finally:
out.close()
src.close()
if config.IMAGES_DIR.exists():
shutil.copytree(config.IMAGES_DIR, dest / "images", dirs_exist_ok=True)
print(f"Backed up to {target}")
def serve():
if not config.PUBLIC_URL:
sys.exit("Set PUBLIC_URL (for example https://calendar.example.com) in the environment or in .env.")
if not (config.STATIC_DIR / "index.html").exists():
sys.exit("The front end isn't built yet. Run: cd frontend && npm ci && npm run build")
import uvicorn
from parentcalendar import extraction
env = os.environ.get
print(f"ParentCalendar {env('APP_VERSION', 'dev')} ({env('APP_COMMIT', 'unknown')}, {env('APP_COMMIT_DATE', 'unknown')})")
settings = { # what the app actually uses, defaults included
"PUBLIC_URL": config.PUBLIC_URL, "DATA_DIR": config.DATA_DIR, "HOST": config.HOST, "PORT": config.PORT,
"OLLAMA_URL": extraction.OLLAMA_URL, "EXTRACT_MODEL": extraction.MODEL, "EXTRACT_THINK": int(extraction.THINK),
"EXTRACT_THINK_LEVEL": extraction.THINK_LEVEL or "", "EXTRACT_TEMPERATURE": extraction.TEMPERATURE,
"EXTRACT_TOP_P": "" if extraction.TOP_P is None else extraction.TOP_P,
"EXTRACT_TOP_K": "" if extraction.TOP_K is None else extraction.TOP_K,
"EXTRACT_NUM_CTX": extraction.NUM_CTX, "EXTRACT_KEEP_ALIVE": extraction.KEEP_ALIVE, "EXTRACT_DOUBLE_READ": int(extraction.DOUBLE_READ),
"EXTRACT_IGNORE": ",".join(sorted(extraction.IGNORE)), "IMAGE_RETENTION_DAYS": config.IMAGE_RETENTION_DAYS,
"SHOW_SCAN_STATS": int(config.SHOW_SCAN_STATS),
"ANTHROPIC_API_KEY": "set" if env("ANTHROPIC_API_KEY") else "unset", # never print the key
}
print("Settings: " + " ".join(f"{k}={v}" for k, v in settings.items()))
# The app's own log lines (scan timings, failures), formatted like uvicorn's. Other libraries stay at warnings.
logging.basicConfig(format="%(levelname)s: %(message)s")
logging.getLogger("parentcalendar").setLevel(logging.INFO)
uvicorn.run("parentcalendar.app:app", host=config.HOST, port=config.PORT, proxy_headers=True)
if __name__ == "__main__":
args = sys.argv[1:]
if args[:1] == ["backup"] and len(args) == 2:
backup(args[1])
elif not args:
serve()
else:
sys.exit(__doc__)