December 17, 2012

Civilize your Python @decorators

Here's a quick tip. I was trying to use Sphinx's autodoc on a function that I had decorated, and found that the docstrings were consumed by the process, and therefore that the function did not appear in the documentation output.

After looking around a bit, I found the relevant mention in the Sphinx docs:

From Python 2.5, functools.wraps() can be used to create well-behaved decorating functions.

It's easy to use. functools.wraps is itself a decorator, appropriately, that you use to decorate the function that your decorator returns, passing it the function that you're in the process of decorating.

Here's a sample from the python docs themselves.

>>> def my_decorator(f):
...     @wraps(f)
...     def wrapper(*args, **kwds):
...         print 'Calling decorated function'
...         return f(*args, **kwds)
...     return wrapper
...
>>> @my_decorator
... def example():
...     """Docstring"""
...     print 'Called example function'
...

After reading this, you should never again skip this step. It's just the right thing to do.