3030import traceback
3131import types
3232import warnings
33- from weakref import ref , WeakKeyDictionary
33+ import weakref
34+ from weakref import WeakKeyDictionary , WeakMethod
3435
3536import numpy as np
3637
@@ -145,111 +146,6 @@ def __call__(self, s):
145146 return int (s )
146147
147148
148- class _BoundMethodProxy (object ):
149- """
150- Our own proxy object which enables weak references to bound and unbound
151- methods and arbitrary callables. Pulls information about the function,
152- class, and instance out of a bound method. Stores a weak reference to the
153- instance to support garbage collection.
154-
155- @organization: IBM Corporation
156- @copyright: Copyright (c) 2005, 2006 IBM Corporation
157- @license: The BSD License
158-
159- Minor bugfixes by Michael Droettboom
160- """
161- def __init__ (self , cb ):
162- self ._hash = hash (cb )
163- self ._destroy_callbacks = []
164- try :
165- try :
166- if six .PY3 :
167- self .inst = ref (cb .__self__ , self ._destroy )
168- else :
169- self .inst = ref (cb .im_self , self ._destroy )
170- except TypeError :
171- self .inst = None
172- if six .PY3 :
173- self .func = cb .__func__
174- self .klass = cb .__self__ .__class__
175- else :
176- self .func = cb .im_func
177- self .klass = cb .im_class
178- except AttributeError :
179- self .inst = None
180- self .func = cb
181- self .klass = None
182-
183- def add_destroy_callback (self , callback ):
184- self ._destroy_callbacks .append (_BoundMethodProxy (callback ))
185-
186- def _destroy (self , wk ):
187- for callback in self ._destroy_callbacks :
188- try :
189- callback (self )
190- except ReferenceError :
191- pass
192-
193- def __getstate__ (self ):
194- d = self .__dict__ .copy ()
195- # de-weak reference inst
196- inst = d ['inst' ]
197- if inst is not None :
198- d ['inst' ] = inst ()
199- return d
200-
201- def __setstate__ (self , statedict ):
202- self .__dict__ = statedict
203- inst = statedict ['inst' ]
204- # turn inst back into a weakref
205- if inst is not None :
206- self .inst = ref (inst )
207-
208- def __call__ (self , * args , ** kwargs ):
209- """
210- Proxy for a call to the weak referenced object. Take
211- arbitrary params to pass to the callable.
212-
213- Raises `ReferenceError`: When the weak reference refers to
214- a dead object
215- """
216- if self .inst is not None and self .inst () is None :
217- raise ReferenceError
218- elif self .inst is not None :
219- # build a new instance method with a strong reference to the
220- # instance
221-
222- mtd = types .MethodType (self .func , self .inst ())
223-
224- else :
225- # not a bound method, just return the func
226- mtd = self .func
227- # invoke the callable and return the result
228- return mtd (* args , ** kwargs )
229-
230- def __eq__ (self , other ):
231- """
232- Compare the held function and instance with that held by
233- another proxy.
234- """
235- try :
236- if self .inst is None :
237- return self .func == other .func and other .inst is None
238- else :
239- return self .func == other .func and self .inst () == other .inst ()
240- except Exception :
241- return False
242-
243- def __ne__ (self , other ):
244- """
245- Inverse of __eq__.
246- """
247- return not self .__eq__ (other )
248-
249- def __hash__ (self ):
250- return self ._hash
251-
252-
253149def _exception_printer (exc ):
254150 traceback .print_exc ()
255151
@@ -334,13 +230,11 @@ def connect(self, s, func):
334230 """Register *func* to be called when signal *s* is generated.
335231 """
336232 self ._func_cid_map .setdefault (s , WeakKeyDictionary ())
337- # Note proxy not needed in python 3.
338- # TODO rewrite this when support for python2.x gets dropped.
339- proxy = _BoundMethodProxy (func )
233+ proxy = WeakMethod (func )
340234 if proxy in self ._func_cid_map [s ]:
341235 return self ._func_cid_map [s ][proxy ]
342236
343- proxy . add_destroy_callback ( self ._remove_proxy )
237+ weakref . finalize ( proxy , self ._remove_proxy )
344238 self ._cid += 1
345239 cid = self ._cid
346240 self ._func_cid_map [s ][proxy ] = cid
@@ -382,12 +276,13 @@ def process(self, s, *args, **kwargs):
382276 All of the functions registered to receive callbacks on *s* will be
383277 called with ``*args`` and ``**kwargs``.
384278 """
385- if s in self .callbacks :
386- for cid , proxy in list (six .iteritems (self .callbacks [s ])):
279+ for ref in list (self .callbacks .get (s , {}).values ()):
280+ func = ref ()
281+ if func is None :
282+ self ._remove_proxy (ref )
283+ else :
387284 try :
388- proxy (* args , ** kwargs )
389- except ReferenceError :
390- self ._remove_proxy (proxy )
285+ func (* args , ** kwargs )
391286 # this does not capture KeyboardInterrupt, SystemExit,
392287 # and GeneratorExit
393288 except Exception as exc :
@@ -1483,10 +1378,10 @@ class Grouper(object):
14831378 def __init__ (self , init = ()):
14841379 mapping = self ._mapping = {}
14851380 for x in init :
1486- mapping [ref (x )] = [ref (x )]
1381+ mapping [weakref . ref (x )] = [weakref . ref (x )]
14871382
14881383 def __contains__ (self , item ):
1489- return ref (item ) in self ._mapping
1384+ return weakref . ref (item ) in self ._mapping
14901385
14911386 def clean (self ):
14921387 """
@@ -1504,13 +1399,13 @@ def join(self, a, *args):
15041399 arguments.
15051400 """
15061401 mapping = self ._mapping
1507- set_a = mapping .setdefault (ref (a ), [ref (a )])
1402+ set_a = mapping .setdefault (weakref . ref (a ), [weakref . ref (a )])
15081403
15091404 for arg in args :
1510- set_b = mapping .get (ref (arg ))
1405+ set_b = mapping .get (weakref . ref (arg ))
15111406 if set_b is None :
1512- set_a .append (ref (arg ))
1513- mapping [ref (arg )] = set_a
1407+ set_a .append (weakref . ref (arg ))
1408+ mapping [weakref . ref (arg )] = set_a
15141409 elif set_b is not set_a :
15151410 if len (set_b ) > len (set_a ):
15161411 set_a , set_b = set_b , set_a
@@ -1528,17 +1423,17 @@ def joined(self, a, b):
15281423
15291424 mapping = self ._mapping
15301425 try :
1531- return mapping [ref (a )] is mapping [ref (b )]
1426+ return mapping [weakref . ref (a )] is mapping [weakref . ref (b )]
15321427 except KeyError :
15331428 return False
15341429
15351430 def remove (self , a ):
15361431 self .clean ()
15371432
15381433 mapping = self ._mapping
1539- seta = mapping .pop (ref (a ), None )
1434+ seta = mapping .pop (weakref . ref (a ), None )
15401435 if seta is not None :
1541- seta .remove (ref (a ))
1436+ seta .remove (weakref . ref (a ))
15421437
15431438 def __iter__ (self ):
15441439 """
@@ -1567,7 +1462,7 @@ def get_siblings(self, a):
15671462 """
15681463 self .clean ()
15691464
1570- siblings = self ._mapping .get (ref (a ), [ref (a )])
1465+ siblings = self ._mapping .get (weakref . ref (a ), [weakref . ref (a )])
15711466 return [x () for x in siblings ]
15721467
15731468
0 commit comments