diff options
| author | Georg Brandl <georg@python.org> | 2008-12-30 02:09:29 +0100 |
|---|---|---|
| committer | Georg Brandl <georg@python.org> | 2008-12-30 02:09:29 +0100 |
| commit | b16fc1a0ae62ebb0c97511da7ae04d890c7a9ad3 (patch) | |
| tree | 8bdd9694c882bbb79144d8b30a1c6d6aaf4f9145 /sphinx/ext | |
| parent | bc4c6b9214603c8a04b965eae7ddebaa61727530 (diff) | |
| download | sphinx-b16fc1a0ae62ebb0c97511da7ae04d890c7a9ad3.tar.gz | |
First iteration of an autodoc that handles attribute documentation.
Diffstat (limited to 'sphinx/ext')
| -rw-r--r-- | sphinx/ext/autodoc.py | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index f94afc75..ddea1e44 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -22,6 +22,7 @@ from docutils.parsers.rst import directives from docutils.statemachine import ViewList from sphinx.util import rpartition, nested_parse_with_titles +from sphinx.pycode import ModuleAnalyzer, PycodeError clstypes = (type, ClassType) try: @@ -313,7 +314,7 @@ class RstGenerator(object): 'for automodule %s' % name) return (path or '') + base, [], None, None - elif what in ('exception', 'function', 'class'): + elif what in ('exception', 'function', 'class', 'data'): if mod is None: if path: mod = path.rstrip('.') @@ -434,7 +435,9 @@ class RstGenerator(object): modfile = None # e.g. for builtin and C modules for part in objpath: todoc = getattr(todoc, part) - except (ImportError, AttributeError), err: + # also get a source code analyzer for attribute docs + analyzer = ModuleAnalyzer.for_module(mod) + except (ImportError, AttributeError, PycodeError), err: self.warn('autodoc can\'t import/find %s %r, it reported error: "%s", ' 'please check your spelling and sys.path' % (what, str(fullname), err)) @@ -503,6 +506,15 @@ class RstGenerator(object): else: sourcename = 'docstring of %s' % fullname + # add content from attribute documentation + attr_docs = analyzer.find_attr_docs() + if what in ('data', 'attribute'): + key = ('.'.join(objpath[:-1]), objpath[-1]) + if key in attr_docs: + no_docstring = True + for i, line in enumerate(attr_docs[key]): + self.result.append(indent + line, sourcename, i) + # add content from docstrings if not no_docstring: for i, line in enumerate(self.get_doc(what, fullname, todoc)): @@ -524,9 +536,9 @@ class RstGenerator(object): self.env.autodoc_current_class = objpath[0] # add members, if possible - _all = members == ['__all__'] + all_members = members == ['__all__'] members_check_module = False - if _all: + if all_members: # unqualified :members: given if what == 'module': if hasattr(todoc, '__all__'): @@ -555,14 +567,28 @@ class RstGenerator(object): else: all_members = [(mname, getattr(todoc, mname)) for mname in members] + # search for members in source code too + namespace = '.'.join(objpath) # will be empty for modules + for (membername, member) in all_members: - if _all and membername.startswith('_'): + # if isattr is True, the member is documented as an attribute + isattr = False + # if content is not None, no extra content from docstrings will be added + content = None + + if all_members and membername.startswith('_'): # ignore members whose name starts with _ by default skip = True else: - # ignore undocumented members if :undoc-members: is not given - doc = getattr(member, '__doc__', None) - skip = not self.options.undoc_members and not doc + if (namespace, membername) in attr_docs: + # keep documented attributes + skip = False + isattr = True + else: + # ignore undocumented members if :undoc-members: is not given + doc = getattr(member, '__doc__', None) + skip = not self.options.undoc_members and not doc + # give the user a chance to decide whether this member should be skipped if self.env.app: # let extensions preprocess docstrings @@ -573,10 +599,11 @@ class RstGenerator(object): if skip: continue - content = None if what == 'module': if isinstance(member, (FunctionType, BuiltinFunctionType)): memberwhat = 'function' + elif isattr: + memberwhat = 'attribute' elif isinstance(member, clstypes): if member.__name__ != membername: # assume it's aliased @@ -588,10 +615,13 @@ class RstGenerator(object): else: memberwhat = 'class' else: - # XXX: todo -- attribute docs continue else: - if isinstance(member, clstypes): + if inspect.isroutine(member): + memberwhat = 'method' + elif isattr: + memberwhat = 'attribute' + elif isinstance(member, clstypes): if member.__name__ != membername: # assume it's aliased memberwhat = 'attribute' @@ -599,12 +629,9 @@ class RstGenerator(object): source='') else: memberwhat = 'class' - elif inspect.isroutine(member): - memberwhat = 'method' elif isdescriptor(member): memberwhat = 'attribute' else: - # XXX: todo -- attribute docs continue # give explicitly separated module name, so that members of inner classes # can be documented |
