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/>.
18 from contextlib
import contextmanager
22 from sqlalchemy
import create_engine
, event
24 from mediagoblin
import mg_globals
25 from mediagoblin
.db
.base
import Base
27 _log
= logging
.getLogger(__name__
)
29 from mediagoblin
.tools
.transition
import DISABLE_GLOBALS
31 def set_models_as_attributes(obj
):
33 Set all models as attributes on this object, for convenience
35 TODO: This should eventually be deprecated.
37 for k
, v
in six
.iteritems(Base
._decl
_class
_registry
):
41 if not DISABLE_GLOBALS
:
42 from mediagoblin
.db
.base
import Session
44 class DatabaseMaster(object):
45 def __init__(self
, engine
):
48 set_models_as_attributes(self
)
57 def check_session_clean(self
):
58 for dummy
in Session():
59 _log
.warn("STRANGE: There are elements in the sql session. "
60 "Please report this and help us track this down.")
63 def reset_after_request(self
):
72 from sqlalchemy
.orm
import sessionmaker
74 class DatabaseManager(object):
76 Manage database connections.
78 The main method here is session_scope which can be used with a
79 "with" statement to get a session that is properly torn down
80 by the end of execution.
82 def __init__(self
, engine
):
84 self
.Session
= sessionmaker(bind
=engine
)
85 set_models_as_attributes(self
)
88 def session_scope(self
):
90 This is a context manager, use like::
92 with dbmanager.session_scope() as request.db:
95 session
= self
.Session()
97 #####################################
98 # Functions to emulate DatabaseMaster
99 #####################################
104 def check_session_clean():
105 # Is this implemented right?
106 for dummy
in session
:
107 _log
.warn("STRANGE: There are elements in the sql session. "
108 "Please report this and help us track this down.")
111 def reset_after_request():
117 session
.check_session_clean
= check_session_clean
118 session
.reset_after_request
= reset_after_request
120 set_models_as_attributes(session
)
121 #####################################
131 def load_models(app_config
):
132 import mediagoblin
.db
.models
134 for plugin
in mg_globals
.global_config
.get('plugins', {}).keys():
135 _log
.debug("Loading %s.models", plugin
)
137 __import__(plugin
+ ".models")
138 except ImportError as exc
:
139 _log
.debug("Could not load {0}.models: {1}".format(
144 def _sqlite_fk_pragma_on_connect(dbapi_con
, con_record
):
145 """Enable foreign key checking on each new sqlite connection"""
146 dbapi_con
.execute('pragma foreign_keys=on')
149 def _sqlite_disable_fk_pragma_on_connect(dbapi_con
, con_record
):
151 Disable foreign key checking on each new sqlite connection
152 (Good for migrations!)
154 dbapi_con
.execute('pragma foreign_keys=off')
157 def setup_connection_and_db_from_config(app_config
, migrations
=False, app
=None):
158 engine
= create_engine(app_config
['sql_engine'])
160 # @@: Maybe make a weak-ref so an engine can get garbage
161 # collected? Not that we expect to make a lot of MediaGoblinApp
162 # instances in a single process...
165 # Enable foreign key checking for sqlite
166 if app_config
['sql_engine'].startswith('sqlite://'):
168 event
.listen(engine
, 'connect',
169 _sqlite_disable_fk_pragma_on_connect
)
171 event
.listen(engine
, 'connect', _sqlite_fk_pragma_on_connect
)
173 # logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
176 return DatabaseManager(engine
)
179 Session
.configure(bind
=engine
)
181 return DatabaseMaster(engine
)
184 def check_db_migrations_current(db
):