71 lines
2.9 KiB
Python
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__)
|