Spaces:
Sleeping
Sleeping
| """ | |
| Local dev server — Windows-safe SelectorEventLoop runner. | |
| Use this instead of `uvicorn main:app` on Windows. It guarantees SelectorEventLoop, | |
| which psycopg_async requires (ProactorEventLoop, the Windows default, fails with psycopg3). | |
| reload=False is intentional — reload spawns subprocesses that lose the loop. | |
| Reads host and port from APP_BASE_URL in .env (e.g. http://192.168.1.36:7880). | |
| Reads log level from LOG_LEVEL in .env. | |
| Usage: | |
| uv run python dev_server.py | |
| Note: main.py is the FastAPI app entry point — used by uvicorn directly and by HF Spaces. | |
| This script is only needed for local Windows development. | |
| """ | |
| import asyncio | |
| import os | |
| import selectors | |
| import sys | |
| from urllib.parse import urlparse | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| import uvicorn | |
| def _host_port_from_base_url(url: str) -> tuple[str, int]: | |
| parsed = urlparse(url) | |
| host = parsed.hostname or "127.0.0.1" | |
| port = parsed.port or 8000 | |
| return host, port | |
| HOST, PORT = _host_port_from_base_url(os.getenv("APP_BASE_URL", "http://127.0.0.1:8000")) | |
| LOG_LEVEL = os.getenv("LOG_LEVEL", "info").lower() | |
| async def _serve(): | |
| config = uvicorn.Config("main:app", host=HOST, port=PORT, log_level=LOG_LEVEL) | |
| server = uvicorn.Server(config) | |
| await server.serve() | |
| if __name__ == "__main__": | |
| try: | |
| if sys.platform == "win32": | |
| # loop_factory requires Python 3.12+ — we're on 3.13, safe. | |
| asyncio.run( | |
| _serve(), | |
| loop_factory=lambda: asyncio.SelectorEventLoop(selectors.SelectSelector()), | |
| ) | |
| else: | |
| asyncio.run(_serve()) | |
| except KeyboardInterrupt: | |
| pass # Ctrl+C — server already shut down cleanly via uvicorn's signal handler | |