autosummary: Add :recursive: option to autosummary directive

This commit is contained in:
Takeshi KOMIYA 2020-02-23 01:51:43 +09:00
parent 665458561f
commit 476b73b6ca
8 changed files with 58 additions and 4 deletions

View File

@ -104,6 +104,20 @@ The :mod:`sphinx.ext.autosummary` extension does this in three parts:
.. versionadded:: 1.0
* You can specify the ``recursive`` option to generate documents for
modules and sub-packages recursively. It defaults to disabled.
For example, ::
.. autosummary::
:recursive:
sphinx.environment.BuildEnvironment
It is needed to enable :confval:`autosummary_recursive` also to
use this option.
.. versionadded:: 3.1
:program:`sphinx-autogen` -- generate autodoc stub pages
--------------------------------------------------------

View File

@ -224,6 +224,7 @@ class Autosummary(SphinxDirective):
option_spec = {
'toctree': directives.unchanged,
'nosignatures': directives.flag,
'recursive': directives.flag,
'template': directives.unchanged,
}

View File

@ -60,7 +60,8 @@ class DummyApplication:
AutosummaryEntry = NamedTuple('AutosummaryEntry', [('name', str),
('path', str),
('template', str)])
('template', str),
('recursive', bool)])
def setup_documenters(app: Any) -> None:
@ -266,8 +267,13 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
_warn('[autosummary] failed to import %r: %s' % (name, e))
continue
if entry.recursive and not recursive:
_warn('[autosummary] :resursive: option found. But ignored. '
'Please read document for autosummary_recursive option')
content = generate_autosummary_content(name, obj, parent, template, entry.template,
imported_members, app, recursive)
imported_members, app,
recursive and entry.recursive)
filename = os.path.join(path, name + suffix)
if os.path.isfile(filename):
@ -347,11 +353,13 @@ def find_autosummary_in_lines(lines: List[str], module: Any = None, filename: st
module_re = re.compile(
r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$')
autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?')
recursive_arg_re = re.compile(r'^\s+:recursive:\s*$')
toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
documented = [] # type: List[AutosummaryEntry]
recursive = False
toctree = None # type: str
template = None
current_module = module
@ -360,6 +368,11 @@ def find_autosummary_in_lines(lines: List[str], module: Any = None, filename: st
for line in lines:
if in_autosummary:
m = recursive_arg_re.match(line)
if m:
recursive = True
continue
m = toctree_arg_re.match(line)
if m:
toctree = m.group(1)
@ -384,7 +397,7 @@ def find_autosummary_in_lines(lines: List[str], module: Any = None, filename: st
if current_module and \
not name.startswith(current_module + '.'):
name = "%s.%s" % (current_module, name)
documented.append(AutosummaryEntry(name, toctree, template))
documented.append(AutosummaryEntry(name, toctree, template, recursive))
continue
if not line.strip() or line.startswith(base_indent + " "):
@ -396,6 +409,7 @@ def find_autosummary_in_lines(lines: List[str], module: Any = None, filename: st
if m:
in_autosummary = True
base_indent = m.group(1)
recursive = False
toctree = None
template = None
continue

View File

@ -41,6 +41,7 @@
.. autosummary::
:toctree: modules
:recursive:
{% for item in modules %}
{{ item }}
{%- endfor %}

View File

@ -5,5 +5,11 @@ API Reference
.. autosummary::
:toctree: generated
:recursive:
package
.. autosummary::
:toctree: generated
package2

View File

@ -0,0 +1,13 @@
from os import * # NOQA
class Foo:
def __init__(self):
pass
def bar(self):
pass
@property
def baz(self):
pass

View File

@ -292,6 +292,11 @@ def test_autosummary_recursive_enabled(app, status, warning):
if toctree:
assert not (generated / toctree).exists()
# autosummary without :recursive: option
generated = app.srcdir / 'generated'
assert (generated / 'package2.rst').exists()
assert not (generated / 'package2.module.rst').exists()
@pytest.mark.sphinx('dummy', testroot='ext-autosummary-recursive',
srcdir='ext-autosummary-recursive-disabled',
@ -382,7 +387,7 @@ def test_autosummary_imported_members(app, status, warning):
@pytest.mark.sphinx(testroot='ext-autodoc')
def test_generate_autosummary_docs_property(app):
with patch('sphinx.ext.autosummary.generate.find_autosummary_in_files') as mock:
mock.return_value = [AutosummaryEntry('target.methods.Base.prop', 'prop', None)]
mock.return_value = [AutosummaryEntry('target.methods.Base.prop', 'prop', None, False)]
generate_autosummary_docs([], output_dir=app.srcdir, builder=app.builder, app=app)
content = (app.srcdir / 'target.methods.Base.prop.rst').text()