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

decorate classmethods #86

Closed
mahmoud opened this issue Aug 1, 2016 · 3 comments
Closed

decorate classmethods #86

mahmoud opened this issue Aug 1, 2016 · 3 comments

Comments

@mahmoud
Copy link
Owner

mahmoud commented Aug 1, 2016

@hynek wants em: https://hynek.me/articles/decorators/

@mahmoud
Copy link
Owner Author

mahmoud commented Aug 3, 2016

Haha, sorry to disappoint, but after some experimentation, it's quite clear that this API doesn't make sense. Have a look at this test:

def test_wraps_wrappers():
    call_list = []

    def call_list_appender(func):
        @wraps(func)
        def appender(*a, **kw):
            call_list.append((a, kw))
            return func(*a, **kw)
        return appender

    class Num(object):
        def __init__(self, num):
            self.num = num

        @call_list_appender
        @classmethod
        def added(cls, x, y=1):
            return cls(x + y)

    assert Num(1).num == 1
    assert Num.added(0, 2).num == 2

    assert len(call_list) == 1

All the details aside, the func that is passed to call_list_appender is a classmethod instance. Classmethods are not callable objects. Done deal. Pretty sure this is mentioned in Graham's gigantic decorator posts, too.

The solve is to simply reverse the order of the decoration in your code, and add better exception messaging to boltons, of course:

...
        @classmethod
        @call_list_appender
        def added(cls, x, y=1):
            return cls(x + y)
...

The above works fine for me. This is one of those corner cases that makes wrapt so complex, and another reason why I only call out wraps as a replacement for decorator.py, not wrapt. I'll leave this issue open until I have those boltons exceptions in place.

@mahmoud mahmoud closed this as completed in 4140386 Aug 3, 2016
@hynek
Copy link
Contributor

hynek commented Aug 3, 2016

Well, you could simplify this to the fact that it’s about descriptors in general. :) I only used classmethods as a concrete example. And yeah, shit’s complicated but descriptors happen.

@hynek
Copy link
Contributor

hynek commented Aug 3, 2016

(please ping me when you release this fix so I can update the error message in the post :))

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

2 participants