| """Database package exports.
|
|
|
| This package exposes both the new SQLAlchemy-based ``DatabaseManager`` and the
|
| legacy SQLite-backed ``Database`` class that the existing application modules
|
| still import via ``from database import Database``. During the transition phase
|
| we dynamically load the legacy implementation from the root ``database.py``
|
| module (renamed here as ``legacy_database`` when importing) and fall back to the
|
| new manager if that module is unavailable.
|
| """
|
|
|
| from importlib import util as _importlib_util
|
| from pathlib import Path as _Path
|
| from typing import Optional as _Optional, Any as _Any
|
|
|
| from .db_manager import DatabaseManager
|
|
|
|
|
| def _load_legacy_module():
|
| """Load the legacy root-level ``database.py`` module if it exists.
|
|
|
| This is used to support older entry points like ``get_database`` and the
|
| ``Database`` class that live in the legacy file.
|
| """
|
|
|
| legacy_path = _Path(__file__).resolve().parent.parent / "database.py"
|
| if not legacy_path.exists():
|
| return None
|
|
|
| spec = _importlib_util.spec_from_file_location("legacy_database", legacy_path)
|
| if spec is None or spec.loader is None:
|
| return None
|
|
|
| module = _importlib_util.module_from_spec(spec)
|
| try:
|
| spec.loader.exec_module(module)
|
| except Exception:
|
|
|
| return None
|
|
|
| return module
|
|
|
|
|
| def _load_legacy_database_class() -> _Optional[type]:
|
| """Load the legacy ``Database`` class from ``database.py`` if available."""
|
|
|
| module = _load_legacy_module()
|
| if module is None:
|
| return None
|
| return getattr(module, "Database", None)
|
|
|
|
|
| def _load_legacy_get_database() -> _Optional[callable]:
|
| """Load the legacy ``get_database`` function from ``database.py`` if available."""
|
|
|
| module = _load_legacy_module()
|
| if module is None:
|
| return None
|
| return getattr(module, "get_database", None)
|
|
|
|
|
| _LegacyDatabase = _load_legacy_database_class()
|
| _LegacyGetDatabase = _load_legacy_get_database()
|
| _db_manager_instance: _Optional[DatabaseManager] = None
|
|
|
|
|
| if _LegacyDatabase is not None:
|
| Database = _LegacyDatabase
|
| else:
|
| Database = DatabaseManager
|
|
|
|
|
| def get_database(*args: _Any, **kwargs: _Any) -> _Any:
|
| """Return a database instance compatible with legacy callers.
|
|
|
| The resolution order is:
|
|
|
| 1. If the legacy ``database.py`` file exists and exposes ``get_database``,
|
| use that function (this returns the legacy singleton used by the
|
| Gradio crypto dashboard and other older modules).
|
| 2. Otherwise, return a singleton instance of ``DatabaseManager`` from the
|
| new SQLAlchemy-backed implementation.
|
| """
|
|
|
| if _LegacyGetDatabase is not None:
|
| return _LegacyGetDatabase(*args, **kwargs)
|
|
|
| global _db_manager_instance
|
| if _db_manager_instance is None:
|
| _db_manager_instance = DatabaseManager()
|
|
|
| _db_manager_instance.init_database()
|
| return _db_manager_instance
|
|
|
|
|
| __all__ = ["DatabaseManager", "Database", "get_database"]
|
|
|