60 lines
2.1 KiB
Python
60 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
from typing import Any
|
|
|
|
import uvicorn
|
|
|
|
from settings import Settings, load_settings
|
|
|
|
|
|
def merge_settings(base: Settings, overrides: dict[str, Any]) -> Settings:
|
|
base_dict = base.model_dump() if hasattr(base, "model_dump") else {k: v for k, v in vars(base).items() if not k.startswith("_")}
|
|
clean_overrides = {k: v for k, v in overrides.items() if v is not None}
|
|
return Settings(**{**base_dict, **clean_overrides})
|
|
|
|
|
|
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
p = argparse.ArgumentParser(description="Start FastAPI app with configurable settings")
|
|
p.add_argument("--config", "-c", help="Path to YAML config file (overrides env/.env)", default=None)
|
|
p.add_argument("--host", help="Host to bind", default=None)
|
|
p.add_argument("--port", type=int, help="Port to bind", default=None)
|
|
p.add_argument("--workers", type=int, help="Number of workers (uvicorn)", default=None)
|
|
p.add_argument("--log-level", help="Log level for uvicorn", default=None)
|
|
p.add_argument("--reload", action="store_true", help="Enable reload (development)")
|
|
return p.parse_args(argv)
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> None:
|
|
args = parse_args(argv)
|
|
|
|
if args.config:
|
|
os.environ["CONFIG_FILE"] = args.config
|
|
|
|
base = load_settings()
|
|
overrides: dict[str, Any] = {
|
|
"host": args.host,
|
|
"port": args.port,
|
|
"workers": args.workers,
|
|
"log_level": args.log_level,
|
|
}
|
|
final_settings = merge_settings(base, overrides)
|
|
|
|
uvicorn_kwargs = {
|
|
"app": "app:app",
|
|
"host": final_settings.host,
|
|
"port": int(final_settings.port),
|
|
"log_level": final_settings.log_level,
|
|
"workers": int(final_settings.workers) if final_settings.workers and final_settings.workers > 0 else None,
|
|
"reload": args.reload,
|
|
}
|
|
uvicorn_kwargs = {k: v for k, v in uvicorn_kwargs.items() if v is not None}
|
|
|
|
print("Starting app with settings:", final_settings.model_dump() if hasattr(final_settings, "model_dump") else vars(final_settings))
|
|
uvicorn.run(**uvicorn_kwargs)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|