Files
conference-room-booking-system/backend/migrations/env.py
2025-09-07 07:15:30 -04:00

101 lines
3.1 KiB
Python

"""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
# Attempt to find the first .env file in current or parent directories
env_path = Path(__file__).resolve().parent
while (env_path / ".env").exists() is False and env_path != env_path.parent:
env_path = env_path.parent
if (env_path / ".env").exists():
load_dotenv(dotenv_path=env_path / ".env")
else:
raise FileNotFoundError("No .env file found in current or parent directories.")
# For these imports to work, we need to have the .env file loaded first.
from backend.db import DATABASE_URL # noqa: E402
from backend.models import Base # noqa: E402
# 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())