-
-
Notifications
You must be signed in to change notification settings - Fork 292
Description
Describe the use case
The merge command should support the process_revision_directives parameter in its programmatic API, consistent with the revision command.
Currently, while both commands support revision_environment (which runs env.py), only the revision command accepts a programmatic process_revision_directives parameter. This creates an API
inconsistency when using Alembic programmatically to customize revision generation logic for merge operations.
Databases / Backends / Drivers targeted
All databases - this is a general Alembic API feature request.
Example Use
Current behavior - revision command (works):
from alembic import command
from alembic.config import Config
config = Config("alembic.ini")
def my_process_revision_directives(context, revision, directives):
"""Custom revision ID generation logic"""
for directive in directives:
directive.rev_id = generate_custom_id() # Custom logic
This works - process_revision_directives parameter is supported
command.revision(
config,
message="Add new feature",
process_revision_directives=my_process_revision_directives
)
Desired behavior - merge command (currently doesn't work):
# This fails with TypeError - process_revision_directives is not accepted
command.merge(
config,
revisions=("head1", "head2"),
message="Merge branches",
process_revision_directives=my_process_revision_directives # ❌ Not supported
)
Current workaround:
Users must configure the hook in env.py, which affects all operations:
# env.py
def process_revision_directives(context, revision, directives):
# This applies to ALL revision/merge commands
for directive in directives:
directive.rev_id = generate_custom_id()
context.configure(
process_revision_directives=process_revision_directives
)
This workaround doesn't allow per-command customization when using the programmatic API.
Proposed API:
def merge(
config: Config,
revisions: _RevIdType,
message: Optional[str] = None,
branch_label: Optional[_RevIdType] = None,
rev_id: Optional[str] = None,
process_revision_directives: Optional[ProcessRevisionDirectiveFn] = None, # NEW
) -> Optional[Script]:
"""
:param process_revision_directives: optional callable that allows
programmatic customization of the revision directives. Same signature
as the callable described at
:paramref:`.EnvironmentContext.configure.process_revision_directives`
"""
# Implementation already uses RevisionContext internally,
# just need to accept and pass through the parameter
Use cases:
- Different logic for merges vs regular revisions: Apply special revision ID schemes or metadata only to merge commits
- CI/CD automation: Programmatic scripts that customize merge behavior without modifying env.py
- Multi-tenant environments: Different revision ID generation based on runtime context
Additional context
- The merge command already uses RevisionContext internally (since 1.12.0 when revision_environment support was added via
alembic merge
ignoresrevision_environment
and cannot find the hooks defined inenv.py
#1299) - The implementation would be minimal - just accepting and passing through the parameter
- This would make the API consistent between revision and merge commands
- The parameter would be optional and backward-compatible
Reference:
- alembic/command.py::revision() - Lines 194-320 (already supports this parameter)
- alembic/command.py::merge() - Lines 382-439 (should support this parameter)
- alembic/autogenerate/api.py::RevisionContext - Already supports process_revision_directives
Versions.
- OS: macOS (but applies to all platforms)
- Python: 3.9+
- Alembic: 1.16.5 (latest)
- SQLAlchemy: 1.4+/2.0+
- Database: All
- DBAPI: All