[SQL-CVS] r699 - in trunk/SQLObject/sqlobject: . tests
SQLObject is a Python ORM.
Brought to you by:
ianbicking,
phd
From: <sub...@co...> - 2005-04-01 17:45:07
|
Author: ianb Date: 2005-04-01 17:45:03 +0000 (Fri, 01 Apr 2005) New Revision: 699 Added: trunk/SQLObject/sqlobject/threadinglocal.py Modified: trunk/SQLObject/sqlobject/dbconnection.py trunk/SQLObject/sqlobject/tests/dbtest.py Log: Added ConnectionHub, an alternate way to set up connections on a process or thread basis. I'm not sure how to test it yet, except by providing a different implementation of setupClass which uses it (now commented out) Modified: trunk/SQLObject/sqlobject/dbconnection.py =================================================================== --- trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 17:37:04 UTC (rev 698) +++ trunk/SQLObject/sqlobject/dbconnection.py 2005-04-01 17:45:03 UTC (rev 699) @@ -3,6 +3,7 @@ True, False = 1==1, 0==1 import threading +from threadinglocal import local as threading_local import re import warnings import atexit @@ -255,7 +256,8 @@ elif self.autoCommit: if self.debug: self.printDebug(conn, 'auto', 'COMMIT') - conn.commit() + if not getattr(conn, 'autocommit', False): + conn.commit() else: if self.debug: self.printDebug(conn, 'auto', 'ROLLBACK') @@ -727,6 +729,60 @@ return self.rollback() +class ConnectionHub(object): + + """ + This object serves as a hub for connections, so that you can pass + in a ConnectionHub to a SQLObject subclass as though it was a + connection, but actually bind a real database connection later. + You can also bind connections on a per-thread basis. + + You must hang onto the original ConnectionHub instance, as you + cannot retrieve it again from the class or instance. + + To use the hub, do something like:: + + hub = ConnectionHub() + class MyClass(SQLObject): + _connection = hub + + hub.threadConnection = connectionFromURI('...') + + """ + + def __init__(self): + self.threadingLocal = threading_local() + + def __get__(self, obj, type=None): + return self.getConnection() + + def __set__(self, obj, value): + obj.__dict__['_connection'] = value + + def getConnection(self): + try: + return self.threadingLocal.connection + except AttributeError: + try: + return self.processConnection + except AttributeError: + raise AttributeError( + "No connection has been defined for this thread " + "or process") + + def _set_threadConnection(self, value): + self.threadingLocal.connection = value + + def _get_threadConnection(self): + return self.threadingLocal.connection + + def _del_threadConnection(self): + del self.threadingLocal.connection + + threadConnection = property(_get_threadConnection, + _set_threadConnection, + _del_threadConnection) + class ConnectionURIOpener(object): def __init__(self): Modified: trunk/SQLObject/sqlobject/tests/dbtest.py =================================================================== --- trunk/SQLObject/sqlobject/tests/dbtest.py 2005-04-01 17:37:04 UTC (rev 698) +++ trunk/SQLObject/sqlobject/tests/dbtest.py 2005-04-01 17:45:03 UTC (rev 699) @@ -63,10 +63,19 @@ B, then do setupClass([B, A]) and B won't be destroyed or cleared until after A is destroyed or cleared. """ + global hub if not isinstance(soClasses, (list, tuple)): soClasses = [soClasses] connection = getConnection() for soClass in soClasses: + ## This would be an alternate way to register connections... + #try: + # hub + #except NameError: + # hub = sqlobject.dbconnection.ConnectionHub() + #soClass._connection = hub + #hub.threadConnection = connection + #hub.processConnection = connection soClass._connection = connection installOrClear(soClasses) return soClasses Added: trunk/SQLObject/sqlobject/threadinglocal.py =================================================================== --- trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 17:37:04 UTC (rev 698) +++ trunk/SQLObject/sqlobject/threadinglocal.py 2005-04-01 17:45:03 UTC (rev 699) @@ -0,0 +1,35 @@ +try: + import threading +except ImportError: + # No threads, so "thread local" means process-global + class local(object): + pass +else: + try: + local = threading.local + except AttributeError: + # Added in 2.4, but now we'll have to define it ourselves + import thread + class local(object): + + def __init__(self): + self.__dict__['__objs'] = {} + + def __getattr__(self, attr, g=thread.get_ident): + try: + return self.__dict__['__objs'][g()][attr] + except KeyError: + raise AttributeError( + "No variable %s defined for the thread %s" + % (attr, g())) + + def __setattr__(self, attr, value, g=thread.get_ident): + self.__dict__['__objs'].setdefault(g(), {})[attr] = value + + def __delattr__(self, attr, g=thread.get_ident): + try: + del self.__dict__['__objs'][g()][attr] + except KeyError: + raise AttributeError( + "No variable %s defined for thread %s" + % (attr, g())) |