diff --git a/gluon/console.py b/gluon/console.py index 57604362..e3d519a2 100644 --- a/gluon/console.py +++ b/gluon/console.py @@ -259,6 +259,12 @@ web2py will attempt to run a GUI to ask for it when starting the web server '(default is %(default)s), see -S above. NOTE: when the APP_ENV ' 'argument of -S include a controller c automatic import of ' 'models is always enabled') + g.add_argument('--force_migrate', + default=False, + action='store_true', + help= + 'force DAL to migrate all tables that should be migrated when enabled; ' + 'monkeypatch in the DAL class to force _migrate_enabled=True') g.add_argument('-R', '--run', type=existing_file, metavar='PYTHON_FILE', help= diff --git a/gluon/shell.py b/gluon/shell.py index bb2c0d2c..a7a38148 100644 --- a/gluon/shell.py +++ b/gluon/shell.py @@ -216,7 +216,8 @@ def run( bpython=False, python_code=None, cron_job=False, - scheduler_job=False): + scheduler_job=False, + force_migrate=False): """ Start interactive shell or run Python script (startfile) in web2py controller environment. appname is formatted like: @@ -246,6 +247,19 @@ def run( os.mkdir(adir) fileutils.create_app(adir) + if force_migrate: + import_models = True + from gluon.dal import DAL + orig_init = DAL.__init__ + + def custom_init(*args, **kwargs): + kwargs['migrate_enabled'] = True + kwargs['migrate'] = True + logger.info('Forcing migrate_enabled=True') + orig_init(*args, **kwargs) + + DAL.__init__ = custom_init + if c: import_models = True extra_request = {} @@ -298,6 +312,15 @@ def run( print(traceback.format_exc()) if import_models: BaseAdapter.close_all_instances('rollback') + elif force_migrate: + try: + execfile("scripts/migrator.py", _env) + if import_models: + BaseAdapter.close_all_instances('commit') + except: + print(traceback.format_exc()) + if import_models: + BaseAdapter.close_all_instances('rollback') else: if not plain: if bpython: diff --git a/gluon/widget.py b/gluon/widget.py index c5944420..a3922b14 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -741,7 +741,7 @@ def start(): sys.argv = [options.run or ''] + options.args run(options.shell, plain=options.plain, bpython=options.bpython, import_models=options.import_models, startfile=options.run, - cron_job=options.cron_job) + cron_job=options.cron_job, force_migrate=options.force_migrate) return if options.cron_run: diff --git a/scripts/migrator.py b/scripts/migrator.py new file mode 100644 index 00000000..d94c5fa6 --- /dev/null +++ b/scripts/migrator.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +''' +To use, e.g. python .\web2py.py -S APPNAME --force_migrate +''' + +import logging + +logger = logging.getLogger("web2py") + + +def get_databases(request): + dbs = {} + global_env = globals() + for (key, value) in global_env.items(): + try: + cond = isinstance(value, GQLDB) + except: + cond = isinstance(value, SQLDB) + if cond: + dbs[key] = value + return dbs + + +logger.debug('Getting all databases') +databases = get_databases(None) +logger.debug('databases = %s', databases) +for db_name in databases: + logger.debug('Migrating %s', db_name) + db = databases[db_name] + tables = db.tables + for table_name in tables: + # Force migration of lazy tables + logger.debug("Ensuring migration of table '%s'", table_name) + db(db[table_name]).isempty() + db.commit()