Skip to content

Commit

Permalink
Updates for Flask-SQLAlchemy 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Oct 21, 2022
1 parent de822d8 commit 5175294
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 27 deletions.
17 changes: 13 additions & 4 deletions src/flask_migrate/templates/flask-multidb/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')


def get_engine(bind_key=None):
try:
# this works with Flask-SQLAlchemy>=3
return current_app.extensions['migrate'].db.get_engine(

This comment has been minimized.

Copy link
@davidism

davidism Nov 17, 2022

Contributor

db.get_engine was deprecated in Flask-SQLAlchemy 3. Use db.engines[bind_key].

This comment has been minimized.

Copy link
@miguelgrinberg

miguelgrinberg Nov 17, 2022

Author Owner

Thanks. I will update this.

This comment has been minimized.

Copy link
@miguelgrinberg

miguelgrinberg Nov 17, 2022

Author Owner

I'm going to guess you do not want this kind of feedback, but since this happened a few times in the past and keeps happening with projects you manage, I'd like to mention that this type of merely cosmetic and non-functional change causes pain to maintainers of related projects, and more importantly to developers, who really should not have to know or deal with this type of minutia.

I'm not sure you realize this, but when a developer upgrades Flask-SQLAlchemy to 3.x and Flask-Migrate to 4.x, their project will break, because their Alembic env.py file cannot be automatically upgraded, since it is installed for the developer to customize. Neither Alembic nor Flask-Migrate provide tools to merge updates to this file, so the merging effort will have to be carried out by developers.

So I just want to state that I'm not happy with the influx of developers who blame me for the breakages and need assistance to restore migrations. I would like to suggest you avoid making changes like these in the future if at all possible. Thank you.

bind_key=bind_key)
except TypeError:
# this works with Flask-SQLAlchemy<3
return current_app.extensions['migrate'].db.get_engine(bind=bind_key)


# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
Expand All @@ -38,8 +49,7 @@
for bind in bind_names:
context.config.set_section_option(
bind, "sqlalchemy.url",
str(current_app.extensions['migrate'].db.get_engine(
bind=bind).url).replace('%', '%%'))
str(get_engine(bind_key=bind).url).replace('%', '%%'))
target_db = current_app.extensions['migrate'].db

# other values from the config, defined by the needs of env.py,
Expand Down Expand Up @@ -132,8 +142,7 @@ def process_revision_directives(context, revision, directives):
}
for name in bind_names:
engines[name] = rec = {}
rec['engine'] = current_app.extensions['migrate'].db.get_engine(
bind=name)
rec['engine'] = get_engine(bind_key=name)

for name, rec in engines.items():
engine = rec['engine']
Expand Down
6 changes: 5 additions & 1 deletion tests/app.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#!/bin/env python
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
Expand Down
6 changes: 5 additions & 1 deletion tests/app_compare_type1.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
Expand Down
6 changes: 5 additions & 1 deletion tests/app_compare_type2.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
Expand Down
6 changes: 5 additions & 1 deletion tests/app_custom_directory.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
Expand Down
6 changes: 5 additions & 1 deletion tests/app_custom_directory_path.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from pathlib import Path

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
Expand Down
8 changes: 6 additions & 2 deletions tests/app_multidb.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#!/bin/env python
import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app1.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(
basedir, 'app1.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_BINDS'] = {
"db1": "sqlite:///app2.db",
"db1": "sqlite:///" + os.path.join(basedir, "app2.db"),
}

db = SQLAlchemy(app)
Expand Down
7 changes: 4 additions & 3 deletions tests/test_custom_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ def test_migrate_upgrade(self):
(o, e, s) = run_cmd('app.py', 'flask db upgrade')
self.assertTrue(s == 0)

from .app import db, User
db.session.add(User(name='test'))
db.session.commit()
from .app import app, db, User
with app.app_context():
db.session.add(User(name='test'))
db.session.commit()

with open('migrations/README', 'rt') as f:
assert f.readline().strip() == 'Custom template.'
Expand Down
21 changes: 12 additions & 9 deletions tests/test_migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ def test_migrate_upgrade(self):
(o, e, s) = run_cmd('app.py', 'flask db upgrade')
self.assertTrue(s == 0)

from .app import db, User
db.session.add(User(name='test'))
db.session.commit()
from .app import app, db, User
with app.app_context():
db.session.add(User(name='test'))
db.session.commit()

def test_custom_directory(self):
(o, e, s) = run_cmd('app_custom_directory.py', 'flask db init')
Expand All @@ -73,9 +74,10 @@ def test_custom_directory(self):
(o, e, s) = run_cmd('app_custom_directory.py', 'flask db upgrade')
self.assertTrue(s == 0)

from .app_custom_directory import db, User
db.session.add(User(name='test'))
db.session.commit()
from .app_custom_directory import app, db, User
with app.app_context():
db.session.add(User(name='test'))
db.session.commit()

def test_custom_directory_path(self):
(o, e, s) = run_cmd('app_custom_directory_path.py', 'flask db init')
Expand All @@ -85,9 +87,10 @@ def test_custom_directory_path(self):
(o, e, s) = run_cmd('app_custom_directory_path.py', 'flask db upgrade')
self.assertTrue(s == 0)

from .app_custom_directory_path import db, User
db.session.add(User(name='test'))
db.session.commit()
from .app_custom_directory_path import app, db, User
with app.app_context():
db.session.add(User(name='test'))
db.session.commit()

def test_compare_type(self):
(o, e, s) = run_cmd('app_compare_type1.py', 'flask db init')
Expand Down
12 changes: 8 additions & 4 deletions tests/test_multidb_migrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ def run_cmd(app, cmd):
process = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(stdout, stderr) = process.communicate()
print('\n$ ' + cmd)
print(stdout.decode('utf-8'))
print(stderr.decode('utf-8'))
return stdout, stderr, process.wait()


Expand Down Expand Up @@ -65,10 +68,11 @@ def test_multidb_migrate_upgrade(self):
self.assertIn(('group',), tables)

# ensure the databases can be written to
from .app_multidb import db, User, Group
db.session.add(User(name='test'))
db.session.add(Group(name='group'))
db.session.commit()
from .app_multidb import app, db, User, Group
with app.app_context():
db.session.add(User(name='test'))
db.session.add(Group(name='group'))
db.session.commit()

# ensure the downgrade works
(o, e, s) = run_cmd('app_multidb.py', 'flask db downgrade')
Expand Down

0 comments on commit 5175294

Please sign in to comment.