postelrich
postelrich

Reputation: 3496

Problems with decorator with arguments to wrap class method

I am trying to write a decorator with arguments that wraps methods for a particular class. I've tried both a function and a class decorator and run into different errors. Playing around with arguments for the signatures hasn't helped.

Example usage

class X(object):
    def __init__():
        self.a = True
        self.b = ""

    @my_deco([])
    def xfunc(self, x, y):
        do stuff...

foo = X()
foo.xfunc()

Function decorator:

def my_deco(param1):
    def wrapped(func):
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return func(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return param1
        return wrapped_f
    return wrapped

Gives this error: TypeError: wrapped() takes exactly 1 argument (3 given)

Class decorator:

class my_deco(object):

    def __init__(self, param1=False):
        self.param1 = param1

    def __call__(self, f):

        @wraps(f)
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return f(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return self.param1
        return wrapped_f
    #
    #def __get__(self, obj, objtype):
    #    """Support instance methods."""
    #    import functools
    #    return functools.partial(self.__call__, obj)

Gives this error: TypeError: call() takes exactly 2 arguments (3 given)

Any clues how to get this to work?

Upvotes: 0

Views: 1363

Answers (1)

postelrich
postelrich

Reputation: 3496

In trying to create runnable code to post as an example, I came across my error. Probably got mixed up at some point in writing the wrapper and trying to get it to work, I overlooked a simple mistake.

Below is the working example. The mistake I made, was I didn't pass a parameter to the decorator for the method I was testing, thus causing the exception. This explains the problem since the decorator was expecting a parameter.

def my_deco(param1):
    def wrapped(func):
        def wrapped_f(self, *args, **kwargs):
            try:
                self.a = True
                return func(self, *args, **kwargs)
            except Exception as e:
                self.b = str(e)
                self.a = False
                return param1
        return wrapped_f
    return wrapped

class Base(object):
    def __init__(self, attr1, attr2):
        self.attr1 = attr1
        self.attr2 = attr2
        self.a = False
        self.b = ""

    @my_deco([])
    def xfunc(self, x, y):
        return x + y

def ClassFactory(attr1, attr2, base=Base):
    class NewClass(Base):
        def __init__(self):
            super(NewClass, self).__init__(attr1, attr2)

    return NewClass

ChildClass = ClassFactory("foo", "bar")
child = ChildClass()

print child.xfunc(1, 2) # no exception
print child.xfunc('x', 2) # throws exception

Upvotes: 1

Related Questions