From b18488a6d39486cc15427c5ba281b72172a86353 Mon Sep 17 00:00:00 2001 From: Piotr Dec Date: Tue, 7 Oct 2025 00:06:04 +0200 Subject: [PATCH] Pydantic --- app/config/__init__.py | 1 + app/config/settings.py | 28 ++++++++++++++++++++++++++++ app/main.py | 35 ++++++++--------------------------- pyproject.toml | 1 + 4 files changed, 38 insertions(+), 27 deletions(-) create mode 100644 app/config/__init__.py create mode 100644 app/config/settings.py diff --git a/app/config/__init__.py b/app/config/__init__.py new file mode 100644 index 0000000..1fb2e97 --- /dev/null +++ b/app/config/__init__.py @@ -0,0 +1 @@ +from .settings import get_settings diff --git a/app/config/settings.py b/app/config/settings.py new file mode 100644 index 0000000..cf95017 --- /dev/null +++ b/app/config/settings.py @@ -0,0 +1,28 @@ +from functools import lru_cache + +from pydantic_settings import BaseSettings, SettingsConfigDict +from pydantic import BaseModel +from pathlib import Path +import yaml + +class AppConfig(BaseModel): + host: str = "127.0.0.1" + port: int = 8000 + reload: bool = True + +class Settings(BaseSettings): + model_config = SettingsConfigDict(env_prefix="KARL_", env_nested_delimiter="__") + app: AppConfig = AppConfig() + + @classmethod + def from_yaml(cls, path: Path | str = "config/config.yaml") -> "Settings": + p = Path(path) + data = {} + if p.exists(): + with p.open("r", encoding="utf-8") as fh: + data = yaml.safe_load(fh) or {} + return cls(**data) + +@lru_cache +def get_settings() -> Settings: + return Settings.from_yaml() diff --git a/app/main.py b/app/main.py index c299144..bb425d1 100644 --- a/app/main.py +++ b/app/main.py @@ -1,11 +1,9 @@ -import os - -import yaml from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from jinja2 import Environment, FileSystemLoader, select_autoescape from app.api.v1 import router as api_v1_router +from app.config import get_settings # Inicjalizacja Jinja2 templates_env = Environment( @@ -13,26 +11,7 @@ templates_env = Environment( autoescape=select_autoescape(["html", "xml"]), ) - -def load_config() -> dict: - """ - Ładuje konfigurację z pliku YAML. - Domyślna ścieżka: config/config.yaml - Można nadpisać przez APP_CONFIG_FILE. - """ - config_path = os.getenv("APP_CONFIG_FILE", "config/config.yaml") - if not os.path.exists(config_path): - # Zwróć minimalną domyślną konfigurację, jeśli plik nie istnieje - return { - "app": {"host": "127.0.0.1", "port": 8000, "reload": True}, - } - with open(config_path, "r", encoding="utf-8") as f: - return yaml.safe_load(f) or {} - - app = FastAPI(title="Karl", version="0.1.0") -# Załaduj konfigurację do stanu aplikacji -app.state.config = load_config() # Rejestracja routera API pod /api/v1 app.include_router(api_v1_router, prefix="/api/v1", tags=["v1"]) @@ -48,8 +27,10 @@ async def index(request: Request) -> HTMLResponse: def run() -> None: import uvicorn - cfg = getattr(app.state, "config", {}) - host = cfg.get("app", {}).get("host", "127.0.0.1") - port = int(cfg.get("app", {}).get("port", 8000)) - reload = bool(cfg.get("app", {}).get("reload", True)) - uvicorn.run("app.main:app", host=host, port=port, reload=reload) + settings = get_settings() + uvicorn.run( + "app.main:app", + host=settings.app.host, + port=settings.app.port, + reload=settings.app.reload, + ) diff --git a/pyproject.toml b/pyproject.toml index 43f7787..c7db9ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "fastapi>=0.115.0", "uvicorn[standard]>=0.30.0", "jinja2>=3.1.4", + "pydantic-settings>=2.4.0", "pyyaml>=6.0.2", ]