Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters to decorator at runtime

Tags:

python

If I create a python decorator function like this

def retry_until_true(tries, delay=60):
    """
    Decorator to rety a function or method until it returns True.
    """
    def deco_retry(f):
        def f_retry(*args, **kwargs):
            mtries  = tries
            rv = f(*args, **kwargs)
            while mtries > 0:
                if rv is True:
                    return True
                mtries -= 1
                time.sleep(delay)
                rv = f(*args, **kwargs)
            return False
        return f_retry
    return deco_retry

I can use it like this

    @retry_until_true(20, delay=30)
    def check_something_function(x, y):
        ...
        return True

But is there a way to pass different values for 'tries' and 'delay' to the decorator at runtime, so that 20 and 30 are variables?

like image 547
gklinich Avatar asked Aug 07 '12 23:08

gklinich


1 Answers

You can use a class as a decorator, with instance variables for tries and delay:

class RetryUntilTrue(object):
    def __init__(self, f=None, tries=10, delay=30):
        self.f = f
        self.tries = tries
        self.delay = delay

    def __call__(self, *args, **kwargs):
        if self.f is None:
            self.f = args[0]
        else:
            tries = self.tries
            while tries:
                if self.f(*args, **kwargs):
                    return True

                tries -= 1
                time.sleep(self.delay)

Usage:

@RetryUntilTrue
def foo(x):
    pass

foo.tries = 20
foo.delay = 1

@RetryUntilTrue(tries=100, delay=9999)
def bar(x):
    pass

bar.tries -= 1
bar.delay = foo.delay
like image 192
Joel Cornett Avatar answered Sep 29 '22 21:09

Joel Cornett