6

I'm trying to use Sphinx to document one base class and 2 child classes with google style docstring classes. I'm particularly stuggling with inherited attributes:

class Base(object):
    """Base class.

    Attributes:
         a (int): one attribute
         b (int): another one
    """

    def __init__(self):
        self.a = 3
        self.b = 5

class FirstChild(Base):
    """First Child of Base.

    Attributes:
        c (float): child class attribute
    """

    def __init__(self):
        self.c = 3.1

class SecondChild(Base):
    """Second Child of Base."""
    pass

Here is the rst file:

.. automodule:: my_package.my_module
    :members:
    :undoc-members:
    :show-inheritance:
    :inherited-members:

Sphinx displays attributes a and b only on class Base. In FirstChild, there is only c, and no attribute in SecondChild, even with the :inherited-members: tag.

Is there a way to have a, b and c displayed in the child classes without having to copy/paste descriptions in FirstChild/SecondChild docstrings ?

Thanks!

mzjn
  • 48,958
  • 13
  • 128
  • 248
marc_bllv
  • 63
  • 5
  • 2
    This open issue looks similar to your problem: https://github.com/sphinx-doc/sphinx/issues/741 – mzjn Nov 16 '17 at 08:10

1 Answers1

1

By using a decorator you can extract the attributes from the parent and insert them on the inherited class.

    def docstring_inherit(parent):
        def inherit(obj):
            spaces = "    "
            if not str(obj.__doc__).__contains__("Attributes:"):
                obj.__doc__ += "\n" + spaces + "Attributes:\n"
            obj.__doc__ = str(obj.__doc__).rstrip() + "\n"
            for attribute in parent.__doc__.split("Attributes:\n")[-1].lstrip().split("\n"):
                obj.__doc__ += spaces * 2 + str(attribute).lstrip().rstrip() + "\n"
            return obj
    
        return inherit

    class Base(object):
        """Base class.
    
        Attributes:
             a (int): one attribute
             b (int): another one
        """
    
        def __init__(self):
            self.a = 3
            self.b = 5


    @docstring_inherit(Base)
    class FirstChild(Base):
    """First Child of Base.

    Attributes:
        c (float): child class attribute
    """
       def __init__(self):
           self.c = 3.1

I hope it resolves the question others with the same doubt.

print(FirstChild.__doc__)
"""
First Child of Base.

    Attributes:
        c (float): child class attribute
        a (int): one attribute
        b (int): another one
        

"""