setting.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. """Application configuration settings."""
  2. import os
  3. from urllib.parse import quote_plus
  4. from dotenv import load_dotenv
  5. # Load .env from project root (if present)
  6. load_dotenv()
  7. def build_database_uri():
  8. """Build a SQLAlchemy MySQL DSN from environment variables.
  9. Password resolution order:
  10. 1. MYSQL_PASSWORD environment variable
  11. 2. Secret store via keyring (service 'ginger_mysql' and username)
  12. 3. Empty password (not recommended)
  13. """
  14. user = os.getenv("MYSQL_USER", "root")
  15. raw_password = os.getenv("MYSQL_PASSWORD")
  16. # Try secret store if password not provided in env
  17. if not raw_password:
  18. try:
  19. import keyring
  20. raw_password = keyring.get_password("ginger_mysql", user)
  21. except Exception:
  22. raw_password = None
  23. password = quote_plus(raw_password or "")
  24. host = os.getenv("MYSQL_HOST", "127.0.0.1")
  25. port = os.getenv("MYSQL_PORT", "3306")
  26. db_name = os.getenv("MYSQL_DB", "flask")
  27. charset = os.getenv("MYSQL_CHARSET", "utf8mb4")
  28. return (
  29. f"mysql+pymysql://{user}:{password}@{host}:{port}/{db_name}"
  30. f"?charset={charset}"
  31. )
  32. class BaseConfig:
  33. """Base configuration shared by all environments."""
  34. SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-key")
  35. DEBUG = False
  36. TESTING = False
  37. MYSQL_USER = os.getenv("MYSQL_USER", "root")
  38. MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD", "")
  39. MYSQL_HOST = os.getenv("MYSQL_HOST", "127.0.0.1")
  40. MYSQL_PORT = os.getenv("MYSQL_PORT", "3306")
  41. MYSQL_DB = os.getenv("MYSQL_DB", "flask")
  42. MYSQL_CHARSET = os.getenv("MYSQL_CHARSET", "utf8mb4")
  43. SQLALCHEMY_DATABASE_URI = build_database_uri()
  44. SQLALCHEMY_TRACK_MODIFICATIONS = False
  45. class DevelopmentConfig(BaseConfig):
  46. """Development configurations."""
  47. DEBUG = True
  48. class ProductionConfig(BaseConfig):
  49. """Production configurations."""
  50. DEBUG = False
  51. class TestingConfig(BaseConfig):
  52. """Testing configurations."""
  53. TESTING = True
  54. DEBUG = True
  55. config = {
  56. "development": DevelopmentConfig,
  57. "production": ProductionConfig,
  58. "testing": TestingConfig,
  59. "default": DevelopmentConfig,
  60. }