4

Suppose I have a class

class A(object):
  def myfunction():
    """A."""
    pass

and a subclass

class B(A):
  def myfunction():
    pass

is it possible to inherit the API doc of B.myfunction from A.myfunction with sphinx? The documentation for B.myfunction should be "A." as well.

mzjn
  • 48,958
  • 13
  • 128
  • 248
alfa
  • 3,058
  • 3
  • 25
  • 36

1 Answers1

5

In python, you can set an object's documentation by assigning to its "docstring" __doc__ after it is created. The cleanest way to do this is by using a decorator that copies the docstring of the parent class. You can even provide an additional docstring for B.myfunction, and append it to the documentation of A.myfunction (since you are presumably specializing it). Using the following decorator (adapted from my answer to a similar question), you can copy the docstring of the overridden function like this:

def copydoc(fromfunc, sep="\n"):
    """
    Decorator: Copy the docstring of `fromfunc`
    """
    def _decorator(func):
        sourcedoc = fromfunc.__doc__
        if func.__doc__ == None:
            func.__doc__ = sourcedoc
        else:
            func.__doc__ = sep.join([sourcedoc, func.__doc__])
        return func
    return _decorator

class A(object):
  def myfunction():
    """Documentation for A."""
    pass

class B(A):
  @copydoc(A.myfunction)
  def myfunction():
    """Extra details for B."""
    pass

Result:

>>> help(B.myfunction)
Help on method myfunction in module __main__:

myfunction() unbound __main__.B method
    Documentation for A.
    Extra details for B.

This needs to explicitly say where you're copying the docstring from: @copydoc(A.myfunction). It is arguably more flexible than a fully automatic solution, since you can choose where to copy from.

Based on the answers to this question, I conclude that a clean, fully automatic solution is not possible: "Functions only become methods at runtime", says this answer, so the decorator has no way to look up the parent class name in the function object. The best you could do is a decorator @copydoc(A). That's very easy, but then you might as well add the source method's name and retain the flexibility. (If you don't agree, comment and I'll provide the code).

Community
  • 1
  • 1
alexis
  • 48,685
  • 16
  • 101
  • 161
  • Very good answer. It's a little bit strange that such a simple thing is not possible in python because of its flexibility. :D – alfa Dec 06 '12 at 14:20
  • I have implemented a more powerful version of this answer here: https://stackoverflow.com/questions/60000179/sphinx-insert-argument-documentation-from-parent-method/60012943#60012943 – Samufi Feb 01 '20 at 00:30