mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Refactor: Add import_object()
This commit is contained in:
parent
d4728d0cb8
commit
1d64ade749
@ -14,9 +14,8 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
import traceback
|
|
||||||
|
|
||||||
from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types
|
from six import iterkeys, iteritems, itervalues, text_type, class_types, string_types
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.utils import assemble_option_dict
|
from docutils.utils import assemble_option_dict
|
||||||
@ -24,7 +23,7 @@ from docutils.parsers.rst import Directive
|
|||||||
from docutils.statemachine import ViewList
|
from docutils.statemachine import ViewList
|
||||||
|
|
||||||
import sphinx
|
import sphinx
|
||||||
from sphinx.ext.autodoc.importer import mock, import_module
|
from sphinx.ext.autodoc.importer import mock, import_object
|
||||||
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
||||||
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
||||||
from sphinx.util import rpartition, force_decode
|
from sphinx.util import rpartition, force_decode
|
||||||
@ -384,56 +383,15 @@ class Documenter(object):
|
|||||||
|
|
||||||
Returns True if successful, False if an error occurred.
|
Returns True if successful, False if an error occurred.
|
||||||
"""
|
"""
|
||||||
if self.objpath:
|
|
||||||
logger.debug('[autodoc] from %s import %s',
|
|
||||||
self.modname, '.'.join(self.objpath))
|
|
||||||
# always enable mock import hook
|
|
||||||
# it will do nothing if autodoc_mock_imports is empty
|
|
||||||
with mock(self.env.config.autodoc_mock_imports):
|
with mock(self.env.config.autodoc_mock_imports):
|
||||||
try:
|
try:
|
||||||
logger.debug('[autodoc] import %s', self.modname)
|
ret = import_object(self.modname, self.objpath, self.objtype,
|
||||||
obj = import_module(self.modname, self.env.config.autodoc_warningiserror)
|
attrgetter=self.get_attr,
|
||||||
parent = None
|
warningiserror=self.env.config.autodoc_warningiserror)
|
||||||
self.module = obj
|
self.module, self.parent, self.object_name, self.object = ret
|
||||||
logger.debug('[autodoc] => %r', obj)
|
|
||||||
for part in self.objpath:
|
|
||||||
parent = obj
|
|
||||||
logger.debug('[autodoc] getattr(_, %r)', part)
|
|
||||||
obj = self.get_attr(obj, part)
|
|
||||||
logger.debug('[autodoc] => %r', obj)
|
|
||||||
self.object_name = part
|
|
||||||
self.parent = parent
|
|
||||||
self.object = obj
|
|
||||||
return True
|
return True
|
||||||
except (AttributeError, ImportError) as exc:
|
except ImportError as exc:
|
||||||
if self.objpath:
|
self.directive.warn(exc.args[0])
|
||||||
errmsg = 'autodoc: failed to import %s %r from module %r' % \
|
|
||||||
(self.objtype, '.'.join(self.objpath), self.modname)
|
|
||||||
else:
|
|
||||||
errmsg = 'autodoc: failed to import %s %r' % \
|
|
||||||
(self.objtype, self.fullname)
|
|
||||||
|
|
||||||
if isinstance(exc, ImportError):
|
|
||||||
# import_module() raises ImportError having real exception obj and
|
|
||||||
# traceback
|
|
||||||
real_exc, traceback_msg = exc.args
|
|
||||||
if isinstance(real_exc, SystemExit):
|
|
||||||
errmsg += ('; the module executes module level statement ' +
|
|
||||||
'and it might call sys.exit().')
|
|
||||||
elif isinstance(real_exc, ImportError):
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
real_exc.args[0])
|
|
||||||
else:
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
traceback_msg)
|
|
||||||
else:
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
traceback.format_exc())
|
|
||||||
|
|
||||||
if PY2:
|
|
||||||
errmsg = errmsg.decode('utf-8') # type: ignore
|
|
||||||
logger.debug(errmsg)
|
|
||||||
self.directive.warn(errmsg)
|
|
||||||
self.env.note_reread()
|
self.env.note_reread()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -15,11 +15,14 @@ import traceback
|
|||||||
import contextlib
|
import contextlib
|
||||||
from types import FunctionType, MethodType, ModuleType
|
from types import FunctionType, MethodType, ModuleType
|
||||||
|
|
||||||
|
from six import PY2
|
||||||
|
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.inspect import safe_getattr
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Generator, List, Set # NOQA
|
from typing import Any, Callable, Generator, List, Set # NOQA
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -144,3 +147,50 @@ def import_module(modname, warningiserror=False):
|
|||||||
# Importing modules may cause any side effects, including
|
# Importing modules may cause any side effects, including
|
||||||
# SystemExit, so we need to catch all errors.
|
# SystemExit, so we need to catch all errors.
|
||||||
raise ImportError(exc, traceback.format_exc())
|
raise ImportError(exc, traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
|
def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warningiserror=False):
|
||||||
|
# type: (str, List[unicode], str, Callable[[Any, unicode], Any]) -> Any
|
||||||
|
if objpath:
|
||||||
|
logger.debug('[autodoc] from %s import %s', modname, '.'.join(objpath))
|
||||||
|
else:
|
||||||
|
logger.debug('[autodoc] import %s', modname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = import_module(modname, warningiserror=warningiserror)
|
||||||
|
logger.debug('[autodoc] => %r', module)
|
||||||
|
obj = module
|
||||||
|
parent = None
|
||||||
|
object_name = None
|
||||||
|
for attrname in objpath:
|
||||||
|
parent = obj
|
||||||
|
logger.debug('[autodoc] getattr(_, %r)', attrname)
|
||||||
|
obj = attrgetter(obj, attrname)
|
||||||
|
logger.debug('[autodoc] => %r', obj)
|
||||||
|
object_name = attrname
|
||||||
|
return [module, parent, object_name, obj]
|
||||||
|
except (AttributeError, ImportError) as exc:
|
||||||
|
if objpath:
|
||||||
|
errmsg = ('autodoc: failed to import %s %r from module %r' %
|
||||||
|
(objtype, '.'.join(objpath), modname))
|
||||||
|
else:
|
||||||
|
errmsg = 'autodoc: failed to import %s %r' % (objtype, modname)
|
||||||
|
|
||||||
|
if isinstance(exc, ImportError):
|
||||||
|
# import_module() raises ImportError having real exception obj and
|
||||||
|
# traceback
|
||||||
|
real_exc, traceback_msg = exc.args
|
||||||
|
if isinstance(real_exc, SystemExit):
|
||||||
|
errmsg += ('; the module executes module level statement '
|
||||||
|
'and it might call sys.exit().')
|
||||||
|
elif isinstance(real_exc, ImportError):
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % real_exc.args[0]
|
||||||
|
else:
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % traceback_msg
|
||||||
|
else:
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % traceback.format_exc()
|
||||||
|
|
||||||
|
if PY2:
|
||||||
|
errmsg = errmsg.decode('utf-8') # type: ignore
|
||||||
|
logger.debug(errmsg)
|
||||||
|
raise ImportError(errmsg)
|
||||||
|
Loading…
Reference in New Issue
Block a user