from pydantic import BaseModel, Field, AnyUrl from typing import Optional import os def str_to_bool(value): """ Convert a string to a boolean. Accepts common truthy/falsey string values. Raises ValueError for unrecognized inputs. """ if not isinstance(value, str): raise TypeError("Input must be a string.") value_lower = value.strip().lower() truthy = {"true", "1", "yes", "y", "on"} falsey = {"false", "0", "no", "n", "off"} if value_lower in truthy: return True elif value_lower in falsey: return False else: raise ValueError(f"Cannot convert '{value}' to boolean.") class Settings(BaseModel): DATABASE_URL: str = os.getenv("DATABASE_URL", "postgresql+asyncpg://postgres:postgres@localhost:5432/tasks") RABBITMQ_URL: str = os.getenv("RABBITMQ_URL", "amqp://guest:guest@localhost/") RABBITMQ_EXCHANGE: str = os.getenv("RABBITMQ_EXCHANGE", "tasks") RABBITMQ_EXCHANGE_TYPE: str = "topic" MAX_RETRIES: int = int(os.getenv("MAX_RETRIES", "3")) DNS_TIMEOUT: float = float(os.getenv("DNS_TIMEOUT", "3.0")) DNS_LIFETIME: float = float(os.getenv("DNS_LIFETIME", "5.0")) SMTP_TIMEOUT: float = float(os.getenv("SMTP_TIMEOUT", "10.0")) HTTP_TIMEOUT: float = float(os.getenv("HTTP_TIMEOUT", "8.0")) smtp_host: str = os.getenv("SMTP_HOST", "localhost") smtp_port: int = os.getenv("SMTP_PORT", "587") smtp_user: Optional[str] = os.getenv("SMTP_USER") smtp_password: Optional[str] = os.getenv("SMTP_PASSWORD") smtp_starttls: bool = str_to_bool(os.getenv("SMTP_STARTTLS", "true")) smtp_sender_fallback: str = os.getenv("SMTP_SENDER", "noreply@example.com") settings = Settings()