"""Alembic env.py for an async engine (from `alembic init -t async`), wired to the app's models. The URL comes from DATABASE_URL, never from alembic.ini, so no credentials are committed. """ import asyncio import os from alembic import context from sqlalchemy import pool from sqlalchemy.engine import Connection from sqlalchemy.ext.asyncio import create_async_engine import app.models # noqa: F401 (registers every model on Base.metadata) from app.db import Base target_metadata = Base.metadata URL = os.environ.get("DATABASE_URL", "sqlite+aiosqlite:///./app.db") def run_migrations_offline() -> None: context.configure(url=URL, target_metadata=target_metadata, literal_binds=True, render_as_batch=True) with context.begin_transaction(): context.run_migrations() def do_run_migrations(connection: Connection) -> None: # render_as_batch lets ALTER-style changes work on SQLite; harmless elsewhere. context.configure(connection=connection, target_metadata=target_metadata, render_as_batch=True) with context.begin_transaction(): context.run_migrations() async def run_migrations_online() -> None: engine = create_async_engine(URL, poolclass=pool.NullPool) async with engine.connect() as connection: await connection.run_sync(do_run_migrations) await engine.dispose() if context.is_offline_mode(): run_migrations_offline() else: asyncio.run(run_migrations_online())