Пример #1
0
    def testCallback(self) -> None:

        self.args = [None, None]

        def f1(*args):
            self.args[0] = args

        def f2(*args):
            self.args[1] = args

        c = Callback()
        c.Register(f1)

        c(1, 2)

        assert self.args[0] == (1, 2)

        c.Unregister(f1)
        self.args[0] = None
        c(10, 20)
        assert self.args[0] == None

        def foo():
            pass

        c.Unregister(foo)
Пример #2
0
    def test_extra_args(self) -> None:
        """
        Tests the extra-args parameter in Register method.
        """
        self.zulu_calls: List[Any] = []

        def zulu_one(*args):
            self.zulu_calls.append(args)

        def zulu_too(*args):
            self.zulu_calls.append(args)

        alpha = Callback()
        alpha.Register(zulu_one, (1, 2))

        assert self.zulu_calls == []

        alpha("a")
        assert self.zulu_calls == [(1, 2, "a")]

        alpha("a", "b", "c")
        assert self.zulu_calls == [(1, 2, "a"), (1, 2, "a", "b", "c")]

        # Test a second method with extra-args
        alpha.Register(zulu_too, (9, ))

        alpha("a")
        assert self.zulu_calls == [
            (1, 2, "a"),
            (1, 2, "a", "b", "c"),
            (1, 2, "a"),
            (9, "a"),
        ]
Пример #3
0
    def testCallbacksRegister(self) -> None:
        """
        Callbacks().Register() when used as a context manager unregisters the callbacks
        automatically when the context ends.
        """
        c1 = Callback()
        c2 = Callback()

        events = []

        def bar(when):
            events.append(when)

        with Callbacks() as callbacks:
            callbacks.Register(c1, bar)
            callbacks.Register(c2, bar)

            c1(when="c1-first")
            c2(when="c2-first")
            assert events == ["c1-first", "c2-first"]

        c1(when="c1-second")
        c2(when="c2-second")

        assert events == ["c1-first", "c2-first"]
Пример #4
0
    def testNeedsUnregister(self) -> None:
        c = Callback()

        # Even when the function isn't registered, we not raise an error.
        def Func():
            pass

        # self.assertNotRaises(RuntimeError, c.Unregister, Func)
        c.Unregister(Func)
Пример #5
0
    def testRemoveCallbackPlain(self) -> None:
        class C:
            def __init__(self, name):
                self.name = name

            def OnCallback(self):
                pass

            def __eq__(self, other):
                return self.name == other.name

            def __ne__(self, other):
                return not self == other

        instance1 = C("instance")
        instance2 = C("instance")
        assert instance1 == instance2

        c = Callback()
        c.Register(instance1.OnCallback)
        c.Register(instance2.OnCallback)

        # removing first callback, and checking that it was actually removed as expected
        c.Unregister(instance1.OnCallback)
        assert not c.Contains(instance1.OnCallback) == True

        # self.assertNotRaises(RuntimeError, c.Unregister, instance1.OnCallback)
        c.Unregister(instance1.OnCallback)

        # removing second callback, and checking that it was actually removed as expected
        c.Unregister(instance2.OnCallback)
        assert not c.Contains(instance2.OnCallback) == True

        # self.assertNotRaises(RuntimeError, c.Unregister, instance2.OnCallback)
        c.Unregister(instance2.OnCallback)
Пример #6
0
    def testWeakMethodProxy2(self) -> None:
        def Foo():
            self.called = True

        proxy = WeakMethodProxy(Foo)

        c = Callback()
        c.Register(proxy)
        c()
        assert self.called
        assert c.Contains(proxy)
Пример #7
0
    def testRegisterTwice(self) -> None:
        self.called = 0

        def After(*args):
            self.called += 1

        c = Callback()
        c.Register(After)
        c.Register(After)
        c.Register(After)
        c()
        assert self.called == 1
Пример #8
0
    def testCallbackAndPartial(self) -> None:
        from functools import partial

        called = []

        def Method(a):
            called.append(a)

        c = Callback()
        c.Register(lambda: Method("lambda"))
        c.Register(partial(Method, "partial"))
        c()
        assert called == ["lambda", "partial"]
