from typing import AsyncGenerator from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import DeclarativeBase from app.config import settings class Base(DeclarativeBase): pass def _make_engine(): return create_async_engine(settings.database_url, echo=False) def _make_session_factory(engine): return async_sessionmaker(engine, expire_on_commit=False) # Lazily initialised on first use so tests can patch settings before import _engine = None _session_factory = None def get_engine(): global _engine if _engine is None: _engine = _make_engine() return _engine def get_session_factory(): global _session_factory if _session_factory is None: _session_factory = _make_session_factory(get_engine()) return _session_factory # Alias kept for Alembic and bot usage AsyncSessionLocal = None # populated on first call to get_session_factory() async def get_db() -> AsyncGenerator[AsyncSession, None]: factory = get_session_factory() async with factory() as session: yield session