Merge pull request #4232 from sphinx-doc/4212_autosummary-importsafe

4212 autosummary importsafe
This commit is contained in:
Takeshi KOMIYA 2017-11-11 18:31:14 +09:00 committed by GitHub
commit 63a5eaf185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 9 deletions

View File

@ -43,6 +43,7 @@ Features added
* #4168: improve zh search with jieba
* HTML themes can set up default sidebars through ``theme.conf``
* #3160: html: Use ``<kdb>`` to represent ``:kbd:`` role
* #4212: autosummary: catch all exceptions when importing modules
Features removed

View File

@ -15,7 +15,6 @@ import re
import sys
import inspect
import traceback
import warnings
from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types
@ -25,7 +24,7 @@ from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList
import sphinx
from sphinx.ext.autodoc.importer import _MockImporter
from sphinx.ext.autodoc.importer import _MockImporter, import_module
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
from sphinx.util import rpartition, force_decode
from sphinx.locale import _
@ -392,10 +391,7 @@ class Documenter(object):
import_hook = _MockImporter(self.env.config.autodoc_mock_imports)
try:
logger.debug('[autodoc] import %s', self.modname)
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ImportWarning)
with logging.skip_warningiserror(not self.env.config.autodoc_warningiserror):
__import__(self.modname)
import_module(self.modname, self.env.config.autodoc_warningiserror)
parent = None
obj = self.module = sys.modules[self.modname]
logger.debug('[autodoc] => %r', obj)
@ -420,6 +416,8 @@ class Documenter(object):
if isinstance(e, SystemExit):
errmsg += ('; the module executes module level statement ' +
'and it might call sys.exit().')
elif isinstance(e, ImportError):
errmsg += '; the following exception was raised:\n%s' % e.args[0]
else:
errmsg += '; the following exception was raised:\n%s' % \
traceback.format_exc()

View File

@ -10,6 +10,8 @@
"""
import sys
import traceback
import warnings
from types import FunctionType, MethodType, ModuleType
from sphinx.util import logging
@ -116,3 +118,18 @@ class _MockImporter(object):
sys.modules[name] = module
self.mocked_modules.append(name)
return module
def import_module(modname, warningiserror=False):
"""
Call __import__(modname), convert exceptions to ImportError
"""
try:
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=ImportWarning)
with logging.skip_warningiserror(not warningiserror):
return __import__(modname)
except BaseException:
# Importing modules may cause any side effects, including
# SystemExit, so we need to catch all errors.
raise ImportError(traceback.format_exc())

View File

@ -73,6 +73,7 @@ from sphinx.environment.adapters.toctree import TocTree
from sphinx.util import import_object, rst, logging
from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.ext.autodoc import Options
from sphinx.ext.autodoc.importer import import_module
if False:
# For type annotation
@ -512,8 +513,7 @@ def _import_by_name(name):
modname = '.'.join(name_parts[:-1])
if modname:
try:
__import__(modname)
mod = sys.modules[modname]
mod = import_module(modname)
return getattr(mod, name_parts[-1]), mod, modname
except (ImportError, IndexError, AttributeError):
pass
@ -525,9 +525,10 @@ def _import_by_name(name):
last_j = j
modname = '.'.join(name_parts[:j])
try:
__import__(modname)
import_module(modname)
except ImportError:
continue
if modname in sys.modules:
break

View File

@ -0,0 +1,4 @@
import sys
# Fail module import in a catastrophic way
sys.exit(1)

View File

@ -1,6 +1,11 @@
:autolink:`autosummary_dummy_module.Foo`
:autolink:`autosummary_importfail`
.. autosummary::
:toctree: generated
autosummary_dummy_module
autosummary_dummy_module.Foo
autosummary_importfail