diff options
Diffstat (limited to 'sphinx/ext/autodoc.py')
-rw-r--r-- | sphinx/ext/autodoc.py | 39 |
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 |