config.py•2.25 kB
"""Configuration management using Pydantic Settings."""
from typing import Literal
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
class Config(BaseSettings):
"""Application configuration loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
)
# B4B API Configuration
b4b_api_base_url: str = Field(
default="http://localhost:8000",
description="Base URL for B4B API",
)
b4b_api_version: str = Field(
default="v1",
description="API version to use",
)
# Timeouts (in seconds)
api_timeout: int = Field(
default=30,
description="Request timeout in seconds",
ge=1,
)
api_connect_timeout: int = Field(
default=10,
description="Connection timeout in seconds",
ge=1,
)
# Retry Configuration
max_retries: int = Field(
default=3,
description="Maximum number of retry attempts",
ge=0,
le=10,
)
retry_backoff: float = Field(
default=1.0,
description="Backoff multiplier for retries",
ge=0.1,
)
# Token Management
token_refresh_threshold_minutes: int = Field(
default=15,
description="Minutes before token expiry to trigger refresh",
ge=1,
)
# Logging
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = Field(
default="INFO",
description="Logging level",
)
# Rate Limiting
rate_limit_requests: int = Field(
default=100,
description="Maximum requests per time window",
ge=1,
)
@property
def api_base_url(self) -> str:
"""Get the full API base URL with version."""
base = self.b4b_api_base_url.rstrip("/")
version = self.b4b_api_version.strip("/")
return f"{base}/api/{version}"
# Global configuration instance
_config: Config | None = None
def get_config() -> Config:
"""Get the global configuration instance."""
global _config
if _config is None:
_config = Config()
return _config