I have a problem using docstrings with decorators. Given the following example:
def decorator(f):
    def _decorator():
        print 'decorator active'
        f()
    return _decorator
@decorator
def foo():
    '''the magic foo function'''
    print 'this is function foo'
help(foo)
Now the help doesn't show me the docstring of foo as expected, it shows:
Help on function _decorator in module __main__:
_decorator()
Without the decorator, the help is correct:
Help on function foo in module __main__:
foo()
    the magic foo function
I know, that the function foo is wrapped by the decorator, and so the function object is not the function foo any more. But what is a nice solution to get the docstring (and the help) as expected?
All modules should normally have docstrings, and all functions and classes exported by a module should also have docstrings. Public methods (including the __init__ constructor) should also have docstrings. A package may be documented in the module docstring of the __init__.py file in the package directory.
Accessing Docstrings: The docstrings can be accessed using the __doc__ method of the object or using the help function.
Docstrings are accessible from the doc attribute (__doc__) for any of the Python objects and also with the built-in help() function. An object's docstring is defined by including a string constant as the first statement in the object's definition.
Module docstrings are placed at the top of the file even before any imports. Module docstrings should include the following: A brief description of the module and its purpose. A list of any classes, exception, functions, and any other objects exported by the module.
Use functools.wraps() to update the attributes of the decorator:
from functools import wraps
def decorator(f):
    @wraps(f)
    def _decorator():
        print 'decorator active'
        f()
    return _decorator
@decorator
def foo():
    '''the magic foo function'''
    print 'this is function foo'
help(foo)
Also see the Standard Library documentation for functools.
I found a solution, but don't know if it's really nice:
def decorator(f):
    def _decorator():
        print 'decorator active'
        f()
    _decorator.__name__=f.__name__
    _decorator.__doc__=f.__doc__
    return _decorator
The part with _decorator.__name__=f.__name__ seems a little bit hideous... What do you think?
Take a look at functools.wraps: http://docs.python.org/library/functools.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With