Flask-migrate: missing kwarg engine_name in migrations created with flask db init, after switching to multiple databases

Created on 15 Jan 2018  路  2Comments  路  Source: miguelgrinberg/Flask-Migrate

I had a database which already had migrations. I added a second database, re-running flask db init --multidb as you suggested at https://github.com/miguelgrinberg/Flask-Migrate/issues/179. Worked fine. But, when I want to upgrade or downgrade one of the old migrations (old means, they where created by flask db migrate when I had only one database), I get the error

Traceback (most recent call last):
  File "/[...]/bin/flask", line 11, in <module>
    sys.exit(main())
  File "/[...]/lib/python3.6/site-packages/flask/cli.py", line 507, in main
    cli.main(args=args, prog_name=name)
  File "/[...]/lib/python3.6/site-packages/flask/cli.py", line 374, in main
    return AppGroup.main(self, *args, **kwargs)
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/[...]/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/[...]/lib/python3.6/site-packages/flask/cli.py", line 251, in decorator
    return __ctx.invoke(f, *args, **kwargs)
  File "/[...]/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/[...]/lib/python3.6/site-packages/flask_migrate/cli.py", line 132, in upgrade
    _upgrade(directory, revision, sql, tag, x_arg)
  File "/[...]/lib/python3.6/site-packages/flask_migrate/__init__.py", line 244, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/[...]/lib/python3.6/site-packages/alembic/command.py", line 174, in upgrade
    script.run_env()
  File "/[...]/lib/python3.6/site-packages/alembic/script/base.py", line 416, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/[...]/lib/python3.6/site-packages/alembic/util/pyfiles.py", line 93, in load_python_file
    module = load_module_py(module_id, path)
  File "/[...]/lib/python3.6/site-packages/alembic/util/compat.py", line 68, in load_module_py
    module_id, path).load_module(module_id)
  File "<frozen importlib._bootstrap_external>", line 399, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 823, in load_module
  File "<frozen importlib._bootstrap_external>", line 682, in load_module
  File "<frozen importlib._bootstrap>", line 251, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 675, in _load
  File "<frozen importlib._bootstrap>", line 655, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 205, in _call_with_frames_removed
  File "migrations/env.py", line 158, in <module>
    run_migrations_online()
  File "migrations/env.py", line 138, in run_migrations_online
    context.run_migrations(engine_name=name)
  File "<string>", line 8, in run_migrations
  File "/[...]/lib/python3.6/site-packages/alembic/runtime/environment.py", line 807, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/[...]/lib/python3.6/site-packages/alembic/runtime/migration.py", line 321, in run_migrations
    step.migration_fn(**kw)
TypeError: upgrade() got an unexpected keyword argument 'engine_name'

This is, because flask-Migrate is passing the engine_name as a parameter now, which it (understandably) didn't do before flask db init --multidb. I can fix this by refactoring each instance of def upgrade() to def upgrade(**kwargs) or def upgrade(engine_name) and analogously for ocurrences of def downgrade() in the existing migration files. But to me, it feels paradigmatically wrong to change anything in a migration. Maybe I am wrong with this, but is there a possibility for flask-Migrate to prevent me from refactoring the migrations?

question

Most helpful comment

I actually missed this difference between the migration scripts for one vs. multi database. I honestly don't think there is anything wrong with modifying existing migration scripts, as long as you don't change the actual migration logic.

If you look at one of the multi-db migrations you'll find what you need to change, you'll simply need to replace the upgrade and downgrade functions with:

def upgrade(engine_name):
    globals()["upgrade_%s" % engine_name]()

def downgrade(engine_name):
    globals()["downgrade_%s" % engine_name]()

Then rename your original upgrade() and downgrade() to upgrade_() and downgrade_(), and finally add empty upgrade_dbname() and downgrade_dbname() functions for your additional database(s).

All 2 comments

I actually missed this difference between the migration scripts for one vs. multi database. I honestly don't think there is anything wrong with modifying existing migration scripts, as long as you don't change the actual migration logic.

If you look at one of the multi-db migrations you'll find what you need to change, you'll simply need to replace the upgrade and downgrade functions with:

def upgrade(engine_name):
    globals()["upgrade_%s" % engine_name]()

def downgrade(engine_name):
    globals()["downgrade_%s" % engine_name]()

Then rename your original upgrade() and downgrade() to upgrade_() and downgrade_(), and finally add empty upgrade_dbname() and downgrade_dbname() functions for your additional database(s).

@jonathan-scholbach & @miguelgrinberg I found the question above and also this one [#179] (https://github.com/miguelgrinberg/Flask-Migrate/issues/179) extremely helpful.

I really appreciate it. Thank you very much!

Was this page helpful?
0 / 5 - 0 ratings