Библиотека SQL-миграций для баз данных. Миграции — это обычные .sql файлы.
Требования
Python >= 3.10.
Драйвер целевой СУБД (см. таблицу ниже). Для SQLite ничего дополнительно устанавливать не нужно — используется модуль стандартной библиотеки sqlite3.
Установка
Базовый пакет (включает только поддержку SQLite):
pip install classic-migrations
Поддержка конкретных СУБД подключается опциональными зависимостями (extras):
СУБД |
extra |
драйвер (значение DATABASE_DRIVER) |
|---|---|---|
SQLite |
— |
sqlite3 |
PostgreSQL |
postgres |
psycopg |
MySQL |
mysql |
pymysql |
Oracle |
oracle |
oracledb |
Microsoft SQL Server |
pymssql |
pymssql |
pip install classic-migrations[postgres]
pip install classic-migrations[mysql]
Или через uv:
uv add classic-migrations
uv add "classic-migrations[postgres]"
Пакет предоставляет исполняемую команду migrations:
migrations --help
Настройка
Все настройки читаются из переменных окружения или из .env файла в текущем каталоге. Переменные окружения имеют приоритет над значениями из .env.
Пример .env:
# каталоги с файлами миграций, разделённые двоеточием
SOURCES=./migrations
# имя таблицы истории (опционально, по умолчанию "migrations")
MIGRATIONS_TABLE=migrations
# настройки подключения к базе данных
DATABASE_DRIVER=sqlite3
DATABASE_USER=
DATABASE_USER_DOMAIN=
DATABASE_PASSWORD=
DATABASE_HOST=
DATABASE_PORT=
DATABASE_NAME=./db.sqlite
Если задан DATABASE_USER_DOMAIN, то имя пользователя формируется как DOMAIN\USER.
Полный список настроек:
Переменная |
Назначение |
Значение по умолчанию |
|---|---|---|
SOURCES |
пути к каталогам миграций, разделённые двоеточием |
(пусто) |
DATABASE_DRIVER |
имя модуля драйвера подключения (sqlite3, psycopg, pymysql, oracledb, pymssql) |
(пусто) |
DATABASE_USER |
имя пользователя БД |
(пусто) |
DATABASE_USER_DOMAIN |
домен пользователя БД (опционально) |
(пусто) |
DATABASE_PASSWORD |
пароль |
(пусто) |
DATABASE_HOST |
хост |
(пусто) |
DATABASE_PORT |
порт (преобразуется в целое число) |
(пусто) |
DATABASE_NAME |
имя БД (или путь к файлу для SQLite) |
(пусто) |
MIGRATIONS_TABLE |
имя таблицы истории |
migrations |
MIGRATIONS_SCHEMA |
схема, в которой размещается таблица истории (игнорируется для БД без поддержки схем) |
(пусто) |
OLD_MIGRATIONS_SCHEMA |
схема legacy-таблицы versions (yoyo-migrations) |
(пусто) |
Файлы миграций
Миграция — это .sql файл в каталоге миграций. Имя файла (без расширения) становится идентификатором миграции.
В начальном комментарии файла можно указать директивы:
-- depends: 20260821_01_init, 20260822_02_users
-- transactional: true
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);
Директивы:
-- depends: <id>, <id>, ... — список миграций, от которых зависит текущая, через запятую. Имена должны соответствовать реальным миграциям, иначе выбрасывается исключение NoMigration;
-- transactional: true|false — выполнять ли миграцию в транзакции (по умолчанию true; если не указано — поведение определяется возможностями СУБД).
Для отката миграции используется файл <имя>.rollback.sql — имя с вставкой .rollback перед расширением, размещённый рядом с основной миграцией. У rollback-файла допускается только директива -- transactional.
Хуки
В каталоге миграций могут находиться зарезервированные файлы-хуки. Они не являются миграциями, не попадают в таблицу истории и всегда выполняются вне транзакции:
pre-apply.sql — выполняется перед применением набора миграций;
post-apply.sql — после применения набора миграций;
pre-rollback.sql — перед откатом набора миграций;
post-rollback.sql — после отката набора миграций.
Команды
Доступные команды: list, apply, rollback.
Общий параметр, принимаемый всеми командами:
-v — увеличить подробность вывода. Можно повторять: -v → WARNING, -vv → INFO, -vvv → DEBUG (по умолчанию ERROR).
list
Показывает миграции источника и их статус в текущей БД:
migrations list
--history — показать только применённые миграции.
apply
Применяет неприменённые миграции (в топологическом порядке):
migrations apply [migration_name]
migration_name — позиционный необязательный аргумент: применить миграции до указанной включительно; без него — все доступные;
--fake — только создать записи в истории, без выполнения SQL миграций и хуков;
--plan — не применять миграции, а только вывести список тех, которые можно применить к текущей БД.
rollback
Откатывает применённые миграции (в обратном топологическом порядке):
migrations rollback [migration_name]
migration_name — позиционный необязательный аргумент: откатить миграции до указанной включительно; без него — все применённые;
--fake — только создать записи в истории, без выполнения SQL отката и хуков;
--plan — не откатывать миграции, а только вывести список тех, которые можно откатить в текущей БД.
Если у миграции нет .rollback.sql файла, при откате записывается только событие ROLLED_BACK в историю — SQL не выполняется.
Использование как библиотеки
Публичный API:
from classic.migrations import (
BadConnectionURI,
BadMigration,
InvalidArgument,
MigrationConflict,
MigrationLockError,
MigrationsCollection,
Migrator,
NoMigration,
)
MigrationsCollection работает только с источниками миграций (каталогами .sql файлов) и не имеет доступа к БД:
MigrationsCollection(sources) — sources — путь к каталогу миграций (строка) или список путей. Читает миграции и хуки один раз и переиспользует их при последующих вызовах;
list() — список миграций источника, отсортированный топологически;
to_apply(history, target=None) — по логу событий истории вычисляет применённые и возвращает (hooks, migrations): хуки и неприменённые миграции в топологическом порядке; target — «до указанной включительно»;
to_rollback(history, target=None) — аналогично, но возвращает применённые миграции в обратном топологическом порядке;
applied_ids(history) — статический метод: возвращает множество id миграций, чей последний статус в истории — APPLIED.
Migrator принимает параметры БД, выбирает Backend по имени драйвера и выполняет миграции (сам не содержит SQL). Параметры конструктора:
driver — имя модуля драйвера (sqlite3, psycopg, pymysql, oracledb, pymssql);
db_host, db_port, db_name, db_user, db_pass — параметры подключения;
migration_table='migrations' — имя таблицы истории;
migration_schema=None — схема таблицы истории;
versions_schema=None — схема legacy-таблицы versions.
Migrator — контекстный менеджер: при входе устанавливает соединение и берёт advisory-lock, при выходе закрывает соединение. Методы должны вызываться только внутри with:
history() — лог событий таблицы истории (список кортежей (migration_id, created_at, status));
apply(migrations, hooks, fake=False) — применяет миграции; fake=True — только записи в истории, без SQL и хуков;
rollback(migrations, hooks, fake=False) — откатывает миграции (аналогично apply);
close() — закрывает соединение (обычно не нужен — соединение закрывается при выходе из with).
Применение миграций:
from classic.migrations import Migrator, MigrationsCollection
db = Migrator(
driver='psycopg',
db_host='localhost',
db_port=5432,
db_name='tests',
db_user='test',
db_pass='test',
)
migrations = MigrationsCollection('./migrations')
with db:
history = db.history()
hooks, unapplied = migrations.to_apply(history)
db.apply(unapplied, hooks)
Откат миграций:
with db:
history = db.history()
hooks, applied = migrations.to_rollback(history)
db.rollback(applied, hooks)
Схема таблицы истории
Библиотека создаёт одну служебную таблицу — append-only лог событий:
CREATE TABLE {migration_table} (
id INTEGER PRIMARY KEY AUTOINCREMENT,
migration_id VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL,
status VARCHAR(16) NOT NULL -- 'APPLIED' | 'ROLLED_BACK' | 'PENDING'
);
Каждое применение или откат миграции дописывает строку-событие. Актуальный статус миграции определяется её последним событием. Сверка хешей применённых миграций не выполняется.
Для нетранзакционных СУБД запись в историю производится до применения (статус PENDING), а после успешного выполнения — APPLIED.
При первом запуске данные из legacy-таблицы versions (yoyo-migrations) переносятся как события APPLIED; сама таблица не удаляется.
Особенности бэкендов
Oracle
Бэкенд Oracle берёт advisory-lock через SYS.DBMS_LOCK.REQUEST. Пользователю, под которым выполняются миграции, необходимо право EXECUTE на SYS.DBMS_LOCK; без него вход в with migrator: завершится ошибкой MigrationLockError.
В контейнерных образах gvenzl/oracle-* это право выдаётся скриптом инициализации docker/oracle-init/01_grant_dbms_lock.sql. Локально он монтируется в /container-entrypoint-initdb.d (см. docker-compose.yml) и выполняется при первом старте контейнера. В CI (job test-oracle в .github/workflows/test.yml) скрипт выполняется после checkout через docker exec, поскольку сервис-контейнеры GitHub Actions стартуют до checkout и не позволяют смонтировать каталог из репозитория.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file classic_migrations-2.0.1.tar.gz.
File metadata
- Download URL: classic_migrations-2.0.1.tar.gz
- Upload date:
- Size: 36.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19c1ebd87d35c15b77b31c80299b87407727b5ef198364ccd5d70a7b00204938
|
|
| MD5 |
dec444452211441b5ab57fba240b02f5
|
|
| BLAKE2b-256 |
9f6a9b4fe3bf1c71857cce99c2406fe387969f8d2ba967f57a0120c861c87e39
|
Provenance
The following attestation bundles were made for classic_migrations-2.0.1.tar.gz:
Publisher:
publish.yml on variasov/classic-migrations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
classic_migrations-2.0.1.tar.gz -
Subject digest:
19c1ebd87d35c15b77b31c80299b87407727b5ef198364ccd5d70a7b00204938 - Sigstore transparency entry: 2781891429
- Sigstore integration time:
-
Permalink:
variasov/classic-migrations@d880c41b76df7906adad83c4c3d871ccc60e8bb6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/variasov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d880c41b76df7906adad83c4c3d871ccc60e8bb6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file classic_migrations-2.0.1-py3-none-any.whl.
File metadata
- Download URL: classic_migrations-2.0.1-py3-none-any.whl
- Upload date:
- Size: 36.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df40b3b0257541154cbd9041446c3fdcdb255d2b4e9a858a462110deac53be6b
|
|
| MD5 |
be0a30f94da4084026bcb3b8c5a99497
|
|
| BLAKE2b-256 |
755c1a6a864d511e408feb3ee9226a06f6729aaad6e3463d20c906208aee3120
|
Provenance
The following attestation bundles were made for classic_migrations-2.0.1-py3-none-any.whl:
Publisher:
publish.yml on variasov/classic-migrations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
classic_migrations-2.0.1-py3-none-any.whl -
Subject digest:
df40b3b0257541154cbd9041446c3fdcdb255d2b4e9a858a462110deac53be6b - Sigstore transparency entry: 2781892840
- Sigstore integration time:
-
Permalink:
variasov/classic-migrations@d880c41b76df7906adad83c4c3d871ccc60e8bb6 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/variasov
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d880c41b76df7906adad83c4c3d871ccc60e8bb6 -
Trigger Event:
push
-
Statement type: