pg-quaestor
In ancient Rome, a quaestor was the official in charge of the treasury — here, it manages your PostgreSQL schema and data, your real treasure.
Lightweight PostgreSQL migration module with named migrations and dependency resolution.
Install
pip install pg-quaestor
Quick Start
import asyncio
import asyncpg
from pg_quaestor import MigrationRegistry
registry = MigrationRegistry()
@registry.register("create_users")
async def create_users(conn):
await conn.execute("CREATE TABLE users (email text PRIMARY KEY)")
@registry.register("add_status", depends_on=["create_users"])
async def add_status(conn):
await conn.execute(
"ALTER TABLE users ADD COLUMN status text NOT NULL DEFAULT 'active'"
)
async def main():
conn = await asyncpg.connect("postgresql://localhost/myapp")
applied = await registry.run(conn, "myapp")
print(f"Applied migrations: {applied}")
await conn.close()
asyncio.run(main())
API Reference
| Symbol | Signature | Description |
|---|---|---|
MigrationRegistry() |
MigrationRegistry() |
Create a new registry. No arguments. |
.register() |
register(name: str, depends_on: list[str] | None = None) -> Callable |
Decorator. Registers an async migration function. |
.run() |
async run(conn: asyncpg.Connection, prefix: str) -> list[str] |
Execute all unapplied migrations. Returns names applied in this call. |
.migrations |
migrations -> dict[str, MigrationDefinition] |
The registry's own mapping. |
MigrationDefinition is not exported from pg_quaestor. A migration function is async def migration(conn: asyncpg.Connection) -> None. Pass a connection. Taking one from a pool is the caller's job.
How It Works
- Applied migrations are tracked in
{prefix}_migrationsin the schema named by the connection'ssearch_path. The library does not changesearch_path. prefixis a bare identifier of 1 to 52 characters ([A-Za-z_][A-Za-z0-9_]*). The table name is quoted, soMyAppstaysMyApp_migrations.- Each row stores
name(text, primary key) andapplied_at(timestamptz, UTC, set by the runner). - Each migration runs in one transaction on that connection. The runner inserts the tracking row in the same transaction and commits. A raised exception rolls the migration's SQL and the tracking row back together. Migrations already committed in that run stay applied. The next
runretries the failed one. - The migration must not
COMMIT,ROLLBACK, or close the connection. The runner does not detect a migration that does. CREATE INDEX CONCURRENTLY,DROP INDEX CONCURRENTLY,VACUUM,REINDEX CONCURRENTLY, andCREATE DATABASEare outside this version. There is no flag to run a migration outside a transaction.runraisesValueErrorif the connection is already inside a transaction.- A session advisory lock on
hashtextextended(prefix, 0)is held for the run, so two runners for the same prefix take turns. Different prefixes lock independently. - Dependencies are resolved with Kahn's algorithm. A missing or circular dependency raises
ValueErrorand applies nothing further. Independent migrations run in alphabetical order. - Several registries share one database by using different prefixes.
- Requires PostgreSQL 11 or newer.
- Progress and errors are logged to the
pg_quaestorlogger.
Metadata
Release files for pg-quaestor 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pg_quaestor-0.1.0.tar.gz | 11.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pg_quaestor-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.2 kB
Release files / pg_quaestor-0.1.0.tar.gz
| Download URL | pg_quaestor-0.1.0.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3c6a515fe78045af6df20eb780ce154728a352c2b38439a6b5e439105e36af48
|
|
BLAKE2b-256 checksum How to use checksums |
007a6ac545e688f84bf65003ab788d343159d3c9c0fa9ce96631c4093d3c449d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / pg_quaestor-0.1.0-py3-none-any.whl
| Download URL | pg_quaestor-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c9284cecd626a71db1729705b9c8d2fcfd7c1d8efac61ae6550b658fd4e96c4
|
|
BLAKE2b-256 checksum How to use checksums |
244c41fc80a453f33e8ac1c811ed27d3f9c206db2e92ebc3a1ecb4ac84d32352
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|