Inherit class docstrings when generating documentation using Sphinx

47 views Asked by At

I am trying to inherit docstrings from a parent class when generating documentation using Sphinx. Here's a minimal repro:

@dataclass
class A():
    """
    Attributes:
        a:
            This is the variable 'a'
    """
    a: int = 0

@dataclass
class B(A):
    """
    Attributes:
        b:
            This is the variable 'b'
    """
    b: int = 0

My conf.py looks like this:

import os
import sys
sys.path.insert(0, os.path.abspath('../test_config'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.autodoc.typehints']
autodoc_inherit_docstrings = True

and this is what my .rst file looks like:

Classes
===================
.. autoclass:: test_config.A()

.. autoclass:: test_config.B()
   :members:
   :show-inheritance:
   :inherited-members:

This gives me:

enter image description here

However, I still am unable to import A's docstring into B.

Similar questions have been asked before here and here but both of them make use of a decorator. For reasons beyond the scope of this question, I will NOT be able to use a decorator.

I also tried autodoc_inherit_docstrings=True in the conf.py to no avail.

What would be the best way to go about this? Does Sphinx not support this out of the box?

Thank you!

1

There are 1 answers

0
Gokul On

I was able to do it with the help of autodoc-process-docstring, which was registered as a custom extension.

Something like this:

def modify_docstring(app, what, name, obj, options, lines):
    # Access the existing docstring
    original_docstring = "\n".join(lines)

    # Get the parent class docstring
    parent_docstring = ""
    if obj.__bases__:  # Check if the class has a parent
        parent_class = obj.__bases__[0]  # Assuming single inheritance
        parent_class_name = parent_class.__name__
        try:
            parent_docstring = parent_class.__doc__
        except AttributeError:
            pass  # Handle cases where parent has no docstring

    modified_docstring =  f"{original_docstring}{parent_docstring}"

    print(f"Modified Docstring: \n {modified_docstring}\n")

    # Update the lines with the modified docstring
    lines[:] = modified_docstring.splitlines()

# Connect the handler to the event
def setup(app):
    app.connect('autodoc-process-docstring', modify_docstring)
    return {'version': '0.1'}