[PEAK] dispatch: around generic function with next_method (bug)

Radek Kanovsky rk at dat.cz
Mon Jan 17 13:42:06 EST 2005

On Mon, Jan 17, 2005 at 11:42:49AM -0500, Phillip J. Eby wrote:

> It's method_chain() that's broken, it should be able to safely chain method 
> chains, but I didn't write a test that exercised the case where a callable 
> is a chain with a 'next_method'.  I've added a test case now and fixed it.
> Thanks for all the useful bug reports; I haven't made any real use of 
> before/after/around stuff yet myself, just the tests.

I discovered bug during experiments with my TemplateFunction. It was
rather hard as I blamed myself formerly :-) Purpose of TemplateFunction
could be obvious from small example:

    # template function parametrized by three parameters
    # (parameters do not correspond to function arguments)
    tf = TemplateFunction(['p1','p2','p3'])

    [tf.t_when('p1 in object')]
    def whenDefault (a1, a2) :
        print 'whenDefault'

    [tf.t_when('p1 in int')]
    def whenInt (next_method, a1, a2) :
        print 'whenInt'
        next_method(a1, a2)

    [tf.t_around('p2 in object')]
    def aroundDefault (next_method, a1, a2) :
        print 'aroundDefault'
        next_method(a1, a2)

    # create callable function for given parameters
    cf = tf[1,'a', None]

    # use compiled function many times
    >>> cf(1,1)

I am not sure about syntax, names and all of its usability nevertheless
the first draft is here:

    from peak.core import *
    from dispatch.functions import GenericFunction, Dispatcher
    from protocols.advice import add_assignment_advisor, getFrameInfo
    import sys

    class TemplateFunction (Dispatcher) :
        def __init__ (self, params) :
            Dispatcher.__init__(self, params)

        combine = GenericFunction.combine.im_func

        def _decorate(self, cond, qual) :
            frame = sys._getframe(2)
            cond = self.parseRule(cond, frame=frame) or cond

            def registerMethod(frm, name, value, old_locals) :
                func = qual,value
                kind,module,locals_,globals_ = getFrameInfo(frm)
                if kind=='class':
                    raise NotImplementedError
                    self[cond] = func
                #if old_locals.get(name) in (self,self.delegate):
                #    return self.delegate
                return value
            return add_assignment_advisor(registerMethod,frame=frame)

        def t_when (self, cond) :
            return self._decorate(cond, 'primary')

        def t_before (self, cond) :
            return self._decorate(cond, 'before')

        def t_after (self, cond) :
            return self._decorate(cond, 'after')

        def t_around (self, cond) :
            return self._decorate(cond, 'around')


More information about the PEAK mailing list