Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve original @classmethod, @staticmethod or @property

Tags:

python

I understand that @decorator.decorator doesn't allow to decorate above @staticmethod, @classmethod (and perhaps also @property). I understand the usage:

class A(object):
    @classmethod
    @mydecorator
    def my_method(cls): pass

But, in a debugging module, I still want to try to do it dynamically. So I was wondering what is the way to retrieve the original method from those descriptor(?). I've read few responses, but I'm still confused...

I see some example with a class, and retrieving:

class my_class(property):
    def __get__(self, obj, cls):
        return self.fget.__get__(None, cls)

I love the signature-preserving of decorator, but still not sure how to do this. The logic I try to implement is:

import decorator

def mydecorator(f, *d_args, **d_kwargs):
    if (isinstance(f, classmethod)):
        return classmethod(mydecorator(f.__get__.?WHATELSE?))
    elif (isinstance(f, staticmethod)):
        return staticmethod(mydecorator(f.__get__.?WHATELSE?))
    elif (isinstance(f, property)):
        return property(mydecorator(f.__get__.?WHATELSE?))
    else:
        return decorator.decorator(f)

I'm trying to do this in Python 2.6, so I also welcome pointing that @decorator is changed (corrected?) in future version of python.

Thanks.

like image 868
Danosaure Avatar asked Dec 27 '22 05:12

Danosaure


1 Answers

Considering:

>>> def original():pass

>>> classmethod(original).__func__ == original
True
>>> staticmethod(original).__func__ == original
True
>>> property(original).fget == original
True

Your function should be something like:

import decorator

def mydecorator(f, *d_args, **d_kwargs):
    if (isinstance(f, classmethod)):
        return classmethod(mydecorator(f.__func__))
    elif (isinstance(f, staticmethod)):
        return staticmethod(mydecorator(f.__func__))
    elif (isinstance(f, property)):
        return property(mydecorator(f.fget))
    else:
        return decorator.decorator(f)

UPD: Sorry for inattention. In 2.* prior to 2.7. , you should do something like:

import decorator
def mydecorator(f, *d_args, **d_kwargs):
    if (isinstance(f, classmethod)):
        return classmethod(mydecorator(f.__get__(True).im_func))
    elif (isinstance(f, staticmethod)):
        return staticmethod(mydecorator(f.__get__(True)))
    elif (isinstance(f, property)):
        return property(mydecorator(f.fget))
    else:
        return decorator.decorator(f)

Note that those True objects in f.__get__(True).im_func statement could be replaced by any object except None.

like image 180
Odomontois Avatar answered Dec 31 '22 14:12

Odomontois