Note
this section discusses the internal API of Alembic as regards the internal system of defining migration operation directives. This section is only useful for developers who wish to extend the capabilities of Alembic. For end-user guidance on Alembic migration operations, please see Operation Reference.
Within migration scripts, actual database migration operations are handled via an instance of Operations. The Operations class lists out available migration operations that are linked to a MigrationContext, which communicates instructions originated by the Operations object into SQL that is sent to a database or SQL output stream.
Most methods on the Operations class are generated dynamically using a “plugin” system, described in the next section Operation Plugins. Additionally, when Alembic migration scripts actually run, the methods on the current Operations object are proxied out to the alembic.op module, so that they are available using module-style access.
For an overview of how to use an Operations object directly in programs, as well as for reference to the standard operation methods as well as “batch” methods, see Operation Reference.
The Operations object is extensible using a plugin system. This system allows one to add new op.<some_operation> methods at runtime. The steps to use this system are to first create a subclass of MigrateOperation, register it using the Operations.register_operation() class decorator, then build a default “implementation” function which is established using the Operations.implementation_for() decorator.
New in version 0.8.0: - the Operations class is now an open namespace that is extensible via the creation of new MigrateOperation subclasses.
Below we illustrate a very simple operation CreateSequenceOp which will implement a new method op.create_sequence() for use in migration scripts:
from alembic.operations import Operations, MigrateOperation
@Operations.register_operation("create_sequence")
class CreateSequenceOp(MigrateOperation):
"""Create a SEQUENCE."""
def __init__(self, sequence_name, schema=None):
self.sequence_name = sequence_name
self.schema = schema
@classmethod
def create_sequence(cls, operations, sequence_name, **kw):
"""Issue a "CREATE SEQUENCE" instruction."""
op = CreateSequenceOp(sequence_name, **kw)
return operations.invoke(op)
def reverse(self):
# only needed to support autogenerate
return DropSequenceOp(self.sequence_name, schema=self.schema)
@Operations.register_operation("drop_sequence")
class DropSequenceOp(MigrateOperation):
"""Drop a SEQUENCE."""
def __init__(self, sequence_name, schema=None):
self.sequence_name = sequence_name
self.schema = schema
@classmethod
def drop_sequence(cls, operations, sequence_name, **kw):
"""Issue a "DROP SEQUENCE" instruction."""
op = DropSequenceOp(sequence_name, **kw)
return operations.invoke(op)
def reverse(self):
# only needed to support autogenerate
return CreateSequenceOp(self.sequence_name, schema=self.schema)
Above, the CreateSequenceOp and DropSequenceOp classes represent new operations that will be available as op.create_sequence() and op.drop_sequence(). The reason the operations are represented as stateful classes is so that an operation and a specific set of arguments can be represented generically; the state can then correspond to different kinds of operations, such as invoking the instruction against a database, or autogenerating Python code for the operation into a script.
In order to establish the migrate-script behavior of the new operations, we use the Operations.implementation_for() decorator:
@Operations.implementation_for(CreateSequenceOp)
def create_sequence(operations, operation):
if operation.schema is not None:
name = "%s.%s" % (operation.schema, operation.sequence_name)
else:
name = operation.sequence_name
operations.execute("CREATE SEQUENCE %s" % name)
@Operations.implementation_for(DropSequenceOp)
def drop_sequence(operations, operation):
if operation.schema is not None:
name = "%s.%s" % (operation.schema, operation.sequence_name)
else:
name = operation.sequence_name
operations.execute("DROP SEQUENCE %s" % name)
Above, we use the simplest possible technique of invoking our DDL, which is just to call Operations.execute() with literal SQL. If this is all a custom operation needs, then this is fine. However, options for more comprehensive support include building out a custom SQL construct, as documented at sqlalchemy.ext.compiler_toplevel.
With the above two steps, a migration script can now use new methods op.create_sequence() and op.drop_sequence() that will proxy to our object as a classmethod:
def upgrade():
op.create_sequence("my_sequence")
def downgrade():
op.drop_sequence("my_sequence")
The registration of new operations only needs to occur in time for the env.py script to invoke MigrationContext.run_migrations(); within the module level of the env.py script is sufficient.
See also
Autogenerating Custom Operation Directives - how to add autogenerate support to custom operations.
New in version 0.8: - the migration operations available via the Operations class as well as the alembic.op namespace is now extensible using a plugin system.
The migration operations present on Operations are themselves delivered via operation objects that represent an operation and its arguments. All operations descend from the MigrateOperation class, and are registered with the Operations class using the Operations.register_operation() class decorator. The MigrateOperation objects also serve as the basis for how the autogenerate system renders new migration scripts.
The built-in operation objects are listed below.
Represent an add column operation.
This method is proxied on the Operations class, via the Operations.add_column() method.
This method is proxied on the BatchOperations class, via the BatchOperations.add_column() method.
Represent an add constraint operation.
Represent an alter column operation.
This method is proxied on the Operations class, via the Operations.alter_column() method.
This method is proxied on the BatchOperations class, via the BatchOperations.alter_column() method.
Represent an alter table operation.
Represent a bulk insert operation.
This method is proxied on the Operations class, via the Operations.bulk_insert() method.
Represent a create check constraint operation.
This method is proxied on the BatchOperations class, via the BatchOperations.create_check_constraint() method.
This method is proxied on the Operations class, via the Operations.create_check_constraint() method.
Represent a create foreign key constraint operation.
This method is proxied on the BatchOperations class, via the BatchOperations.create_foreign_key() method.
This method is proxied on the Operations class, via the Operations.create_foreign_key() method.
Represent a create index operation.
This method is proxied on the BatchOperations class, via the BatchOperations.create_index() method.
This method is proxied on the Operations class, via the Operations.create_index() method.
Represent a create primary key operation.
This method is proxied on the BatchOperations class, via the BatchOperations.create_primary_key() method.
This method is proxied on the Operations class, via the Operations.create_primary_key() method.
Represent a create table operation.
This method is proxied on the Operations class, via the Operations.create_table() method.
Represent a create unique constraint operation.
This method is proxied on the BatchOperations class, via the BatchOperations.create_unique_constraint() method.
This method is proxied on the Operations class, via the Operations.create_unique_constraint() method.
contains a sequence of operations that would apply to the ‘downgrade’ stream of a script.
See also
Represent a drop column operation.
This method is proxied on the BatchOperations class, via the BatchOperations.drop_column() method.
This method is proxied on the Operations class, via the Operations.drop_column() method.
Represent a drop constraint operation.
This method is proxied on the BatchOperations class, via the BatchOperations.drop_constraint() method.
This method is proxied on the Operations class, via the Operations.drop_constraint() method.
Represent a drop index operation.
This method is proxied on the BatchOperations class, via the BatchOperations.drop_index() method.
This method is proxied on the Operations class, via the Operations.drop_index() method.
Represent a drop table operation.
This method is proxied on the Operations class, via the Operations.drop_table() method.
Represent an execute SQL operation.
This method is proxied on the Operations class, via the Operations.execute() method.
base class for migration command and organization objects.
This system is part of the operation extensibility API.
New in version 0.8.0.
A dictionary that may be used to store arbitrary information along with this MigrateOperation object.
represents a migration script.
E.g. when autogenerate encounters this object, this corresponds to the production of an actual script file.
A normal MigrationScript object would contain a single UpgradeOps and a single DowngradeOps directive. These are accessible via the .upgrade_ops and .downgrade_ops attributes.
In the case of an autogenerate operation that runs multiple times, such as the multiple database example in the “multidb” template, the .upgrade_ops and .downgrade_ops attributes are disabled, and instead these objects should be accessed via the .upgrade_ops_list and .downgrade_ops_list list-based attributes. These latter attributes are always available at the very least as single-element lists.
Changed in version 0.8.1: the .upgrade_ops and .downgrade_ops attributes should be accessed via the .upgrade_ops_list and .downgrade_ops_list attributes if multiple autogenerate passes proceed on the same MigrationScript object.
See also
An instance of DowngradeOps.
See also
A list of DowngradeOps instances.
This is used in place of the MigrationScript.downgrade_ops attribute when dealing with a revision operation that does multiple autogenerate passes.
New in version 0.8.1.
An instance of UpgradeOps.
See also
A list of UpgradeOps instances.
This is used in place of the MigrationScript.upgrade_ops attribute when dealing with a revision operation that does multiple autogenerate passes.
New in version 0.8.1.
Contains a sequence of operations that all apply to a single Table.
Represent a sequence of operations operation.
Represent a rename table operation.
This method is proxied on the Operations class, via the Operations.rename_table() method.
contains a sequence of operations that would apply to the ‘upgrade’ stream of a script.
See also