trac#687: Add unit tests for `redirect` and `redirect_obj`.
[larjonas-mediagoblin.git] / mediagoblin / gmg_commands / dbupdate.py
blob31827cd09638b74fcc0c8492fb9447e09c08aaa0
1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
17 import logging
19 import six
20 from sqlalchemy.orm import sessionmaker
22 from mediagoblin.db.open import setup_connection_and_db_from_config
23 from mediagoblin.db.migration_tools import MigrationManager, AlembicMigrationManager
24 from mediagoblin.init import setup_global_and_app_config
25 from mediagoblin.tools.common import import_component
27 _log = logging.getLogger(__name__)
28 logging.basicConfig()
29 ## Let's not set the level as debug by default to avoid confusing users :)
30 # _log.setLevel(logging.DEBUG)
33 def dbupdate_parse_setup(subparser):
34 pass
37 class DatabaseData(object):
38 def __init__(self, name, models, foundations, migrations):
39 self.name = name
40 self.models = models
41 self.foundations = foundations
42 self.migrations = migrations
44 def make_migration_manager(self, session):
45 return MigrationManager(
46 self.name, self.models, self.foundations, self.migrations, session)
49 def gather_database_data(plugins):
50 """
51 Gather all database data relevant to the extensions we have
52 installed so we can do migrations and table initialization.
54 Returns a list of DatabaseData objects.
55 """
56 managed_dbdata = []
58 # Add main first
59 from mediagoblin.db.models import MODELS as MAIN_MODELS
60 from mediagoblin.db.migrations import MIGRATIONS as MAIN_MIGRATIONS
61 from mediagoblin.db.models import FOUNDATIONS as MAIN_FOUNDATIONS
63 managed_dbdata.append(
64 DatabaseData(
65 u'__main__', MAIN_MODELS, MAIN_FOUNDATIONS, MAIN_MIGRATIONS))
67 for plugin in plugins:
68 try:
69 models = import_component('{0}.models:MODELS'.format(plugin))
70 except ImportError as exc:
71 _log.debug('No models found for {0}: {1}'.format(
72 plugin,
73 exc))
75 models = []
76 except AttributeError as exc:
77 _log.warning('Could not find MODELS in {0}.models, have you \
78 forgotten to add it? ({1})'.format(plugin, exc))
79 models = []
81 try:
82 migrations = import_component('{0}.migrations:MIGRATIONS'.format(
83 plugin))
84 except ImportError as exc:
85 _log.debug('No migrations found for {0}: {1}'.format(
86 plugin,
87 exc))
89 migrations = {}
90 except AttributeError as exc:
91 _log.debug('Could not find MIGRATIONS in {0}.migrations, have you \
92 forgotten to add it? ({1})'.format(plugin, exc))
93 migrations = {}
95 try:
96 foundations = import_component('{0}.models:FOUNDATIONS'.format(plugin))
97 except ImportError as exc:
98 foundations = {}
99 except AttributeError as exc:
100 foundations = {}
102 if models:
103 managed_dbdata.append(
104 DatabaseData(plugin, models, foundations, migrations))
107 return managed_dbdata
110 def run_alembic_migrations(db, app_config, global_config):
111 """Initializes a database and runs all Alembic migrations."""
112 Session = sessionmaker(bind=db.engine)
113 manager = AlembicMigrationManager(Session())
114 manager.init_or_migrate()
117 def run_dbupdate(app_config, global_config):
119 Initialize or migrate the database as specified by the config file.
121 Will also initialize or migrate all extensions (media types, and
122 in the future, plugins)
125 # Set up the database
126 db = setup_connection_and_db_from_config(app_config, migrations=True)
127 # Run the migrations
128 run_all_migrations(db, app_config, global_config)
130 # TODO: Make this happen regardless of python 2 or 3 once ensured
131 # to be "safe"!
132 if six.PY3:
133 run_alembic_migrations(db, app_config, global_config)
136 def run_all_migrations(db, app_config, global_config):
138 Initializes or migrates a database that already has a
139 connection setup and also initializes or migrates all
140 extensions based on the config files.
142 It can be used to initialize an in-memory database for
143 testing.
145 # Gather information from all media managers / projects
146 dbdatas = gather_database_data(
147 list(global_config.get('plugins', {}).keys()))
149 Session = sessionmaker(bind=db.engine)
151 # Setup media managers for all dbdata, run init/migrate and print info
152 # For each component, create/migrate tables
153 for dbdata in dbdatas:
154 migration_manager = dbdata.make_migration_manager(Session())
155 migration_manager.init_or_migrate()
158 def dbupdate(args):
159 global_config, app_config = setup_global_and_app_config(args.conf_file)
160 run_dbupdate(app_config, global_config)