summaryrefslogtreecommitdiff
path: root/sphinx/ext/autosummary/generate.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/ext/autosummary/generate.py')
-rw-r--r--sphinx/ext/autosummary/generate.py83
1 files changed, 52 insertions, 31 deletions
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py
index 4dde73829..0240d2c7c 100644
--- a/sphinx/ext/autosummary/generate.py
+++ b/sphinx/ext/autosummary/generate.py
@@ -13,7 +13,7 @@
generate:
sphinx-autogen -o source/generated source/*.rst
- :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@@ -34,20 +34,18 @@ from jinja2 import TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment
import sphinx.locale
-from sphinx import __display_version__
-from sphinx import package_dir
+from sphinx import __display_version__, package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.ext.autodoc import Documenter
-from sphinx.ext.autosummary import import_by_name, get_documenter
+from sphinx.ext.autodoc.importer import import_module
+from sphinx.ext.autosummary import get_documenter, import_by_name, import_ivar_by_name
from sphinx.locale import __
from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.registry import SphinxComponentRegistry
-from sphinx.util import logging
-from sphinx.util import rst
-from sphinx.util import split_full_qualified_name
+from sphinx.util import logging, rst, split_full_qualified_name
from sphinx.util.inspect import safe_getattr
from sphinx.util.osutil import ensuredir
from sphinx.util.template import SphinxTemplateLoader
@@ -74,6 +72,7 @@ class DummyApplication:
self.warningiserror = False
self.config.add('autosummary_context', {}, True, None)
+ self.config.add('autosummary_filename_map', {}, True, None)
self.config.init_values()
def emit_firstresult(self, *args: Any) -> None:
@@ -87,29 +86,29 @@ AutosummaryEntry = NamedTuple('AutosummaryEntry', [('name', str),
def setup_documenters(app: Any) -> None:
- from sphinx.ext.autodoc import (
- ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
- FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
- InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
- SlotsAttributeDocumenter, DataDeclarationDocumenter, GenericAliasDocumenter,
- SingledispatchFunctionDocumenter,
- )
+ from sphinx.ext.autodoc import (AttributeDocumenter, ClassDocumenter, DataDocumenter,
+ DecoratorDocumenter, ExceptionDocumenter,
+ FunctionDocumenter, MethodDocumenter, ModuleDocumenter,
+ NewTypeAttributeDocumenter, NewTypeDataDocumenter,
+ PropertyDocumenter)
documenters = [
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
- FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
- InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
- SlotsAttributeDocumenter, DataDeclarationDocumenter, GenericAliasDocumenter,
- SingledispatchFunctionDocumenter,
+ FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,
+ NewTypeDataDocumenter, AttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,
] # type: List[Type[Documenter]]
for documenter in documenters:
app.registry.add_documenter(documenter.objtype, documenter)
def _simple_info(msg: str) -> None:
+ warnings.warn('_simple_info() is deprecated.',
+ RemovedInSphinx50Warning, stacklevel=2)
print(msg)
def _simple_warn(msg: str) -> None:
+ warnings.warn('_simple_warn() is deprecated.',
+ RemovedInSphinx50Warning, stacklevel=2)
print('WARNING: ' + msg, file=sys.stderr)
@@ -143,11 +142,11 @@ class AutosummaryRenderer:
if isinstance(app, (Sphinx, DummyApplication)):
if app.translator:
self.env.add_extension("jinja2.ext.i18n")
- self.env.install_gettext_translations(app.translator) # type: ignore
+ self.env.install_gettext_translations(app.translator)
elif isinstance(app, Builder):
if app.app.translator:
self.env.add_extension("jinja2.ext.i18n")
- self.env.install_gettext_translations(app.app.translator) # type: ignore
+ self.env.install_gettext_translations(app.app.translator)
def exists(self, template_name: str) -> bool:
"""Check if template file exists."""
@@ -230,7 +229,8 @@ class ModuleScanner:
def generate_autosummary_content(name: str, obj: Any, parent: Any,
template: AutosummaryRenderer, template_name: str,
imported_members: bool, app: Any,
- recursive: bool, context: Dict) -> str:
+ recursive: bool, context: Dict,
+ modname: str = None, qualname: str = None) -> str:
doc = get_documenter(app, obj, parent)
def skip_member(obj: Any, name: str, objtype: str) -> bool:
@@ -289,6 +289,13 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
items = [] # type: List[str]
for _, modname, ispkg in pkgutil.iter_modules(obj.__path__):
fullname = name + '.' + modname
+ try:
+ module = import_module(fullname)
+ if module and hasattr(module, '__sphinx_mock__'):
+ continue
+ except ImportError:
+ pass
+
items.append(fullname)
public = [x for x in items if not x.split('.')[-1].startswith('_')]
return public, items
@@ -319,7 +326,9 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
ns['attributes'], ns['all_attributes'] = \
get_members(obj, {'attribute', 'property'})
- modname, qualname = split_full_qualified_name(name)
+ if modname is None or qualname is None:
+ modname, qualname = split_full_qualified_name(name)
+
if doc.objtype in ('method', 'attribute', 'property'):
ns['class'] = qualname.rsplit(".", 1)[0]
@@ -347,7 +356,7 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
info: Callable = None, base_path: str = None,
builder: Builder = None, template_dir: str = None,
imported_members: bool = False, app: Any = None,
- overwrite: bool = True) -> None:
+ overwrite: bool = True, encoding: str = 'utf-8') -> None:
if info:
warnings.warn('info argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
@@ -390,6 +399,11 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
# keep track of new files
new_files = []
+ if app:
+ filename_map = app.config.autosummary_filename_map
+ else:
+ filename_map = {}
+
# write
for entry in sorted(set(items), key=str):
if entry.path is None:
@@ -401,31 +415,38 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
ensuredir(path)
try:
- name, obj, parent, mod_name = import_by_name(entry.name)
+ name, obj, parent, modname = import_by_name(entry.name)
+ qualname = name.replace(modname + ".", "")
except ImportError as e:
- _warn(__('[autosummary] failed to import %r: %s') % (entry.name, e))
- continue
+ try:
+ # try to importl as an instance attribute
+ name, obj, parent, modname = import_ivar_by_name(entry.name)
+ qualname = name.replace(modname + ".", "")
+ except ImportError:
+ _warn(__('[autosummary] failed to import %r: %s') % (entry.name, e))
+ continue
context = {}
if app:
context.update(app.config.autosummary_context)
content = generate_autosummary_content(name, obj, parent, template, entry.template,
- imported_members, app, entry.recursive, context)
+ imported_members, app, entry.recursive, context,
+ modname, qualname)
- filename = os.path.join(path, name + suffix)
+ filename = os.path.join(path, filename_map.get(name, name) + suffix)
if os.path.isfile(filename):
- with open(filename) as f:
+ with open(filename, encoding=encoding) as f:
old_content = f.read()
if content == old_content:
continue
elif overwrite: # content has changed
- with open(filename, 'w') as f:
+ with open(filename, 'w', encoding=encoding) as f:
f.write(content)
new_files.append(filename)
else:
- with open(filename, 'w') as f:
+ with open(filename, 'w', encoding=encoding) as f:
f.write(content)
new_files.append(filename)