Skip to content

Commit

Permalink
Support the new flask cli based on click
Browse files Browse the repository at this point in the history
Fixes #114
  • Loading branch information
miguelgrinberg committed Jul 31, 2016
1 parent 03e568c commit 8c208b5
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 15 deletions.
16 changes: 10 additions & 6 deletions flask_migrate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,12 @@ def get_config(self, directory, x_arg=None, opts=None):
setattr(config.cmd_opts, opt, True)
if x_arg is not None:
if not getattr(config.cmd_opts, 'x', None):
setattr(config.cmd_opts, 'x', [x_arg])
else:
config.cmd_opts.x.append(x_arg)
setattr(config.cmd_opts, 'x', [])
if isinstance(x_arg, list) or isinstance(x_arg, tuple):
for x in x_arg:
config.cmd_opts.x.append(x)
else:
config.cmd_opts.x.append(x_arg)
return self.call_configure_callbacks(config)


Expand All @@ -84,7 +87,7 @@ def get_config(self, directory, x_arg=None, opts=None):
help=("Multiple databases migraton (default is "
"False)"))
def init(directory=None, multidb=False):
"""Generates a new migration"""
"""Creates a new migration repository"""
if directory is None:
directory = current_app.extensions['migrate'].directory
config = Config()
Expand Down Expand Up @@ -122,7 +125,8 @@ def init(directory=None, multidb=False):
help=('Populate revision script with andidate migration '
'operatons, based on comparison of database to '
'model'))
@MigrateCommand.option('-m', '--message', dest='message', default=None)
@MigrateCommand.option('-m', '--message', dest='message', default=None,
help='Revision message')
@MigrateCommand.option('-d', '--directory', dest='directory', default=None,
help=("migration script directory (default is "
"'migrations')"))
Expand Down Expand Up @@ -180,7 +184,7 @@ def migrate(directory=None, message=None, sql=False, head='head', splice=False,
@MigrateCommand.option('-d', '--directory', dest='directory', default=None,
help=("migration script directory (default is "
"'migrations')"))
def edit(revision='current', directory=None):
def edit(directory=None, revision='current'):
"""Edit current revision."""
if alembic_version >= (0, 8, 0):
config = current_app.extensions['migrate'].migrate.get_config(
Expand Down
223 changes: 223 additions & 0 deletions flask_migrate/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import click
from flask.cli import with_appcontext
from flask_migrate import init as _init
from flask_migrate import revision as _revision
from flask_migrate import migrate as _migrate
from flask_migrate import edit as _edit
from flask_migrate import merge as _merge
from flask_migrate import upgrade as _upgrade
from flask_migrate import downgrade as _downgrade
from flask_migrate import show as _show
from flask_migrate import history as _history
from flask_migrate import heads as _heads
from flask_migrate import branches as _branches
from flask_migrate import current as _current
from flask_migrate import stamp as _stamp

@click.group()
def db():
"""Perform database migrations."""
pass


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('--multidb', is_flag=True,
help=('Support multiple databases'))
@with_appcontext
def init(directory, multidb):
"""Creates a new migration repository."""
_init(directory, multidb)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-m', '--message', default=None, help='Revision message')
@click.option('--autogenerate', is_flag=True,
help=('Populate revision script with andidate migration '
'operatons, based on comparison of database to model'))
@click.option('--sql', is_flag=True,
help=('Don\'t emit SQL to database - dump to standard output '
'instead'))
@click.option('--head', default='head',
help=('Specify head revision or <branchname>@head to base new '
'revision on'))
@click.option('--splice', is_flag=True,
help=('Allow a non-head revision as the "head" to splice onto'))
@click.option('--branch-label', default=None,
help=('Specify a branch label to apply to the new revision'))
@click.option('--version-path', default=None,
help=('Specify specific path from config for version file'))
@click.option('--rev-id', default=None,
help=('Specify a hardcoded revision id instead of generating '
'one'))
@with_appcontext
def revision(directory, message, autogenerate, sql, head, splice, branch_label,
version_path, rev_id):
"""Create a new revision file."""
_revision(directory, message, autogenerate, sql, head, splice,
branch_label, version_path, rev_id)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-m', '--message', default=None, help='Revision message')
@click.option('--sql', is_flag=True,
help=('Don\'t emit SQL to database - dump to standard output '
'instead'))
@click.option('--head', default='head',
help=('Specify head revision or <branchname>@head to base new '
'revision on'))
@click.option('--splice', is_flag=True,
help=('Allow a non-head revision as the "head" to splice onto'))
@click.option('--branch-label', default=None,
help=('Specify a branch label to apply to the new revision'))
@click.option('--version-path', default=None,
help=('Specify specific path from config for version file'))
@click.option('--rev-id', default=None,
help=('Specify a hardcoded revision id instead of generating '
'one'))
@with_appcontext
def migrate(directory, message, sql, head, splice, branch_label, version_path,
rev_id):
"""Autogenerate a new revision file (Alias for 'revision --autogenerate')"""
_migrate(directory, message, sql, head, splice, branch_label, version_path,
rev_id)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.argument('revision', default='head')
@with_appcontext
def edit(directory, revision):
"""Edit a revision file"""
_edit(directory, revision)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-m', '--message', default=None, help='Merge revision message')
@click.option('--branch-label', default=None,
help=('Specify a branch label to apply to the new revision'))
@click.option('--rev-id', default=None,
help=('Specify a hardcoded revision id instead of generating '
'one'))
@click.argument('revisions', nargs=-1)
@with_appcontext
def merge(directory, message, branch_label, rev_id, revisions):
"""Merge two revisions together, creating a new revision file"""
_merge(directory, revisions, message, branch_label, rev_id)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('--sql', is_flag=True,
help=('Don\'t emit SQL to database - dump to standard output '
'instead'))
@click.option('--tag', default=None,
help=('Arbitrary "tag" name - can be used by custom "env.py '
'scripts'))
@click.option('-x', '--x-arg', multiple=True,
help='Additional arguments consumed by custom env.py scripts')
@click.argument('revision', default='head')
@with_appcontext
def upgrade(directory, sql, tag, x_arg, revision):
"""Upgrade to a later version"""
_upgrade(directory, revision, sql, tag, x_arg)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('--sql', is_flag=True,
help=('Don\'t emit SQL to database - dump to standard output '
'instead'))
@click.option('--tag', default=None,
help=('Arbitrary "tag" name - can be used by custom "env.py '
'scripts'))
@click.option('-x', '--x-arg', multiple=True,
help='Additional arguments consumed by custom env.py scripts')
@click.argument('revision', default='-1')
@with_appcontext
def downgrade(directory, sql, tag, x_arg, revision):
"""Revert to a previous version"""
_downgrade(directory, revision, sql, tag, x_arg)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.argument('revision', default='head')
@with_appcontext
def show(directory, revision):
"""Show the revision denoted by the given symbol."""
_show(directory, revision)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-r', '--rev-range', default=None,
help='Specify a revision range; format is [start]:[end]')
@click.option('-v', '--verbose', is_flag=True, help='Use more verbose output')
@with_appcontext
def history(directory, rev_range, verbose):
"""List changeset scripts in chronological order."""
_history(directory, rev_range, verbose)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-v', '--verbose', is_flag=True, help='Use more verbose output')
@click.option('--resolve-dependencies', is_flag=True,
help='Treat dependency versions as down revisions')
@with_appcontext
def heads(directory, verbose, resolve_dependencies):
"""Show current available heads in the script directory"""
_heads(directory, verbose, resolve_dependencies)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-v', '--verbose', is_flag=True, help='Use more verbose output')
@with_appcontext
def branches(directory, verbose):
"""Show current branch points"""
_branches(directory, verbose)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('-v', '--verbose', is_flag=True, help='Use more verbose output')
@click.option('--head-only', is_flag=True,
help='Deprecated. Use --verbose for additional output')
@with_appcontext
def current(directory, verbose, head_only):
"""Display the current revision for each database."""
_current(directory, verbose, head_only)


@db.command()
@click.option('-d', '--directory', default=None,
help=('migration script directory (default is "migrations")'))
@click.option('--sql', is_flag=True,
help=('Don\'t emit SQL to database - dump to standard output '
'instead'))
@click.option('--tag', default=None,
help=('Arbitrary "tag" name - can be used by custom "env.py '
'scripts'))
@click.argument('revision', default='head')
@with_appcontext
def stamp(directory, sql, tag, revision):
"""'stamp' the revision table with the given revision; don't run any
migrations"""
_stamp(directory, revision, sql, tag)
5 changes: 5 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
'alembic>=0.6',
'Flask-Script>=0.6'
],
entry_points={
'flask.commands': [
'db=flask_migrate.cli:db'
],
},
test_suite="tests",
classifiers=[
'Environment :: Web Environment',
Expand Down
1 change: 1 addition & 0 deletions tests/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db)
Expand Down
1 change: 1 addition & 0 deletions tests/app_compare_type1.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db, compare_type=True)
Expand Down
1 change: 1 addition & 0 deletions tests/app_compare_type2.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db, compare_type=True)
Expand Down
1 change: 1 addition & 0 deletions tests/app_custom_directory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db, directory='temp_folder/temp_migrations')
Expand Down
1 change: 1 addition & 0 deletions tests/app_multidb.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app1.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_BINDS'] = {
"db1": "sqlite:///app2.db",
}
Expand Down
3 changes: 0 additions & 3 deletions tests/test_migrate.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,3 @@ def test_compare_type(self):
self.assertTrue(s == 0)
self.assertTrue(b'Detected type change from VARCHAR(length=128) '
b'to String(length=10)' in e)

if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit 8c208b5

Please sign in to comment.