def test_handler_garbage_collection_3(self): test = NotifyTestObject() signal = Signal(AbstractSignal.ANY_ACCEPTS) handler = HandlerGarbageCollectionTestCase.HandlerObject(test) def accepting_handler(*arguments): test.simple_handler_100(*arguments) return arguments[0] signal.connect(accepting_handler) signal.connect(handler.simple_handler) self.assertEqual(len(signal._handlers), 2) signal.emit(1) del handler self.collect_garbage() self.assertEqual(len(signal._handlers), 2) signal.emit(2) # This time emission is stopped by accumulator, but still the gc-collected handler # must be removed. self.assertEqual(len(signal._handlers), 1) test.assert_results(101, 102)
def test_argument_passing (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit (45, 'abc') test.assert_results ((45, 'abc'))
def initialize (self): signal = Signal () signal.connect (_ignoring_handler) signal.connect (_ignoring_handler, 1) signal.connect (_ignoring_handler, 'a', 'b') signal.connect (_ignoring_handler, None, True, False) self.__signal = signal
def test_emission_stop_3 (self): def stop_emission (): was_stopped = signal.emission_stopped signal.stop_emission () return was_stopped, signal.emission_stopped signal = Signal (Signal.VALUE_LIST) signal.connect (stop_emission) self.assertEqual (signal.emit (), [(False, True)])
def test_value_list_accumulator (self): signal = Signal (AbstractSignal.VALUE_LIST) self.assertEqual (signal.emit (), []) signal.connect (lambda: 50) self.assertEqual (signal.emit (), [50]) signal.connect (lambda: None) signal.connect (lambda: ()) self.assertEqual (signal.emit (), [50, None, ()])
def test_emission_stop_3(self): def stop_emission(): was_stopped = signal.emission_stopped signal.stop_emission() return was_stopped, signal.emission_stopped signal = Signal(Signal.VALUE_LIST) signal.connect(stop_emission) self.assertEqual(signal.emit(), [(False, True)])
def test_handler_garbage_collection_3 (self): test = NotifyTestObject () signal = Signal (AbstractSignal.ANY_ACCEPTS) handler = HandlerGarbageCollectionTestCase.HandlerObject (test) def accepting_handler (*arguments): test.simple_handler_100 (*arguments) return arguments[0] signal.connect (accepting_handler) signal.connect (handler.simple_handler) self.assertEqual (len (signal._handlers), 2) signal.emit (1) del handler self.collect_garbage () self.assertEqual (len (signal._handlers), 2) signal.emit (2) # This time emission is stopped by accumulator, but still the gc-collected handler # must be removed. self.assertEqual (len (signal._handlers), 1) test.assert_results (101, 102)
def test_block(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.emit(1) signal.block(test.simple_handler) signal.emit(2) test.assert_results(1)
def test_disconnect(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.emit() signal.disconnect(test.simple_handler) signal.emit() test.assert_results(())
def test_mixed_argument_passing(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_keywords_handler) signal.emit(ham='spam') signal.emit(42) signal.emit(1, 2, 3, foo='bar') test.assert_results({'ham': 'spam'}, (42, {}), (1, 2, 3, { 'foo': 'bar' }))
def test_last_value_accumulator(self): signal = Signal(AbstractSignal.LAST_VALUE) self.assertEqual(signal.emit(), None) signal.connect(lambda: 15) self.assertEqual(signal.emit(), 15) signal.connect(lambda: 'abc') self.assertEqual(signal.emit(), 'abc')
def test_connect_with_arguments(self): test = NotifyTestObject() signal = Signal() signal.connect_safe(test.simple_handler, 'one argument') signal.connect_safe(test.simple_handler, 'first', 'second', 3) signal.emit() signal.emit('a', 'b') test.assert_results('one argument', ('first', 'second', 3), ('one argument', 'a', 'b'), ('first', 'second', 3, 'a', 'b'))
def initialize (self): signal = Signal () object = _Dummy () signal.connect (object.ignoring_handler) signal.connect (object.ignoring_handler, 1) signal.connect (object.ignoring_handler, 'a', 'b') signal.connect (object.ignoring_handler, None, True, False) self.__signal = signal # To keep it alive. self.__object = object
def test_emission_level_2 (self): test = NotifyTestObject () signal = Signal () def reemit_if_shallow (): test.results.append (signal.emission_level) if signal.emission_level < 3: signal.emit () signal.connect (reemit_if_shallow) signal.emit () test.assert_results (1, 2, 3)
def test_blocking_1 (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit (1) with signal.blocking (test.simple_handler): signal.emit (2) signal.emit (3) test.assert_results (1, 3)
def test_block (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit (1) signal.block (test.simple_handler) signal.emit (2) test.assert_results (1)
def test_disconnect (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit () signal.disconnect (test.simple_handler) signal.emit () test.assert_results (())
def test_blocking_2 (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit (1) with nested (ignoring_exceptions (), signal.blocking (test.simple_handler)): signal.emit (2) raise Exception signal.emit (3) test.assert_results (1, 3)
def test_connecting_1(self): test = NotifyTestObject() signal = Signal() signal.emit(1) with signal.connecting(test.simple_handler): signal.emit(2) signal.emit(3) test.assert_results(2)
def test_connect_with_arguments (self): test = NotifyTestObject () signal = Signal () signal.connect_safe (test.simple_handler, 'one argument') signal.connect_safe (test.simple_handler, 'first', 'second', 3) signal.emit () signal.emit ('a', 'b') test.assert_results ('one argument', ('first', 'second', 3), ('one argument', 'a', 'b'), ('first', 'second', 3, 'a', 'b'))
def test_mixed_argument_passing (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_keywords_handler) signal.emit (ham = 'spam') signal.emit (42) signal.emit (1, 2, 3, foo = 'bar') test.assert_results ({ 'ham': 'spam' }, (42, { }), (1, 2, 3, { 'foo': 'bar' }))
def test_disconnect_in_recursive_emission_2(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.self_disconnecting_recursive_handler) test.signal.emit(0) test.assert_results(0, 1, 2)
def test_connect_in_recursive_emission_2(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.safe_connecting_recursive_handler) test.signal.emit(0) test.assert_results(0, 1, 2, 3, 4, 104, 103, 102, 101, 100)
def test_recursive_invocation_1(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.recursive_handler) test.signal.emit(0) test.assert_results(0, 1, 2, 3, 4)
def test_last_value_accumulator (self): signal = Signal (AbstractSignal.LAST_VALUE) self.assertEqual (signal.emit (), None) signal.connect (lambda: 15) self.assertEqual (signal.emit (), 15) signal.connect (lambda: 'abc') self.assertEqual (signal.emit (), 'abc')
def test_disconnect_in_recursive_emission_1(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.simple_handler_100) test.signal.connect(test.disconnecting_recursive_handler) test.signal.emit(0) test.assert_results(100, 0, 101, 1, 102, 2, 3, 4)
def test_recursive_invocation_2(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.recursive_handler) test.signal.connect(test.simple_handler_100) test.signal.emit(0) test.assert_results(0, 1, 2, 3, 4, 104, 103, 102, 101, 100)
def test_connecting_safely_2(self): test = NotifyTestObject() signal = Signal() signal.emit(1) with nested(ignoring_exceptions(), signal.connecting_safely(test.simple_handler)): signal.emit(2) raise Exception signal.emit(3) test.assert_results(2)
def test_emission_level_1(self): signal = Signal(Signal.VALUE_LIST) self.assertEqual(signal.emission_level, 0) signal.connect(lambda: signal.emission_level) self.assertEqual(signal.emit(), [1]) signal = Signal(Signal.VALUE_LIST) def stop_emission_and_get_level(): signal.stop_emission() return signal.emission_level signal.connect(stop_emission_and_get_level) self.assertEqual(signal.emit(), [1])
def test_emission_stop_2(self): def reemit_signal(number): signal.stop_emission() if number < 10: signal(number + 1) test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.connect(reemit_signal) # This must never be called since emission is stopped by the previous handler. signal.connect(test.simple_handler) signal.emit(0) test.assert_results(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
def test_emission_stop_1(self): def stop_emission(): signal.stop_emission() test = NotifyTestObject() signal = Signal() signal.connect(stop_emission) signal.connect(test.simple_handler) signal.emit() test.assert_results()
def test_block_in_recursive_emission_2(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.simple_handler) test.signal.connect(lambda x: test.signal.block(test.simple_handler)) test.signal.connect(test.simple_handler) test.signal.emit(1) test.assert_results(1)
def test_connect(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.emit() self.assert_(signal.has_handlers()) self.assert_(signal) test.assert_results(())
def test_emission_stop_2 (self): def reemit_signal (number): signal.stop_emission () if number < 10: signal (number + 1) test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.connect (reemit_signal) # This must never be called since emission is stopped by the previous handler. signal.connect (test.simple_handler) signal.emit (0) test.assert_results (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
def test_unblock_in_recursive_emission_2(self): test = self._RecursiveTestObject(Signal()) test.signal.connect(test.simple_handler_100) test.signal.connect(test.unblocking_recursive_handler) test.signal.connect(test.simple_handler_100) test.signal.block(test.simple_handler_100) test.signal.block(test.simple_handler_100) test.signal.emit(0) test.assert_results(0, 1, 2, 3, 104, 4, 104, 103, 102, 101, 100)
def test_argument_passing(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.emit(45, 'abc') test.assert_results((45, 'abc'))
def test_emission_stop_1 (self): def stop_emission (): signal.stop_emission () test = NotifyTestObject () signal = Signal () signal.connect (stop_emission) signal.connect (test.simple_handler) signal.emit () test.assert_results ()
def test_handler_garbage_collection_2 (self): test = NotifyTestObject () signal = Signal () handler = HandlerGarbageCollectionTestCase.HandlerObject (test) signal.connect (lambda *ignored: signal.stop_emission ()) signal.connect (handler.simple_handler) self.assertEqual (len (signal._handlers), 2) signal.emit (1) del handler self.collect_garbage () self.assertEqual (len (signal._handlers), 2) signal.emit (2) # Even though emission is stopped by the first handler, signal must still notice # that it should remove the second one. self.assertEqual (len (signal._handlers), 1) test.assert_results ()
def test_connect (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.emit () self.assert_ (signal.has_handlers ()) self.assert_ (signal) test.assert_results (())
def test_emission_level_1 (self): signal = Signal (Signal.VALUE_LIST) self.assertEqual (signal.emission_level, 0) signal.connect (lambda: signal.emission_level) self.assertEqual (signal.emit (), [1]) signal = Signal (Signal.VALUE_LIST) def stop_emission_and_get_level (): signal.stop_emission () return signal.emission_level signal.connect (stop_emission_and_get_level) self.assertEqual (signal.emit (), [1])
def test_emission_level_2(self): test = NotifyTestObject() signal = Signal() def reemit_if_shallow(): test.results.append(signal.emission_level) if signal.emission_level < 3: signal.emit() signal.connect(reemit_if_shallow) signal.emit() test.assert_results(1, 2, 3)
def test_handler_garbage_collection_1(self): test = NotifyTestObject() signal = Signal() handler = HandlerGarbageCollectionTestCase.HandlerObject(test) signal.connect(handler.simple_handler) self.assert_(signal._handlers is not None) signal.emit(1) del handler self.collect_garbage() self.assert_(signal._handlers is not None) signal.emit(2) self.assert_(signal._handlers is None) test.assert_results(1)
def test_handler_garbage_collection_1 (self): test = NotifyTestObject () signal = Signal () handler = HandlerGarbageCollectionTestCase.HandlerObject (test) signal.connect (handler.simple_handler) self.assert_(signal._handlers is not None) signal.emit (1) del handler self.collect_garbage () self.assert_(signal._handlers is not None) signal.emit (2) self.assert_(signal._handlers is None) test.assert_results (1)
def _create_signal(self): """ Create the signal that will be returned by C{L{changed}} property. Default implementation returns an instance of C{L{Signal <signal.Signal>}} class without accumulator, but derived classes may wish to override this. Note that this method will be called only when getting C{changed} property and only if there is no signal yet. I.e. only for the first reading at all or first reading after a call to C{L{_remove_signal}}. Return value of this method is a little bit tricky. It must return a tuple of two objects, first being an instance of C{L{AbstractSignal}}. The second object must be either the same signal object I{or} a reference to it, i.e. object with C{__call__} method returning the signal. In the second case, you will most likely want to return a weak reference, but there is no restriction. @rtype: C{L{AbstractSignal}}, C{object} @returns: See method description for details. """ signal = Signal() return signal, signal
def test_custom_accumulator (self): class CustomAccumulator (AbstractSignal.AbstractAccumulator): def get_initial_value (self): return 10 def accumulate_value (self, accumulated_value, value_to_add): return accumulated_value + value_to_add def should_continue (self, accumulated_value): return accumulated_value <= 50 def post_process_value (self, accumulated_value): return -accumulated_value signal = Signal (CustomAccumulator ()) self.assertEqual (signal.emit (), -10) signal.connect (lambda: 15) self.assertEqual (signal.emit (), -25) signal.connect (lambda: 20) self.assertEqual (signal.emit (), -45) signal.connect (lambda: 30) self.assertEqual (signal.emit (), -75) # This handler should never be invoked. signal.connect (lambda: 50) self.assertEqual (signal.emit (), -75)
def test_connecting_safely_1 (self): test = NotifyTestObject () signal = Signal () signal.emit (1) with signal.connecting_safely (test.simple_handler): signal.emit (2) with signal.connecting_safely (test.simple_handler): signal.emit (3) signal.emit (4) signal.emit (5) test.assert_results (2, 3, 4)
def test_all_accept_accumulator (self): signal = Signal (AbstractSignal.ALL_ACCEPT) self.assertEqual (signal.emit (), True) signal.connect (lambda: True) self.assertEqual (signal.emit (), True) signal.connect (lambda: 'I accept') self.assertEqual (signal.emit (), 'I accept') signal.connect (lambda: []) self.assertEqual (signal.emit (), []) signal.connect (lambda: True) self.assertEqual (signal.emit (), [])
def test_connect_disconnect (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.connect (test.simple_handler_100) signal.emit (1) # This must be a no-op. signal.connect (test.simple_handler) signal.disconnect (test.simple_handler) signal.emit (2) # This must be a no-op. signal.connect (test.simple_handler_100) signal.disconnect (test.simple_handler_100) signal.emit (3) test.assert_results (1, 101, 2, 102, 3, 103)
def test_disconnect_blocked_handler_3 (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.connect (test.simple_handler) signal.emit (1) signal.block (test.simple_handler) signal.emit (2) signal.disconnect_all (test.simple_handler) signal.emit (3) signal.connect (test.simple_handler) signal.emit (4) signal.unblock (test.simple_handler) signal.emit (5) test.assert_results (1, 1, 4, 5)
def test_disconnect_blocked_handler_3(self): test = NotifyTestObject() signal = Signal() signal.connect(test.simple_handler) signal.connect(test.simple_handler) signal.emit(1) signal.block(test.simple_handler) signal.emit(2) signal.disconnect_all(test.simple_handler) signal.emit(3) signal.connect(test.simple_handler) signal.emit(4) signal.unblock(test.simple_handler) signal.emit(5) test.assert_results(1, 1, 4, 5)
def test_custom_accumulator(self): class CustomAccumulator(AbstractSignal.AbstractAccumulator): def get_initial_value(self): return 10 def accumulate_value(self, accumulated_value, value_to_add): return accumulated_value + value_to_add def should_continue(self, accumulated_value): return accumulated_value <= 50 def post_process_value(self, accumulated_value): return -accumulated_value signal = Signal(CustomAccumulator()) self.assertEqual(signal.emit(), -10) signal.connect(lambda: 15) self.assertEqual(signal.emit(), -25) signal.connect(lambda: 20) self.assertEqual(signal.emit(), -45) signal.connect(lambda: 30) self.assertEqual(signal.emit(), -75) # This handler should never be invoked. signal.connect(lambda: 50) self.assertEqual(signal.emit(), -75)
def test_connect_with_keywords(self): test = NotifyTestObject() signal = Signal() signal.connect_safe(test.simple_keywords_handler, a=1) signal.connect_safe(test.simple_keywords_handler, a=2, b=3) signal.emit() signal.emit(b=42) signal.emit('ham') test.assert_results( {'a': 1}, { 'a': 2, 'b': 3 }, # Note that emission keyword arguments must override # connection-time keyword arguments. { 'a': 1, 'b': 42 }, { 'a': 2, 'b': 42 }, ('ham', { 'a': 1 }), ('ham', { 'a': 2, 'b': 3 }))
def test_any_accepts_accumulator (self): signal = Signal (AbstractSignal.ANY_ACCEPTS) self.assertEqual (signal.emit (), False) signal.connect (lambda: False) self.assertEqual (signal.emit (), False) signal.connect (lambda: ()) self.assertEqual (signal.emit (), ()) signal.connect (lambda: 'I accept') self.assertEqual (signal.emit (), 'I accept') signal.connect (lambda: ()) self.assertEqual (signal.emit (), 'I accept')
def test_disconnect_all (self): test = NotifyTestObject () signal = Signal () signal.connect (test.simple_handler) signal.connect (test.simple_handler) signal.connect (test.simple_handler) signal.emit (1) signal.disconnect (test.simple_handler) signal.emit (2) signal.disconnect_all (test.simple_handler) signal.emit (3) test.assert_results (1, 1, 1, 2, 2)
def test_connect_with_keywords (self): test = NotifyTestObject () signal = Signal () signal.connect_safe (test.simple_keywords_handler, a = 1) signal.connect_safe (test.simple_keywords_handler, a = 2, b = 3) signal.emit () signal.emit (b = 42) signal.emit ('ham') test.assert_results ({ 'a': 1 }, { 'a': 2, 'b' : 3 }, # Note that emission keyword arguments must override # connection-time keyword arguments. { 'a': 1, 'b': 42 }, { 'a': 2, 'b' : 42 }, ('ham', { 'a': 1 }), ('ham', { 'a': 2, 'b' : 3 }))
def test_handler_garbage_collection_2(self): test = NotifyTestObject() signal = Signal() handler = HandlerGarbageCollectionTestCase.HandlerObject(test) signal.connect(lambda *ignored: signal.stop_emission()) signal.connect(handler.simple_handler) self.assertEqual(len(signal._handlers), 2) signal.emit(1) del handler self.collect_garbage() self.assertEqual(len(signal._handlers), 2) signal.emit(2) # Even though emission is stopped by the first handler, signal must still notice # that it should remove the second one. self.assertEqual(len(signal._handlers), 1) test.assert_results()