Skip to content
Advertisement

Why am I unable to get docstring printed out using sphinx python package?

I am using Sphinx to document out my functions. However, it does not read my doc strings for function with a decorator. Sphinx just replace the function doc strings with <The magic happens here>

My functions are written in this manner with a decorator. How do i make Sphinx detect the doc strings in the function.

Folder is in this format

  • Project
    • Functions – function.py
      • docs
def wrap(pre, post):
    """ Wrapper """

    def decorate(func):
        """ Decorator """

        def call(*args, **kwargs):
            """ The magic happens here """
            pre(func)
            result = func(*args, **kwargs)
            post(func)
            return result
        return call
    return decorate

def entering(func, *args):
    """ Pre function logging """
    logging.debug("Entered {}".format(func.__name__))
    # logging.info(func.__doc__)
    logging.debug("Function at line {} in {}".format(func.__code__.co_firstlineno, func.__code__.co_filename))
    try:
        logging.debug("The argument {} is {}".format(func.__code__.co_varnames[0], *args))
    except IndexError:
        logging.debug("No arguments")


def exiting(func):
    """ Post function logging """
    logging.debug("Exited {}".format(func.__name__))

@wrap(entering, exiting)
def function(a, b):
    """
    Function to execute
    :param a:
    :param b:
    :return: Sum of a+b
    """
    return a+b

Advertisement

Answer

You need your decorate function to copy the docstring from func onto call before returning it. Otherwise Sphinx can only get the docstring of call, not the docstring of the original function.

You can do this yourself by directly doing call.__doc__ = func.__doc__, or you could use the functools.wraps decorator from the standard library to do it for you (which also copies a few other attributes by default, and can be customized quite a bit).

I’d try:

import functools

def wrap(pre, post):
    """ Wrapper """

    def decorate(func):
        """ Decorator """

        @functools.wraps(func)              # this copies over the docstring and more
        def call(*args, **kwargs):
            """ The magic happens here """
            pre(func)
            result = func(*args, **kwargs)
            post(func)
            return result
        return call
    return decorate
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement