def testDeadCallbackCleared(self): my_object = _MyClass() my_object.SetAlpha(0) my_object.SetBravo(0) self._value = [] class B(object): def event(s, value): # @NoSelf self._b_value = value class A(object): def event(s, obj, value): # @NoSelf self._a_value = value a = A() b = B() # Test After/Remove with a callback and sender_as_parameter callback.After(my_object.SetAlpha, a.event, sender_as_parameter=True) callback.After(my_object.SetAlpha, b.event, sender_as_parameter=False) w = weakref.ref(a) my_object.SetAlpha(3) assert 3 == self._a_value assert 3 == self._b_value del a my_object.SetAlpha(4) assert 3 == self._a_value assert 4 == self._b_value assert w() is None
def testOnClassMethod(self): class A(object): @classmethod def foo(cls): pass self.after_exec_class_method = 0 def FooAfterClassMethod(): self.after_exec_class_method += 1 self.after_exec_self_method = 0 def FooAfterSelfMethod(): self.after_exec_self_method += 1 callback.After(A.foo, FooAfterClassMethod) a = A() callback.After(a.foo, FooAfterSelfMethod) a.foo() assert 1 == self.after_exec_class_method assert 1 == self.after_exec_self_method callback.Remove(A.foo, FooAfterClassMethod) a.foo() assert 1 == self.after_exec_class_method assert 2 == self.after_exec_self_method
def testLessArgs(self): class C: def foo(self, _x, _y, **_kwargs): pass def after_2(x, y, *args, **kwargs): self.after_2_res = x, y def after_1(x, *args, **kwargs): self.after_1_res = x def after_0(*args, **kwargs): self.after_0_res = 0 self.after_2_res = None self.after_1_res = None self.after_0_res = None c = C() callback.After(c.foo, after_2) callback.After(c.foo, after_1) callback.After(c.foo, after_0) c.foo(10, 20, foo=1) assert self.after_2_res == (10, 20) assert self.after_1_res == 10 assert self.after_0_res == 0
def testAfterBeforeHandleError(self, monkeypatch): class C(object): def Method(self, x): return x * 2 def AfterMethod(*args): self.before_called += 1 raise RuntimeError def BeforeMethod(*args): self.after_called += 1 raise RuntimeError self.before_called = 0 self.after_called = 0 c = C() callback.Before(c.Method, BeforeMethod) callback.After(c.Method, AfterMethod) # handled_errors = [] # def HandleErrorOnCallback(func, *args, **kwargs): # handled_errors.append(func) # # monkeypatch.setattr(callback, 'HandleErrorOnCallback', HandleErrorOnCallback) handled_errors = [] def HandleException(func, *args, **kwargs): handled_errors.append(func) monkeypatch.setattr(handle_exception, 'HandleException', HandleException) assert c.Method(10) == 20 assert self.before_called == 1 assert self.after_called == 1 assert len(handled_errors) == 2 assert c.Method(20) == 40 assert self.before_called == 2 assert self.after_called == 2 assert len(handled_errors) == 4 # Testing with a non-function. class Alpha: pass callback.After(c.Method, Alpha()) assert c.Method(20) == 40 assert len(handled_errors) == 7
def testInstanceOverride(self): callback.Before(self.a.foo, self.before) callback.After(self.a.foo, self.after) self.a.foo(1) assert self.foo_called == (self.a, 1) assert self.after_called == (1,) assert self.before_called == (1,) assert self.after_count == 1 assert self.before_count == 1 self.b.foo(2) assert self.foo_called == (self.b, 2) assert self.after_called == (1,) assert self.before_called == (1,) assert self.after_count == 1 assert self.before_count == 1 assert callback.Remove(self.a.foo, self.before) == True self.a.foo(2) assert self.foo_called == (self.a, 2) assert self.after_called == (2,) assert self.before_called == (1,) assert self.after_count == 2 assert self.before_count == 1 callback.Before(self.a.foo, self.before) callback.Before(self.a.foo, self.before) # Registering twice has no effect the 2nd time self.a.foo(5) assert self.before_called == (5,) assert self.before_count == 2
def testClassOverride(self): callback.Before(self.C.foo, self.before) callback.After(self.C.foo, self.after) self.a.foo(1) assert self.foo_called == (self.a, 1) assert self.after_called == (self.a, 1) assert self.after_count == 1 assert self.before_called == (self.a, 1) assert self.before_count == 1 self.b.foo(2) assert self.foo_called == (self.b, 2) assert self.after_called == (self.b, 2) assert self.after_count == 2 assert self.before_called == (self.b, 2) assert self.before_count == 2 callback.Remove(self.C.foo, self.before) self.a.foo(3) assert self.foo_called == (self.a, 3) assert self.after_called == (self.a, 3) assert self.after_count == 3 assert self.before_called == (self.b, 2) assert self.before_count == 2
def testActionMethodDies(self): class A: def foo(self): pass def FooAfter(): self.after_exec += 1 self.after_exec = 0 a = A() weak_a = weakref.ref(a) callback.After(a.foo, FooAfter) a.foo() assert self.after_exec == 1 del a # IMPORTANT: behaviour change. The description below is for the previous # behaviour. That is not true anymore (the circular reference is not kept anymore) # callback creates a circular reference; that's ok, because we want # to still be able to do "x = a.foo" and keep a strong reference to it assert weak_a() is None
def testBoundMethodsRight(self): foo = self.a.foo foo = callback.Before(foo, self.before) foo = callback.After(foo, self.after) foo(10) assert self.before_count == 1 assert self.after_count == 1
def testBoundMethodsWrong(self): foo = self.a.foo callback.Before(foo, self.before) callback.After(foo, self.after) foo(10) assert 0 == self.before_count assert 0 == self.after_count
def testSenderDies2(self): callback.After(self.a.foo, self.after, True) self.a.foo(1) assert self.after_called == (self.a, 1) a = weakref.ref(self.a) self.after_called = None self.foo_called = None del self.a assert a() is None
def testAfterRegisterMultipleAndUnregisterOnce(self): class A: def foo(self): pass a = A() def FooAfter1(): callback.Remove(a.foo, FooAfter1) self.after_exec += 1 def FooAfter2(): self.after_exec += 1 self.after_exec = 0 callback.After(a.foo, FooAfter1) callback.After(a.foo, FooAfter2) a.foo() # it was iterating in the original after, so, this case # was only giving 1 result and not 2 as it should assert 2 == self.after_exec a.foo() assert 3 == self.after_exec a.foo() assert 4 == self.after_exec callback.After(a.foo, FooAfter2) callback.After(a.foo, FooAfter2) callback.After(a.foo, FooAfter2) a.foo() assert 5 == self.after_exec callback.Remove(a.foo, FooAfter2) a.foo() assert 5 == self.after_exec
def testAfterRemove(self): my_object = _MyClass() my_object.SetAlpha(0) my_object.SetBravo(0) callback.After(my_object.SetAlpha, my_object.SetBravo) my_object.SetAlpha(1) assert my_object.bravo == 1 callback.Remove(my_object.SetAlpha, my_object.SetBravo) my_object.SetAlpha(2) assert my_object.bravo == 1
def test_sender_as_parameter_after_and_before(self): self.zulu_calls = [] def zulu_one(*args): self.zulu_calls.append((1, args)) def zulu_too(*args): self.zulu_calls.append((2, args)) callback.Before(self.a.foo, zulu_one, sender_as_parameter=True) callback.After(self.a.foo, zulu_too) assert self.zulu_calls == [] self.a.foo(0) assert self.zulu_calls == [(1, (self.a, 0)), (2, (0,))]
def testWithCallable(self): class Stub(object): def call(self, _b): pass class Aux(object): def __call__(self, _b): self.called = True s = Stub() a = Aux() callback.After(s.call, a) s.call(True) assert a.called
def testAfterRemoveCallback(self): my_object = _MyClass() my_object.SetAlpha(0) my_object.SetBravo(0) # Test After/Remove with a callback event = callback.Callback() callback.After(my_object.SetAlpha, event) event.Register(my_object.SetBravo) my_object.SetAlpha(3) assert my_object.bravo == 3 callback.Remove(my_object.SetAlpha, event) my_object.SetAlpha(4) assert my_object.bravo == 3
def testAfterRemoveCallbackAndSenderAsParameter(self): my_object = _MyClass() my_object.SetAlpha(0) my_object.SetBravo(0) def event(obj_or_value, value): self._value = value # Test After/Remove with a callback and sender_as_parameter callback.After(my_object.SetAlpha, event, sender_as_parameter=True) my_object.SetAlpha(3) assert self._value == 3 callback.Remove(my_object.SetAlpha, event) my_object.SetAlpha(4) assert self._value == 3