Пример #9
0
    def testUnregisterAll(self) -> None:
        c = Callback()

        # self.assertNotRaises(AttributeError, c.UnregisterAll)
        c.UnregisterAll()

        self.called = False

        def Func():
            self.called = True

        c.Register(Func)
        c.UnregisterAll()

        c()
        assert self.called == False
Пример #10
0
    def testCallbackInstanceWeakRef(self) -> None:
        class Obj:
            def __init__(self):
                self.called = False

            def __call__(self):
                self.called = True

        c = Callback()
        obj = Obj()
        c.Register(obj)
        c()
        assert c.Contains(obj)
        assert obj.called
        obj_ref = weakref.ref(obj)
        del obj
        assert obj_ref() is None
Пример #11
0
    def testAfterRemoveCallback(self) -> None:
        my_object = _MyClass()
        my_object.SetAlpha(0)
        my_object.SetBravo(0)

        # Test After/Remove with a callback
        event = Callback()
        After(my_object.SetAlpha, event)
        event.Register(my_object.SetBravo)

        my_object.SetAlpha(3)
        assert my_object.bravo == 3

        Remove(my_object.SetAlpha, event)

        my_object.SetAlpha(4)
        assert my_object.bravo == 3
Пример #12
0
    def testWeakMethodProxy(self) -> None:
        class Obj:
            def Foo(self):
                self.called = True

        obj = Obj()
        proxy = WeakMethodProxy(obj.Foo)

        c = Callback()
        c.Register(proxy)
        c()
        assert obj.called
        assert c.Contains(proxy)
        obj_ref = weakref.ref(obj)
        del obj
        assert obj_ref() is None
        c()
        assert len(c) == 0
Пример #13
0
    def testKeepStrongReference(self) -> None:
        class Obj:
            __CALLBACK_KEEP_STRONG_REFERENCE__ = True

            def __init__(self):
                self.called = False

            def __call__(self):
                self.called = True

        c = Callback()
        obj = Obj()
        c.Register(obj)
        c()
        assert c.Contains(obj)
        assert obj.called
        obj_ref = weakref.ref(obj)
        del obj
        # Not collected because of __CALLBACK_KEEP_STRONG_REFERENCE__ in the class.
        assert obj_ref() is not None
Пример #14
0
    def testRemoveCallbackContext(self) -> None:
        """Callback.Register() returns a context that can be used to unregister that call."""
        events = []

        def bar(when):
            events.append(when)

        contexts = []
        c1 = Callback()
        contexts.append(c1.Register(bar))

        c2 = Callback()
        contexts.append(c2.Register(bar))

        c1("c1-first")
        c2("c2-first")

        assert events == ["c1-first", "c2-first"]

        for context in contexts:
            context.Unregister()

        c1("c1-second")
        c2("c2-second")
        assert events == ["c1-first", "c2-first"]
Пример #15
0
    def testContains(self) -> None:
        def foo(x):
            pass

        c = Callback()
        assert not c.Contains(foo)
        c.Register(foo)

        assert c.Contains(foo)
        c.Unregister(foo)
        assert not c.Contains(foo)
Пример #16
0
        class A(object):
            c = Callback()

            def __init__(self, **ka):
                super().__init__(**ka)
                self.value = 0.0
                self.other_value = 0.0
                self.c.Register(self._UpdateBValue)

            def SetValue(self, value):
                self.value = value
                self.c(value)

            def _UpdateBValue(self, new_value):
                self.other_value = new_value / 0  # division by zero
Пример #17
0
        class B(object):
            c = Callback()

            def __init__(self, **ka):
                super().__init__(**ka)
                self._a = A()
                self.value = 0.0
                self.c.Register(self._UpdateAValue)

            def SetValue(self, value):
                self.value = value
                self.c(value * 0.1)

            def _UpdateAValue(self, new_value):
                self._a.SetValue(new_value)
Пример #18
0
    def testCallbackReceiverDies(self) -> None:
        class A:
            def on_foo(dummy, *args):  # @NoSelf
                self.args = args

        self.args = None
        a = A()
        weak_a = weakref.ref(a)

        foo = Callback()
        foo.Register(a.on_foo)

        foo(1, 2)
        assert self.args == (1, 2)
        assert weak_a() is a

        foo(3, 4)
        assert self.args == (3, 4)
        assert weak_a() is a

        del a
        assert weak_a() is None
        foo(5, 6)
        assert self.args == (3, 4)
