summaryrefslogtreecommitdiff
path: root/sphinx/ext/autodoc.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/ext/autodoc.py')
-rw-r--r--sphinx/ext/autodoc.py39
1 files changed, 27 insertions, 12 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 405d24c88..59e585678 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -31,7 +31,7 @@ from sphinx.application import ExtensionError
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util.compat import Directive
from sphinx.util.inspect import getargspec, isdescriptor, safe_getmembers, \
- safe_getattr, object_description, is_builtin_class_method
+ safe_getattr, object_description, is_builtin_class_method, isenumattribute
from sphinx.util.docstrings import prepare_docstring
try:
@@ -86,17 +86,24 @@ class Options(dict):
class _MockModule(object):
"""Used by autodoc_mock_imports."""
+ __file__ = '/dev/null'
+ __path__ = '/dev/null'
+
def __init__(self, *args, **kwargs):
- pass
+ self.__all__ = []
def __call__(self, *args, **kwargs):
+ if args and type(args[0]) in [FunctionType, MethodType]:
+ # Appears to be a decorator, pass through unchanged
+ return args[0]
return _MockModule()
+ def _append_submodule(self, submod):
+ self.__all__.append(submod)
+
@classmethod
def __getattr__(cls, name):
- if name in ('__file__', '__path__'):
- return '/dev/null'
- elif name[0] == name[0].upper():
+ if name[0] == name[0].upper():
# Not very good, we assume Uppercase names are classes...
mocktype = type(name, (), {})
mocktype.__module__ = __name__
@@ -109,9 +116,12 @@ def mock_import(modname):
if '.' in modname:
pkg, _n, mods = modname.rpartition('.')
mock_import(pkg)
- mod = _MockModule()
- sys.modules[modname] = mod
- return mod
+ if isinstance(sys.modules[pkg], _MockModule):
+ sys.modules[pkg]._append_submodule(mods)
+
+ if modname not in sys.modules:
+ mod = _MockModule()
+ sys.modules[modname] = mod
ALL = object()
@@ -304,8 +314,9 @@ def format_annotation(annotation):
return '%s[%s]' % (qualified_name, param_str)
elif hasattr(typing, 'CallableMeta') and \
isinstance(annotation, typing.CallableMeta) and \
- hasattr(annotation, '__args__') and \
+ getattr(annotation, '__args__', None) is not None and \
hasattr(annotation, '__result__'):
+ # Skipped in the case of plain typing.Callable
args = annotation.__args__
if args is None:
return qualified_name
@@ -372,7 +383,9 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
formatted.append('*' + format_arg_with_annotation(varargs))
if kwonlyargs:
- formatted.append('*')
+ if not varargs:
+ formatted.append('*')
+
for kwarg in kwonlyargs:
arg_fd = StringIO()
arg_fd.write(format_arg_with_annotation(kwarg))
@@ -524,7 +537,7 @@ class Documenter(object):
try:
dbg('[autodoc] import %s', self.modname)
for modname in self.env.config.autodoc_mock_imports:
- dbg('[autodoc] adding a mock module %s!', self.modname)
+ dbg('[autodoc] adding a mock module %s!', modname)
mock_import(modname)
__import__(self.modname)
parent = None
@@ -1284,7 +1297,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
u':class:`%s`' % b.__name__ or
u':class:`%s.%s`' % (b.__module__, b.__name__)
for b in self.object.__bases__]
- self.add_line(_(u' Bases: %s') % ', '.join(bases),
+ self.add_line(u' ' + _(u'Bases: %s') % ', '.join(bases),
sourcename)
def get_doc(self, encoding=None, ignore=1):
@@ -1479,6 +1492,8 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
def import_object(self):
ret = ClassLevelDocumenter.import_object(self)
+ if isenumattribute(self.object):
+ self.object = self.object.value
if isdescriptor(self.object) and \
not isinstance(self.object, self.method_types):
self._datadescriptor = True