From 337a5c484a0d5249f8e0ec5017db3152e83c00e7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 28 Nov 2018 02:25:04 +0900 Subject: [PATCH] Fix annotaions for extensions --- sphinx/ext/autosectionlabel.py | 5 +++- sphinx/ext/doctest.py | 4 ++-- sphinx/ext/graphviz.py | 36 +++++++++++++++------------- sphinx/ext/ifconfig.py | 2 +- sphinx/ext/imgmath.py | 15 ++++++------ sphinx/ext/inheritance_diagram.py | 9 ++++--- sphinx/ext/intersphinx.py | 2 +- sphinx/ext/jsmath.py | 14 +++++++---- sphinx/ext/mathjax.py | 15 ++++++++---- sphinx/ext/todo.py | 39 ++++++++++++++++++------------- sphinx/ext/viewcode.py | 4 +++- 11 files changed, 88 insertions(+), 57 deletions(-) diff --git a/sphinx/ext/autosectionlabel.py b/sphinx/ext/autosectionlabel.py index 459817a4c..4c601b497 100644 --- a/sphinx/ext/autosectionlabel.py +++ b/sphinx/ext/autosectionlabel.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for details. """ +from typing import cast + from docutils import nodes from sphinx.locale import __ @@ -37,7 +39,8 @@ def register_sections_as_label(app, document): for node in document.traverse(nodes.section): labelid = node['ids'][0] docname = app.env.docname - ref_name = getattr(node[0], 'rawsource', node[0].astext()) + title = cast(nodes.title, node[0]) + ref_name = getattr(node[0], 'rawsource', title.astext()) if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + ref_name) else: diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index f74e9e32e..b295fead6 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -36,7 +36,7 @@ from sphinx.util.osutil import relpath if False: # For type annotation - from typing import Any, Callable, Dict, IO, Iterable, List, Optional, Sequence, Set, Tuple # NOQA + from typing import Any, Callable, Dict, IO, Iterable, List, Optional, Sequence, Set, Tuple, Type # NOQA from sphinx.application import Sphinx # NOQA from sphinx.util.typing import unicode # NOQA @@ -109,7 +109,7 @@ class TestDirective(SphinxDirective): if not test: test = code code = doctestopt_re.sub('', code) - nodetype = nodes.literal_block + nodetype = nodes.literal_block # type: Type[nodes.TextElement] if self.name in ('testsetup', 'testcleanup') or 'hide' in self.options: nodetype = nodes.comment if self.arguments: diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 732e87cee..c2b08bce1 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -33,9 +33,14 @@ from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL if False: # For type annotation from docutils.parsers.rst import Directive # NOQA - from typing import Any, Dict, List, Tuple # NOQA + from typing import Any, Dict, List, Tuple, Union # NOQA from sphinx.application import Sphinx # NOQA from sphinx.util.typing import unicode # NOQA + from sphinx.writers.html import HTMLTranslator # NOQA + from sphinx.writers.latex import LaTeXTranslator # NOQA + from sphinx.writers.manpage import ManualPageTranslator # NOQA + from sphinx.writers.texinfo import TexinfoTranslator # NOQA + from sphinx.writers.text import TextTranslator # NOQA logger = logging.getLogger(__name__) @@ -93,7 +98,7 @@ class graphviz(nodes.General, nodes.Inline, nodes.Element): def figure_wrapper(directive, node, caption): - # type: (Directive, nodes.Node, unicode) -> nodes.figure + # type: (Directive, graphviz, unicode) -> nodes.figure figure_node = nodes.figure('', node) if 'align' in node: figure_node['align'] = node.attributes.pop('align') @@ -101,8 +106,7 @@ def figure_wrapper(directive, node, caption): parsed = nodes.Element() directive.state.nested_parse(ViewList([caption], source=''), directive.content_offset, parsed) - caption_node = nodes.caption(parsed[0].rawsource, '', - *parsed[0].children) + caption_node = nodes.caption(parsed[0].rawsource, '', *parsed[0].children) caption_node.source = parsed[0].source caption_node.line = parsed[0].line figure_node += caption_node @@ -110,7 +114,7 @@ def figure_wrapper(directive, node, caption): def align_spec(argument): - # type: (Any) -> bool + # type: (Any) -> str return directives.choice(argument, ('left', 'center', 'right')) @@ -213,7 +217,7 @@ class GraphvizSimple(SphinxDirective): def render_dot(self, code, options, format, prefix='graphviz'): - # type: (nodes.NodeVisitor, unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode] + # type: (Union[HTMLTranslator, LaTeXTranslator, TexinfoTranslator], unicode, Dict, unicode, unicode) -> Tuple[unicode, unicode] # NOQA """Render graphviz code into a PNG or PDF output file.""" graphviz_dot = options.get('graphviz_dot', self.builder.config.graphviz_dot) hashkey = (code + str(options) + str(graphviz_dot) + @@ -227,7 +231,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): return relfn, outfn if (hasattr(self.builder, '_graphviz_warned_dot') and - self.builder._graphviz_warned_dot.get(graphviz_dot)): + self.builder._graphviz_warned_dot.get(graphviz_dot)): # type: ignore # NOQA return None, None ensuredir(path.dirname(outfn)) @@ -253,8 +257,8 @@ def render_dot(self, code, options, format, prefix='graphviz'): logger.warning(__('dot command %r cannot be run (needed for graphviz ' 'output), check the graphviz_dot setting'), graphviz_dot) if not hasattr(self.builder, '_graphviz_warned_dot'): - self.builder._graphviz_warned_dot = {} - self.builder._graphviz_warned_dot[graphviz_dot] = True + self.builder._graphviz_warned_dot = {} # type: ignore + self.builder._graphviz_warned_dot[graphviz_dot] = True # type: ignore return None, None try: # Graphviz may close standard input when an error occurs, @@ -278,7 +282,7 @@ def render_dot(self, code, options, format, prefix='graphviz'): def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None, alt=None): - # type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode, unicode, unicode) -> Tuple[unicode, unicode] # NOQA + # type: (HTMLTranslator, graphviz, unicode, Dict, unicode, unicode, unicode) -> Tuple[unicode, unicode] # NOQA format = self.builder.config.graphviz_output_format try: if format not in ('png', 'svg'): @@ -331,12 +335,12 @@ def render_dot_html(self, node, code, options, prefix='graphviz', def html_visit_graphviz(self, node): - # type: (nodes.NodeVisitor, graphviz) -> None + # type: (HTMLTranslator, graphviz) -> None render_dot_html(self, node, node['code'], node['options']) def render_dot_latex(self, node, code, options, prefix='graphviz'): - # type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode) -> None + # type: (LaTeXTranslator, graphviz, unicode, Dict, unicode) -> None try: fname, outfn = render_dot(self, code, options, 'pdf', prefix) except GraphvizError as exc: @@ -369,12 +373,12 @@ def render_dot_latex(self, node, code, options, prefix='graphviz'): def latex_visit_graphviz(self, node): - # type: (nodes.NodeVisitor, graphviz) -> None + # type: (LaTeXTranslator, graphviz) -> None render_dot_latex(self, node, node['code'], node['options']) def render_dot_texinfo(self, node, code, options, prefix='graphviz'): - # type: (nodes.NodeVisitor, graphviz, unicode, Dict, unicode) -> None + # type: (TexinfoTranslator, graphviz, unicode, Dict, unicode) -> None try: fname, outfn = render_dot(self, code, options, 'png', prefix) except GraphvizError as exc: @@ -391,7 +395,7 @@ def texinfo_visit_graphviz(self, node): def text_visit_graphviz(self, node): - # type: (nodes.NodeVisitor, graphviz) -> None + # type: (TextTranslator, graphviz) -> None if 'alt' in node.attributes: self.add_text(_('[graph: %s]') % node['alt']) else: @@ -400,7 +404,7 @@ def text_visit_graphviz(self, node): def man_visit_graphviz(self, node): - # type: (nodes.NodeVisitor, graphviz) -> None + # type: (ManualPageTranslator, graphviz) -> None if 'alt' in node.attributes: self.body.append(_('[graph: %s]') % node['alt']) else: diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py index a66023107..156aaf614 100644 --- a/sphinx/ext/ifconfig.py +++ b/sphinx/ext/ifconfig.py @@ -57,7 +57,7 @@ class IfConfig(SphinxDirective): def process_ifconfig_nodes(app, doctree, docname): - # type: (Sphinx, nodes.Node, unicode) -> None + # type: (Sphinx, nodes.document, unicode) -> None ns = dict((confval.name, confval.value) for confval in app.config) ns.update(app.config.__dict__.copy()) ns['builder'] = app.builder.name diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index 87e84f36f..d708c1fa4 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -31,12 +31,13 @@ from sphinx.util.pycompat import sys_encoding if False: # For type annotation - from typing import Any, Dict, List, Tuple # NOQA + from typing import Any, Dict, List, Tuple, Union # NOQA from sphinx.addnodes import displaymath # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA from sphinx.config import Config # NOQA from sphinx.util.typing import unicode # NOQA + from sphinx.writers.html import HTMLTranslator # NOQA logger = logging.getLogger(__name__) @@ -215,7 +216,7 @@ def convert_dvi_to_svg(dvipath, builder): def render_math(self, math): - # type: (nodes.NodeVisitor, unicode) -> Tuple[unicode, int] + # type: (HTMLTranslator, unicode) -> Tuple[unicode, int] """Render the LaTeX math expression *math* using latex and dvipng or dvisvgm. @@ -251,7 +252,7 @@ def render_math(self, math): try: dvipath = compile_math(latex, self.builder) except InvokeError: - self.builder._imgmath_warned_latex = True + self.builder._imgmath_warned_latex = True # type: ignore return None, None # .dvi -> .png/.svg @@ -261,7 +262,7 @@ def render_math(self, math): elif image_format == 'svg': imgpath, depth = convert_dvi_to_svg(dvipath, self.builder) except InvokeError: - self.builder._imgmath_warned_image_translator = True + self.builder._imgmath_warned_image_translator = True # type: ignore return None, None # Move generated image on tempdir to build dir @@ -284,14 +285,14 @@ def cleanup_tempdir(app, exc): def get_tooltip(self, node): - # type: (nodes.NodeVisitor, nodes.math) -> unicode + # type: (HTMLTranslator, Union[nodes.math, nodes.math_block]) -> unicode if self.builder.config.imgmath_add_tooltips: return ' alt="%s"' % self.encode(node.astext()).strip() return '' def html_visit_math(self, node): - # type: (nodes.NodeVisitor, nodes.math) -> None + # type: (HTMLTranslator, nodes.math) -> None try: fname, depth = render_math(self, '$' + node.astext() + '$') except MathExtError as exc: @@ -314,7 +315,7 @@ def html_visit_math(self, node): def html_visit_displaymath(self, node): - # type: (nodes.NodeVisitor, nodes.math_block) -> None + # type: (HTMLTranslator, nodes.math_block) -> None if node['nowrap']: latex = node.astext() else: diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 81a90aabe..ee262383c 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -56,6 +56,9 @@ if False: from sphinx.application import Sphinx # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.util.typing import unicode # 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 @@ -386,7 +389,7 @@ def get_graph_hash(node): 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. @@ -419,7 +422,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. """ @@ -435,7 +438,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. """ diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index 804124897..082cc7768 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -287,7 +287,7 @@ def load_mappings(app): def missing_reference(app, env, node, contnode): - # type: (Sphinx, BuildEnvironment, nodes.Node, nodes.Node) -> None + # type: (Sphinx, BuildEnvironment, nodes.Element, nodes.TextElement) -> None """Attempt to resolve a missing reference via intersphinx references.""" target = node['reftarget'] inventories = InventoryAdapter(env) diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index 0df5d4413..ed4f7739e 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -10,9 +10,13 @@ :license: BSD, see LICENSE for details. """ +from typing import cast + from docutils import nodes import sphinx +from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.domains.math import MathDomain from sphinx.errors import ExtensionError from sphinx.locale import _ from sphinx.util.math import get_node_equation_number @@ -27,14 +31,14 @@ if False: def html_visit_math(self, node): - # type: (nodes.NodeVisitor, nodes.Node) -> None + # type: (HTMLTranslator, nodes.math) -> None self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight')) self.body.append(self.encode(node.astext()) + '') raise nodes.SkipNode def html_visit_displaymath(self, node): - # type: (HTMLTranslator, nodes.Node) -> None + # type: (HTMLTranslator, nodes.math_block) -> None if node['nowrap']: self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight')) self.body.append(self.encode(node.astext())) @@ -69,9 +73,11 @@ def install_jsmath(app, env): raise ExtensionError('jsmath_path config value must be set for the ' 'jsmath extension to work') - if env.get_domain('math').has_equations(): # type: ignore + builder = cast(StandaloneHTMLBuilder, app.builder) + domain = cast(MathDomain, env.get_domain('math')) + if domain.has_equations(): # Enable jsmath only if equations exists - app.builder.add_js_file(app.config.jsmath_path) # type: ignore + builder.add_js_file(app.config.jsmath_path) def setup(app): diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index e8c0d4b44..d4303378c 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -12,10 +12,13 @@ """ import json +from typing import cast from docutils import nodes import sphinx +from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.domains.math import MathDomain from sphinx.errors import ExtensionError from sphinx.locale import _ from sphinx.util.math import get_node_equation_number @@ -30,7 +33,7 @@ if False: def html_visit_math(self, node): - # type: (nodes.NodeVisitor, nodes.Node) -> None + # type: (HTMLTranslator, nodes.math) -> None self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate nohighlight')) self.body.append(self.builder.config.mathjax_inline[0] + self.encode(node.astext()) + @@ -39,7 +42,7 @@ def html_visit_math(self, node): def html_visit_displaymath(self, node): - # type: (HTMLTranslator, nodes.Node) -> None + # type: (HTMLTranslator, nodes.math_block) -> None self.body.append(self.starttag(node, 'div', CLASS='math notranslate nohighlight')) if node['nowrap']: self.body.append(self.encode(node.astext())) @@ -79,16 +82,18 @@ def install_mathjax(app, env): raise ExtensionError('mathjax_path config value must be set for the ' 'mathjax extension to work') - if env.get_domain('math').has_equations(): # type: ignore + builder = cast(StandaloneHTMLBuilder, app.builder) + domain = cast(MathDomain, env.get_domain('math')) + if domain.has_equations(): # Enable mathjax only if equations exists options = {'async': 'async'} if app.config.mathjax_options: options.update(app.config.mathjax_options) - app.builder.add_js_file(app.config.mathjax_path, **options) # type: ignore + builder.add_js_file(app.config.mathjax_path, **options) if app.config.mathjax_config: body = "MathJax.Hub.Config(%s)" % json.dumps(app.config.mathjax_config) - app.builder.add_js_file(None, type="text/x-mathjax-config", body=body) # type: ignore # NOQA + builder.add_js_file(None, type="text/x-mathjax-config", body=body) def setup(app): diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index 7585b0f2b..8f7cd838a 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -12,6 +12,8 @@ :license: BSD, see LICENSE for details. """ +from typing import cast + from docutils import nodes from docutils.parsers.rst import directives from docutils.parsers.rst.directives.admonitions import BaseAdmonition @@ -30,6 +32,8 @@ if False: from sphinx.application import Sphinx # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.util.typing import unicode # NOQA + from sphinx.writers.html import HTMLTranslator # NOQA + from sphinx.writers.latex import LaTeXTranslator # NOQA logger = logging.getLogger(__name__) @@ -64,19 +68,21 @@ class Todo(BaseAdmonition, SphinxDirective): (todo,) = super(Todo, self).run() if isinstance(todo, nodes.system_message): return [todo] + elif isinstance(todo, todo_node): + todo.insert(0, nodes.title(text=_('Todo'))) + set_source_info(self, todo) - todo.insert(0, nodes.title(text=_('Todo'))) - set_source_info(self, todo) - - targetid = 'index-%s' % self.env.new_serialno('index') - # Stash the target to be retrieved later in latex_visit_todo_node. - todo['targetref'] = '%s:%s' % (self.env.docname, targetid) - targetnode = nodes.target('', '', ids=[targetid]) - return [targetnode, todo] + targetid = 'index-%s' % self.env.new_serialno('index') + # Stash the target to be retrieved later in latex_visit_todo_node. + todo['targetref'] = '%s:%s' % (self.env.docname, targetid) + targetnode = nodes.target('', '', ids=[targetid]) + return [targetnode, todo] + else: + raise RuntimeError # never reached here def process_todos(app, doctree): - # type: (Sphinx, nodes.Node) -> None + # type: (Sphinx, nodes.document) -> None # collect all todos in the environment # this is not done in the directive itself because it some transformations # must have already been run, e.g. substitutions @@ -103,7 +109,8 @@ def process_todos(app, doctree): }) if env.config.todo_emit_warnings: - logger.warning(__("TODO entry found: %s"), node[1].astext(), + label = cast(nodes.Element, node[1]) + logger.warning(__("TODO entry found: %s"), label.astext(), location=node) @@ -126,7 +133,8 @@ class TodoList(SphinxDirective): def process_todo_nodes(app, doctree, fromdocname): - # type: (Sphinx, nodes.Node, unicode) -> None + # type: (Sphinx, nodes.document, unicode) -> None + node = None # type: nodes.Element if not app.config['todo_include_todos']: for node in doctree.traverse(todo_node): node.parent.remove(node) @@ -140,7 +148,7 @@ def process_todo_nodes(app, doctree, fromdocname): for node in doctree.traverse(todolist): if node.get('ids'): - content = [nodes.target()] + content = [nodes.target()] # type: List[nodes.Element] else: content = [] @@ -212,16 +220,15 @@ def merge_info(app, env, docnames, other): def visit_todo_node(self, node): # type: (nodes.NodeVisitor, todo_node) -> None self.visit_admonition(node) - # self.visit_admonition(node, 'todo') def depart_todo_node(self, node): - # type: (nodes.NodeVisitor, todo_node) -> None + # type: (HTMLTranslator, todo_node) -> None self.depart_admonition(node) def latex_visit_todo_node(self, node): - # type: (nodes.NodeVisitor, todo_node) -> None + # type: (LaTeXTranslator, todo_node) -> None title = node.pop(0).astext().translate(tex_escape_map) self.body.append(u'\n\\begin{sphinxadmonition}{note}{') # If this is the original todo node, emit a label that will be referenced by @@ -233,7 +240,7 @@ def latex_visit_todo_node(self, node): def latex_depart_todo_node(self, node): - # type: (nodes.NodeVisitor, todo_node) -> None + # type: (LaTeXTranslator, todo_node) -> None self.body.append('\\end{sphinxadmonition}\n') diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 927a807c6..65a0c46f9 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -143,12 +143,14 @@ def env_merge_info(app, env, docnames, other): def missing_reference(app, env, node, contnode): - # type: (Sphinx, BuildEnvironment, nodes.Node, nodes.Node) -> nodes.Node + # type: (Sphinx, BuildEnvironment, nodes.Element, nodes.Node) -> nodes.Node # resolve our "viewcode" reference nodes -- they need special treatment if node['reftype'] == 'viewcode': return make_refnode(app.builder, node['refdoc'], node['reftarget'], node['refid'], contnode) + return None + def collect_pages(app): # type: (Sphinx) -> Iterator[Tuple[unicode, Dict[unicode, Any], unicode]]