"""Application configuration settings.""" import os from urllib.parse import quote_plus from dotenv import load_dotenv # Load .env from project root (if present) load_dotenv() def build_database_uri(): """Build a SQLAlchemy MySQL DSN from environment variables. Password resolution order: 1. MYSQL_PASSWORD environment variable 2. Secret store via keyring (service 'ginger_mysql' and username) 3. Empty password (not recommended) """ user = os.getenv("MYSQL_USER", "root") raw_password = os.getenv("MYSQL_PASSWORD") # Try secret store if password not provided in env if not raw_password: try: import keyring raw_password = keyring.get_password("ginger_mysql", user) except Exception: raw_password = None password = quote_plus(raw_password or "") host = os.getenv("MYSQL_HOST", "127.0.0.1") port = os.getenv("MYSQL_PORT", "3306") db_name = os.getenv("MYSQL_DB", "flask") charset = os.getenv("MYSQL_CHARSET", "utf8mb4") return ( f"mysql+pymysql://{user}:{password}@{host}:{port}/{db_name}" f"?charset={charset}" ) class BaseConfig: """Base configuration shared by all environments.""" SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key") DEBUG = False TESTING = False MYSQL_USER = os.getenv("MYSQL_USER", "root") MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD", "") MYSQL_HOST = os.getenv("MYSQL_HOST", "127.0.0.1") MYSQL_PORT = os.getenv("MYSQL_PORT", "3306") MYSQL_DB = os.getenv("MYSQL_DB", "flask") MYSQL_CHARSET = os.getenv("MYSQL_CHARSET", "utf8mb4") SQLALCHEMY_DATABASE_URI = build_database_uri() SQLALCHEMY_TRACK_MODIFICATIONS = False class DevelopmentConfig(BaseConfig): """Development configurations.""" DEBUG = True class ProductionConfig(BaseConfig): """Production configurations.""" DEBUG = False class TestingConfig(BaseConfig): """Testing configurations.""" TESTING = True DEBUG = True config = { "development": DevelopmentConfig, "production": ProductionConfig, "testing": TestingConfig, "default": DevelopmentConfig, }