"""
Configuration management using pydantic-settings.
Loads configuration from environment variables with ODOO_ and REDIS_ prefixes.
"""
from __future__ import annotations
from functools import lru_cache
from typing import Literal
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
class OdooSettings(BaseSettings):
"""Odoo connection settings."""
model_config = SettingsConfigDict(
env_prefix="ODOO_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
url: str = Field(..., description="Odoo instance URL")
db: str = Field(..., description="Odoo database name")
username: str = Field(..., description="Odoo username/email")
api_key: str = Field(..., description="Odoo API key")
timeout: int = Field(default=30, ge=5, le=300, description="Request timeout in seconds")
@field_validator("url")
@classmethod
def validate_url(cls, v: str) -> str:
"""Ensure URL doesn't have trailing slash."""
return v.rstrip("/")
class RedisSettings(BaseSettings):
"""Redis cache settings."""
model_config = SettingsConfigDict(
env_prefix="REDIS_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
url: str = Field(default="redis://localhost:6379/0", description="Redis connection URL")
enabled: bool = Field(default=True, description="Enable/disable caching")
default_ttl: int = Field(default=300, ge=60, le=3600, description="Default TTL in seconds")
class LoggingSettings(BaseSettings):
"""Logging configuration."""
model_config = SettingsConfigDict(
env_prefix="LOG_",
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
level: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = Field(default="INFO")
format: Literal["json", "text"] = Field(default="json")
class Settings(BaseSettings):
"""Combined application settings."""
odoo: OdooSettings = Field(default_factory=OdooSettings)
redis: RedisSettings = Field(default_factory=RedisSettings)
logging: LoggingSettings = Field(default_factory=LoggingSettings)
@lru_cache
def get_settings() -> Settings:
"""Get cached settings instance."""
return Settings()
# Convenience accessor
settings = get_settings()