Migri is a simple async Python migration tool. You can use the CLI (run yourself or from a shell script) or import the exposed functions and run programatically. Currently supports PostgreSQL (asyncpg), SQLite (aiosqlite), and MySQL (aiomysql).
migri is currently in alpha and although unlikely, the implementation may change
Using async database libraries is useful when a service/application is already using an async library. It's extra overhead to install a synchronous library just to run migrations. Practically speaking, though, there isn't much benefit to running migrations asynchronously since migrations must be applied synchronously. Besides, the number of migrations for a service is generally small.
pip install migri[mysql]
pip install migri[postgresql]
pip install migri[sqlite]
Create a migrations directory and add your migrations. Migrations are applied in
lexicographical order (e.g. 0001_initial.sql then 0002_add_user_data.py and so on).
Currently .sql and .py files are supported. If you write a Python migration file,
ensure that it contains an async function migrate. An instance of asyncpg's Connection
class will be passed into the function.
async def migrate(conn) -> bool:
await conn.execute("INSERT INTO categories (name) VALUES ($1)", "Animals")
return TrueRun migri migrate. Provide database credentials via arguments or environment variables:
--db-nameorDB_NAME(required)--db-userorDB_USER--db-passorDB_PASS--db-hostorDB_HOST--db-portorDB_PORT
Other options:
-d, --dialectorDB_DIALECT(mysql,postgresql,sqlite, note that currently onlypostgresqlis supported. If not set,migriwill attempt to infer the dialect (and library to use) using the database port.)-l, --log-levelorLOG_LEVEL(defaulterror)
When you run migrate, migri will create a table called applied_migration (if it
doesn't exist). This is how migri tracks which migrations have already been applied.
If you want to test your migrations without applying them, you can use the dry run
flag: --dry-run.
Unfortunately, dry run mode does not work with SQLite at this moment. If you want to try to get it to work, see the issue.
Dry run mode also doesn't work w/ MySQL because DDL statements implicitly commit.
Migri can be called with a shell script (e.g. when a container is starting) or you can apply migrations from your application:
from migri import apply_migrations, PostgreSQLConnection
async def migrate():
conn = PostgreSQLConnection(
"sampledb",
db_user="user",
db_pass="passpass",
db_host="localhost",
db_port=5432
)
async with conn:
await apply_migrations("migrations", conn)- Set up local Python versions (e.g.
pyenv local 3.7.7 3.8.3) - Run
docker-compose upto start Postgresql. - Install nox with
pip install nox. - Run
nox.
Docstrings are formatted in the Sphinx format.
- Don't record empty migrations - warn user
- Add dry run mode for testing migrations
- Output migration results
- Test modules not found
- Test/handle incorrect migrate function signature (in migration Python files)
- Add colorful output 🍭 for enhanced readability
- Make error output more readable