I'm trying to create automatic tests for alembic, specifically to test that the revision --autogenerate command provides the expected migrations. Instead of running from the command line, I want to obtain the suggested revisions programmatically and run them to confirm that the effect on the test database is as expected.
I have two models - initial_model_base and removed_column_base, the idea is that when I run an autogenerated revision for the second time, alembic should detect that the second model has 1 less column and create a revision to remove it. However, I'm getting ValueError: no dispatch function for object: <alembic.operations.ops.ModifyTableOps. Here is the full stack trace:
File "C:\Users\Ronel\Desktop\repos\test_alembic\tests\tests.py", line 152, in test_removing_column() File "C:\Users\Ronel\Desktop\repos\test_alembic\tests\tests.py", line 109, in test_removing_column ops.invoke(op) File "C:\Users\Ronel\AppData\Roaming\Python\Python310\site-packages\alembic\operations\base.py", line 396, in invoke fn = self._to_impl.dispatch( File "C:\Users\Ronel\AppData\Roaming\Python\Python310\site-packages\alembic\util\langhelpers.py", line 258, in dispatch raise ValueError("no dispatch function for object: %s" % obj) ValueError: no dispatch function for object: <alembic.operations.ops.ModifyTableOps object at 0x0000028C0FBC1ED0>
The table I use for testing is test_alembic_schema.employees so to prevent other tables getting affected I provided an include_object function to the config kwargs.
def include_object(object, name, type_, reflected, compare_to):
if type_ == "table":
if object.schema == "test_alembic_schema" and object.name == 'employees':
return True
else:
return False
else:
return True
mc = MigrationContext.configure(
connection=DB_DEV.connection,
opts={
'compare_type': True,
'include_schemas': True,
'include_object': include_object
}
)
ops = Operations(mc)
def test_creation():
diff_ops = produce_migrations(
context=mc,
metadata=initial_model_base.metadata
)
with DB_DEV.transaction(autocommit=True):
for op in diff_ops.upgrade_ops.ops:
ops.invoke(op)
employees = DB_DEV.get_table(table_name='employees', schema_name='test_alembic_schema')
assert len(employees.c) == 8
assert employees.c.id.primary_key
assert not employees.c.first_name.primary_key
def test_removing_column():
diff_ops = produce_migrations(
context=mc,
metadata=removed_column_base.metadata
)
with DB_DEV.transaction(autocommit=True):
for op in diff_ops.upgrade_ops.ops:
ops.invoke(op)
employees = DB_DEV.get_table(table_name='employees', schema_name='test_alembic_schema')
col_found = False
for col in employees.columns:
if col.name == 'created':
col_found = True
if col_found:
assert True
else:
assert False
I am confused as to why the operation to create a table succeeds but to amend it fails. Do you have ideas how this can be fixed so both operations work as expected?