1. Guido Draheim
  2. trac-dvbcronrecording-plugin

Commits

Guido Draheim  committed 27bae16

invent TracAlchemyBridge 2.0.0

  • Participants
  • Parent commits 3d4f577
  • Branches default

Comments (0)

Files changed (3)

File .settings/org.eclipse.core.resources.prefs

View file
  • Ignore whitespace
-#Sun Jul 10 11:46:17 CEST 2011
+#Fri Sep 02 12:38:21 CEST 2011
 eclipse.preferences.version=1
 encoding//src/dvbcronrecording/channels.py=utf-8
 encoding//src/dvbcronrecording/channelsconf.py=utf-8
 encoding//src/dvbcronrecording/core.py=utf-8
 encoding//src/dvbcronrecording/db/tsab.py=utf-8
+encoding//src/dvbcronrecording/db/tsab2.py=utf-8
 encoding//src/dvbcronrecording/init.py=utf-8
 encoding//src/dvbcronrecording/tuning.py=utf-8
 encoding//src/setup.py=utf8

File src/dvbcronrecording/db/session.py

View file
  • Ignore whitespace
-from tsab import engine, session
+from tsab2 import engine, session
 from sqlalchemy.orm import create_session
 
 _session = None
 def context(env):
     global _session
     if _session is None:
-        _session = session(env) # create_session(bind=engine(env))
+        # _session = session(env) 
+        _session = create_session(bind=engine(env), autocommit=True, autoflush=True)
     return _session
 
 def db_cnx(env): return context(env)

File src/dvbcronrecording/db/tsab2.py

View file
  • Ignore whitespace
+# -*- coding: utf-8 -*-
+"""
+    Trac SQLAlchemy Bridge
+    ======================
+
+    tracext.sa
+    ~~~~~~~~~~
+
+    This module enables a plugin developer to use SQLAlchemy for database work.
+
+    For some usage example there's nothing better than `source code`__.
+
+    :copyright: 2008 by Armin Ronacher, Pedro Algarvio.
+    :license: WTFPL.
+
+
+    .. __: http://tl10nm.ufsoft.org/browser
+
+"""
+#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+#                    Version 2, December 2004
+#
+# Copyright (C) 2008 Armin Ronacher, Pedro Algarvio.
+#  14 rue de Plaisance, 75014 Paris, France
+# Everyone is permitted to copy and distribute verbatim or modified
+# copies of this license document, and changing it is allowed as long
+# as the name is changed.
+#
+#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+#   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+#
+#  0. You just DO WHAT THE FUCK YOU WANT TO.
+#
+# http://en.wikipedia.org/wiki/WTFPL
+#
+# Authors:
+#    Armin Ronacher <armin.ronacher@active-4.com>
+#    Pedro Algarvio <ufs@ufsoft.org>
+#    Guido Draheim <guidod@gmx.de>
+
+#__version__     = '0.2.0'
+#__author__      = 'Armin Ronacher, Pedro Algarvio, Guido Draheim'
+#__email__       = 'armin.ronacher@active-4.com, ufs@ufsoft.org, guidod@gmx.de'
+#__package__     = 'TracSQLAlchemyBridge'
+#__license__     = 'WTFPL'
+#__url__         = 'http://trac-hacks.org/wiki/TracSqlAlchemyBridgeIntegration'
+#__summary__     = 'Bridge for a plugin developer to use SQLAlchemy with trac'
+#__description__ = __doc__
+
+from weakref import WeakKeyDictionary
+from threading import local #@UnusedImport
+from sqlalchemy.engine import create_engine
+from sqlalchemy.orm import create_session, scoped_session #@UnusedImport
+from sqlalchemy.pool import NullPool
+from sqlalchemy.engine.url import URL
+from trac.db.api import DatabaseManager
+from trac.db.util import ConnectionWrapper
+
+
+class TracPool(NullPool):
+    def __init__(self, creator, pool_size=5, **kw):
+        NullPool.__init__(self, pool_size, **kw)
+        self.env = None
+        self.connection = None
+        self._creator = self._do_creator # override!!
+    def use(self, env):
+        self.env = env
+        self.logger = env.log
+        return self
+    def status(self):
+        return "TracPool"
+    def _do_creator(self):
+        if self.connection is None:
+            self.connection = self.env.get_db_cnx()
+        cnx = self.connection.cnx
+        while isinstance(cnx, ConnectionWrapper):
+            cnx = cnx.cnx
+        return cnx
+    def _do_return_conn(self, conn):
+        if self.connection:
+            # Don't let SQLAlchemy close the connection, trac handles that
+            ###  self.connection.close()
+            # just allow the garbage collector to see that it is unused
+            self.connection = None
+
+_engines = WeakKeyDictionary()
+
+def engine(env):
+    engine = _engines.get(env)
+    if engine is None:
+        schema = DatabaseManager(env).connection_uri.split(':')[0]
+        echo = env.config.get('logging', 'log_level').lower() == 'debug'
+        
+        class TracEnvPool(TracPool):
+            def __init__(self, creator, pool_size=5, **kw):
+                TracPool.__init__(self, creator, pool_size, **kw)
+                self.use(env)
+
+        engine = create_engine(URL(schema), poolclass=TracEnvPool,
+                               creator=None, echo=echo)
+        if echo:
+            # make sqlalchemy log to trac's logger
+            if hasattr(env, 'get_logger'):
+                engine.logger = env.get_logger(__name__)
+            else:
+                engine.logger = env.log
+        _engines[env] = engine
+    try:
+        return engine.begin()
+    except AttributeError:
+        # Older SQLAlchemy
+        return engine
+
+
+def session(env):
+    try:
+        db_session = create_session(engine(env), autocommit=True)
+        db_session.begin()
+    except TypeError:
+        # Older SqlAlchemy
+        db_session = create_session(engine(env), transactional=True)
+        db_session.add = db_session.save
+    # Keep session opened for as long as possible by keeping it attached to
+    # env; avoids it to be garbage collected since trac explicitly calls gc
+    # to avoid memory leaks
+    env.db_session = db_session
+    return db_session
+
+__all__ = ['engine', 'session']