On Jan 4, 10:43 am, [EMAIL PROTECTED] wrote:
> Hi,

Hi

[...]
> # Does not work: all enhanced methods only call the last wrapped originial
> # method. It seems the name 'method' in the surrounding scope of the
> # def _(...) function definition only refers to the last loop value(?)
> def ERRONEOUS_enhance_all_methods(cls, replacement):
>     for methodname in cls.__dict__:
>         if not methodname.startswith("__"):
>             method = getattr(cls, methodname)
>             def _f(*args, **kwargs):
>                 return replacement(method, *args, **kwargs)
>             _f.__name__ = methodname
>             setattr(cls, methodname, types.MethodType(_f, None, cls))
>

This is normal: After ERRONEOUS_enhance_all_methods is called, the
value method is the one from the last iteration of the loop. All
subsequent references to 'method' (in function _f) will return that
last value. To solve this problem you need to fix the object 'method'
is bound to in function _f:

def enhance_all_methods(cls, replacement):
    # The following binds 'method' to its current value in _f
    def replace(method):
        def _f(*args, **kwargs):
            return replacement(method, *args, **kwargs)
        return _f
    for methodname in cls.__dict__:
        if not methodname.startswith("__"):
            _f = replace(getattr(cls, methodname))
            _f.__name__ = methodname
            setattr(cls, methodname, types.MethodType(_f, None, cls))

Of course this looks more like your first version, which trims down to
the following and is probably a better option:

def enhance_all_methods(cls, replacement):
    for methodname in cls.__dict__:
        if not methodname.startswith("__"):
            enhance_method(cls, methodname, replacement)

HTH

--
Arnaud

-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to