Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run a migration with Python Alembic by code?

I am trying to migrate a SQL database using sqlAlchemy and Alembic. I would like to make simple migration scripts directly in Python code, and not by using Alembic CLI, as described in the docs.

I only found this SO question on this topic: Using Alembic API from inside application code

Using this question + Flask-Alembic source code, I tried these simple commands. engine is linked to my db & metadata contains the information for the migration.

I think I am very close, and the solution should be in one line of code... I'm struggling.

from alembic.config import Config
from alembic import command, autogenerate
from alembic.script import ScriptDirectory
from alembic.runtime.environment import EnvironmentContext

alembic_cfg = Config()
alembic_cfg.set_main_option("script_location", "migrations")
alembic_cfg.set_main_option("url", "postgresql://user:pass@postgres:5432/mydb")

alembic_script = ScriptDirectory.from_config(alembic_cfg)
alembic_env = EnvironmentContext(alembic_cfg, alembic_script)

conn = engine.connect()
alembic_env.configure(connection=conn, target_metadata=metadata)
alembic_context = alembic_env.get_context()

I am able to use the following commands to see that it works and detects what fields have to migrate :

autogenerate.compare_metadata(alembic_context, metadata)
autogenerate.produce_migrations(alembic_context, metadata)

However, I am not able to run the migrations. I tried several commands, and always get an error...

Ex, if I run:

with alembic_env.begin_transaction():
    alembic_env.run_migrations()

I get :

/usr/local/lib/python2.7/site-packages/alembic/runtime/migration.pyc in run_migrations(self, **kw)
    301         head_maintainer = HeadMaintainer(self, heads)
    302 
--> 303         for step in self._migrations_fn(heads, self):
    304             with self.begin_transaction(_per_migration=True):
    305                 if self.as_sql and not head_maintainer.heads:

TypeError: 'NoneType' object is not callable

Could anyone help me. I think the solution is a one-liner, but I cannot find how to run the migration on my database...

For information, I have never done any migration on this DB with Alembic, maybe there is the need of an "init" ?

Thanks a lot.

like image 255
bobby Avatar asked Aug 18 '16 14:08

bobby


1 Answers

for step in self._migrations_fn(heads, self):

Here we shall describe in what order you want to migrate. The sequence consists of steps, each of have step.migration_fn(**kw).

How to fix

The last step you need is add _migrations_fn while you do alembic_env.configure.

def do_upgrade(revision, context):
    return alembic_script._upgrade_revs(script.get_heads(), revision)

alembic_env.configure(connection=conn, target_metadata=metadata, fn=do_upgrade)

script.get_heads() returns the last migration. Replace, if you need a specific revision, instead of the last.

Related links:

  • Using Alembic API from inside application code

    https://bitbucket.org/davidism/flask-alembic/src/e036f063af1ba667c74560264639a93d812dfd51/flask_alembic/extension.py?at=default&fileviewer=file-view-default#extension.py-324

like image 89
asduj Avatar answered Nov 02 '22 22:11

asduj