3939 prepare the session, e.g. ["set datestyle to german", ...]
4040 closeable: if this is set to true, then closing connections will
4141 be allowed, but by default this will be silently ignored
42+ threadlocal: an optional class for representing thread-local data
43+ that will be used instead of our Python implementation
44+ (threading.local is faster, but cannot be used in all cases)
4245
4346 Additionally, you have to pass the parameters for the actual
4447 PostgreSQL connection which are passed via PyGreSQL,
6568the connection will be automatically closed when the thread dies.
6669You can change this behavior be setting the closeable parameter.
6770
71+ Note that by setting the threadlocal parameter to threading.local,
72+ getting connections may become a bit faster, but this may not work in
73+ all environments (for instance, mod_wsgi is known to cause problems
74+ since it clears the threading.local data between requests).
75+
6876
6977Requirements:
7078
71- Minimum requirement: Python 2.2 and PyGreSQL 3.4.
72- Recommended: Python 2.4.3 and PyGreSQL 3.8.
79+ Python >= 2.2, < 3.0, PyGreSQL >= 3.4.
7380
7481
7582Ideas for improvement:
95102__date__ = "$Date$"
96103
97104
105+ import ThreadingLocal
98106from DBUtils .SteadyPg import SteadyPgConnection
99107
100108
@@ -108,8 +116,8 @@ class PersistentPg:
108116
109117 version = __version__
110118
111- def __init__ (self , maxusage = None , setsession = None , closeable = False ,
112- * args , ** kwargs ):
119+ def __init__ (self , maxusage = None , setsession = None ,
120+ closeable = False , threadlocal = None , * args , ** kwargs ):
113121 """Set up the persistent PostgreSQL connection generator.
114122
115123 maxusage: maximum number of reuses of a single connection
@@ -120,6 +128,9 @@ def __init__(self, maxusage=None, setsession=None, closeable=False,
120128 the session, e.g. ["set datestyle to ...", "set time zone ..."]
121129 closeable: if this is set to true, then closing connections will
122130 be allowed, but by default this will be silently ignored
131+ threadlocal: an optional class for representing thread-local data
132+ that will be used instead of our Python implementation
133+ (threading.local is faster, but cannot be used in all cases)
123134 args, kwargs: the parameters that shall be used to establish
124135 the PostgreSQL connections using class PyGreSQL pg.DB()
125136
@@ -128,7 +139,7 @@ def __init__(self, maxusage=None, setsession=None, closeable=False,
128139 self ._setsession = setsession
129140 self ._closeable = closeable
130141 self ._args , self ._kwargs = args , kwargs
131- self .thread = local ()
142+ self .thread = ( threadlocal or ThreadingLocal . local ) ()
132143
133144 def steady_connection (self ):
134145 """Get a steady, non-persistent PyGreSQL connection."""
@@ -144,81 +155,3 @@ def connection(self):
144155 con = self .steady_connection ()
145156 self .thread .connection = con
146157 return con
147-
148-
149- try : # import a class for representing thread-local objects
150- from threading import local
151- except ImportError : # for Python < 2.4, use the following simple implementation
152- from threading import currentThread , enumerate , RLock
153- class _localbase (object ):
154- __slots__ = '_local__key' , '_local__args' , '_local__lock'
155- def __new__ (cls , * args , ** kwargs ):
156- self = object .__new__ (cls )
157- key = '_local__key' , 'thread.local.' + str (id (self ))
158- object .__setattr__ (self , '_local__key' , key )
159- object .__setattr__ (self , '_local__args' , (args , kwargs ))
160- object .__setattr__ (self , '_local__lock' , RLock ())
161- if args or kwargs and (cls .__init__ is object .__init__ ):
162- raise TypeError ("Initialization arguments are not supported" )
163- d = object .__getattribute__ (self , '__dict__' )
164- currentThread ().__dict__ [key ] = d
165- return self
166- def _patch (self ):
167- key = object .__getattribute__ (self , '_local__key' )
168- d = currentThread ().__dict__ .get (key )
169- if d is None :
170- d = {}
171- currentThread ().__dict__ [key ] = d
172- object .__setattr__ (self , '__dict__' , d )
173- cls = type (self )
174- if cls .__init__ is not object .__init__ :
175- args , kwargs = object .__getattribute__ (self , '_local__args' )
176- cls .__init__ (self , * args , ** kwargs )
177- else :
178- object .__setattr__ (self , '__dict__' , d )
179- class local (_localbase ):
180- def __getattribute__ (self , name ):
181- lock = object .__getattribute__ (self , '_local__lock' )
182- lock .acquire ()
183- try :
184- _patch (self )
185- return object .__getattribute__ (self , name )
186- finally :
187- lock .release ()
188- def __setattr__ (self , name , value ):
189- lock = object .__getattribute__ (self , '_local__lock' )
190- lock .acquire ()
191- try :
192- _patch (self )
193- return object .__setattr__ (self , name , value )
194- finally :
195- lock .release ()
196- def __delattr__ (self , name ):
197- lock = object .__getattribute__ (self , '_local__lock' )
198- lock .acquire ()
199- try :
200- _patch (self )
201- return object .__delattr__ (self , name )
202- finally :
203- lock .release ()
204- def __del__ ():
205- threading_enumerate = enumerate
206- __getattribute__ = object .__getattribute__
207- def __del__ (self ):
208- try :
209- key = __getattribute__ (self , '_local__key' )
210- threads = list (threading_enumerate ())
211- except Exception :
212- return
213- for thread in threads :
214- try :
215- __dict__ = thread .__dict__
216- except AttributeError :
217- continue
218- if key in __dict__ :
219- try :
220- del __dict__ [key ]
221- except KeyError :
222- pass
223- return __del__
224- __del__ = __del__ ()
0 commit comments