Пример #19
0
    def testCallbackWithMagicMock(self, mocker) -> None:
        """
        Check that we can register mock.MagicMock objects in callbacks.

        This makes it easier to test that public callbacks are being called with correct arguments.

        Usage (in testing, of course):

            save_listener = mock.MagicMock(spec=lambda: None)
            project_manager.on_save.Register(save_listener)
            project_manager.SlotSave()
            assert save_listener.call_args == mock.call('foo.file', '.txt')

        Instead of the more traditional:

            def OnSave(filename, ext):
                self.filename = filename
                self.ext = ext

            self.filename = None
            self.ext = ext

            project_manager.on_save.Register(OnSave)
            project_manager.SlotSave()
            assert (self.filename, self.ext) == ('foo.file', '.txt')
        """
        c = Callback()

        with pytest.raises(RuntimeError):
            c.Register(mocker.MagicMock())

        magic_mock = mocker.stub()
        c = Callback()
        c.Register(magic_mock)

        c(10, name="X")
        assert magic_mock.call_args_list == [mocker.call(10, name="X")]

        c(20, name="Y")
        assert magic_mock.call_args_list == [
            mocker.call(10, name="X"),
            mocker.call(20, name="Y"),
        ]

        c.Unregister(magic_mock)
        c(30, name="Z")
        assert len(magic_mock.call_args_list) == 2
Пример #20
0
    def testHandleErrorOnCallback(self, mocker) -> None:
        self.called = 0

        def After(*args, **kwargs):
            self.called += 1
            raise RuntimeError("test")

        def After2(*args, **kwargs):
            self.called += 1
            raise RuntimeError("test2")

        c = Callback()
        c.Register(After)
        c.Register(After2)

        # test the default behaviour: errors are not handled and stop execution as usual
        self.called = 0
        c = Callback()
        c.Register(After)
        c.Register(After2)
        with pytest.raises(RuntimeError):
            c()
        assert self.called == 1
Пример #21
0
 def testWeakRefToCallback(self) -> None:
     c = Callback()
     c_ref = weakref.ref(c)
     assert c_ref() is c
Пример #22
0
    def testKeyReusedAfterDead(self, monkeypatch) -> None:
        self._gotten_key = False

        def GetKey(*args, **kwargs):
            self._gotten_key = True
            return 1

        monkeypatch.setattr(Callback, "_GetKey", GetKey)

        def AfterMethod(*args):
            pass

        def AfterMethodB(*args):
            pass

        c = Callback()

        c.Register(AfterMethod)
        self._gotten_key = False
        assert not c.Contains(AfterMethodB)
        assert c.Contains(AfterMethod)
        assert self._gotten_key

        # As we made _GetKey return always the same, this will make it remove one and add the
        # other one, so, the contains will have to check if they're actually the same or not.
        c.Register(AfterMethodB)
        self._gotten_key = False
        assert c.Contains(AfterMethodB)
        assert not c.Contains(AfterMethod)
        assert self._gotten_key

        class A:
            def __init__(self):
                self._a = 0

            def GetA(self):
                return self._a

            def SetA(self, value):
                self._a = value

            a = property(GetA, SetA)

        a = A()
        # If registering a bound, it doesn't contain the unbound
        c.Register(a.SetA)
        assert not c.Contains(AfterMethodB)
        assert not c.Contains(A.SetA)
        assert c.Contains(a.SetA)

        # But if registering an unbound, it contains the bound
        c.Register(A.SetA)
        assert not c.Contains(AfterMethodB)
        assert c.Contains(A.SetA)
        assert c.Contains(a.SetA)

        c.Register(a.SetA)
        assert len(c) == 1
        del a
        assert not c.Contains(AfterMethodB)
        assert len(c) == 0

        a = A()
        from oop_ext.foundation.callback._callback import _CallbackWrapper

        c.Register(_CallbackWrapper(WeakMethodRef(a.SetA)))
        assert len(c) == 1
        del a
        assert not c.Contains(AfterMethodB)
        assert len(c) == 0