Spaces:
Running
Running
File size: 4,451 Bytes
09801ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | """
DataVision β Centralized Configuration Module
Uses Pydantic Settings v2 for type-safe, environment-driven configuration.
All settings are loaded from environment variables or .env files.
Required variables will raise validation errors on startup if missing.
"""
import os
from typing import Optional, Literal
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field
class Settings(BaseSettings):
"""Application configuration loaded from environment variables."""
model_config = SettingsConfigDict(
env_file=(".env", "../.env"),
env_file_encoding="utf-8",
case_sensitive=True,
extra="ignore",
)
# ββ Environment βββββββββββββββββββββββββββββββββββββββββββββββββ
ENVIRONMENT: Literal["development", "testing", "production"] = "development"
DEBUG: bool = False
APP_NAME: str = "DataVision AI"
APP_VERSION: str = "1.0.0"
# ββ Database ββββββββββββββββββββββββββββββββββββββββββββββββββββ
DATABASE_URL: str = Field(
default="postgresql+asyncpg://datavision:datavision_dev@localhost:5433/datavision",
description="PostgreSQL async connection URL (postgresql+asyncpg://...)"
)
DB_POOL_SIZE: int = 5
DB_MAX_OVERFLOW: int = 10
DB_POOL_PRE_PING: bool = True
DB_POOL_RECYCLE: int = 3600
DB_ECHO: bool = False
# ββ JWT Auth ββββββββββββββββββββββββββββββββββββββββββββββββββββ
JWT_SECRET: str = Field(
default=os.environ.get("JWT_SECRET") or os.environ.get("JWT_SECRET_KEY") or "datavision-production-jwt-secret-key-32bytes-long!",
description="Secret key for signing JWT tokens. Must be kept secret."
)
JWT_ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
REFRESH_TOKEN_EXPIRE_DAYS: int = 7
# ββ Security ββββββββββββββββββββββββββββββββββββββββββββββββββββ
CORS_ORIGINS: str = "*"
ALLOWED_HOSTS: str = "*"
BCRYPT_ROUNDS: int = 12
# ββ Redis (Optional) ββββββββββββββββββββββββββββββββββββββββββββ
REDIS_URL: Optional[str] = None
# ββ LLM Providers βββββββββββββββββββββββββββββββββββββββββββββββ
GROQ_API_KEY: Optional[str] = None
GROQ_KEY_1: Optional[str] = None
GROQ_KEY_2: Optional[str] = None
GROQ_KEY_3: Optional[str] = None
OPENAI_API_KEY: Optional[str] = None
GOOGLE_API_KEY: Optional[str] = None
ANTHROPIC_API_KEY: Optional[str] = None
OPENROUTER_API_KEY: Optional[str] = None
# ββ Email βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
RESEND_API_KEY: Optional[str] = None
FROM_EMAIL: str = "noreply@datavision.ai"
# ββ OAuth βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
GOOGLE_CLIENT_ID: Optional[str] = None
GOOGLE_CLIENT_SECRET: Optional[str] = None
GITHUB_CLIENT_ID: Optional[str] = None
GITHUB_CLIENT_SECRET: Optional[str] = None
@property
def cors_origins_list(self) -> list[str]:
"""Parse CORS_ORIGINS from comma-separated string to list."""
if self.CORS_ORIGINS == "*":
return ["*"]
return [origin.strip() for origin in self.CORS_ORIGINS.split(",") if origin.strip()]
@property
def is_production(self) -> bool:
return self.ENVIRONMENT == "production"
@property
def is_development(self) -> bool:
return self.ENVIRONMENT == "development"
# Singleton settings instance
_settings: Optional[Settings] = None
def get_settings() -> Settings:
"""Get or create the global Settings singleton."""
global _settings
if _settings is None:
_settings = Settings()
return _settings
|