import os import platform import secrets from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() def get_system_encoding(): """Get the system's preferred encoding with UTF-8 fallback.""" try: # Try to get the preferred encoding import locale preferred_encoding = locale.getpreferredencoding(False) # Ensure it's UTF-8 or a compatible encoding if preferred_encoding.lower() not in ['utf-8', 'utf8', 'utf_8']: # On Windows, try to set UTF-8 if platform.system() == 'Windows': try: os.environ['PYTHONIOENCODING'] = 'utf-8' preferred_encoding = 'utf-8' except: preferred_encoding = 'utf-8' else: preferred_encoding = 'utf-8' return preferred_encoding except: return 'utf-8' class Config: """Base configuration class.""" # Set default encoding DEFAULT_ENCODING = get_system_encoding() # Supabase configuration SUPABASE_URL = os.environ.get('SUPABASE_URL') or '' SUPABASE_KEY = os.environ.get('SUPABASE_KEY') or '' # LinkedIn OAuth configuration CLIENT_ID = os.environ.get('CLIENT_ID') or '' CLIENT_SECRET = os.environ.get('CLIENT_SECRET') or '' REDIRECT_URL = os.environ.get('REDIRECT_URL') or '' # Hugging Face configuration # Check for lowercase hugging_key first (for dev), then uppercase HUGGING_KEY (for production) HUGGING_KEY = os.environ.get('hugging_key') or os.environ.get('HUGGING_KEY') or '' # JWT configuration - generate a secure key if not provided JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or os.environ.get('SECRET_KEY') or secrets.token_hex(32) # Database configuration DATABASE_URL = os.environ.get('DATABASE_URL') or '' # Application configuration - generate a secure key if not provided SECRET_KEY = os.environ.get('SECRET_KEY') or secrets.token_hex(32) DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true' # Scheduler configuration SCHEDULER_ENABLED = os.environ.get('SCHEDULER_ENABLED', 'True').lower() == 'true' # Unicode/Encoding configuration FORCE_UTF8 = os.environ.get('FORCE_UTF8', 'True').lower() == 'true' UNICODE_LOGGING = os.environ.get('UNICODE_LOGGING', 'True').lower() == 'true' # Environment detection ENVIRONMENT = os.environ.get('ENVIRONMENT', 'development').lower() IS_WINDOWS = platform.system() == 'Windows' IS_DOCKER = os.environ.get('DOCKER_CONTAINER', '').lower() == 'true' # Set environment-specific encoding settings if FORCE_UTF8: os.environ['PYTHONIOENCODING'] = 'utf-8' os.environ['PYTHONUTF8'] = '1' # Debug and logging settings LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO' if ENVIRONMENT == 'production' else 'DEBUG') UNICODE_SAFE_LOGGING = UNICODE_LOGGING and not IS_WINDOWS # Celery configuration CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0') CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0') # Validate required configuration values @classmethod def validate_config(cls): """Validate that all required config values are set.""" required_vars = ['SUPABASE_URL', 'SUPABASE_KEY', 'JWT_SECRET_KEY'] missing_vars = [] for var in required_vars: if not getattr(cls, var, None) or getattr(cls, var) == 'your-secret-key-change-in-production': missing_vars.append(var) if missing_vars: raise ValueError(f"Missing required environment variables: {', '.join(missing_vars)}. Please check your .env file.") # Validate configuration after class definition Config.validate_config()