mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge pull request #7686 from tk0miya/7685_autosummary_imported_members
Fix #7685: autosummary: imported members are listed unexpectedly
This commit is contained in:
commit
74351b2d43
2
CHANGES
2
CHANGES
@ -101,6 +101,8 @@ Bugs fixed
|
||||
* #7551: autosummary: a nested class is indexed as non-nested class
|
||||
* #7661: autosummary: autosummary directive emits warnings twices if failed to
|
||||
import the target module
|
||||
* #7685: autosummary: The template variable "members" contains imported members
|
||||
even if :confval:`autossummary_imported_members` is False
|
||||
* #7535: sphinx-autogen: crashes when custom template uses inheritance
|
||||
* #7536: sphinx-autogen: crashes when template uses i18n feature
|
||||
* #7653: sphinx-quickstart: Fix multiple directory creation for nested relpath
|
||||
|
@ -18,6 +18,7 @@
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import inspect
|
||||
import locale
|
||||
import os
|
||||
import pkgutil
|
||||
@ -176,6 +177,56 @@ class AutosummaryRenderer:
|
||||
# -- Generating output ---------------------------------------------------------
|
||||
|
||||
|
||||
class ModuleScanner:
|
||||
def __init__(self, app: Any, obj: Any) -> None:
|
||||
self.app = app
|
||||
self.object = obj
|
||||
|
||||
def get_object_type(self, name: str, value: Any) -> str:
|
||||
return get_documenter(self.app, value, self.object).objtype
|
||||
|
||||
def is_skipped(self, name: str, value: Any, objtype: str) -> bool:
|
||||
try:
|
||||
return self.app.emit_firstresult('autodoc-skip-member', objtype,
|
||||
name, value, False, {})
|
||||
except Exception as exc:
|
||||
logger.warning(__('autosummary: failed to determine %r to be documented, '
|
||||
'the following exception was raised:\n%s'),
|
||||
name, exc, type='autosummary')
|
||||
return False
|
||||
|
||||
def scan(self, imported_members: bool) -> List[str]:
|
||||
members = []
|
||||
for name in dir(self.object):
|
||||
try:
|
||||
value = safe_getattr(self.object, name)
|
||||
except AttributeError:
|
||||
value = None
|
||||
|
||||
objtype = self.get_object_type(name, value)
|
||||
if self.is_skipped(name, value, objtype):
|
||||
continue
|
||||
|
||||
try:
|
||||
if inspect.ismodule(value):
|
||||
imported = True
|
||||
elif safe_getattr(value, '__module__') != self.object.__name__:
|
||||
imported = True
|
||||
else:
|
||||
imported = False
|
||||
except AttributeError:
|
||||
imported = False
|
||||
|
||||
if imported_members:
|
||||
# list all members up
|
||||
members.append(name)
|
||||
elif imported is False:
|
||||
# list not-imported members up
|
||||
members.append(name)
|
||||
|
||||
return members
|
||||
|
||||
|
||||
def generate_autosummary_content(name: str, obj: Any, parent: Any,
|
||||
template: AutosummaryRenderer, template_name: str,
|
||||
imported_members: bool, app: Any,
|
||||
@ -246,7 +297,8 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
|
||||
ns.update(context)
|
||||
|
||||
if doc.objtype == 'module':
|
||||
ns['members'] = dir(obj)
|
||||
scanner = ModuleScanner(app, obj)
|
||||
ns['members'] = scanner.scan(imported_members)
|
||||
ns['functions'], ns['all_functions'] = \
|
||||
get_members(obj, {'function'}, imported=imported_members)
|
||||
ns['classes'], ns['all_classes'] = \
|
||||
|
@ -1,4 +1,4 @@
|
||||
from os import * # NOQA
|
||||
from os import path # NOQA
|
||||
from typing import Union
|
||||
|
||||
|
||||
@ -17,7 +17,23 @@ class Foo:
|
||||
pass
|
||||
|
||||
|
||||
def bar(x: Union[int, str], y: int = 1):
|
||||
class _Baz:
|
||||
pass
|
||||
|
||||
|
||||
def bar(x: Union[int, str], y: int = 1) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def _quux():
|
||||
pass
|
||||
|
||||
|
||||
class Exc(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class _Exc(Exception):
|
||||
pass
|
||||
|
||||
|
||||
|
@ -19,7 +19,10 @@ from sphinx import addnodes
|
||||
from sphinx.ext.autosummary import (
|
||||
autosummary_table, autosummary_toc, mangle_signature, import_by_name, extract_summary
|
||||
)
|
||||
from sphinx.ext.autosummary.generate import AutosummaryEntry, generate_autosummary_docs, main as autogen_main
|
||||
from sphinx.ext.autosummary.generate import (
|
||||
AutosummaryEntry, generate_autosummary_content, generate_autosummary_docs,
|
||||
main as autogen_main
|
||||
)
|
||||
from sphinx.testing.util import assert_node, etree_parse
|
||||
from sphinx.util.docutils import new_document
|
||||
from sphinx.util.osutil import cd
|
||||
@ -189,6 +192,83 @@ def test_escaping(app, status, warning):
|
||||
assert str_content(title) == 'underscore_module_'
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='ext-autosummary')
|
||||
def test_autosummary_generate_content_for_module(app):
|
||||
import autosummary_dummy_module
|
||||
template = Mock()
|
||||
|
||||
generate_autosummary_content('autosummary_dummy_module', autosummary_dummy_module, None,
|
||||
template, None, False, app, False, {})
|
||||
assert template.render.call_args[0][0] == 'module'
|
||||
|
||||
context = template.render.call_args[0][1]
|
||||
assert context['members'] == ['Exc', 'Foo', '_Baz', '_Exc', '__builtins__',
|
||||
'__cached__', '__doc__', '__file__', '__name__',
|
||||
'__package__', '_quux', 'bar', 'qux']
|
||||
assert context['functions'] == ['bar']
|
||||
assert context['all_functions'] == ['_quux', 'bar']
|
||||
assert context['classes'] == ['Foo']
|
||||
assert context['all_classes'] == ['Foo', '_Baz']
|
||||
assert context['exceptions'] == ['Exc']
|
||||
assert context['all_exceptions'] == ['Exc', '_Exc']
|
||||
assert context['attributes'] == ['qux']
|
||||
assert context['all_attributes'] == ['qux']
|
||||
assert context['fullname'] == 'autosummary_dummy_module'
|
||||
assert context['module'] == 'autosummary_dummy_module'
|
||||
assert context['objname'] == ''
|
||||
assert context['name'] == ''
|
||||
assert context['objtype'] == 'module'
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='ext-autosummary')
|
||||
def test_autosummary_generate_content_for_module_skipped(app):
|
||||
import autosummary_dummy_module
|
||||
template = Mock()
|
||||
|
||||
def skip_member(app, what, name, obj, skip, options):
|
||||
if name in ('Foo', 'bar', 'Exc'):
|
||||
return True
|
||||
|
||||
app.connect('autodoc-skip-member', skip_member)
|
||||
generate_autosummary_content('autosummary_dummy_module', autosummary_dummy_module, None,
|
||||
template, None, False, app, False, {})
|
||||
context = template.render.call_args[0][1]
|
||||
assert context['members'] == ['_Baz', '_Exc', '__builtins__', '__cached__', '__doc__',
|
||||
'__file__', '__name__', '__package__', '_quux', 'qux']
|
||||
assert context['functions'] == []
|
||||
assert context['classes'] == []
|
||||
assert context['exceptions'] == []
|
||||
|
||||
|
||||
@pytest.mark.sphinx(testroot='ext-autosummary')
|
||||
def test_autosummary_generate_content_for_module_imported_members(app):
|
||||
import autosummary_dummy_module
|
||||
template = Mock()
|
||||
|
||||
generate_autosummary_content('autosummary_dummy_module', autosummary_dummy_module, None,
|
||||
template, None, True, app, False, {})
|
||||
assert template.render.call_args[0][0] == 'module'
|
||||
|
||||
context = template.render.call_args[0][1]
|
||||
assert context['members'] == ['Exc', 'Foo', 'Union', '_Baz', '_Exc', '__builtins__',
|
||||
'__cached__', '__doc__', '__file__', '__loader__',
|
||||
'__name__', '__package__', '__spec__', '_quux',
|
||||
'bar', 'path', 'qux']
|
||||
assert context['functions'] == ['bar']
|
||||
assert context['all_functions'] == ['_quux', 'bar']
|
||||
assert context['classes'] == ['Foo']
|
||||
assert context['all_classes'] == ['Foo', '_Baz']
|
||||
assert context['exceptions'] == ['Exc']
|
||||
assert context['all_exceptions'] == ['Exc', '_Exc']
|
||||
assert context['attributes'] == ['qux']
|
||||
assert context['all_attributes'] == ['qux']
|
||||
assert context['fullname'] == 'autosummary_dummy_module'
|
||||
assert context['module'] == 'autosummary_dummy_module'
|
||||
assert context['objname'] == ''
|
||||
assert context['name'] == ''
|
||||
assert context['objtype'] == 'module'
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='ext-autosummary')
|
||||
def test_autosummary_generate(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
Loading…
Reference in New Issue
Block a user