diff --git a/pydispatch/dispatcher.py b/pydispatch/dispatcher.py index 923cbb4..27a9bd5 100644 --- a/pydispatch/dispatcher.py +++ b/pydispatch/dispatcher.py @@ -264,7 +264,7 @@ def liveReceivers(receivers): -def getAllReceivers( sender = Any, signal = Any ): +def getAllReceivers( sender = Any, signal = Any, copySlots = True ): """Get list of all receivers from global tables This gets all receivers which should receive @@ -282,6 +282,8 @@ def getAllReceivers( sender = Any, signal = Any ): # Add receivers that receive *any* signal from *any* sender. getReceivers( Any, Any ), ): + if copySlots: + set = list(set) for receiver in set: if receiver: # filter out dead instance-method weakrefs try: @@ -326,10 +328,12 @@ def send(signal=Any, sender=Anonymous, *arguments, **named): possible to not have all receivers called if a raises an error. """ + copy_slots = named.pop("copySlots", True) + # Call each receiver with whatever arguments it can accept. # Return a list of tuple pairs [(receiver, response), ... ]. responses = [] - for receiver in liveReceivers(getAllReceivers(sender, signal)): + for receiver in liveReceivers(getAllReceivers(sender, signal, copy_slots)): response = robustapply.robustApply( receiver, signal=signal, diff --git a/tests/test_dispatcher.py b/tests/test_dispatcher.py index 8119f4f..f974f48 100644 --- a/tests/test_dispatcher.py +++ b/tests/test_dispatcher.py @@ -13,6 +13,11 @@ def __call__( self, a ): def a( self, a ): return a +class Callable2(object): + def a(self, val): + disconnect(self.a, "test") + return val + class DispatcherTests(unittest.TestCase): """Test suite for dispatcher (barely started)""" @@ -139,7 +144,23 @@ def testDisconnectUnconnected(self): errors.DispatcherKeyError, dispatcher.disconnect, x, signal='not-registered' ) - + def testDisconnectDuringCall(self): + val0 = Callable2() + connect(val0.a, "test") + val1 = Callable2() + connect(val1.a, "test") + + # Then we should have two connections. + assert len(list(getAllReceivers(signal = "test"))) == 2 + + # When sending the signal + result = send("test", val = 10) + + # Then we should get two results + assert result == [(val0.a, 10), (val1.a, 10)] + # And both connections should be removed + assert len(list(getAllReceivers(signal = "test"))) == 0 + def getSuite(): return unittest.makeSuite(DispatcherTests,'test')