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

Radek Kanovsky rk at dat.cz
Mon Jan 17 11:06:31 EST 2005

Following generic function doesn't work:

    from peak.api import *

    def gm (obj) :

    [gm.when('obj in object')]
    def gmObj (obj) :
        print 'gmObj', obj

    [gm.when('obj in int')]
    def gmInt (next_method, obj) :
        print 'gmInt', obj

    [gm.around('obj in object')]
    def aroundObj (next_method, obj) :
        print 'aroundObj', obj

    >>> gm(1)
    TypeError: gmInt() takes exactly 2 arguments (3 given)

Problem is in method GenericFunction.combine() which tries to connect
'primary' and 'around' parts and calls 'method_chain' such way
that 'gmInt' is turned into bound method twice (via instancemethod
construct). As every binding "eats" one argument from gmInt signature,
we get metioned TypeError.

I have found easier to fix 'method_chain()' than 'combine()', but 
it is not probably optimal.


--- strategy.py (revision 36)
+++ strategy.py (working copy)
@@ -43,7 +43,7 @@
 from protocols import Protocol, Adapter, StickyAdapter
 from protocols.advice import getMRO
 import protocols, operator, inspect
-from types import ClassType, InstanceType
+from types import ClassType, InstanceType, MethodType
 ClassTypes = (ClassType, type)
 from sys import _getframe
 from weakref import WeakKeyDictionary
@@ -594,6 +594,8 @@
             return method   # not a function, therefore not chainable
         if args and args[0]=='next_method':
+            if type(method)==MethodType and getattr(method,'im_self',None) :
+                # method is already bound
+                return method
             next_method = method_chain(methods)
             return instancemethod(method,next_method,type(next_method))

More information about the PEAK mailing list