summaryrefslogtreecommitdiff
path: root/sphinx/ext/inheritance_diagram.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/ext/inheritance_diagram.py')
-rw-r--r--sphinx/ext/inheritance_diagram.py88
1 files changed, 45 insertions, 43 deletions
diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py
index cf81251ee..ed583b694 100644
--- a/sphinx/ext/inheritance_diagram.py
+++ b/sphinx/ext/inheritance_diagram.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
r"""
sphinx.ext.inheritance_diagram
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -36,21 +35,22 @@ r"""
:license: BSD, see LICENSE for details.
"""
+import builtins
import inspect
import re
import sys
from hashlib import md5
+from typing import Iterable, cast
from docutils import nodes
from docutils.parsers.rst import directives
-from six import text_type
-from six.moves import builtins
import sphinx
-from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \
- render_dot_texinfo, figure_wrapper
-from sphinx.pycode import ModuleAnalyzer
-from sphinx.util import force_decode
+from sphinx import addnodes
+from sphinx.ext.graphviz import (
+ graphviz, figure_wrapper,
+ render_dot_html, render_dot_latex, render_dot_texinfo
+)
from sphinx.util.docutils import SphinxDirective
if False:
@@ -58,6 +58,9 @@ if False:
from typing import Any, Dict, List, Tuple, Dict, Optional # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.environment import BuildEnvironment # NOQA
+ from sphinx.writers.html import HTMLTranslator # NOQA
+ from sphinx.writers.latex import LaTeXTranslator # NOQA
+ from sphinx.writers.texinfo import TexinfoTranslator # NOQA
module_sig_re = re.compile(r'''^(?:([\w.]*)\.)? # module names
@@ -66,7 +69,7 @@ module_sig_re = re.compile(r'''^(?:([\w.]*)\.)? # module names
def try_import(objname):
- # type: (unicode) -> Any
+ # type: (str) -> Any
"""Import a object or module using *name* and *currentmodule*.
*name* should be a relative name from *currentmodule* or
a fully-qualified name.
@@ -75,8 +78,8 @@ def try_import(objname):
"""
try:
__import__(objname)
- return sys.modules.get(objname) # type: ignore
- except (ImportError, ValueError): # ValueError,py27 -> ImportError,py3
+ return sys.modules.get(objname)
+ except ImportError:
matched = module_sig_re.match(objname)
if not matched:
@@ -88,13 +91,13 @@ def try_import(objname):
return None
try:
__import__(modname)
- return getattr(sys.modules.get(modname), attrname, None) # type: ignore
- except (ImportError, ValueError): # ValueError,py27 -> ImportError,py3
+ return getattr(sys.modules.get(modname), attrname, None)
+ except ImportError:
return None
def import_classes(name, currmodule):
- # type: (unicode, unicode) -> Any
+ # type: (str, str) -> Any
"""Import a class using its fully-qualified *name*."""
target = None
@@ -129,7 +132,7 @@ class InheritanceException(Exception):
pass
-class InheritanceGraph(object):
+class InheritanceGraph:
"""
Given a list of classes, determines the set of classes that they inherit
from all the way to the root "object", and then is able to generate a
@@ -137,7 +140,7 @@ class InheritanceGraph(object):
"""
def __init__(self, class_names, currmodule, show_builtins=False,
private_bases=False, parts=0, aliases=None, top_classes=[]):
- # type: (unicode, str, bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> None # NOQA
+ # type: (List[str], str, bool, bool, int, Optional[Dict[str, str]], List[Any]) -> None
"""*class_names* is a list of child classes to show bases from.
If *show_builtins* is True, then Python builtins will be shown
@@ -152,7 +155,7 @@ class InheritanceGraph(object):
'inheritance diagram')
def _import_classes(self, class_names, currmodule):
- # type: (unicode, str) -> List[Any]
+ # type: (List[str], str) -> List[Any]
"""Import a list of classes."""
classes = [] # type: List[Any]
for name in class_names:
@@ -160,7 +163,7 @@ class InheritanceGraph(object):
return classes
def _class_info(self, classes, show_builtins, private_bases, parts, aliases, top_classes):
- # type: (List[Any], bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA
+ # type: (List[Any], bool, bool, int, Optional[Dict[str, str]], List[Any]) -> List[Tuple[str, str, List[str], str]] # NOQA
"""Return name and bases for all classes that are ancestors of
*classes*.
@@ -187,16 +190,13 @@ class InheritanceGraph(object):
tooltip = None
try:
if cls.__doc__:
- enc = ModuleAnalyzer.for_module(cls.__module__).encoding
doc = cls.__doc__.strip().split("\n")[0]
- if not isinstance(doc, text_type):
- doc = force_decode(doc, enc)
if doc:
tooltip = '"%s"' % doc.replace('"', '\\"')
except Exception: # might raise AttributeError for strange classes
pass
- baselist = [] # type: List[unicode]
+ baselist = [] # type: List[str]
all_classes[cls] = (nodename, fullname, baselist, tooltip)
if fullname in top_classes:
@@ -217,7 +217,7 @@ class InheritanceGraph(object):
return list(all_classes.values())
def class_name(self, cls, parts=0, aliases=None):
- # type: (Any, int, Optional[Dict[unicode, unicode]]) -> unicode
+ # type: (Any, int, Optional[Dict[str, str]]) -> str
"""Given a class object, return a fully-qualified name.
This works for things I've tested in matplotlib so far, but may not be
@@ -238,7 +238,7 @@ class InheritanceGraph(object):
return result
def get_all_class_names(self):
- # type: () -> List[unicode]
+ # type: () -> List[str]
"""Get all of the class names involved in the graph."""
return [fullname for (_, fullname, _, _) in self.class_info]
@@ -261,16 +261,16 @@ class InheritanceGraph(object):
}
def _format_node_attrs(self, attrs):
- # type: (Dict) -> unicode
+ # type: (Dict) -> str
return ','.join(['%s=%s' % x for x in sorted(attrs.items())])
def _format_graph_attrs(self, attrs):
- # type: (Dict) -> unicode
+ # type: (Dict) -> str
return ''.join(['%s=%s;\n' % x for x in sorted(attrs.items())])
def generate_dot(self, name, urls={}, env=None,
graph_attrs={}, node_attrs={}, edge_attrs={}):
- # type: (unicode, Dict, BuildEnvironment, Dict, Dict, Dict) -> unicode
+ # type: (str, Dict, BuildEnvironment, Dict, Dict, Dict) -> str
"""Generate a graphviz dot graph from the classes that were passed in
to __init__.
@@ -292,7 +292,7 @@ class InheritanceGraph(object):
n_attrs.update(env.config.inheritance_node_attrs)
e_attrs.update(env.config.inheritance_edge_attrs)
- res = [] # type: List[unicode]
+ res = [] # type: List[str]
res.append('digraph %s {\n' % name)
res.append(self._format_graph_attrs(g_attrs))
@@ -316,7 +316,7 @@ class InheritanceGraph(object):
return ''.join(res)
-class inheritance_diagram(nodes.General, nodes.Element):
+class inheritance_diagram(graphviz):
"""
A docutils node to use as a placeholder for the inheritance diagram.
"""
@@ -362,36 +362,37 @@ class InheritanceDiagram(SphinxDirective):
aliases=self.config.inheritance_alias,
top_classes=node['top-classes'])
except InheritanceException as err:
- return [node.document.reporter.warning(err.args[0],
- line=self.lineno)]
+ return [node.document.reporter.warning(err, line=self.lineno)]
# Create xref nodes for each target of the graph's image map and
# add them to the doc tree so that Sphinx can resolve the
# references to real URLs later. These nodes will eventually be
# removed from the doctree after we're done with them.
for name in graph.get_all_class_names():
- refnodes, x = class_role(
+ refnodes, x = class_role( # type: ignore
'class', ':class:`%s`' % name, name, 0, self.state)
node.extend(refnodes)
# Store the graph object so we can use it to generate the
# dot file later
node['graph'] = graph
- # wrap the result in figure node
- caption = self.options.get('caption')
- if caption:
- node = figure_wrapper(self, node, caption)
- return [node]
+ if 'caption' not in self.options:
+ self.add_name(node)
+ return [node]
+ else:
+ figure = figure_wrapper(self, node, self.options['caption'])
+ self.add_name(figure)
+ return [figure]
def get_graph_hash(node):
- # type: (inheritance_diagram) -> unicode
- encoded = (node['content'] + str(node['parts'])).encode('utf-8')
+ # type: (inheritance_diagram) -> str
+ encoded = (node['content'] + str(node['parts'])).encode()
return md5(encoded).hexdigest()[-10:]
def html_visit_inheritance_diagram(self, node):
- # type: (nodes.NodeVisitor, inheritance_diagram) -> None
+ # type: (HTMLTranslator, inheritance_diagram) -> None
"""
Output the graph for HTML. This will insert a PNG with clickable
image map.
@@ -405,7 +406,8 @@ def html_visit_inheritance_diagram(self, node):
graphviz_output_format = self.builder.env.config.graphviz_output_format.upper()
current_filename = self.builder.current_docname + self.builder.out_suffix
urls = {}
- for child in node:
+ pending_xrefs = cast(Iterable[addnodes.pending_xref], node)
+ for child in pending_xrefs:
if child.get('refuri') is not None:
if graphviz_output_format == 'SVG':
urls[child['reftitle']] = "../" + child.get('refuri')
@@ -424,7 +426,7 @@ def html_visit_inheritance_diagram(self, node):
def latex_visit_inheritance_diagram(self, node):
- # type: (nodes.NodeVisitor, inheritance_diagram) -> None
+ # type: (LaTeXTranslator, inheritance_diagram) -> None
"""
Output the graph for LaTeX. This will insert a PDF.
"""
@@ -440,7 +442,7 @@ def latex_visit_inheritance_diagram(self, node):
def texinfo_visit_inheritance_diagram(self, node):
- # type: (nodes.NodeVisitor, inheritance_diagram) -> None
+ # type: (TexinfoTranslator, inheritance_diagram) -> None
"""
Output the graph for Texinfo. This will insert a PNG.
"""
@@ -461,7 +463,7 @@ def skip(self, node):
def setup(app):
- # type: (Sphinx) -> Dict[unicode, Any]
+ # type: (Sphinx) -> Dict[str, Any]
app.setup_extension('sphinx.ext.graphviz')
app.add_node(
inheritance_diagram,