def testNormalFunctions(self): #{{{
     '''Normal function or unbound method'''
     _ = lambda: None
     ub = method(_, None, None)
     for f in (_, ub):
         cw = CallableWrapper(f)
         self.assertFalse(cw._get_ismethod())
 def testNonExistantInstance(self): #{{{
     '''No longer existing instance returns None '''
     A = DummyClass
     a = A()
     w = CallableWrapper(a.DummyMethod)
     del a
     self.assert_(w._getcallable() is None)
 def testDeadWrapper(self):  # {{{
     """Calling a dead wrapper generates a warning"""
     A = DummyClass
     a = A()
     w = CallableWrapper(a.DummyMethod)
     del a
     self.assert_(w._isdead())
 def testRemoveInstance(self): #{{{
     '''Deleting an instance makes for a dead CallableWrapper'''
     A = DummyClass
     a = A()
     w = CallableWrapper(a.DummyMethod)
     del a
     self.assert_(w._isdead())
 def testClassMethodCallable(self): #{{{
     '''Initializing with a class method callable sets weakref on class and stores method's internal function'''
     A = DummyClass
     w = CallableWrapper(A.DummyMethod)
     self.assert_(w._object is not None)
     self.assert_(isinstance(w._object, cref))
     self.assert_(w._object() is A)
     self.assert_(w._function is A.DummyMethod.im_func)
 def testNormalFunction(self): #{{{
     '''Return back normal functions and unbound methods'''
     _ = (lambda: None)
     ub_ = method(_, None, None)
     for f in (_, ub_):
         cw = CallableWrapper(f)
         ret = cw._getref()()
         self.assertEqual(ret, f)
    def testRemoveNonMethodCallable(self): #{{{
        '''Deleting a non-method callable makes for a dead CallableWrapper'''
        def DummyFunction(): #{{{
            return 'DummyFunction'
        # End def #}}}

        w = CallableWrapper(DummyFunction)
        del DummyFunction
        self.assert_(w._isdead())
 def testDeadReferences(self): #{{{
     '''If the reference dies, return None'''
     class _(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     t = _()
     cw = CallableWrapper(t.me, weak=True)
     del t
     self.assertTrue(cw._getref()() is None)
 def testBoundInstanceMethods(self): #{{{
     '''Bound or instance methods'''
     class _(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     t = _()
     for f in (_.me, t.me):
         cw = CallableWrapper(f)
         self.assertTrue(cw._get_ismethod())
 def testClassMethod(self): #{{{
     '''Class method gets class soft reference and function hard reference'''
     class _(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     cw = CallableWrapper(_.me)
     self.assertTrue(cw._object)
     self.assertTrue(isinstance(cw._object, cref))
     self.assertEqual(cw._object(), _)
     self.assertEqual(cw._function, _.me.im_func)
     self.assertEqual(cw._methodtype, METHODTYPE_CLASS)
 def testNormalFunction(self): #{{{
     '''Normal functions and unbound methods'''
     def _(): #{{{
         pass
     # End def #}}}
     funcs = ((_, METHODTYPE_NOTMETHOD), (method(_, None, None), METHODTYPE_UNBOUND))
     for f, mt in funcs:
         cw = CallableWrapper(f)
         self.assertTrue(cw._object is None)
         self.assertTrue(cw._function)
         self.assertTrue(isinstance(cw._function, cref))
         self.assertEqual(cw._function(), f)
         self.assertEqual(cw._methodtype, mt)
 def testMethod(self): #{{{
     '''Bound and instance methods'''
     class _(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     t1, i_ = _.me, _()
     t2 = i_.me
     for f in (t1, t2):
         cw = CallableWrapper(f)
         ret = cw._getcallable()
         self.assertNotEqual(ret, f)
         self.assertEqual(ret, f.im_func)
 def testWrap(self): #{{{
     '''If wrapped, will call the wrap function'''
     def deco(f): #{{{
         def w(s): #{{{
             return 400
         # End def #}}}
         return w
     # End def #}}}
     _ = lambda: 100
     cw = CallableWrapper(_)
     self.assertEqual(cw(), 100)
     cw.wrap(deco)
     self.assertEqual(cw(), 400)
     cw.unwrap()
     self.assertEqual(cw(), 100)
 def testReferences(self): #{{{
     '''Live reference (functions always alive)'''
     t1 = lambda: None
     class t2(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     t3 = t2()
     cw = None
     for f in (t1, t2.me, t3.me):
         cw = CallableWrapper(f, weak=True)
         self.assertEqual(cw._isdead(), False)
     del t3, f
     self.assertTrue(cw._isdead())
 def testInstanceMethod(self): #{{{
     '''Instance method gets instance soft reference and function hard reference'''
     class _(object): #{{{
         def me(self): #{{{
             pass
         # End def #}}}
     # End class #}}}
     t = _()
     cw = CallableWrapper(t.me)
     self.assertTrue(cw._object)
     self.assertTrue(isinstance(cw._object, cref))
     self.assertEqual(cw._object(), t)
     self.assertEqual(cw._function, _.me.im_func)
     self.assertEqual(cw._function, t.me.im_func)
     self.assertEqual(cw._methodtype, METHODTYPE_INSTANCE)
    def testUnWrap(self):  # {{{
        """Unwrap"""

        class A(object):
            def helloworld(self, a, b):
                return "hello world"

        a = A()
        w = CallableWrapper(a.helloworld)
        w.wrap(DummyReplacement)
        a.helloworld = method(w, a, A)

        self.assertEqual(a.helloworld(1, 2), "HELLO: hello world :WORLD")
        self.assertEqual(A().helloworld(1, 2), "hello world")
        w.unwrap()
        self.assertEqual(A().helloworld(1, 2), a.helloworld(1, 2))
 def testWrap(self): #{{{
     '''Proper wrap functionality given proper input'''
     cw = CallableWrapper(self.func)
     cw.wrap(self.deco)
     self.assertTrue(cw._newcall('a', str))
     self.assertFalse(cw._newcall('a', unicode))
     self.assertTrue(cw._newcall(u'a', unicode))
     self.assertFalse(cw._newcall(1, int))
Beispiel #18
0
    def __init__(self, signal, **kwargs): #{{{
        if not iscallable(signal):
            raise TypeError("Argument must be callable.")
        expected = ('weak', 'active', 'activate_on_call')
        if any(kw for kw in kwargs if kw not in expected):
            raise ValueError("Detected unexpected arguments: %s" %', '.join([found]))
        weak = kwargs.get('weak', True)
        self._func = CallableWrapper(signal, weak=weak)
        self.__name__ = self._func.__name__
        funclist = self._funclist = dict()
        conn = self._connections = dict()
        call_funclist = self._call_funclist = dict((n, odict()) for n in ('after', 'replace', 'around', 'before'))
        self._vars = getattr(self, '_vars', dict())
        self._vars.update(active=kwargs.get('active', True),
                callactivate=kwargs.get('activate_on_call', False), caller=callfunc)

        # Initialize values of function lists
        self._init_funclist(funclist)
        self._init_calls(call_funclist)
        self._init_connections(conn)
    def testClassMethodWrap(self):  # {{{
        """Wrapping class method"""

        class A(object):
            def helloworld(self, a, b):
                return "hello world"

        w = CallableWrapper(A.helloworld)
        w.wrap(DummyReplacement)
        A.helloworld = method(w, None, A)

        z = CallableWrapper(A.helloworld)
        z.wrap(DummyReplacement)
        A.helloworld = method(z, None, A)

        a = A()
        self.assertEqual(a.helloworld(1, 2), "HELLO: HELLO: hello world :WORLD :WORLD")
    def testInstanceMethodWrap(self):  # {{{
        """Wrapping instance method"""

        class A(object):
            def helloworld(self, a, b):
                return "hello world"

        a = A()
        w = CallableWrapper(a.helloworld)
        w.wrap(DummyReplacement)
        a.helloworld = method(w, a, A)

        z = CallableWrapper(a.helloworld)
        z.wrap(DummyReplacement)
        a.helloworld = method(z, a, A)

        self.assertEqual(a.helloworld(1, 2), "HELLO: HELLO: hello world :WORLD :WORLD")
        self.assertEqual(A().helloworld(1, 2), "hello world")
 def testMethodWrap(self): #{{{
     '''If return value of arg is not a method, makes it into a method'''
     cw = CallableWrapper(self.func)
     cw.wrap(self.deco)
     self.assertTrue(isinstance(cw._newcall, method))
Beispiel #22
0
class BaseSignal(object): #{{{
    __slots__ = ('__weakref__', '_func', '__name__', '_funclist',
                    '_call_funclist', '_connections', '_vars')
    def __init__(self, signal, **kwargs): #{{{
        if not iscallable(signal):
            raise TypeError("Argument must be callable.")
        expected = ('weak', 'active', 'activate_on_call')
        if any(kw for kw in kwargs if kw not in expected):
            raise ValueError("Detected unexpected arguments: %s" %', '.join([found]))
        weak = kwargs.get('weak', True)
        self._func = CallableWrapper(signal, weak=weak)
        self.__name__ = self._func.__name__
        funclist = self._funclist = dict()
        conn = self._connections = dict()
        call_funclist = self._call_funclist = dict((n, odict()) for n in ('after', 'replace', 'around', 'before'))
        self._vars = getattr(self, '_vars', dict())
        self._vars.update(active=kwargs.get('active', True),
                callactivate=kwargs.get('activate_on_call', False), caller=callfunc)

        # Initialize values of function lists
        self._init_funclist(funclist)
        self._init_calls(call_funclist)
        self._init_connections(conn)
    # End def #}}}

    def _init_funclist_names(self): #{{{
        yield 'before'
        yield 'after'
    # End def #}}}

    def _init_funclist(self, funclist): #{{{
        init = self._init_funclist_names()
        funclist.update((name, []) for name in init)
    # End def #}}}

    def _init_calls(self, call_funclist): #{{{
        cleanlist = self._cleanlist
        for cftype in ('before', 'replace', 'around', 'after'):
            call_funclist[cftype].update(getattr(self, '_init_calls_%s' %cftype)(cleanlist).iteritems())
    # End def #}}}

    def _init_calls_before(self, cleanlist): #{{{
        def call_before(self, cw, func, ret, args, kwargs): #{{{
            callfunc = self.caller
            for bfunc, t in cleanlist('before'):
                callfunc(self, bfunc, 'before', False, None, *args, **kwargs)
            return ret
        # End def #}}}
        return odict(before=call_before)
    # End def #}}}

    def _init_calls_replace(self, cleanlist): #{{{
        return odict()
    # End def #}}}

    def _init_calls_around(self, cleanlist): #{{{
        return odict()
    # End def #}}}

    def _init_calls_after(self, cleanlist): #{{{
        def call_after(self, cw, func, ret, args, kwargs): #{{{
            callfunc = self.caller
            for afunc, t in cleanlist('after'):
                callfunc(self, afunc, 'after', False, None, *args, **kwargs)
            return ret
        # End def #}}}
        return odict(after=call_after)
    # End def #}}}

    def _init_default_connections(self): #{{{
        init = ('after', 'before')
        for n in init:
            yield n
    # End def #}}}

    def _init_connections(self, connections): #{{{
        init = self._init_default_connections()
        connections.update((n, (connect_func, disconnect_func)) for n in init)
    # End def #}}}

    def __call__(self, *args, **kwargs): #{{{
        if not self.valid:
            warn('Calling an invalid signal', RuntimeWarning, stacklevel=2)
            return
        if self.activate_on_call:
            self.active = True
        return self._func(*args, **kwargs)
    # End def #}}}

    def _cleanlist(self, l): #{{{
        # If everything is being deleted e.g. program termination
        # don't do anything and just return
        if not hasattr(self, '_funclist'):
            return
        l = self._funclist[l]
        llen, i = len(l), 0
        while i < llen:
            func = l[i]
            if func.isdead:
                del l[i]
                llen -= 1
            else:
                yield func, i
                i += 1
    # End def #}}}

    def _generate_wrapfactory(self): #{{{
        def do_wrap(func): #{{{
            def newcall(s, *args, **kwargs): #{{{
                ret = None
                callfunclist = self._call_funclist
                for name, cfunc in callfunclist['before'].iteritems():
                    ret = cfunc(self, s, func, ret, args, kwargs)
                ret = func(*args, **kwargs)
                for name, cfunc in callfunclist['after'].iteritems():
                    ret = cfunc(self, s, func, ret, args, kwargs)
                return ret
            # End def #}}}
            return newcall
        # End def #}}}
        return do_wrap
    # End def #}}}

    def reload(self): #{{{
        sfunc = self._func
        if sfunc.isdead:
            return
        sfunc.unwrap()
        sfunc_wrap = sfunc.wrap
        callfunclist = self._call_funclist
        for ctype in ('replace', 'around'):
            for name, citer in callfunclist[ctype].iteritems():
                for cfunc in citer(self):
                    sfunc_wrap(cfunc)
        do_wrap = self._generate_wrapfactory()
        sfunc_wrap(do_wrap)
        self._vars['active'] = True
    # End def #}}}

    def _find_cond(self, **kw): #{{{
        return lambda s, ln, sl, f, i: True
    # End def #}}}

    def _find(self, func, siglistseq=None, **kw): #{{{
        temp_siglistseq = self._funclist
        if siglistseq not in temp_siglistseq:
            siglistseq = temp_siglistseq
        else:
            siglistseq = {siglistseq: temp_siglistseq[siglistseq]}
        del temp_siglistseq
        foundindex = foundlist = None
        fid, cleanlist = cid(func), self._cleanlist
        fcond = self._find_cond(**kw)
        for listname, siglist in siglistseq.iteritems():
            for f, index in cleanlist(listname):
                if f.cid == fid:
                    if not fcond(self, listname, siglist, f, index):
                        continue
                    foundindex, foundlist = index, siglist
                    break
            else:
                continue
            break
        if foundindex is not None:
            return foundindex, foundlist
        return None
    # End def #}}}

    def connect(self, *after, **other_slots): #{{{
        activate = self.activate_on_call
        self.activate_on_call = False
        osg = other_slots.get
        other_slots['after'] = list(after) + list(osg('after', []))

        for name, (cfunc, _) in self._connections.iteritems():
            cfunc(self, name, other_slots)

        self.activate_on_call = activate
        if self.active:
            self.reload()
    # End def #}}}

    def disconnect(self, *after, **other_slots): #{{{
        osg = other_slots.get
        if after or 'after' in other_slots:
            other_slots['after'] = list(after) + list(osg('after', []))
        no_slots = not any(osg(name, None) for name in self._funclist)
        if 'deleteall' not in other_slots:
            other_slots['deleteall'] = no_slots

        for name, (_, dfunc) in self._connections.iteritems():
            dfunc(self, name, other_slots)

        if self.active:
            self.reload()
    # End def #}}}

    def slot(self, name): #{{{
        return (f for f, _ in self._cleanlist(name))
    # End def #}}}

    def _setactive(self, v): #{{{
        opt = self._vars
        orig = opt['active']
        v = bool(v)
        opt['active'] = v
        if orig and not v:
            self._func.unwrap()
        elif not orig and v:
            self.reload()
    # End def #}}}

    def _setcallactivate(self, v): #{{{
        self._vars['callactivate'] = bool(v)
    # End def #}}}

    def _setcaller(self, c): #{{{
        if c is None:
            return
        elif not iscallable(c):
            raise TypeError('caller property must be a valid callable object')
        self._vars['caller'] = CallableWrapper(c, weak=False)
    # End def #}}}

    # Properties #{{{
    func = property(lambda s: s._func)
    valid = property(lambda s: not s._func.isdead)
    connected = property(lambda s: any(s._funclist.itervalues()))
    active = property(lambda s: s._vars['active'], lambda s, v: s._setactive(v))
    activate_on_call = property(lambda s: s._vars['callactivate'], lambda s, v: s._setcallactivate(v))
    caller = property(lambda s: s._vars['caller'], lambda s, c: s._setcaller(c))
    original = property(lambda s: s._func.original)
 def testUnwrap(self): #{{{
     '''Unwrapping returns to default call state'''
     cw = CallableWrapper(self.func)
     cw.wrap(self.deco)
     cw.unwrap()
     self.assertEqual(cw._newcall, cw.call)
 def testNonMethodCallable(self): #{{{
     '''Non-method callable returns actual callable'''
     w = CallableWrapper(DummyFunction)
     self.assert_(w._getcallable() is DummyFunction)
 def testNonMethodWrap(self):  # {{{
     """Wrapping a non-method callable"""
     w = CallableWrapper(DummyFunction)
     w.wrap(DummyReplacement)
     self.assertEqual(w(1, 2), "HELLO: %s :WORLD" % DummyFunction(1, 2))
 def testClassInstance(self): #{{{
     '''Class method callable's im_func returned'''
     A = DummyClass
     w = CallableWrapper(A.DummyMethod)
     self.assert_(w._getcallable() is A.DummyMethod.im_func)
 def testMethodInstance(self): #{{{
     '''Instance method callable's im_func returned'''
     A = DummyClass
     a = A()
     w = CallableWrapper(a.DummyMethod)
     self.assert_(w._getcallable() is a.DummyMethod.im_func)