get-around-api / src /config /settings.py
sam-bot's picture
1st commit
49fd357
"""Application settings using Pydantic Settings."""
import logging
from enum import Enum
from functools import lru_cache
from pathlib import Path
from pydantic_settings import BaseSettings, SettingsConfigDict
class Environment(str, Enum):
"""Application environment."""
DEVELOPMENT = "development"
TESTING = "testing"
PRODUCTION = "production"
class Settings(BaseSettings):
"""Application settings loaded from environment variables.
Settings are loaded from .env files and environment variables.
Environment variables take precedence over .env file values.
Attributes:
environment: Current environment (development, testing, production).
log_level: Logging level as string (DEBUG, INFO, WARNING, ERROR).
api_url: Base URL for the pricing prediction API.
api_host: Host for the FastAPI server.
api_port: Port for the FastAPI server.
dashboard_port: Port for the Streamlit dashboard.
mlflow_tracking_uri: URI for MLflow tracking server.
data_dir: Directory for data files.
models_dir: Directory for serialized models.
"""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
)
# Environment
environment: Environment = Environment.DEVELOPMENT
# Logging
log_level: str = "DEBUG"
# API
api_url: str = "http://localhost:8000"
api_host: str = "0.0.0.0"
api_port: int = 8000
# Dashboard
dashboard_port: int = 8501
# MLflow
mlflow_tracking_uri: str = "./mlruns"
# Paths
data_dir: Path = Path("data")
models_dir: Path = Path("models")
@property
def log_level_int(self) -> int:
"""Get logging level as integer.
Returns:
Logging level constant (e.g., logging.DEBUG, logging.INFO).
"""
return getattr(logging, self.log_level.upper(), logging.INFO)
# Logging config by environment (from ORCHESTRATION.md)
LOGGING_CONFIG: dict[Environment, dict[str, int | str]] = {
Environment.DEVELOPMENT: {
"level": logging.DEBUG,
"format": "%(asctime)s - %(name)s:%(lineno)d - %(levelname)s - %(message)s",
},
Environment.TESTING: {
"level": logging.WARNING,
"format": "%(levelname)s - %(message)s",
},
Environment.PRODUCTION: {
"level": logging.INFO,
"format": "%(asctime)s - %(levelname)s - %(message)s",
},
}
def configure_logging(settings: Settings) -> None:
"""Configure logging based on environment.
Sets up the root logger with appropriate level and format based on
the current environment.
Args:
settings: Application settings instance.
"""
config = LOGGING_CONFIG.get(
settings.environment, LOGGING_CONFIG[Environment.DEVELOPMENT]
)
logging.basicConfig(
level=config["level"],
format=config["format"],
)
@lru_cache
def get_settings() -> Settings:
"""Get cached settings instance.
Uses lru_cache to ensure settings are loaded only once and reused
across the application.
Returns:
Cached Settings instance.
"""
return Settings()