Skip to content

Commit

Permalink
Merge pull request #9233 from tk0miya/3014_autodoc-process-bases
Browse files Browse the repository at this point in the history
Close #3014: autodoc: Add autodoc-process-bases
  • Loading branch information
tk0miya committed May 17, 2021
2 parents 2bf9399 + bc7087a commit b19dc36
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -31,6 +31,8 @@ Features added
* #4257: autodoc: Add :confval:`autodoc_class_signature` to separate the class
entry and the definition of ``__init__()`` method
* #8061, #9218: autodoc: Support variable comment for alias classes
* #3014: autodoc: Add :event:`autodoc-process-bases` to modify the base classes
of the class definitions
* #3257: autosummary: Support instance attributes for classes
* #9129: html search: Show search summaries when html_copy_source = False
* #9120: html theme: Eliminate prompt characters of code-block from copyable
Expand Down
15 changes: 15 additions & 0 deletions doc/usage/extensions/autodoc.rst
Expand Up @@ -763,6 +763,21 @@ needed docstring processing in event :event:`autodoc-process-docstring`:
.. autofunction:: cut_lines
.. autofunction:: between

.. event:: autodoc-process-bases (app, name, obj, options, bases)

.. versionadded:: 4.1

Emitted when autodoc has read and processed a class to determine the
base-classes. *bases* is a list of classes that the event handler can
modify **in place** to change what Sphinx puts into the output. It's
emitted only if ``show-inheritance`` option given.

:param app: the Sphinx application object
:param name: the fully qualified name of the object
:param obj: the object itself
:param options: the options given to the class directive
:param bases: the list of base classes signature. see above.


Skipping members
----------------
Expand Down
20 changes: 13 additions & 7 deletions sphinx/ext/autodoc/__init__.py
Expand Up @@ -1641,18 +1641,23 @@ def add_directive_header(self, sig: str) -> None:

# add inheritance info, if wanted
if not self.doc_as_attr and self.options.show_inheritance:
sourcename = self.get_sourcename()
self.add_line('', sourcename)

if hasattr(self.object, '__orig_bases__') and len(self.object.__orig_bases__):
# A subclass of generic types
# refs: PEP-560 <https://www.python.org/dev/peps/pep-0560/>
bases = [restify(cls) for cls in self.object.__orig_bases__]
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
bases = list(self.object.__orig_bases__)
elif hasattr(self.object, '__bases__') and len(self.object.__bases__):
# A normal class
bases = [restify(cls) for cls in self.object.__bases__]
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), sourcename)
bases = list(self.object.__bases__)
else:
bases = []

self.env.events.emit('autodoc-process-bases',
self.fullname, self.object, self.options, bases)

base_classes = [restify(cls) for cls in bases]
sourcename = self.get_sourcename()
self.add_line('', sourcename)
self.add_line(' ' + _('Bases: %s') % ', '.join(base_classes), sourcename)

def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:
members = get_class_members(self.object, self.objpath, self.get_attr)
Expand Down Expand Up @@ -2737,6 +2742,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member')
app.add_event('autodoc-process-bases')

app.connect('config-inited', migrate_autodoc_member_order, priority=800)

Expand Down
42 changes: 42 additions & 0 deletions tests/test_ext_autodoc_autoclass.py
Expand Up @@ -10,6 +10,7 @@
"""

import sys
from typing import List, Union

import pytest

Expand Down Expand Up @@ -264,6 +265,47 @@ def test_show_inheritance_for_subclass_of_generic_type(app):
]


@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_autodoc_process_bases(app):
def autodoc_process_bases(app, name, obj, options, bases):
assert name == 'target.classes.Quux'
assert obj.__module__ == 'target.classes'
assert obj.__name__ == 'Quux'
assert options == {'show-inheritance': True,
'members': []}
assert bases == [List[Union[int, float]]]

bases.pop()
bases.extend([int, str])

app.connect('autodoc-process-bases', autodoc_process_bases)

options = {'show-inheritance': None}
actual = do_autodoc(app, 'class', 'target.classes.Quux', options)
if sys.version_info < (3, 7):
assert list(actual) == [
'',
'.. py:class:: Quux(*args, **kwds)',
' :module: target.classes',
'',
' Bases: :class:`int`, :class:`str`',
'',
' A subclass of List[Union[int, float]]',
'',
]
else:
assert list(actual) == [
'',
'.. py:class:: Quux(iterable=(), /)',
' :module: target.classes',
'',
' Bases: :class:`int`, :class:`str`',
'',
' A subclass of List[Union[int, float]]',
'',
]


@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_class_doc_from_class(app):
options = {"members": None,
Expand Down

0 comments on commit b19dc36

Please sign in to comment.