mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #6873 from tk0miya/5923_autodoc_inherited_members_can_ignore_specific_superclass
Close #5923: autodoc: allow not to document inherited members of specific super class
This commit is contained in:
commit
e83bb29789
4
CHANGES
4
CHANGES
@ -14,6 +14,8 @@ Incompatible changes
|
||||
* Drop features and APIs deprecated in 1.8.x
|
||||
* #247: autosummary: stub files are overwritten automatically by default. see
|
||||
:confval:`autosummary_generate_overwrite` to change the behavior
|
||||
* #5923: autodoc: the members of ``object`` class are not documented by default
|
||||
when ``:inherited-members:`` and ``:special-members:`` are given.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
@ -23,6 +25,8 @@ Features added
|
||||
|
||||
* #247: autosummary: Add :confval:`autosummary_generate_overwrite` to overwrite
|
||||
old stub file
|
||||
* #5923: autodoc: ``:inherited-members:`` option takes a name of anchestor class
|
||||
not to document inherited members of the class and uppers
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
@ -157,7 +157,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
|
||||
* For classes and exceptions, members inherited from base classes will be
|
||||
left out when documenting all members, unless you give the
|
||||
``inherited-members`` flag option, in addition to ``members``::
|
||||
``inherited-members`` option, in addition to ``members``::
|
||||
|
||||
.. autoclass:: Noodle
|
||||
:members:
|
||||
@ -166,11 +166,29 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
This can be combined with ``undoc-members`` to document *all* available
|
||||
members of the class or module.
|
||||
|
||||
It can take an anchestor class not to document inherited members from it.
|
||||
By default, members of ``object`` class are not documented. To show them
|
||||
all, give ``None`` to the option.
|
||||
|
||||
For example; If your class ``Foo`` is derived from ``list`` class and
|
||||
you don't want to document ``list.__len__()``, you should specify a
|
||||
option ``:inherited-members: list`` to avoid special members of list
|
||||
class.
|
||||
|
||||
Another example; If your class Foo has ``__str__`` special method and
|
||||
autodoc directive has both ``inherited-members`` and ``special-members``,
|
||||
``__str__`` will be documented as in the past, but other special method
|
||||
that are not implemented in your class ``Foo``.
|
||||
|
||||
Note: this will lead to markup errors if the inherited members come from a
|
||||
module whose docstrings are not reST formatted.
|
||||
|
||||
.. versionadded:: 0.3
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
It takes an anchestor class name as an argument.
|
||||
|
||||
* It's possible to override the signature for explicitly documented callable
|
||||
objects (functions, methods, classes) with the regular syntax that will
|
||||
override the signature gained from introspection::
|
||||
|
@ -82,6 +82,14 @@ def members_set_option(arg: Any) -> Union[object, Set[str]]:
|
||||
return {x.strip() for x in arg.split(',')}
|
||||
|
||||
|
||||
def inherited_members_option(arg: Any) -> Union[object, Set[str]]:
|
||||
"""Used to convert the :members: option to auto directives."""
|
||||
if arg is None:
|
||||
return 'object'
|
||||
else:
|
||||
return arg
|
||||
|
||||
|
||||
SUPPRESS = object()
|
||||
|
||||
|
||||
@ -515,6 +523,17 @@ class Documenter:
|
||||
The user can override the skipping decision by connecting to the
|
||||
``autodoc-skip-member`` event.
|
||||
"""
|
||||
def is_filtered_inherited_member(name: str) -> bool:
|
||||
if inspect.isclass(self.object):
|
||||
for cls in self.object.__mro__:
|
||||
if cls.__name__ == self.options.inherited_members and cls != self.object:
|
||||
# given member is a member of specified *super class*
|
||||
return True
|
||||
elif name in cls.__dict__:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
ret = []
|
||||
|
||||
# search for members in source code too
|
||||
@ -545,13 +564,16 @@ class Documenter:
|
||||
if want_all and membername.startswith('__') and \
|
||||
membername.endswith('__') and len(membername) > 4:
|
||||
# special __methods__
|
||||
if self.options.special_members is ALL and \
|
||||
membername != '__doc__':
|
||||
keep = has_doc or self.options.undoc_members
|
||||
elif self.options.special_members and \
|
||||
self.options.special_members is not ALL and \
|
||||
membername in self.options.special_members:
|
||||
keep = has_doc or self.options.undoc_members
|
||||
if self.options.special_members is ALL:
|
||||
if membername == '__doc__':
|
||||
keep = False
|
||||
elif is_filtered_inherited_member(membername):
|
||||
keep = False
|
||||
else:
|
||||
keep = has_doc or self.options.undoc_members
|
||||
elif self.options.special_members:
|
||||
if membername in self.options.special_members:
|
||||
keep = has_doc or self.options.undoc_members
|
||||
elif (namespace, membername) in attr_docs:
|
||||
if want_all and membername.startswith('_'):
|
||||
# ignore members whose name starts with _ by default
|
||||
@ -565,8 +587,11 @@ class Documenter:
|
||||
keep = self.options.private_members and \
|
||||
(has_doc or self.options.undoc_members)
|
||||
else:
|
||||
# ignore undocumented members if :undoc-members: is not given
|
||||
keep = has_doc or self.options.undoc_members
|
||||
if self.options.members is ALL and is_filtered_inherited_member(membername):
|
||||
keep = False
|
||||
else:
|
||||
# ignore undocumented members if :undoc-members: is not given
|
||||
keep = has_doc or self.options.undoc_members
|
||||
|
||||
# give the user a chance to decide whether this member
|
||||
# should be skipped
|
||||
@ -740,7 +765,7 @@ class ModuleDocumenter(Documenter):
|
||||
|
||||
option_spec = {
|
||||
'members': members_option, 'undoc-members': bool_option,
|
||||
'noindex': bool_option, 'inherited-members': bool_option,
|
||||
'noindex': bool_option, 'inherited-members': inherited_members_option,
|
||||
'show-inheritance': bool_option, 'synopsis': identity,
|
||||
'platform': identity, 'deprecated': bool_option,
|
||||
'member-order': identity, 'exclude-members': members_set_option,
|
||||
@ -1039,7 +1064,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
member_order = 20
|
||||
option_spec = {
|
||||
'members': members_option, 'undoc-members': bool_option,
|
||||
'noindex': bool_option, 'inherited-members': bool_option,
|
||||
'noindex': bool_option, 'inherited-members': inherited_members_option,
|
||||
'show-inheritance': bool_option, 'member-order': identity,
|
||||
'exclude-members': members_set_option,
|
||||
'private-members': bool_option, 'special-members': members_option,
|
||||
|
@ -581,6 +581,30 @@ def test_autodoc_inherited_members(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_inherited_members_Base(app):
|
||||
options = {"members": None,
|
||||
"inherited-members": "Base",
|
||||
"special-members": None}
|
||||
|
||||
# check methods for object class are shown
|
||||
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
|
||||
assert ' .. py:method:: Derived.inheritedmeth()' in actual
|
||||
assert ' .. py:method:: Derived.inheritedclassmeth' not in actual
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_inherited_members_None(app):
|
||||
options = {"members": None,
|
||||
"inherited-members": "None",
|
||||
"special-members": None}
|
||||
|
||||
# check methods for object class are shown
|
||||
actual = do_autodoc(app, 'class', 'target.inheritance.Derived', options)
|
||||
assert ' .. py:method:: Derived.__init__' in actual
|
||||
assert ' .. py:method:: Derived.__str__' in actual
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_imported_members(app):
|
||||
options = {"members": None,
|
||||
|
Loading…
Reference in New Issue
Block a user