summaryrefslogtreecommitdiff
path: root/sphinx/ext
diff options
context:
space:
mode:
authorRob Ruana <rob@relentlessidiot.com>2014-01-19 12:31:07 -0500
committerRob Ruana <rob@relentlessidiot.com>2014-01-19 12:31:07 -0500
commita8b06aa17015396b9bd5accb5cca4644f69f307d (patch)
treed38b9d2e011dccc1a319674799b499b2f31ffece /sphinx/ext
parent49b952d84136ef89132de8d48b4b937b816f0c22 (diff)
parent2a8cf7c7781a4554adbcb4bae6bec2a40bfc156d (diff)
downloadsphinx-a8b06aa17015396b9bd5accb5cca4644f69f307d.tar.gz
Merged birkenfeld/sphinx into default
Diffstat (limited to 'sphinx/ext')
-rw-r--r--sphinx/ext/autodoc.py33
-rw-r--r--sphinx/ext/graphviz.py3
-rw-r--r--sphinx/ext/inheritance_diagram.py26
-rw-r--r--sphinx/ext/viewcode.py22
4 files changed, 63 insertions, 21 deletions
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 571f36cb..86837ff8 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -70,6 +70,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()
@@ -332,6 +361,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]
@@ -1453,6 +1485,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')
diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py
index 800e9ca8..32bb96d3 100644
--- a/sphinx/ext/graphviz.py
+++ b/sphinx/ext/graphviz.py
@@ -178,6 +178,9 @@ def render_dot(self, code, options, format, prefix='graphviz'):
if p.returncode != 0:
raise GraphvizError('dot exited with error:\n[stderr]\n%s\n'
'[stdout]\n%s' % (stderr, stdout))
+ if not path.isfile(outfn):
+ raise GraphvizError('dot did not produce an output file:\n[stderr]\n%s\n'
+ '[stdout]\n%s' % (stderr, stdout))
return relfn, outfn
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index 2d1d6e30..fd973544 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -154,8 +154,18 @@ class InheritanceGraph(object):
nodename = self.class_name(cls, parts)
fullname = self.class_name(cls, 0)
+ # Use first line of docstring as tooltip, if available
+ tooltip = None
+ try:
+ if cls.__doc__:
+ doc = cls.__doc__.strip().split("\n")[0]
+ if doc:
+ tooltip = '"%s"' % doc.replace('"', '\\"')
+ except Exception: # might raise AttributeError for strange classes
+ pass
+
baselist = []
- all_classes[cls] = (nodename, fullname, baselist)
+ all_classes[cls] = (nodename, fullname, baselist, tooltip)
for base in cls.__bases__:
if not show_builtins and base in builtins:
continue
@@ -168,7 +178,7 @@ class InheritanceGraph(object):
for cls in classes:
recurse(cls)
- return all_classes
+ return all_classes.values()
def class_name(self, cls, parts=0):
"""Given a class object, return a fully-qualified name.
@@ -188,7 +198,7 @@ class InheritanceGraph(object):
def get_all_class_names(self):
"""Get all of the class names involved in the graph."""
- return [fullname for (_, fullname, _) in self.class_info.values()]
+ return [fullname for (_, fullname, _, _) in self.class_info]
# These are the default attrs for graphviz
default_graph_attrs = {
@@ -241,17 +251,13 @@ class InheritanceGraph(object):
res.append('digraph %s {\n' % name)
res.append(self._format_graph_attrs(g_attrs))
- for cls, (name, fullname, bases) in sorted(self.class_info.items()):
+ for name, fullname, bases, tooltip in sorted(self.class_info):
# Write the node
this_node_attrs = n_attrs.copy()
if fullname in urls:
this_node_attrs['URL'] = '"%s"' % urls[fullname]
- # Use first line of docstring as tooltip, if available
- if cls.__doc__:
- doc = cls.__doc__.strip().split("\n")[0]
- if doc:
- doc = doc.replace('"', '\\"')
- this_node_attrs['tooltip'] = '"%s"' % doc
+ if tooltip:
+ this_node_attrs['tooltip'] = tooltip
res.append(' "%s" [%s];\n' %
(name, self._format_node_attrs(this_node_attrs)))
diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py
index 962b543b..36fb47d2 100644
--- a/sphinx/ext/viewcode.py
+++ b/sphinx/ext/viewcode.py
@@ -24,17 +24,17 @@ def doctree_read(app, doctree):
def has_tag(modname, fullname, docname):
entry = env._viewcode_modules.get(modname, None)
- if entry is None:
- try:
- analyzer = ModuleAnalyzer.for_module(modname)
- except Exception:
- env._viewcode_modules[modname] = False
- return
+ try:
+ analyzer = ModuleAnalyzer.for_module(modname)
+ except Exception:
+ env._viewcode_modules[modname] = False
+ return
+ if not isinstance(analyzer.code, unicode):
+ code = analyzer.code.decode(analyzer.encoding)
+ else:
+ code = analyzer.code
+ if entry is None or entry[0] != code:
analyzer.find_tags()
- if not isinstance(analyzer.code, unicode):
- code = analyzer.code.decode(analyzer.encoding)
- else:
- code = analyzer.code
entry = code, analyzer.tags, {}
env._viewcode_modules[modname] = entry
elif entry is False:
@@ -142,7 +142,7 @@ def collect_pages(app):
if not modnames:
return
- app.builder.info(' _modules/index')
+ app.builder.info(' _modules/index', nonl=True)
html = ['\n']
# the stack logic is needed for using nested lists for submodules
stack = ['']