diff options
author | shimizukawa <shimizukawa@gmail.com> | 2014-06-09 22:45:05 +0900 |
---|---|---|
committer | shimizukawa <shimizukawa@gmail.com> | 2014-06-09 22:45:05 +0900 |
commit | 8a3c7011f84e50e52cfd9457b33aa0f4fd876116 (patch) | |
tree | 9a0e5df28ee17dbc92a3e989f01996d8c509895a /sphinx/ext/autodoc.py | |
parent | 5d9d0c0314fe0a0ed19869452b336db618242dc2 (diff) | |
parent | e26cdac8bcf2ba84e543c32de4fbe58d66a4f82c (diff) | |
download | sphinx-8a3c7011f84e50e52cfd9457b33aa0f4fd876116.tar.gz |
merge with stable
Diffstat (limited to 'sphinx/ext/autodoc.py')
-rw-r--r-- | sphinx/ext/autodoc.py | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 34197a39..280d1fd2 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -17,6 +17,7 @@ import inspect import traceback from types import FunctionType, BuiltinFunctionType, MethodType +from six import PY3, iteritems, itervalues, text_type, class_types from docutils import nodes from docutils.utils import assemble_option_dict from docutils.statemachine import ViewList @@ -29,7 +30,6 @@ 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, safe_repr, is_builtin_class_method -from sphinx.util.pycompat import base_exception, class_types from sphinx.util.docstrings import prepare_docstring @@ -54,9 +54,10 @@ class DefDict(dict): return dict.__getitem__(self, key) except KeyError: return self.default - def __nonzero__(self): + def __bool__(self): # docutils check "if option_spec" return True + __nonzero__ = __bool__ # for python2 compatibility identity = lambda x: x @@ -70,6 +71,35 @@ class Options(dict): return None +class _MockModule(object): + """Used by autodoc_mock_imports.""" + def __init__(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + return _MockModule() + + @classmethod + def __getattr__(cls, name): + if name in ('__file__', '__path__'): + return '/dev/null' + elif name[0] == name[0].upper(): + # Not very good, we assume Uppercase names are classes... + mocktype = type(name, (), {}) + mocktype.__module__ = __name__ + return mocktype + else: + return _MockModule() + +def mock_import(modname): + if '.' in modname: + pkg, _n, mods = modname.rpartition('.') + mock_import(pkg) + mod = _MockModule() + sys.modules[modname] = mod + return mod + + ALL = object() INSTANCEATTR = object() @@ -235,7 +265,7 @@ class Documenter(object): @staticmethod def get_attr(obj, name, *defargs): """getattr() override for types such as Zope interfaces.""" - for typ, func in AutoDirective._special_attrgetters.iteritems(): + for typ, func in iteritems(AutoDirective._special_attrgetters): if isinstance(obj, typ): return func(obj, name, *defargs) return safe_getattr(obj, name, *defargs) @@ -332,6 +362,9 @@ class Documenter(object): self.modname, '.'.join(self.objpath)) 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) + mock_import(modname) __import__(self.modname) parent = None obj = self.module = sys.modules[self.modname] @@ -411,7 +444,7 @@ class Documenter(object): # try to introspect the signature try: args = self.format_args() - except Exception, err: + except Exception as err: self.directive.warn('error while formatting arguments for ' '%s: %s' % (self.fullname, err)) args = None @@ -448,7 +481,7 @@ class Documenter(object): docstring = self.get_attr(self.object, '__doc__', None) # make sure we have Unicode docstrings, then sanitize and split # into lines - if isinstance(docstring, unicode): + if isinstance(docstring, text_type): return [prepare_docstring(docstring, ignore)] elif isinstance(docstring, str): # this will not trigger on Py3 return [prepare_docstring(force_decode(docstring, encoding), @@ -472,9 +505,9 @@ class Documenter(object): # set sourcename and add content from attribute documentation if self.analyzer: # prevent encoding errors when the file name is non-ASCII - if not isinstance(self.analyzer.srcname, unicode): - filename = unicode(self.analyzer.srcname, - sys.getfilesystemencoding(), 'replace') + if not isinstance(self.analyzer.srcname, text_type): + filename = text_type(self.analyzer.srcname, + sys.getfilesystemencoding(), 'replace') else: filename = self.analyzer.srcname sourcename = u'%s:docstring of %s' % (filename, self.fullname) @@ -518,7 +551,7 @@ class Documenter(object): if self.analyzer: attr_docs = self.analyzer.find_attr_docs() namespace = '.'.join(self.objpath) - for item in attr_docs.iteritems(): + for item in iteritems(attr_docs): if item[0][0] == namespace: analyzed_member_names.add(item[0][1]) if not want_all: @@ -659,7 +692,7 @@ class Documenter(object): # document non-skipped members memberdocumenters = [] for (mname, member, isattr) in self.filter_members(members, want_all): - classes = [cls for cls in AutoDirective._registry.itervalues() + classes = [cls for cls in itervalues(AutoDirective._registry) if cls.can_document_member(member, mname, isattr, self)] if not classes: # don't know how to document this member @@ -731,7 +764,7 @@ class Documenter(object): # parse right now, to get PycodeErrors on parsing (results will # be cached anyway) self.analyzer.find_attr_docs() - except PycodeError, err: + except PycodeError as err: self.env.app.debug('[autodoc] module analyzer failed: %s', err) # no source file -- e.g. for builtin and C modules self.analyzer = None @@ -1096,7 +1129,7 @@ class ClassDocumenter(ModuleLevelDocumenter): docstrings.append(initdocstring) doc = [] for docstring in docstrings: - if not isinstance(docstring, unicode): + if not isinstance(docstring, text_type): docstring = force_decode(docstring, encoding) doc.append(prepare_docstring(docstring)) return doc @@ -1131,7 +1164,7 @@ class ExceptionDocumenter(ClassDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): return isinstance(member, class_types) and \ - issubclass(member, base_exception) + issubclass(member, BaseException) class DataDocumenter(ModuleLevelDocumenter): @@ -1180,7 +1213,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): return inspect.isroutine(member) and \ not isinstance(parent, ModuleDocumenter) - if sys.version_info >= (3, 0): + if PY3: def import_object(self): ret = ClassLevelDocumenter.import_object(self) if not ret: @@ -1202,7 +1235,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): return ret if isinstance(self.object, classmethod) or \ (isinstance(self.object, MethodType) and - self.object.im_self is not None): + self.object.__self__ is not None): self.directivetype = 'classmethod' # document class and static members before ordinary ones self.member_order = self.member_order - 1 @@ -1394,7 +1427,7 @@ class AutoDirective(Directive): try: self.genopt = Options(assemble_option_dict( self.options.items(), doc_class.option_spec)) - except (KeyError, ValueError, TypeError), err: + except (KeyError, ValueError, TypeError) as err: # an option is either unknown or has a wrong type msg = self.reporter.error('An option to %s is either unknown or ' 'has an invalid value: %s' % (self.name, err), @@ -1458,6 +1491,7 @@ def setup(app): app.add_config_value('autodoc_member_order', 'alphabetic', True) app.add_config_value('autodoc_default_flags', [], True) app.add_config_value('autodoc_docstring_signature', True, True) + app.add_config_value('autodoc_mock_imports', [], True) app.add_event('autodoc-process-docstring') app.add_event('autodoc-process-signature') app.add_event('autodoc-skip-member') |