from pathlib import Path from pydantic_settings import BaseSettings, SettingsConfigDict _PROJECT_ROOT = Path(__file__).parent.parent.parent class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", extra="ignore", ) # PostgreSQL (local dev) postgres_user: str = "olist" postgres_password: str = "olist_secret" postgres_db: str = "olist_dw" postgres_host: str = "localhost" postgres_port: int = 5432 database_url: str = str(_PROJECT_ROOT / "data" / "olist.db") # MLflow (local dev / training only) mlflow_tracking_uri: str = "http://localhost:5000" # FastAPI fastapi_url: str = "http://localhost:8000" # Data paths — override via DATA_DIR / RAW_DATA_DIR env vars in containers data_dir: Path = _PROJECT_ROOT / "data" raw_data_dir: Path = _PROJECT_ROOT / "data" / "raw" # ML model paths (used instead of MLflow in deployed environments) churn_model_path: str = str(_PROJECT_ROOT / "models" / "churn_model.joblib") segmentation_model_path: str = str(_PROJECT_ROOT / "models" / "segmentation_pipeline.joblib") @property def processed_data_dir(self) -> Path: return self.data_dir / "processed" @property def sync_database_url(self) -> str: """psycopg2-compatible URL for Alembic / Airflow.""" return self.database_url.replace("postgresql+psycopg://", "postgresql+psycopg2://") @property def sqlalchemy_database_url(self) -> str: """Return a SQLAlchemy-compatible URL, adding sqlite:/// prefix if needed.""" url = self.database_url if not url.startswith(("sqlite", "postgresql", "mysql", "mssql")): return f"sqlite:///{url}" return url settings = Settings()