Coming from this post. The accepted answer works nicely with decorators which take no argument. I'm trying to extend this solution to make it take arguments for the applying decorator.
In detail, I have functions which make external api calls. Because those calls fail frequently, I applied retry decorator from this library to all the functions. To avoid putting the @retry(...)
line again and again for all the functions, I decided to centralize them in a class. I created RetryClass and put all the functions as classmethod
in the class. Now, I'm looking for a way to apply the retry
decorator for all the methods of the class, so that I can just keep adding new methods in the class and it will automatically apply the retry
decorator for the new methods.
Note: the retry decorator takes arguments.
@retry(wait_random_min=100, wait_random_max=300, stop_max_attempt_number=3)
Here is my code:
from retrying import retry
def for_all_methods(decorator):
def decorate(cls):
for attr in cls.__dict__:
if callable(getattr(cls, attr)):
setattr(cls, attr, decorator(getattr(cls, attr)))
return cls
return decorate
@for_all_methods(retry(wait_random_min=100, wait_random_max=300, stop_max_attempt_number=3))
class RetryClass(object):
@classmethod
def a(cls):
pass
def test():
RetryClass.a()
return
This throws the following error:
Traceback (most recent call last):
File "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 1596, in <module>
globals = debugger.run(setup['file'], None, None, is_module)
File "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", line 974, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/Users/gyoho/Datatron/Dev/class-decorator/main.py", line 26, in <module>
test()
File "/Users/gyoho/Datatron/Dev/class-decorator/main.py", line 22, in test
RetryClass.a()
TypeError: unbound method a() must be called with RetryClass instance as first argument (got nothing instead)
However, commenting out the class decorator runs with no error. Is there anything I'm missing?