Inherit a parent class docstring as __doc__ attribute
Question: There is a question about [Inherit docstrings in Python class
inheritance](http://stackoverflow.com/questions/2025562/inherit-docstrings-in-
python-class-inheritance), but the answers there deal with method docstrings.

My question is how to inherit a docstring of a parent class as the `__doc__`
attribute. The usecase is that [Django rest framework](http://django-rest-
framework.org) generates nice documentation in the html version of your API
based on your view classes' docstrings. But when inheriting a base class (with
a docstring) in a class without a docstring, the API doesn't show the
docstring.

It might very well be that sphinx and other tools do the right thing and
handle the docstring inheritance for me, but django rest framework looks at
the (empty) `.__doc__` attribute.

    
    
    class ParentWithDocstring(object):
        """Parent docstring"""
        pass
    
    
    class SubClassWithoutDoctring(ParentWithDocstring):
        pass
    
    
    parent = ParentWithDocstring()
    print parent.__doc__  # Prints "Parent docstring".
    subclass = SubClassWithoutDoctring()
    print subclass.__doc__  # Prints "None"
    

I've tried something like `super(SubClassWithoutDocstring, self).__doc__`, but
that also only got me a `None`.


Answer: Since you cannot assign a new `__doc__` docstring to a class (in CPython at
least), you'll have to use a metaclass:

    
    
    import inspect
    
    def inheritdocstring(name, bases, attrs):
        if not '__doc__' in attrs:
            # create a temporary 'parent' to (greatly) simplify the MRO search
            temp = type('temporaryclass', bases, {})
            for cls in inspect.getmro(temp):
                if cls.__doc__ is not None:
                    attrs['__doc__'] = cls.__doc__
                    break
    
        return type(name, bases, attrs)
    

Yes, we jump through an extra hoop or two, but the above metaclass will find
the correct `__doc__` however convoluted you make your inheritance graph.

Usage:

    
    
    >>> class ParentWithDocstring(object):
    ...     """Parent docstring"""
    ... 
    >>> class SubClassWithoutDocstring(ParentWithDocstring):
    ...     __metaclass__ = inheritdocstring
    ... 
    >>> SubClassWithoutDocstring.__doc__
    'Parent docstring'
    

The alternative is to set `__doc__` in `__init__`, as an instance variable:

    
    
    def __init__(self):
        try:
            self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
        except StopIteration:
            pass
    

Then at least your instances have a docstring:

    
    
    >>> class SubClassWithoutDocstring(ParentWithDocstring):
    ...     def __init__(self):
    ...         try:
    ...             self.__doc__ = next(cls.__doc__ for cls in inspect.getmro(type(self)) if cls.__doc__ is not None)
    ...         except StopIteration:
    ...             pass
    ... 
    >>> SubClassWithoutDocstring().__doc__
    'Parent docstring'
    

As of Python 3.3 (which fixed [issue
12773](http://bugs.python.org/issue12773)), you _can_ finally just set the
`__doc__` attribute of custom classes, so then you can use a class decorator
instead:

    
    
    import inspect
    
    def inheritdocstring(cls):
        for base in inspect.getmro(cls):
            if base.__doc__ is not None:
                cls.__doc__ = base.__doc__
                break
        return cls
    

which then can be applied thus:

    
    
    >>> @inheritdocstring
    ... class SubClassWithoutDocstring(ParentWithDocstring):
    ...     pass
    ... 
    >>> SubClassWithoutDocstring.__doc__
    'Parent docstring'
    

