"""Alembic configuration for database migrations in the Numinar coding project backend. Sets up the Alembic environment for running migrations in offline and online modes, configuring the database connection and target metadata. """ import asyncio from logging.config import fileConfig from pathlib import Path from typing import cast from alembic import context from dotenv import load_dotenv from sqlalchemy import Connection from sqlalchemy import pool from sqlalchemy.ext.asyncio import async_engine_from_config from backend.db import DATABASE_URL from backend.models import Base # Try to load .env from local directory first, then parent directory if not found local_env = Path(__file__).resolve().parent.parent / ".env" parent_env = Path(__file__).resolve().parent.parent.parent / ".env" if local_env.exists(): load_dotenv(dotenv_path=local_env) elif parent_env.exists(): load_dotenv(dotenv_path=parent_env) # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) # type: ignore # add your model's MetaData object here target_metadata = Base.metadata def run_migrations_offline() -> None: """Run migrations in 'offline' mode. Configures the migration context using a database URL without creating an engine, suitable for environments where a database connection is unavailable. Emits SQL statements to the script output. """ # url = config.get_main_option("sqlalchemy.url") url = DATABASE_URL context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, ) with context.begin_transaction(): context.run_migrations() def do_run_migrations(connection: Connection) -> None: """Run migrations with the given database connection. Args: connection: The SQLAlchemy database connection to use for migrations. """ context.configure(connection=connection, target_metadata=target_metadata) with context.begin_transaction(): context.run_migrations() async def run_migrations_online() -> None: """Run migrations in 'online' mode. Creates an asynchronous SQLAlchemy engine and runs migrations using a database connection, suitable for environments with an active database. """ configuration = cast(dict[str, str], config.get_section(config.config_ini_section)) configuration["sqlalchemy.url"] = DATABASE_URL connectable = async_engine_from_config( configuration, prefix="sqlalchemy.", poolclass=pool.NullPool, ) async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) await connectable.dispose() if context.is_offline_mode(): run_migrations_offline() else: asyncio.run(run_migrations_online())