[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()))
|