Calvin Spealman wrote: > I'd like to make a claim about the following example, that > update_wrapper should be improved to preserve the behavior of known, > built-in decorators. In this case, I'm talking about staticmethod. The > order I list here feels natural, but it obviously doesn't work. The only > reason it doesn't seems to be that it is trying to decorate the > descriptor, not the function itself. This is expected, but it could > certainly be smart enough to detect a descriptor and attempt to get the > actual callable underneath, could it not? It would not work for all > cases, of course. > > >>> def d(f): > ... def nf(*a, **kw): > ... print "decorated function called" > ... return f(*a, **kwargs) > ... functools.update_wrapper(nf, f) > ... return nf > ... > >>> class A(object): > ... @d > ... @staticmethod > ... def a(self): > ... print "a" > ... > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > File "<stdin>", line 3, in A > File "<stdin>", line 5, in d > File > "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/functools.py", > line 33, in update_wrapper > setattr(wrapper, attr, getattr(wrapped, attr)) > AttributeError: 'staticmethod' object has no attribute '__module__' d expects a function object, this code gives it a nonfunction object - that's a bug in the function definition. Decorators differ in whether or not they are stackable with other function decorators (i.e. they return a function object, or another callable with a compatible API), or whether they can only be used as terminal decorators (i.e. they return something that doesn't look like a function). classmethod and staticmethod fit in the latter category, and I don't see any reason to change them. Consider what happens in your example without the update_wrapper line: >>> def d(f): ... def new(*args, **kwds): ... print "Calling decorated function" ... return f(*args, **kwds) ... return new ... >>> class A(object): ... @d ... @staticmethod ... def a(*args, **kwds): ... print "Method called" ... print "Args:", args ... print "Keywords:", kwds ... >>> A().a() Calling decorated function Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in new TypeError: 'staticmethod' object is not callable If anything, the AttributeError from update wrapper is a net win since the buggy code breaks at class definition time rather than when you try to call the broken method. Cheers, Nick. P.S. Checking for __get__ won't help with detecting non-function descriptors anyway - function objects themselves define that method in order to provide Python's normal instance method binding behaviour. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia --------------------------------------------------------------- http://www.boredomandlaziness.org
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4