Skip to main content

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}_migrations in the schema named by the connection's search_path. The library does not change search_path.
  • prefix is a bare identifier of 1 to 52 characters ([A-Za-z_][A-Za-z0-9_]*). The table name is quoted, so MyApp stays MyApp_migrations.
  • Each row stores name (text, primary key) and applied_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 run retries 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, and CREATE DATABASE are outside this version. There is no flag to run a migration outside a transaction.
  • run raises ValueError if 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 ValueError and 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_quaestor logger.

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)

Source distribution for pg-quaestor 0.1.0
File Size Uploaded
pg_quaestor-0.1.0.tar.gz 11.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pg-quaestor 0.1.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page