Skip to content

add rev_id generator function feature to environment.configure(), will apply to revision, merge #1732

@jiayun

Description

@jiayun

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:

  1. Different logic for merges vs regular revisions: Apply special revision ID schemes or metadata only to merge commits
  2. CI/CD automation: Programmatic scripts that customize merge behavior without modifying env.py
  3. Multi-tenant environments: Different revision ID generation based on runtime context

Additional context

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting infowaiting for the submitter to give more informationuse casenot quite a feature and not quite a bug, something we just didn't think of

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions