diff --git a/README.md b/README.md index b8576fd..181edd1 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,30 @@ alembic_postgresql_enum.set_configuration( ) ) ``` + +Default configuration: +```python +alembic_postgresql_enum.Config( + add_type_ignore = False, + include_name = lambda _: True, + drop_unused_enums = True, + detect_enum_values_changes = True, +) +``` + ## Features * [Creation of enums](#creation-of-enum) * [Deletion of unreferenced enums](#deletion-of-unreferenced-enum) -* [Creation of new enum values](#creation-of-new-enum-values) -* [Deletion of enums values](#deletion-of-enums-values) -* [Renaming of enum values](#rename-enum-value) +* [Detection of enum values changes](#detection-of-enum-values-changes) + * [Creation of new enum values](#creation-of-new-enum-values) + * [Deletion of enums values](#deletion-of-enums-values) + * [Renaming of enum values](#rename-enum-value) * [Omitting managing enums](#omitting-managing-enums) -### Creation of enum +## Creation of enum -#### When table is created +### When table is created ```python class MyEnum(enum.Enum): @@ -93,7 +105,7 @@ def downgrade(): # ### end Alembic commands ### ``` -#### When column is added +### When column is added ```python class MyEnum(enum.Enum): one = 1 @@ -125,7 +137,7 @@ def downgrade(): # ### end Alembic commands ### ``` -### Deletion of unreferenced enum +## Deletion of unreferenced enum If enum is defined in postgres schema, but its mentions removed from code - It will be automatically removed ```python class ExampleTable(BaseModel): @@ -148,6 +160,10 @@ def downgrade(): # ### end Alembic commands ### ``` +## Detection of enum values changes + +***Can be disabled with `detect_enum_values_changes` configuration flag turned off*** + ### Creation of new enum values If new enum value is defined sync_enum_values function call will be added to migration to account for it @@ -221,6 +237,7 @@ def downgrade(): # ### end Alembic commands ### ``` + ### Rename enum value In this case you must manually edit migration @@ -286,7 +303,7 @@ Do not forget to switch places old and new values for downgrade All defaults in postgres will be renamed automatically as well -### Omitting managing enums +## Omitting managing enums If configured `include_name` function returns `False` given enum will be not managed. ```python diff --git a/alembic_postgresql_enum/compare_dispatch.py b/alembic_postgresql_enum/compare_dispatch.py index 0099e9b..82d6337 100644 --- a/alembic_postgresql_enum/compare_dispatch.py +++ b/alembic_postgresql_enum/compare_dispatch.py @@ -76,12 +76,14 @@ def compare_enums( create_new_enums(definitions, declarations.enum_values, schema, upgrade_ops) - drop_unused_enums(definitions, declarations.enum_values, schema, upgrade_ops) - - sync_changed_enums( - definitions, - declarations.enum_values, - declarations.enum_table_references, - schema, - upgrade_ops, - ) + if configuration.drop_unused_enums: + drop_unused_enums(definitions, declarations.enum_values, schema, upgrade_ops) + + if configuration.detect_enum_values_changes: + sync_changed_enums( + definitions, + declarations.enum_values, + declarations.enum_table_references, + schema, + upgrade_ops, + ) diff --git a/alembic_postgresql_enum/configuration.py b/alembic_postgresql_enum/configuration.py index 4d73f78..63c8b7f 100644 --- a/alembic_postgresql_enum/configuration.py +++ b/alembic_postgresql_enum/configuration.py @@ -6,6 +6,8 @@ class Config: add_type_ignore: bool = False include_name: Callable[[str], bool] = lambda _: True + drop_unused_enums: bool = True + detect_enum_values_changes: bool = True _config = Config() diff --git a/alembic_postgresql_enum/sql_commands/column_default.py b/alembic_postgresql_enum/sql_commands/column_default.py index 0d21175..f191cc9 100644 --- a/alembic_postgresql_enum/sql_commands/column_default.py +++ b/alembic_postgresql_enum/sql_commands/column_default.py @@ -66,7 +66,6 @@ def rename_default_if_required( return column_default_value if default_value.endswith("[]"): - # remove old type postfix column_default_value = default_value[: default_value.find("::")] diff --git a/tests/sync_enum_values/test_render.py b/tests/sync_enum_values/test_render.py index c85eb8c..6b2d36a 100644 --- a/tests/sync_enum_values/test_render.py +++ b/tests/sync_enum_values/test_render.py @@ -26,6 +26,37 @@ from tests.utils.migration_context import create_migration_context +class TestDisabledSyncEnumValues(CompareAndRunTestCase): + """Check that enum variants are updated when new variant is added""" + + config = Config(detect_enum_values_changes=False) + + old_enum_variants = ["active", "passive"] + new_enum_variants = old_enum_variants + ["banned"] + + def get_database_schema(self) -> MetaData: + schema = get_schema_with_enum_variants(self.old_enum_variants) + return schema + + def get_target_schema(self) -> MetaData: + schema = get_schema_with_enum_variants(self.new_enum_variants) + return schema + + def get_expected_upgrade(self) -> str: + return f""" + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + """ + + def get_expected_downgrade(self) -> str: + return f""" + # ### commands auto generated by Alembic - please adjust! ### + pass + # ### end Alembic commands ### + """ + + class TestAddNewEnumValueRender(CompareAndRunTestCase): """Check that enum variants are updated when new variant is added""" diff --git a/tests/test_enum_creation/test_drop_column.py b/tests/test_enum_creation/test_drop_column.py index e188247..849af79 100644 --- a/tests/test_enum_creation/test_drop_column.py +++ b/tests/test_enum_creation/test_drop_column.py @@ -1,5 +1,6 @@ from typing import TYPE_CHECKING +from alembic_postgresql_enum import Config from alembic_postgresql_enum.operations import DropEnumOp from tests.base.run_migration_test_abc import CompareAndRunTestCase @@ -63,6 +64,36 @@ def get_expected_downgrade(self) -> str: """ +class TestDisabledDeleteEnumAfterDropColumn(CompareAndRunTestCase): + """Check that library correctly removes unused enum after drop_column""" + + config = Config( + drop_unused_enums=False, + ) + enum_variants_to_delete = ["active", "passive"] + + def get_database_schema(self) -> MetaData: + return get_schema_with_enum_variants(self.enum_variants_to_delete) + + def get_target_schema(self) -> MetaData: + return get_schema_without_enum() + + def get_expected_upgrade(self) -> str: + return f""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('{USER_TABLE_NAME}', '{USER_STATUS_COLUMN_NAME}') + # ### end Alembic commands ### + """ + + def get_expected_downgrade(self) -> str: + # For some reason alembic decided to add redundant autoincrement=False on downgrade + return f""" + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('{USER_TABLE_NAME}', sa.Column('{USER_STATUS_COLUMN_NAME}', postgresql.ENUM({', '.join(map(repr, self.enum_variants_to_delete))}, name='{USER_STATUS_ENUM_NAME}', create_type=False), autoincrement=False, nullable=True)) + # ### end Alembic commands ### + """ + + class TestDeleteEnumAfterDropColumnWithArray(CompareAndRunTestCase): """Check that library correctly removes unused enum after drop_column. Enum is used in ARRAY"""