proxywhirl.migrations¶
Database migration utilities for ProxyWhirl.
This module provides a programmatic API for running Alembic migrations, following ProxyWhirl’s library-first architecture. It allows applications to manage database schema versions without requiring command-line tools.
Key Features: - Programmatic migration execution - Current revision checking - Pending migrations detection - Database initialization - Async SQLite support
Best Practices: - Always backup databases before migrations - Test migrations in development first - Use check_pending_migrations() in CI/CD - Call run_migrations() on application startup
Example:
from proxywhirl.migrations import run_migrations, get_current_revision
# Run all pending migrations
await run_migrations("sqlite+aiosqlite:///./mydb.db")
# Check current version
revision = await get_current_revision("sqlite+aiosqlite:///./mydb.db")
print(f"Database at revision: {revision}")
Functions¶
|
Check if there are pending migrations that need to be applied. |
|
Downgrade database to a previous revision. |
|
Get the current migration revision of the database. |
|
Get the latest (head) migration revision available. |
|
Get the migration history showing all applied migrations. |
|
Initialize a new database with the latest schema. |
|
Run all pending migrations up to target revision. |
|
Stamp the database with a specific revision without running migrations. |
Module Contents¶
- async proxywhirl.migrations.check_pending_migrations(database_url=None)[source]¶
Check if there are pending migrations that need to be applied.
This is useful for CI/CD pipelines and application health checks.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL
- Returns:
True if pending migrations exist, False otherwise
- Return type:
Example:
if await check_pending_migrations("sqlite+aiosqlite:///./db.sqlite"): print("WARNING: Pending migrations detected!") await run_migrations()
- async proxywhirl.migrations.downgrade_migrations(database_url=None, target_revision='-1')[source]¶
Downgrade database to a previous revision.
Use with caution in production. Always backup data before downgrading.
- Parameters:
- Raises:
FileNotFoundError – If alembic.ini or migration scripts not found
ValueError – If target revision is invalid
Exception – If downgrade fails
- Return type:
None
Example:
# Downgrade one revision await downgrade_migrations("sqlite+aiosqlite:///./db.sqlite") # Downgrade to specific revision await downgrade_migrations("sqlite+aiosqlite:///./db.sqlite", "58c0fadfa0ca") # Rollback all migrations await downgrade_migrations("sqlite+aiosqlite:///./db.sqlite", "base")
- async proxywhirl.migrations.get_current_revision(database_url=None)[source]¶
Get the current migration revision of the database.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL
- Returns:
Current revision ID, or None if database is uninitialized
- Return type:
str | None
Example:
revision = await get_current_revision("sqlite+aiosqlite:///./db.sqlite") if revision: print(f"Database at revision: {revision}") else: print("Database not initialized")
- async proxywhirl.migrations.get_head_revision(database_url=None)[source]¶
Get the latest (head) migration revision available.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL (used to get config)
- Returns:
Head revision ID
- Return type:
Example:
head = await get_head_revision() current = await get_current_revision() if head != current: print(f"Migrations pending: {current} -> {head}")
- async proxywhirl.migrations.get_migration_history(database_url=None)[source]¶
Get the migration history showing all applied migrations.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL
- Returns:
Migration records with keys revision, down_revision, description.
- Return type:
Example:
history = await get_migration_history() for migration in history: print(f"{migration['revision']}: {migration['description']}")
- async proxywhirl.migrations.initialize_database(database_url=None)[source]¶
Initialize a new database with the latest schema.
This is a convenience function that creates all tables at the current head revision without running individual migrations. Equivalent to running all migrations from scratch.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL
- Raises:
Exception – If database already has schema or initialization fails
- Return type:
None
Example:
# Initialize new database await initialize_database("sqlite+aiosqlite:///./newdb.sqlite")
- async proxywhirl.migrations.run_migrations(database_url=None, target_revision='head')[source]¶
Run all pending migrations up to target revision.
This function executes Alembic migrations programmatically, allowing applications to manage schema versions without CLI tools. It uses async SQLite support for non-blocking execution.
- Parameters:
database_url (str | None) – SQLAlchemy async database URL (e.g., “sqlite+aiosqlite:///./db.sqlite”). If None, uses default from alembic.ini
target_revision (str) – Target revision to migrate to. Defaults to “head” (latest). Can be specific revision ID, relative revision (e.g., “+1”, “-2”), or branch label.
- Raises:
FileNotFoundError – If alembic.ini or migration scripts not found
ValueError – If target revision is invalid
Exception – If migration fails
- Return type:
None
Example:
# Migrate to latest await run_migrations("sqlite+aiosqlite:///./proxywhirl.db") # Migrate to specific revision await run_migrations("sqlite+aiosqlite:///./db.sqlite", "58c0fadfa0ca") # Rollback one revision await run_migrations("sqlite+aiosqlite:///./db.sqlite", "-1")
- async proxywhirl.migrations.stamp_revision(database_url=None, revision='head')[source]¶
Stamp the database with a specific revision without running migrations.
This is useful when importing an existing database that matches a specific schema version, or for recovering from migration issues.
Use with extreme caution! This bypasses actual schema changes.
- Parameters:
- Return type:
None
Example:
# Stamp database as being at head revision await stamp_revision("sqlite+aiosqlite:///./db.sqlite", "head")