Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the proper way to decorate the methods of a class? #3

Closed
jmkacz opened this issue May 12, 2015 · 7 comments
Closed

What is the proper way to decorate the methods of a class? #3

jmkacz opened this issue May 12, 2015 · 7 comments

Comments

@jmkacz
Copy link

jmkacz commented May 12, 2015

This question is involves v0.8.1 versus v0.9.0, and class decoration.

With v0.8.1 and no decorator library, the following worked. Upgrading to v0.9.0 and installing the decorator library fails, because the behavior of the fallback decorator logic from v0.8.1 is different from the behavior of the decorator library.

What is the proper way to decorate the methods of a class, using the retry library?

import itertools
from retry import retry
from sailthru.sailthru_client import SailthruClient
from sailthru.sailthru_error import SailthruClientError

RETRIES_TRIES = 20
RETRIES_DELAY = 0.5
RETRIES_MAX_DELAY = 1.0
RETRIES_BACKOFF = 2
RETRIES_JITTER = (0, 1)

# taken from http://stackoverflow.com/a/6307868
def for_all_methods(decorator):
        def decorate(cls):
                # Collect all methods from the given class, and the classes
                # it inherits from. Then, discard "magic" methods.
                attrs = [attr for attr in itertools.chain(*[other.__dict__.keys() for other in cls.__mro__]) if not (attr.startswith('__') and attr.endswith('__'))]
                for attr in attrs:
                        if callable(getattr(cls, attr)):
                                setattr(cls, attr, decorator(getattr(cls, attr)))
                return cls
        return decorate

@for_all_methods(retry(SailthruClientError, RETRIES_TRIES, RETRIES_DELAY, RETRIES_MAX_DELAY, RETRIES_BACKOFF, RETRIES_JITTER))
class RobustSailthruClient(SailthruClient):
        pass
Traceback (most recent call last):
  File "foo.py", line 30, in <module>
    class RobustSailthruClient(SailthruClient):
  File "foo.py", line 25, in decorate
    setattr(cls, attr, decorator(getattr(cls, attr)))
  File "<string>", line 2, in retry_decorator
  File "/home/jon/.virtualenvs/ei.new/lib/python2.6/site-packages/decorator.py", line 213, in decorator
    evaldict, __wrapped__=func)
  File "/home/jon/.virtualenvs/ei.new/lib/python2.6/site-packages/decorator.py", line 196, in create
    self = cls(func, name, signature, defaults, doc, module)
  File "/home/jon/.virtualenvs/ei.new/lib/python2.6/site-packages/decorator.py", line 131, in __init__
    raise TypeError('You are decorating a non function: %s' % func)
TypeError: You are decorating a non function: <unbound method RobustSailthruClient.cancel_blast>
@jmkacz
Copy link
Author

jmkacz commented May 12, 2015

Given that SailthruClient is coming from a library I pip installed (don't have the source in my code tree).

Is it the case that I would have to fork the library and place it before each function?

@invl
Copy link
Owner

invl commented May 13, 2015

Does v0.8.1 + decorator library work?

@jmkacz
Copy link
Author

jmkacz commented May 13, 2015

v0.8.1 + decorator fails the same way

@jmkacz
Copy link
Author

jmkacz commented May 13, 2015

v0.8.1 or v0.9.0 w/o decorator, and thus failing back to https://github.com/invl/retry/blob/0.8.1/retry/compat.py succeeds

@invl
Copy link
Owner

invl commented May 13, 2015

I don't think retry library is responsible for this, but you could try to change setattr(cls, attr, decorator(getattr(cls, attr))) to setattr(cls, attr, decorator(getattr(cls, attr).im_func))

@invl
Copy link
Owner

invl commented May 20, 2015

Close due to inactivity.

@invl invl closed this as completed May 20, 2015
@janani-s
Copy link

janani-s commented Oct 6, 2015

@invl That worked, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants