Support for migrating PostgreSQL enums with Alembic
Project description
Alembic Enums
Support for migrating PostgreSQL enums with Alembic
The package doesn't detect enum changes or generate migration code automatically, but it provides a helper class to run the enum migrations in Alembic migration scripts.
Problem statement
When you define an enum column with SQLAlchemy, the initial migration defines a custom enum type.
Once the enum type is created, ALTER TYPE allows you to add new values or rename existing ones, but not delete them.
If you need to delete a value from an enum, you must create a new enum type and migrate all the columns to use the new type.
Installation
pip install alembic-enums
Usage
Assume you decided to rename the state
enum values active
and inactive
to enabled
and disabled
:
class Resource(Base):
__tablename__ = "resources"
id = Column(Integer, primary_key=True)
name = Column(String(255), nullable=False)
- state = Column(Enum("enabled", "disabled", name="resource_state"), nullable=False)
+ state = Column(Enum("active", "archived", name="resource_state"), nullable=False)
To migrate the database, we create a new empty migration with alembic revision -m "Rename enum values"
and add the following code to the generated migration script:
from alembic import op
from alembic_enums import EnumMigration, Column
# Define a target column. As in PostgreSQL, the same enum can be used in multiple
# column definitions, you may have more than one target column.
# The constructor arguments are the table name, the column name, and the
# server_default values for the old and new enum types.
column = Column("resources", "state", old_server_default=None, new_server_default=None)
# Define an enum migration. It defines the old and new enum values
# for the enum, and the list of target columns.
enum_migration = EnumMigration(
op=op,
enum_name="resource_state",
old_options=["enabled", "disabled"],
new_options=["active", "archived"],
columns=[column],
)
# Define upgrade and downgrade operations. Inside upgrade_ctx and downgrade_ctx
# context managers, you can update your data.
def upgrade():
with enum_migration.upgrade_ctx():
enum_migration.update_value(column, "enabled", "active")
enum_migration.update_value(column, "disabled", "archived")
def downgrade():
with enum_migration.downgrade_ctx():
enum_migration.update_value(column, "active", "enabled")
enum_migration.update_value(column, "archived", "disabled")
Under the hood, the EnumMigration
class creates a new enum type, updates the target columns to use the new enum type, and deletes the old enum type.
Change column default values
To change the column default values, pass corresponding values to new_server_default and old_server_default arguments of the Column constructor. The new_server_default is used on upgrade, and the old_server_default is used on downgrade.
IMPORTANT: Setting the server_default value to None will remove the default value from the column. If you want to keep the default value as is, set old_server_default and new_server_default to the same value.
For example, to change the default value of the state
column from enabled
to active
:
from alembic_enums import Column
column = Column(
"resources",
"state",
old_server_default="enabled",
new_server_default="active",
)
API reference
EnumMigration
A helper class to run enum migrations in Alembic migration scripts.
Constructor arguments:
op
: an instance ofalembic.operations.Operations
enum_name
: the name of the enum typeold_options
: a list of old enum valuesnew_options
: a list of new enum valuescolumns
: a list ofColumn
instances that use the enum type
Methods:
upgrade_ctx()
: a context manager that creates a new enum type, updates the target columns to use the new enum type, and deletes the old enum typedowngrade_ctx()
: a context manager that performs the opposite operations.update_value(column, old_value, new_value)
: a helper method to update the value of thecolumn
tonew_value
where it wasold_value
before. It's useful to update the data in the upgrade and downgrade operations within theupgrade_ctx
anddowngrade_ctx
context managers.upgrade()
: a shorthand forwith upgrade_ctx(): pass
.downgrade()
: a shorthand forwith downgrade_ctx(): pass
.
Column
A data class to define a target column for an enum migration.
Constructor arguments:
table_name
: the name of the tablecolumn_name
: the name of the columnold_server_default
: the old server_default value. When set to None, the server_default value is removed on downgrade.new_server_default
: the new server_default value. When set to None, the server_default value is removed on upgrade.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for alembic_enums-0.3.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1b91a8e8b91989f0be308ccca2c45d50ee13f2d370a6d9ababacfdc68e33a07e |
|
MD5 | 5a6fad23786d7f3c345661295c24e6b8 |
|
BLAKE2b-256 | 727b242866cc707a29cf5c14d0e0b76024d53617abd4e61a6f3eb0affc8abb45 |