30
30
import traceback
31
31
import types
32
32
import warnings
33
- from weakref import ref , WeakKeyDictionary
33
+ import weakref
34
+ from weakref import WeakKeyDictionary , WeakMethod
34
35
35
36
import numpy as np
36
37
@@ -145,111 +146,6 @@ def __call__(self, s):
145
146
return int (s )
146
147
147
148
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
-
253
149
def _exception_printer (exc ):
254
150
traceback .print_exc ()
255
151
@@ -334,13 +230,11 @@ def connect(self, s, func):
334
230
"""Register *func* to be called when signal *s* is generated.
335
231
"""
336
232
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 )
340
234
if proxy in self ._func_cid_map [s ]:
341
235
return self ._func_cid_map [s ][proxy ]
342
236
343
- proxy . add_destroy_callback ( self ._remove_proxy )
237
+ weakref . finalize ( proxy , self ._remove_proxy )
344
238
self ._cid += 1
345
239
cid = self ._cid
346
240
self ._func_cid_map [s ][proxy ] = cid
@@ -382,12 +276,13 @@ def process(self, s, *args, **kwargs):
382
276
All of the functions registered to receive callbacks on *s* will be
383
277
called with ``*args`` and ``**kwargs``.
384
278
"""
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 :
387
284
try :
388
- proxy (* args , ** kwargs )
389
- except ReferenceError :
390
- self ._remove_proxy (proxy )
285
+ func (* args , ** kwargs )
391
286
# this does not capture KeyboardInterrupt, SystemExit,
392
287
# and GeneratorExit
393
288
except Exception as exc :
@@ -1483,10 +1378,10 @@ class Grouper(object):
1483
1378
def __init__ (self , init = ()):
1484
1379
mapping = self ._mapping = {}
1485
1380
for x in init :
1486
- mapping [ref (x )] = [ref (x )]
1381
+ mapping [weakref . ref (x )] = [weakref . ref (x )]
1487
1382
1488
1383
def __contains__ (self , item ):
1489
- return ref (item ) in self ._mapping
1384
+ return weakref . ref (item ) in self ._mapping
1490
1385
1491
1386
def clean (self ):
1492
1387
"""
@@ -1504,13 +1399,13 @@ def join(self, a, *args):
1504
1399
arguments.
1505
1400
"""
1506
1401
mapping = self ._mapping
1507
- set_a = mapping .setdefault (ref (a ), [ref (a )])
1402
+ set_a = mapping .setdefault (weakref . ref (a ), [weakref . ref (a )])
1508
1403
1509
1404
for arg in args :
1510
- set_b = mapping .get (ref (arg ))
1405
+ set_b = mapping .get (weakref . ref (arg ))
1511
1406
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
1514
1409
elif set_b is not set_a :
1515
1410
if len (set_b ) > len (set_a ):
1516
1411
set_a , set_b = set_b , set_a
@@ -1528,17 +1423,17 @@ def joined(self, a, b):
1528
1423
1529
1424
mapping = self ._mapping
1530
1425
try :
1531
- return mapping [ref (a )] is mapping [ref (b )]
1426
+ return mapping [weakref . ref (a )] is mapping [weakref . ref (b )]
1532
1427
except KeyError :
1533
1428
return False
1534
1429
1535
1430
def remove (self , a ):
1536
1431
self .clean ()
1537
1432
1538
1433
mapping = self ._mapping
1539
- seta = mapping .pop (ref (a ), None )
1434
+ seta = mapping .pop (weakref . ref (a ), None )
1540
1435
if seta is not None :
1541
- seta .remove (ref (a ))
1436
+ seta .remove (weakref . ref (a ))
1542
1437
1543
1438
def __iter__ (self ):
1544
1439
"""
@@ -1567,7 +1462,7 @@ def get_siblings(self, a):
1567
1462
"""
1568
1463
self .clean ()
1569
1464
1570
- siblings = self ._mapping .get (ref (a ), [ref (a )])
1465
+ siblings = self ._mapping .get (weakref . ref (a ), [weakref . ref (a )])
1571
1466
return [x () for x in siblings ]
1572
1467
1573
1468
0 commit comments