예제 #1
0
    def testUnbound(self):
        '''
        We don't accept unbound methods as callback listeners.
        '''

        output = []

        class MyClass(object):

            def MyMethod(self):
                output.append('MyMethod')

        class MyListener(object):

            def Listen(self):
                output.append('Listen')

        a = MyClass()
        a.MyMethod()
        assert output == ['MyMethod']

        # Registering bound method, OK
        b = MyListener()
        After(a.MyMethod, b.Listen)
        a.MyMethod()
        assert output == ['MyMethod', 'MyMethod', 'Listen']

        # Registering unbound method, FAIL
        with pytest.raises(AssertionError):
            After(a.MyMethod, MyListener.Listen)
        assert output == ['MyMethod', 'MyMethod', 'Listen']
예제 #2
0
    def testOnNullClass(self):
        '''
        On Null classes, After/Before has no effect.
        '''

        class MyNullSubClass(Null):
            ''

        count = [0]
        def AfterSetIt():
            count[0] += 1


        AfterSetIt()
        assert count == [1]

        s = Null()
        After(s.SetIt, AfterSetIt)
        s.SetIt()
        assert count == [1]

        s = MyNullSubClass()
        After(s.SetIt, AfterSetIt)
        s.SetIt()
        assert count == [1]
예제 #3
0
def _FTPOpenFile(filename_url):
    '''
    Opens a file (FTP only) and sets things up to close ftp connection when the file is closed.

    :param filename_url:
        .. see:: OpenFile
    '''
    ftp_host = FTPHost(filename_url)
    try:
        # Open remote file in binary mode to maintain the original encoding and end of line.
        open_file = ftp_host.open(filename_url.path, 'rb')

        # Set it up so when open_file is closed, ftp_host closes too
        def FTPClose():
            # Before closing, remove callback to avoid recursion, since ftputil closes all files
            # it has
            from ben10.foundation.callback import Remove
            Remove(open_file.close, FTPClose)

            ftp_host.close()

        from ben10.foundation.callback import After
        After(open_file.close, FTPClose)

        return open_file
    except:
        ftp_host.close()
        raise
예제 #4
0
    def testBeforeAfter(self):

        callback_args = []

        def AfterCallback():
            callback_args.append('after')

        def BeforeCallback():
            callback_args.append('before')

        class MyClass:

            def Hooked(self):
                callback_args.append('hooked')

        my_obj = MyClass()

        callback_args = []
        my_obj.Hooked()
        assert callback_args == ['hooked']

        callback_args = []
        After(my_obj.Hooked, AfterCallback)
        my_obj.Hooked()
        assert callback_args == ['hooked', 'after']

        callback_args = []
        Before(my_obj.Hooked, BeforeCallback)
        my_obj.Hooked()
        assert callback_args == ['before', 'hooked', 'after']
예제 #5
0
    def testOnClassAndOnInstance(self):
        vals = []
        class Stub(object):
            def call(self, *args, **kwargs):
                'Never called!'


        def OnCall1(instance, val):
            vals.append(('call_instance', val))

        def OnCall2(val):
            vals.append(('call_class', val))

        After(Stub.call, OnCall1)
        s = Stub()
        After(s.call, OnCall2)

        s.call(True)
        assert vals == [('call_instance', True), ('call_class', True)]
예제 #6
0
    def testOnClassAndOnInstance2(self):

        class Stub(object):
            def Method(self, *args, **kwargs):
                pass

        def OnCallClass(instance, val):
            vals.append(('call_class', val))

        def OnCallInstance(val):
            vals.append(('call_instance', val))

        # Tricky thing here: because we added the callback in the class (2) after we added it to the
        # instance (1), the callback on the instance cannot be rebound, thus, calling it on the instance
        # won't really trigger the callback on the class (not really what would be expected of the
        # after method, but I couldn't find a reasonable way to overcome that).
        # A solution could be keeping track of all callbacks and rebinding all existent ones in the
        # instances to the one in the class, but it seems overkill for such an odd situation.
        vals = []
        s = Stub()
        After(s.Method, OnCallInstance)  # (1)
        After(Stub.Method, OnCallClass)  # (2)
        s.Method(1)
        assert vals == [('call_instance', 1), ]
        assert Remove(s.Method, OnCallInstance) == True
        assert Remove(Stub.Method, OnCallClass) == True

        vals = []
        s = Stub()
        s.Method(2)
        assert vals == []

        vals = []
        s = Stub()
        After(Stub.Method, OnCallClass)  # (2)
        After(s.Method, OnCallInstance)  # (1)
        s.Method(3)
        assert vals == [('call_class', 3), ('call_instance', 3) ]
예제 #7
0
    def testSingletonOptimization(self):
        class MySingleton(Singleton):
            pass

        def _ObtainStack(*args, **kwargs):
            self._called = True

        After(MySingleton._ObtainStack, _ObtainStack)

        self._called = False
        MySingleton.GetSingleton()
        assert self._called

        self._called = False
        MySingleton.GetSingleton()
        assert not self._called
예제 #8
0
    def testCallbackAndInterfaces(self):
        '''
            Tests if the interface "AssertImplements" works with "callbacked" methods.
        '''
        class My(object):
            ImplementsInterface(_InterfM1)

            def m1(self):
                ''

        def MyCallback():
            ''

        from ben10.foundation.callback import After

        o = My()
        AssertImplements(o, _InterfM1)

        After(o.m1, MyCallback)

        AssertImplements(o, _InterfM1)
        AssertImplements(o, _InterfM1)  # Not raises BadImplementationError