diff options
Diffstat (limited to 'sphinx/ext/inheritance_diagram.py')
| -rw-r--r-- | sphinx/ext/inheritance_diagram.py | 88 |
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, |
