Source code for alchemiq.runtime.engine
"""Process-global async engine and sessionmaker: configure, dispose, create/drop DDL."""
from __future__ import annotations
from typing import Any
from sqlalchemy.ext.asyncio import (
AsyncEngine,
AsyncSession,
async_sessionmaker,
create_async_engine,
)
from alchemiq.exceptions import EngineNotConfiguredError
from alchemiq.model.registry import metadata
_engine: AsyncEngine | None = None
_sessionmaker: async_sessionmaker[AsyncSession] | None = None
def is_configured() -> bool:
"""Return ``True`` if ``configure()`` has been called and the engine is active."""
return _sessionmaker is not None
def require_engine() -> AsyncEngine:
"""Return the active engine, raising ``EngineNotConfiguredError`` if not yet configured."""
if _engine is None:
raise EngineNotConfiguredError(
"alchemiq is not configured; call alchemiq.configure(dsn) first"
)
return _engine
def require_sessionmaker() -> async_sessionmaker[AsyncSession]:
"""Return the active sessionmaker, raising ``EngineNotConfiguredError`` if not configured."""
if _sessionmaker is None:
raise EngineNotConfiguredError(
"alchemiq is not configured; call alchemiq.configure(dsn) first"
)
return _sessionmaker
[docs]
async def dispose() -> None:
"""Dispose the engine and clear state (lifespan shutdown / test teardown)."""
global _engine, _sessionmaker
if _engine is not None:
await _engine.dispose()
_engine = None
_sessionmaker = None
[docs]
async def create_all() -> None:
"""Create all mapped tables in the database (DDL CREATE IF NOT EXISTS)."""
engine = require_engine()
async with engine.begin() as conn:
await conn.run_sync(metadata.create_all)
[docs]
async def drop_all() -> None:
"""Drop all mapped tables from the database (DDL DROP IF EXISTS). Destructive."""
engine = require_engine()
async with engine.begin() as conn:
await conn.run_sync(metadata.drop_all)