@@ -361,9 +361,14 @@ class _BoundMethodProxy(object):
361
361
Minor bugfixes by Michael Droettboom
362
362
'''
363
363
def __init__ (self , cb ):
364
+ self ._hash = hash (cb )
365
+ self ._destroy_callbacks = []
364
366
try :
365
367
try :
366
- self .inst = ref (cb .im_self )
368
+ if six .PY3 :
369
+ self .inst = ref (cb .__self__ , self ._destroy )
370
+ else :
371
+ self .inst = ref (cb .im_self , self ._destroy )
367
372
except TypeError :
368
373
self .inst = None
369
374
if six .PY3 :
@@ -377,6 +382,16 @@ def __init__(self, cb):
377
382
self .func = cb
378
383
self .klass = None
379
384
385
+ def add_destroy_callback (self , callback ):
386
+ self ._destroy_callbacks .append (_BoundMethodProxy (callback ))
387
+
388
+ def _destroy (self , wk ):
389
+ for callback in self ._destroy_callbacks :
390
+ try :
391
+ callback (self )
392
+ except ReferenceError :
393
+ pass
394
+
380
395
def __getstate__ (self ):
381
396
d = self .__dict__ .copy ()
382
397
# de-weak reference inst
@@ -433,6 +448,9 @@ def __ne__(self, other):
433
448
'''
434
449
return not self .__eq__ (other )
435
450
451
+ def __hash__ (self ):
452
+ return self ._hash
453
+
436
454
437
455
class CallbackRegistry (object ):
438
456
"""
@@ -492,17 +510,32 @@ def connect(self, s, func):
492
510
func will be called
493
511
"""
494
512
self ._func_cid_map .setdefault (s , WeakKeyDictionary ())
495
- if func in self ._func_cid_map [s ]:
496
- return self ._func_cid_map [s ][func ]
513
+ # Note proxy not needed in python 3.
514
+ # TODO rewrite this when support for python2.x gets dropped.
515
+ proxy = _BoundMethodProxy (func )
516
+ if proxy in self ._func_cid_map [s ]:
517
+ return self ._func_cid_map [s ][proxy ]
497
518
519
+ proxy .add_destroy_callback (self ._remove_proxy )
498
520
self ._cid += 1
499
521
cid = self ._cid
500
- self ._func_cid_map [s ][func ] = cid
522
+ self ._func_cid_map [s ][proxy ] = cid
501
523
self .callbacks .setdefault (s , dict ())
502
- proxy = _BoundMethodProxy (func )
503
524
self .callbacks [s ][cid ] = proxy
504
525
return cid
505
526
527
+ def _remove_proxy (self , proxy ):
528
+ for signal , proxies in list (six .iteritems (self ._func_cid_map )):
529
+ try :
530
+ del self .callbacks [signal ][proxies [proxy ]]
531
+ except KeyError :
532
+ pass
533
+
534
+ if len (self .callbacks [signal ]) == 0 :
535
+ del self .callbacks [signal ]
536
+ del self ._func_cid_map [signal ]
537
+
538
+
506
539
def disconnect (self , cid ):
507
540
"""
508
541
disconnect the callback registered with callback id *cid*
@@ -513,7 +546,7 @@ def disconnect(self, cid):
513
546
except KeyError :
514
547
continue
515
548
else :
516
- for category , functions in list (
549
+ for signal , functions in list (
517
550
six .iteritems (self ._func_cid_map )):
518
551
for function , value in list (six .iteritems (functions )):
519
552
if value == cid :
@@ -527,11 +560,10 @@ def process(self, s, *args, **kwargs):
527
560
"""
528
561
if s in self .callbacks :
529
562
for cid , proxy in list (six .iteritems (self .callbacks [s ])):
530
- # Clean out dead references
531
- if proxy .inst is not None and proxy .inst () is None :
532
- del self .callbacks [s ][cid ]
533
- else :
563
+ try :
534
564
proxy (* args , ** kwargs )
565
+ except ReferenceError :
566
+ self ._remove_proxy (proxy )
535
567
536
568
537
569
class Scheduler (threading .Thread ):
0 commit comments