From 21b838454f4bb5b6a246b85cb2f521deb7552505 Mon Sep 17 00:00:00 2001 From: Luc Saffre Date: Sat, 3 Jan 2015 20:32:44 +0200 Subject: [PATCH] autodoc: use sourcename also for content generated by autodoc itself Fixes #1061 Fixes #1656 --- sphinx/ext/autodoc.py | 50 ++++++++++++++++++------------ sphinx/ext/autosummary/__init__.py | 7 +++-- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index cf87a1c2e78..7c2f35f4e8f 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -481,14 +481,15 @@ def add_directive_header(self, sig): domain = getattr(self, 'domain', 'py') directive = getattr(self, 'directivetype', self.objtype) name = self.format_name() + sourcename = self.get_sourcename() self.add_line(u'.. %s:%s:: %s%s' % (domain, directive, name, sig), - '') + sourcename) if self.options.noindex: - self.add_line(u' :noindex:', '') + self.add_line(u' :noindex:', sourcename) if self.objpath: # Be explicit about the module, this is necessary since .. class:: # etc. don't support a prepended module name - self.add_line(u' :module: %s' % self.modname, '') + self.add_line(u' :module: %s' % self.modname, sourcename) def get_doc(self, encoding=None, ignore=1): """Decode and return lines of the docstring(s) for the object.""" @@ -514,9 +515,7 @@ def process_doc(self, docstrings): for line in docstringlines: yield line - def add_content(self, more_content, no_docstring=False): - """Add content from docstrings, attribute documentation and user.""" - # set sourcename and add content from attribute documentation + def get_sourcename(self): if self.analyzer: # prevent encoding errors when the file name is non-ASCII if not isinstance(self.analyzer.srcname, text_type): @@ -524,8 +523,14 @@ def add_content(self, more_content, no_docstring=False): sys.getfilesystemencoding(), 'replace') else: filename = self.analyzer.srcname - sourcename = u'%s:docstring of %s' % (filename, self.fullname) + return u'%s:docstring of %s' % (filename, self.fullname) + return u'docstring of %s' % self.fullname + def add_content(self, more_content, no_docstring=False): + """Add content from docstrings, attribute documentation and user.""" + # set sourcename and add content from attribute documentation + sourcename = self.get_sourcename() + if self.analyzer: attr_docs = self.analyzer.find_attr_docs() if self.objpath: key = ('.'.join(self.objpath[:-1]), self.objpath[-1]) @@ -534,8 +539,6 @@ def add_content(self, more_content, no_docstring=False): docstrings = [attr_docs[key]] for i, line in enumerate(self.process_doc(docstrings)): self.add_line(line, sourcename, i) - else: - sourcename = u'docstring of %s' % self.fullname # add content from docstrings if not no_docstring: @@ -794,17 +797,19 @@ def generate(self, more_content=None, real_modname=None, if not self.check_module(): return + sourcename = self.get_sourcename() + # make sure that the result starts with an empty line. This is # necessary for some situations where another directive preprocesses # reST and no starting newline is present - self.add_line(u'', '') + self.add_line(u'', sourcename) # format the object's signature, if any sig = self.format_signature() # generate the directive header and options, if applicable self.add_directive_header(sig) - self.add_line(u'', '') + self.add_line(u'', sourcename) # e.g. the module directive doesn't have content self.indent += self.content_indent @@ -854,15 +859,17 @@ def parse_name(self): def add_directive_header(self, sig): Documenter.add_directive_header(self, sig) + sourcename = self.get_sourcename() + # add some module-specific options if self.options.synopsis: self.add_line( - u' :synopsis: ' + self.options.synopsis, '') + u' :synopsis: ' + self.options.synopsis, sourcename) if self.options.platform: self.add_line( - u' :platform: ' + self.options.platform, '') + u' :platform: ' + self.options.platform, sourcename) if self.options.deprecated: - self.add_line(u' :deprecated:', '') + self.add_line(u' :deprecated:', sourcename) def get_object_members(self, want_all): if want_all: @@ -1108,14 +1115,15 @@ def add_directive_header(self, sig): # add inheritance info, if wanted if not self.doc_as_attr and self.options.show_inheritance: - self.add_line(u'', '') + sourcename = self.get_sourcename() + self.add_line(u'', sourcename) if hasattr(self.object, '__bases__') and len(self.object.__bases__): bases = [b.__module__ in ('__builtin__', 'builtins') and 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), - '') + sourcename) def get_doc(self, encoding=None, ignore=1): lines = getattr(self, '_new_docstrings', None) @@ -1200,18 +1208,19 @@ def can_document_member(cls, member, membername, isattr, parent): def add_directive_header(self, sig): ModuleLevelDocumenter.add_directive_header(self, sig) + sourcename = self.get_sourcename() if not self.options.annotation: try: objrepr = safe_repr(self.object) except ValueError: pass else: - self.add_line(u' :annotation: = ' + objrepr, '') + self.add_line(u' :annotation: = ' + objrepr, sourcename) elif self.options.annotation is SUPPRESS: pass else: self.add_line(u' :annotation: %s' % self.options.annotation, - '') + sourcename) def document_members(self, all_members=False): pass @@ -1311,6 +1320,7 @@ def get_real_modname(self): def add_directive_header(self, sig): ClassLevelDocumenter.add_directive_header(self, sig) + sourcename = self.get_sourcename() if not self.options.annotation: if not self._datadescriptor: try: @@ -1318,12 +1328,12 @@ def add_directive_header(self, sig): except ValueError: pass else: - self.add_line(u' :annotation: = ' + objrepr, '') + self.add_line(u' :annotation: = ' + objrepr, sourcename) elif self.options.annotation is SUPPRESS: pass else: self.add_line(u' :annotation: %s' % self.options.annotation, - '') + sourcename) def add_content(self, more_content, no_docstring=False): if not self._datadescriptor: diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 9be3923719a..08a855846f6 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -69,6 +69,7 @@ from sphinx import addnodes from sphinx.util.compat import Directive from sphinx.pycode import ModuleAnalyzer, PycodeError +from sphinx.ext.autodoc import Options # -- autosummary_toc node ------------------------------------------------------ @@ -131,7 +132,7 @@ def autosummary_table_visit_html(self, node): class FakeDirective: env = {} - genopt = {} + genopt = Options() def get_documenter(obj, parent): """Get an autodoc.Documenter class suitable for documenting the given @@ -194,7 +195,7 @@ def warn(self, msg): def run(self): self.env = env = self.state.document.settings.env - self.genopt = {} + self.genopt = Options() self.warnings = [] self.result = ViewList() @@ -269,6 +270,8 @@ def get_items(self, names): self.warn('failed to import object %s' % real_name) items.append((display_name, '', '', real_name)) continue + if not documenter.check_module(): + continue # try to also get a source code analyzer for attribute docs try: