"""Environnement Alembic pour les migrations de base de données. Ce fichier configure et exécute les migrations SQLAlchemy avec Alembic. Il supporte les migrations synchrones et asynchrones. """ import asyncio from logging.config import fileConfig from sqlalchemy import pool from sqlalchemy.engine import Connection from sqlalchemy.ext.asyncio import async_engine_from_config from alembic import context # Import de la configuration et des modèles from app.core.config import settings from app.core.database import Base # Import explicite de tous les modèles pour autogenerate import app.models # noqa: F401 # Configuration Alembic config = context.config # Interpréter le fichier de configuration pour le logging Python if config.config_file_name is not None: fileConfig(config.config_file_name) # Métadonnées des modèles pour autogenerate target_metadata = Base.metadata # Override de l'URL de connexion depuis settings config.set_main_option("sqlalchemy.url", settings.DATABASE_URL) def run_migrations_offline() -> None: """Exécute les migrations en mode 'offline'. Configure le contexte avec uniquement une URL sans créer d'Engine. Les commandes SQL sont émises vers un fichier script au lieu d'être exécutées directement sur la base de données. """ url = config.get_main_option("sqlalchemy.url") context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, compare_type=True, # Détecte les changements de types compare_server_default=True, # Détecte les changements de valeurs par défaut ) with context.begin_transaction(): context.run_migrations() def do_run_migrations(connection: Connection) -> None: """Exécute les migrations avec une connexion donnée.""" context.configure( connection=connection, target_metadata=target_metadata, compare_type=True, compare_server_default=True, ) with context.begin_transaction(): context.run_migrations() async def run_async_migrations() -> None: """Exécute les migrations en mode asynchrone. Crée un moteur asynchrone et exécute les migrations. """ connectable = async_engine_from_config( config.get_section(config.config_ini_section, {}), prefix="sqlalchemy.", poolclass=pool.NullPool, ) async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) await connectable.dispose() def run_migrations_online() -> None: """Exécute les migrations en mode 'online'. Crée un Engine et associe une connexion au contexte. """ asyncio.run(run_async_migrations()) if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online()