mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Retireve docstirng form base classes (Closes #3140)
This commit is contained in:
@@ -393,6 +393,16 @@ There are also new config values that you can set:
|
|||||||
If ``False`` is given, autodoc forcely suppresses the error if the imported
|
If ``False`` is given, autodoc forcely suppresses the error if the imported
|
||||||
module emits warnings. By default, ``True``.
|
module emits warnings. By default, ``True``.
|
||||||
|
|
||||||
|
.. confval:: autodoc_inherit_docstrings
|
||||||
|
|
||||||
|
This value controls the docstrings inheritance.
|
||||||
|
If set to True the cocstring for classes or methods, if not explicitly set,
|
||||||
|
is inherited form parents.
|
||||||
|
|
||||||
|
The default is ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
Docstring preprocessing
|
Docstring preprocessing
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ from sphinx.util import logging
|
|||||||
from sphinx.util.nodes import nested_parse_with_titles
|
from sphinx.util.nodes import nested_parse_with_titles
|
||||||
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
||||||
safe_getattr, object_description, is_builtin_class_method, \
|
safe_getattr, object_description, is_builtin_class_method, \
|
||||||
isenumclass, isenumattribute
|
isenumclass, isenumattribute, getdoc
|
||||||
from sphinx.util.docstrings import prepare_docstring
|
from sphinx.util.docstrings import prepare_docstring
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@@ -525,6 +525,8 @@ class Documenter(object):
|
|||||||
# type: (unicode, int) -> List[List[unicode]]
|
# type: (unicode, int) -> List[List[unicode]]
|
||||||
"""Decode and return lines of the docstring(s) for the object."""
|
"""Decode and return lines of the docstring(s) for the object."""
|
||||||
docstring = self.get_attr(self.object, '__doc__', None)
|
docstring = self.get_attr(self.object, '__doc__', None)
|
||||||
|
if docstring is None and self.env.config.autodoc_inherit_docstrings:
|
||||||
|
docstring = getdoc(self.object)
|
||||||
# make sure we have Unicode docstrings, then sanitize and split
|
# make sure we have Unicode docstrings, then sanitize and split
|
||||||
# into lines
|
# into lines
|
||||||
if isinstance(docstring, text_type):
|
if isinstance(docstring, text_type):
|
||||||
@@ -682,6 +684,9 @@ class Documenter(object):
|
|||||||
isattr = False
|
isattr = False
|
||||||
|
|
||||||
doc = self.get_attr(member, '__doc__', None)
|
doc = self.get_attr(member, '__doc__', None)
|
||||||
|
if doc is None and self.env.config.autodoc_inherit_docstrings:
|
||||||
|
doc = getdoc(member)
|
||||||
|
|
||||||
# if the member __doc__ is the same as self's __doc__, it's just
|
# if the member __doc__ is the same as self's __doc__, it's just
|
||||||
# inherited and therefore not the member's doc
|
# inherited and therefore not the member's doc
|
||||||
cls = self.get_attr(member, '__class__', None)
|
cls = self.get_attr(member, '__class__', None)
|
||||||
@@ -1617,6 +1622,7 @@ def setup(app):
|
|||||||
app.add_config_value('autodoc_docstring_signature', True, True)
|
app.add_config_value('autodoc_docstring_signature', True, True)
|
||||||
app.add_config_value('autodoc_mock_imports', [], True)
|
app.add_config_value('autodoc_mock_imports', [], True)
|
||||||
app.add_config_value('autodoc_warningiserror', True, True)
|
app.add_config_value('autodoc_warningiserror', True, True)
|
||||||
|
app.add_config_value('autodoc_inherit_docstrings', True, True)
|
||||||
app.add_event('autodoc-process-docstring')
|
app.add_event('autodoc-process-docstring')
|
||||||
app.add_event('autodoc-process-signature')
|
app.add_event('autodoc-process-signature')
|
||||||
app.add_event('autodoc-skip-member')
|
app.add_event('autodoc-skip-member')
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import typing
|
import typing
|
||||||
import inspect
|
import inspect
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
@@ -456,3 +457,98 @@ class Signature(object):
|
|||||||
', '.join(param_strings))
|
', '.join(param_strings))
|
||||||
|
|
||||||
return qualified_name
|
return qualified_name
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 5):
|
||||||
|
getdoc = inspect.getdoc
|
||||||
|
else:
|
||||||
|
# code copyed from the inspect.py module of the standard library
|
||||||
|
# of Python 3.5
|
||||||
|
|
||||||
|
def _findclass(func):
|
||||||
|
cls = sys.modules.get(func.__module__)
|
||||||
|
if cls is None:
|
||||||
|
return None
|
||||||
|
for name in func.__qualname__.split('.')[:-1]:
|
||||||
|
cls = getattr(cls, name)
|
||||||
|
if not inspect.isclass(cls):
|
||||||
|
return None
|
||||||
|
return cls
|
||||||
|
|
||||||
|
def _finddoc(obj):
|
||||||
|
if inspect.isclass(obj):
|
||||||
|
for base in obj.__mro__:
|
||||||
|
if base is not object:
|
||||||
|
try:
|
||||||
|
doc = base.__doc__
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
if doc is not None:
|
||||||
|
return doc
|
||||||
|
return None
|
||||||
|
|
||||||
|
if inspect.ismethod(obj):
|
||||||
|
name = obj.__func__.__name__
|
||||||
|
self = obj.__self__
|
||||||
|
if (inspect.isclass(self) and
|
||||||
|
getattr(getattr(self, name, None), '__func__') is obj.__func__):
|
||||||
|
# classmethod
|
||||||
|
cls = self
|
||||||
|
else:
|
||||||
|
cls = self.__class__
|
||||||
|
elif inspect.isfunction(obj):
|
||||||
|
name = obj.__name__
|
||||||
|
cls = _findclass(obj)
|
||||||
|
if cls is None or getattr(cls, name) is not obj:
|
||||||
|
return None
|
||||||
|
elif inspect.isbuiltin(obj):
|
||||||
|
name = obj.__name__
|
||||||
|
self = obj.__self__
|
||||||
|
if (inspect.isclass(self) and
|
||||||
|
self.__qualname__ + '.' + name == obj.__qualname__):
|
||||||
|
# classmethod
|
||||||
|
cls = self
|
||||||
|
else:
|
||||||
|
cls = self.__class__
|
||||||
|
# Should be tested before isdatadescriptor().
|
||||||
|
elif isinstance(obj, property):
|
||||||
|
func = obj.fget
|
||||||
|
name = func.__name__
|
||||||
|
cls = _findclass(func)
|
||||||
|
if cls is None or getattr(cls, name) is not obj:
|
||||||
|
return None
|
||||||
|
elif inspect.ismethoddescriptor(obj) or inspect.isdatadescriptor(obj):
|
||||||
|
name = obj.__name__
|
||||||
|
cls = obj.__objclass__
|
||||||
|
if getattr(cls, name) is not obj:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for base in cls.__mro__:
|
||||||
|
try:
|
||||||
|
doc = getattr(base, name).__doc__
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
if doc is not None:
|
||||||
|
return doc
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getdoc(object):
|
||||||
|
"""Get the documentation string for an object.
|
||||||
|
|
||||||
|
All tabs are expanded to spaces. To clean up docstrings that are
|
||||||
|
indented to line up with blocks of code, any whitespace than can be
|
||||||
|
uniformly removed from the second line onwards is removed."""
|
||||||
|
try:
|
||||||
|
doc = object.__doc__
|
||||||
|
except AttributeError:
|
||||||
|
return None
|
||||||
|
if doc is None:
|
||||||
|
try:
|
||||||
|
doc = _finddoc(object)
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
return None
|
||||||
|
if not isinstance(doc, str):
|
||||||
|
return None
|
||||||
|
return inspect.cleandoc(doc)
|
||||||
|
|||||||
Reference in New Issue
Block a user