# Author: Simon-Pierre Boucher # Contact: contact@spboucher.ai # Project: Toit-Ka # ----------------------------------------------------------------------------- # run.py : point d'entrée CLI unique de Toit-Ka # serve [port] — API FastAPI + frontend (défaut 8097) # etl — une passe : répliques -> toitka.db (normalisation villes/types) # watch [minutes] — boucle : replicate (si configuré) + etl (défaut 30 min) # replicate — tire les snapshots des BD lou-ka / immo-ka (nodes prod) # villes — rapport de canonicalisation des villes (audit) # ----------------------------------------------------------------------------- from __future__ import annotations import os import sys from pathlib import Path ROOT = Path(__file__).resolve().parent def _load_env() -> None: """Charge .env à la main (aucune dépendance), sans écraser l'environnement.""" env = ROOT / ".env" if not env.exists(): return for line in env.read_text(encoding="utf-8").splitlines(): line = line.strip() if not line or line.startswith("#") or "=" not in line: continue k, _, v = line.partition("=") os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'")) def main() -> None: _load_env() cmd = sys.argv[1] if len(sys.argv) > 1 else "serve" if cmd == "serve": import uvicorn port = int(sys.argv[2]) if len(sys.argv) > 2 else 8097 uvicorn.run("toitka.web:app", host="0.0.0.0", port=port) elif cmd == "etl": from toitka import etl etl.run() elif cmd == "watch": from toitka import etl minutes = float(sys.argv[2]) if len(sys.argv) > 2 else 30 etl.watch(minutes * 60) elif cmd == "replicate": from toitka import replicate replicate.run() elif cmd == "villes": from toitka import etl etl.rapport_villes() else: print(__doc__ or "Commandes : serve | etl | watch | replicate | villes") sys.exit(1) if __name__ == "__main__": main()