Skip to main content

Portable migrations

Project description

Air Migrations

Библиотека обертка для алембика. Основная идея обертки, что можно напрямую указать в какую базу необходимо применить миграции, а так же в какую схему (Можно использовать -x чистого алембика) Дополнительно возможно получить сырой sql, который будет применен в БД (алембик не предоставляет это в автоматическом режиме)

#Dev run
python -m air_migrations.cli DB_URL SCHEMA COMMAND

#User
migrate DB_URL SCHEMA COMMAND [REVISION]
#or 
python -m migrate DB_URL SCHEMA COMMAND

Описание

Обязательные флаги

  1. DB_URL - url базы данных следующего вида login:password@localhost:5432/db
  2. SCHEMA - указывается используемая схема (public)
  3. COMMAND - доступны команды [upgrade, downgrade, revision]
  4. REVISION - ревизия миграции (обычно base, head или уникальный номер). Обязателен только в случае использования COMMAND, которые равны [upgrade, downgrade]

Необязательные флаги

  1. --autogenerate, -a - автогенерация ревизии миграции, используется если COMMAND равна "revision", иначе игнорируется
  2. --message, -m - сообщение для генерации ревизии, используется если COMMAND равна "revision", иначе игнорируется
  3. --sql-output, -s - папка для генерации сырого sql относительно ревизий, в момент генерации не применяется к базе данных, но требует подключения. Используется с COMMAND равным [upgrade, downgrade]
  4. --config, -c - местоположение alembic.ini конфига, по-умолчанию в папке запуска

Примеры команд

User

migrate test:test@localhost:5432/test public upgrade head --sql ./
migrate test:test@localhost:5432/test public upgrade head
migrate test:test@localhost:5432/test public downgrade base --sql ./
migrate test:test@localhost:5432/test public downgrade base
migrate test:test@localhost:5432/test public upgrade head

Dev

python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public revision --autogenerate --message 'init'
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public revision --message 'some revision'
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public upgrade head --sql ./
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public upgrade head
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public downgrade base --sql ./
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public downgrade base
python -m air_migrations.cli  dev/alembic.ini test:test@localhost:5432/test public upgrade head

Examples

Применение миграций из кода

#main.py
import os
import subprocess

URL: str = 'test:test@localhost:5432/test'
SCHEMA: str = os.getenv("POSTGRES_SCHEMA_NAME", 'public')

def upgrade_from_code() -> None:
    output = subprocess.run(["migrate", URL, SCHEMA, "upgrade", "head"], capture_output=True, text=True)
    print(output.stdout)


def downgrade_from_code() -> None:
    output = subprocess.run(["migrate", URL, SCHEMA, "downgrade", "base"], capture_output=True, text=True)
    print(output.stdout)

Применение в тестах

#tests/conftest.py
import os
import subprocess

import pytest


URL: str = 'test:test@localhost:5432/test'
SCHEMA: str = os.getenv("POSTGRES_SCHEMA_NAME", 'public')

@pytest.fixture(autouse=True, scope="session")
def db_setup():
    subprocess.run(["migrate", URL, SCHEMA, "upgrade", "head"], capture_output=True, text=True)
    yield
    subprocess.run(["migrate", URL, SCHEMA, "downgrade", "base"], capture_output=True, text=True)

Пример реализации env.py (используется асинхронная версия)

import asyncio
import os
from logging.config import fileConfig

from air_migrations import add_driver_to_url
from sqlalchemy import pool
from sqlalchemy.engine import Connection
from sqlalchemy.ext.asyncio import async_engine_from_config

from alembic import context

# Here import your Base and models
from models import Base, Users

config = context.config
if not config.get_section_option("alembic", "sqlalchemy.url"):
    url = os.getenv("POSTGRES_DATABASE_URL", "")
    url = add_driver_to_url(url)
    config.set_main_option("sqlalchemy.url", url)

if config.config_file_name is not None:
    fileConfig(config.config_file_name)
Base.metadata.schema = config.get_section_option("alembic", "schema")
target_metadata = Base.metadata


def run_migrations_offline() -> None:
    url_ = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url_,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
        version_table_schema=target_metadata.schema,
        echo=True,
    )

    with context.begin_transaction():
        context.run_migrations()


def do_run_migrations(connection: Connection) -> None:
    context.configure(
        connection=connection,
        target_metadata=target_metadata,
        version_table_schema=target_metadata.schema,
        include_schemas=True,
        echo=True,
    )

    with context.begin_transaction():
        if target_metadata.schema is not None:
            # Создание схемы если отсутствует
            context.execute(f"create schema if not exists {target_metadata.schema};")
            context.execute(f"set search_path to {target_metadata.schema}")
        context.run_migrations()


async def run_async_migrations() -> None:
    connectable = async_engine_from_config(
        config.get_section(config.config_ini_section, {}), prefix="sqlalchemy.", poolclass=pool.NullPool, echo=True
    )

    async with connectable.connect() as connection:
        await connection.run_sync(do_run_migrations)
    await connectable.dispose()


def run_migrations_online() -> None:
    """Run migrations in 'online' mode."""

    asyncio.run(run_async_migrations())


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

air_migrations-1.0.1.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

air_migrations-1.0.1-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file air_migrations-1.0.1.tar.gz.

File metadata

  • Download URL: air_migrations-1.0.1.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.9

File hashes

Hashes for air_migrations-1.0.1.tar.gz
Algorithm Hash digest
SHA256 d044a7a2bb9a8807e745325be42105bdce67abfd06161de99124e47fef7c1e73
MD5 bce8b2ebc5df6ffad1015a0fa59a72e7
BLAKE2b-256 cc68768c9c8f5e8e82ab2d0be461f6a385dea8ee63d2e88d1959f9399732f5b6

See more details on using hashes here.

File details

Details for the file air_migrations-1.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for air_migrations-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7934bbf6e3c6885af4e4469efa54b6c9b6f60063e53ca5f7851516e687b4fc0f
MD5 1f9e0fdd8a0f5f3bfc9c1139c8787c9c
BLAKE2b-256 83b8ece8adc6a099b6dc510385f79c5007d1df037aa25295c96ec959fda3bb7e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page