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 | [EMAIL PROTECTED] | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com