From 66c3dd3adb909fd028a190ab9888e6d09b5ce7c7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 14 Nov 2019 02:23:06 +0900 Subject: [PATCH 01/28] Close #6798: autosummary: emit ``autodoc-skip-member`` event on generating stub file --- CHANGES | 1 + doc/usage/extensions/autosummary.rst | 5 +++++ sphinx/ext/autosummary/generate.py | 15 +++++++++++++-- .../test-ext-autosummary-skip-member/conf.py | 18 ++++++++++++++++++ .../test-ext-autosummary-skip-member/index.rst | 4 ++++ .../test-ext-autosummary-skip-member/target.py | 10 ++++++++++ tests/test_ext_autosummary.py | 13 +++++++++++++ 7 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 tests/roots/test-ext-autosummary-skip-member/conf.py create mode 100644 tests/roots/test-ext-autosummary-skip-member/index.rst create mode 100644 tests/roots/test-ext-autosummary-skip-member/target.py diff --git a/CHANGES b/CHANGES index 9d3b51cc4..5a1fcb560 100644 --- a/CHANGES +++ b/CHANGES @@ -33,6 +33,7 @@ Features added character * #6812: Improve a warning message when extensions are not parallel safe * #6818: Improve Intersphinx performance for multiple remote inventories. +* #6798: autosummary: emit ``autodoc-skip-member`` event on generating stub file Bugs fixed ---------- diff --git a/doc/usage/extensions/autosummary.rst b/doc/usage/extensions/autosummary.rst index 16a8cea7e..c5211639e 100644 --- a/doc/usage/extensions/autosummary.rst +++ b/doc/usage/extensions/autosummary.rst @@ -143,6 +143,11 @@ also use these config values: The new files will be placed in the directories specified in the ``:toctree:`` options of the directives. + .. versionchanged:: 2.3 + + Emits :event:`autodoc-skip-member` event as :mod:`~sphinx.ext.autodoc` + does. + .. confval:: autosummary_mock_imports This value contains a list of modules to be mocked up. See diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index c4726f528..177d25e9d 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -138,6 +138,16 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any, if not template.exists(template_name): template_name = 'autosummary/base.rst' + def skip_member(obj: Any, name: str, objtype: str) -> bool: + try: + return app.emit_firstresult('autodoc-skip-member', objtype, name, + obj, False, {}) + except Exception as exc: + logger.warning(__('autosummary: failed to determine %r to be documented.' + 'the following exception was raised:\n%s'), + name, exc, type='autosummary') + return False + def get_members(obj: Any, types: Set[str], include_public: List[str] = [], imported: bool = True) -> Tuple[List[str], List[str]]: items = [] # type: List[str] @@ -148,9 +158,10 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any, continue documenter = get_documenter(app, value, obj) if documenter.objtype in types: + # skip imported members if expected if imported or getattr(value, '__module__', None) == obj.__name__: - # skip imported members if expected - items.append(name) + if not skip_member(value, name, documenter.objtype): + items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items diff --git a/tests/roots/test-ext-autosummary-skip-member/conf.py b/tests/roots/test-ext-autosummary-skip-member/conf.py new file mode 100644 index 000000000..7adf2eb1d --- /dev/null +++ b/tests/roots/test-ext-autosummary-skip-member/conf.py @@ -0,0 +1,18 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath('.')) + + +extensions = ['sphinx.ext.autosummary'] +autosummary_generate = True +autodoc_default_options = {'members': True} + + +def skip_member(app, what, name, obj, skip, options): + if name == 'skipmeth': + return True + + +def setup(app): + app.connect('autodoc-skip-member', skip_member) diff --git a/tests/roots/test-ext-autosummary-skip-member/index.rst b/tests/roots/test-ext-autosummary-skip-member/index.rst new file mode 100644 index 000000000..c376a13c6 --- /dev/null +++ b/tests/roots/test-ext-autosummary-skip-member/index.rst @@ -0,0 +1,4 @@ +.. autosummary:: + :toctree: generate + + target.Foo diff --git a/tests/roots/test-ext-autosummary-skip-member/target.py b/tests/roots/test-ext-autosummary-skip-member/target.py new file mode 100644 index 000000000..aeef054e1 --- /dev/null +++ b/tests/roots/test-ext-autosummary-skip-member/target.py @@ -0,0 +1,10 @@ +class Foo: + """docstring of Foo.""" + + def meth(self): + """docstring of meth.""" + pass + + def skipmeth(self): + """docstring of skipmeth.""" + pass diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 21841cc74..93b2fe9af 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -36,6 +36,11 @@ default_kw = { } +@pytest.fixture(scope='function', autouse=True) +def unload_target_module(): + sys.modules.pop('target', None) + + def test_mangle_signature(): TEST = """ () :: () @@ -304,6 +309,14 @@ def test_generate_autosummary_docs_property(app): ".. autoproperty:: Base.prop") +@pytest.mark.sphinx(testroot='ext-autosummary-skip-member') +def test_autosummary_skip_member(app): + app.build() + + content = (app.srcdir / 'generate' / 'target.Foo.rst').text() + assert 'Foo.skipmeth' not in content + + @pytest.mark.sphinx('dummy', testroot='ext-autosummary', confoverrides={'autosummary_generate': []}) def test_empty_autosummary_generate(app, status, warning): From 491b19d6bb93a6b7aaa1cc7b4004c7f5f52369bb Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Nov 2019 18:15:53 +0900 Subject: [PATCH 02/28] autosummary: Allows to document a member forcedly if skip-member handler returns False --- sphinx/ext/autosummary/generate.py | 15 ++++++++++++--- .../test-ext-autosummary-skip-member/conf.py | 2 ++ .../test-ext-autosummary-skip-member/target.py | 4 ++++ tests/test_ext_autosummary.py | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 177d25e9d..e1dd1be51 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -151,6 +151,7 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any, def get_members(obj: Any, types: Set[str], include_public: List[str] = [], imported: bool = True) -> Tuple[List[str], List[str]]: items = [] # type: List[str] + public = [] # type: List[str] for name in dir(obj): try: value = safe_getattr(obj, name) @@ -160,10 +161,18 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any, if documenter.objtype in types: # skip imported members if expected if imported or getattr(value, '__module__', None) == obj.__name__: - if not skip_member(value, name, documenter.objtype): + skipped = skip_member(value, name, documenter.objtype) + if skipped is True: + pass + elif skipped is False: + # show the member forcedly items.append(name) - public = [x for x in items - if x in include_public or not x.startswith('_')] + public.append(name) + else: + items.append(name) + if name in include_public or not name.startswith('_'): + # considers member as public + public.append(name) return public, items ns = {} # type: Dict[str, Any] diff --git a/tests/roots/test-ext-autosummary-skip-member/conf.py b/tests/roots/test-ext-autosummary-skip-member/conf.py index 7adf2eb1d..7c8f0e9cf 100644 --- a/tests/roots/test-ext-autosummary-skip-member/conf.py +++ b/tests/roots/test-ext-autosummary-skip-member/conf.py @@ -12,6 +12,8 @@ autodoc_default_options = {'members': True} def skip_member(app, what, name, obj, skip, options): if name == 'skipmeth': return True + elif name == '_privatemeth': + return False def setup(app): diff --git a/tests/roots/test-ext-autosummary-skip-member/target.py b/tests/roots/test-ext-autosummary-skip-member/target.py index aeef054e1..fdf557eee 100644 --- a/tests/roots/test-ext-autosummary-skip-member/target.py +++ b/tests/roots/test-ext-autosummary-skip-member/target.py @@ -8,3 +8,7 @@ class Foo: def skipmeth(self): """docstring of skipmeth.""" pass + + def _privatemeth(self): + """docstring of _privatemeth.""" + pass diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 93b2fe9af..1948f6ae7 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -315,6 +315,7 @@ def test_autosummary_skip_member(app): content = (app.srcdir / 'generate' / 'target.Foo.rst').text() assert 'Foo.skipmeth' not in content + assert 'Foo._privatemeth' in content @pytest.mark.sphinx('dummy', testroot='ext-autosummary', From 5f559fbb983b0bfed449daf6f2badf4e2c66098d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Nov 2019 18:34:48 +0900 Subject: [PATCH 03/28] Deprecate sphinx.util.texescape.tex_escape_map --- CHANGES | 2 ++ doc/extdev/deprecated.rst | 10 ++++++++++ sphinx/util/texescape.py | 42 +++++++++++++++++++++++++-------------- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index 9d3b51cc4..49f22b245 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,8 @@ Deprecated * ``sphinx.builders.gettext.POHEADER`` * ``sphinx.io.SphinxStandaloneReader.app`` * ``sphinx.io.SphinxStandaloneReader.env`` +* ``sphinx.util.texescape.tex_escape_map`` +* ``sphinx.util.texescape.tex_hl_escape_map_new`` Features added -------------- diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 8c201b525..1a461d9e6 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -41,6 +41,16 @@ The following is a list of deprecated interfaces. - 4.0 - ``sphinx.io.SphinxStandaloneReader.setup()`` + * - ``sphinx.util.texescape.tex_escape_map`` + - 2.3 + - 4.0 + - ``sphinx.util.texescape.get_escape_func()`` + + * - ``sphinx.util.texescape.tex_hl_escape_map_new`` + - 2.3 + - 4.0 + - ``sphinx.util.texescape.get_hlescape_func()`` + * - ``sphinx.domains.math.MathDomain.add_equation()`` - 2.2 - 4.0 diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py index c3231d3d3..3b9494892 100644 --- a/sphinx/util/texescape.py +++ b/sphinx/util/texescape.py @@ -11,6 +11,9 @@ import re from typing import Callable, Dict +from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias + + tex_replacements = [ # map TeX special chars ('$', r'\$'), @@ -78,11 +81,20 @@ unicode_tex_replacements = [ ('₉', r'\(\sb{\text{9}}\)'), ] -tex_escape_map = {} # type: Dict[int, str] -tex_escape_map_without_unicode = {} # type: Dict[int, str] -tex_replace_map = {} -tex_hl_escape_map_new = {} # type: Dict[int, str] -tex_hl_escape_map_new_without_unicode = {} # type: Dict[int, str] +tex_replace_map = {} # type: Dict[int, str] + +_tex_escape_map = {} # type: Dict[int, str] +_tex_escape_map_without_unicode = {} # type: Dict[int, str] +_tex_hlescape_map = {} # type: Dict[int, str] +_tex_hlescape_map_without_unicode = {} # type: Dict[int, str] + + +deprecated_alias('sphinx.util.texescape', + { + 'tex_escape_map': _tex_escape_map, + 'tex_hl_escape_map_new': _tex_hlescape_map, + }, + RemovedInSphinx40Warning) def get_escape_func(latex_engine: str) -> Callable[[str], str]: @@ -95,12 +107,12 @@ def get_escape_func(latex_engine: str) -> Callable[[str], str]: def escape(s: str) -> str: """Escape text for LaTeX output.""" - return s.translate(tex_escape_map) + return s.translate(_tex_escape_map) def escape_for_unicode_latex_engine(s: str) -> str: """Escape text for unicode supporting LaTeX engine.""" - return s.translate(tex_escape_map_without_unicode) + return s.translate(_tex_escape_map_without_unicode) def get_hlescape_func(latex_engine: str) -> Callable[[str], str]: @@ -113,12 +125,12 @@ def get_hlescape_func(latex_engine: str) -> Callable[[str], str]: def hlescape(s: str) -> str: """Escape text for LaTeX highlighter.""" - return s.translate(tex_hl_escape_map_new) + return s.translate(_tex_hlescape_map) def hlescape_for_unicode_latex_engine(s: str) -> str: """Escape text for unicode supporting LaTeX engine.""" - return s.translate(tex_hl_escape_map_new_without_unicode) + return s.translate(_tex_hlescape_map_without_unicode) def escape_abbr(text: str) -> str: @@ -128,19 +140,19 @@ def escape_abbr(text: str) -> str: def init() -> None: for a, b in tex_replacements: - tex_escape_map[ord(a)] = b - tex_escape_map_without_unicode[ord(a)] = b + _tex_escape_map[ord(a)] = b + _tex_escape_map_without_unicode[ord(a)] = b tex_replace_map[ord(a)] = '_' for a, b in unicode_tex_replacements: - tex_escape_map[ord(a)] = b + _tex_escape_map[ord(a)] = b tex_replace_map[ord(a)] = '_' for a, b in tex_replacements: if a in '[]{}\\': continue - tex_hl_escape_map_new[ord(a)] = b - tex_hl_escape_map_new_without_unicode[ord(a)] = b + _tex_hlescape_map[ord(a)] = b + _tex_hlescape_map_without_unicode[ord(a)] = b for a, b in unicode_tex_replacements: - tex_hl_escape_map_new[ord(a)] = b + _tex_hlescape_map[ord(a)] = b From f3469bcc8fedac8c196a3df7e71a8a47300dcb64 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Nov 2019 19:22:34 +0900 Subject: [PATCH 04/28] Make escape() and hlescape() as public APIs of texescape --- doc/extdev/deprecated.rst | 4 ++-- sphinx/builders/latex/__init__.py | 6 +++-- sphinx/ext/todo.py | 8 +++---- sphinx/highlighting.py | 8 +++---- sphinx/util/template.py | 6 +++-- sphinx/util/texescape.py | 40 +++++++++---------------------- sphinx/writers/latex.py | 10 ++++---- tests/test_build_latex.py | 1 + 8 files changed, 34 insertions(+), 49 deletions(-) diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst index 1a461d9e6..958f4ee4d 100644 --- a/doc/extdev/deprecated.rst +++ b/doc/extdev/deprecated.rst @@ -44,12 +44,12 @@ The following is a list of deprecated interfaces. * - ``sphinx.util.texescape.tex_escape_map`` - 2.3 - 4.0 - - ``sphinx.util.texescape.get_escape_func()`` + - ``sphinx.util.texescape.escape()`` * - ``sphinx.util.texescape.tex_hl_escape_map_new`` - 2.3 - 4.0 - - ``sphinx.util.texescape.get_hlescape_func()`` + - ``sphinx.util.texescape.hlescape()`` * - ``sphinx.domains.math.MathDomain.add_equation()`` - 2.2 diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 9c34b5568..02f147e40 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -440,10 +440,12 @@ def default_latex_use_xindy(config: Config) -> bool: def default_latex_documents(config: Config) -> List[Tuple[str, str, str, str, str]]: """ Better default latex_documents settings. """ + project = texescape.escape(config.project, config.latex_engine) + author = texescape.escape(config.author, config.latex_engine) return [(config.master_doc, make_filename_from_project(config.project) + '.tex', - texescape.escape_abbr(texescape.escape(config.project)), - texescape.escape_abbr(texescape.escape(config.author)), + texescape.escape_abbr(project), + texescape.escape_abbr(author), 'manual')] diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index d2a8a666d..99dc02d3d 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -27,10 +27,9 @@ from sphinx.domains import Domain from sphinx.environment import BuildEnvironment from sphinx.errors import NoUri from sphinx.locale import _, __ -from sphinx.util import logging +from sphinx.util import logging, texescape from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import make_refnode -from sphinx.util.texescape import get_escape_func from sphinx.writers.html import HTMLTranslator from sphinx.writers.latex import LaTeXTranslator @@ -299,11 +298,12 @@ def depart_todo_node(self: HTMLTranslator, node: todo_node) -> None: def latex_visit_todo_node(self: LaTeXTranslator, node: todo_node) -> None: if self.config.todo_include_todos: - escape = get_escape_func(self.config.latex_engine) self.body.append('\n\\begin{sphinxadmonition}{note}{') self.body.append(self.hypertarget_to(node)) + title_node = cast(nodes.title, node[0]) - self.body.append('%s:}' % escape(title_node.astext())) + title = texescape.escape(title_node.astext(), self.config.latex_engine) + self.body.append('%s:}' % title) node.pop(0) else: raise nodes.SkipNode diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 0a6cf8d6e..6804b9de0 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -27,8 +27,7 @@ from sphinx.deprecation import RemovedInSphinx30Warning from sphinx.ext import doctest from sphinx.locale import __ from sphinx.pygments_styles import SphinxStyle, NoneStyle -from sphinx.util import logging -from sphinx.util.texescape import get_hlescape_func, tex_hl_escape_map_new +from sphinx.util import logging, texescape if False: # For type annotation @@ -114,7 +113,7 @@ class PygmentsBridge: # first, escape highlighting characters like Pygments does source = source.translate(escape_hl_chars) # then, escape all characters nonrepresentable in LaTeX - source = source.translate(tex_hl_escape_map_new) + source = texescape.escape(source, self.latex_engine) return '\\begin{Verbatim}[commandchars=\\\\\\{\\}]\n' + \ source + '\\end{Verbatim}\n' @@ -194,8 +193,7 @@ class PygmentsBridge: if self.dest == 'html': return hlsource else: - escape = get_hlescape_func(self.latex_engine) - return escape(hlsource) + return texescape.hlescape(hlsource, self.latex_engine) def get_stylesheet(self): # type: () -> str diff --git a/sphinx/util/template.py b/sphinx/util/template.py index 3a43db9a5..e6e72d079 100644 --- a/sphinx/util/template.py +++ b/sphinx/util/template.py @@ -9,6 +9,7 @@ """ import os +from functools import partial from typing import Dict, List, Union from jinja2.loaders import BaseLoader @@ -69,8 +70,9 @@ class LaTeXRenderer(SphinxRenderer): super().__init__(template_path) # use texescape as escape filter - self.env.filters['e'] = texescape.get_escape_func(latex_engine) - self.env.filters['escape'] = texescape.get_escape_func(latex_engine) + escape = partial(texescape.escape, latex_engine=latex_engine) + self.env.filters['e'] = escape + self.env.filters['escape'] = escape self.env.filters['eabbr'] = texescape.escape_abbr # use JSP/eRuby like tagging instead because curly bracket; the default diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py index 3b9494892..1b44532f5 100644 --- a/sphinx/util/texescape.py +++ b/sphinx/util/texescape.py @@ -9,7 +9,7 @@ """ import re -from typing import Callable, Dict +from typing import Dict from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias @@ -97,40 +97,22 @@ deprecated_alias('sphinx.util.texescape', RemovedInSphinx40Warning) -def get_escape_func(latex_engine: str) -> Callable[[str], str]: - """Get escape() function for given latex_engine.""" - if latex_engine in ('lualatex', 'xelatex'): - return escape_for_unicode_latex_engine - else: - return escape - - -def escape(s: str) -> str: +def escape(s: str, latex_engine: str = None) -> str: """Escape text for LaTeX output.""" - return s.translate(_tex_escape_map) - - -def escape_for_unicode_latex_engine(s: str) -> str: - """Escape text for unicode supporting LaTeX engine.""" - return s.translate(_tex_escape_map_without_unicode) - - -def get_hlescape_func(latex_engine: str) -> Callable[[str], str]: - """Get hlescape() function for given latex_engine.""" if latex_engine in ('lualatex', 'xelatex'): - return hlescape_for_unicode_latex_engine + # unicode based LaTeX engine + return s.translate(_tex_escape_map_without_unicode) else: - return hlescape + return s.translate(_tex_escape_map) -def hlescape(s: str) -> str: +def hlescape(s: str, latex_engine: str = None) -> str: """Escape text for LaTeX highlighter.""" - return s.translate(_tex_hlescape_map) - - -def hlescape_for_unicode_latex_engine(s: str) -> str: - """Escape text for unicode supporting LaTeX engine.""" - return s.translate(_tex_hlescape_map_without_unicode) + if latex_engine in ('lualatex', 'xelatex'): + # unicode based LaTeX engine + return s.translate(_tex_hlescape_map_without_unicode) + else: + return s.translate(_tex_hlescape_map) def escape_abbr(text: str) -> str: diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 5facdc40c..5641c08f8 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -28,11 +28,11 @@ from sphinx.deprecation import ( from sphinx.domains.std import StandardDomain from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, _, __ -from sphinx.util import split_into, logging +from sphinx.util import split_into, logging, texescape from sphinx.util.docutils import SphinxTranslator from sphinx.util.nodes import clean_astext, get_prev_node from sphinx.util.template import LaTeXRenderer -from sphinx.util.texescape import get_escape_func, tex_replace_map +from sphinx.util.texescape import tex_replace_map try: from docutils.utils.roman import toRoman @@ -500,9 +500,6 @@ class LaTeXTranslator(SphinxTranslator): self.compact_list = 0 self.first_param = 0 - # escape helper - self.escape = get_escape_func(self.config.latex_engine) - # sort out some elements self.elements = self.builder.context.copy() @@ -736,6 +733,9 @@ class LaTeXTranslator(SphinxTranslator): # type: (str) -> str return '\\autopageref*{%s}' % self.idescape(id) + def escape(self, s: str) -> str: + return texescape.escape(s, self.config.latex_engine) + def idescape(self, id): # type: (str) -> str return '\\detokenize{%s}' % str(id).translate(tex_replace_map).\ diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 0ebcd0b62..38e99f48a 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -1414,6 +1414,7 @@ def test_default_latex_documents(): 'project': 'STASI™ Documentation', 'author': "Wolfgang Schäuble & G'Beckstein."}) config.init_values() + config.add('latex_engine', None, True, None) expected = [('index', 'stasi.tex', 'STASI™ Documentation', r"Wolfgang Schäuble \& G'Beckstein.\@{}", 'manual')] assert default_latex_documents(config) == expected From 155f4b0d00e72d16eed47581f2fee75e41c452cf Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Nov 2019 22:15:13 +0900 Subject: [PATCH 05/28] Fix #6813: An orphan warning is emitted for included document on Windows --- CHANGES | 3 +++ sphinx/project.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 9d3b51cc4..305ed8f6b 100644 --- a/CHANGES +++ b/CHANGES @@ -59,6 +59,9 @@ Bugs fixed code-block long enough not to fit on one page * #6809: LaTeX: code-block in a danger type admonition can easily spill over bottom of page +* #6813: An orphan warning is emitted for included document on Windows. Thanks + to @drillan + Testing -------- diff --git a/sphinx/project.py b/sphinx/project.py index 81d2b43e0..13ac6d9fd 100644 --- a/sphinx/project.py +++ b/sphinx/project.py @@ -13,6 +13,7 @@ import os from sphinx.locale import __ from sphinx.util import get_matching_files from sphinx.util import logging +from sphinx.util import path_stabilize from sphinx.util.matching import compile_matchers from sphinx.util.osutil import SEP, relpath @@ -71,6 +72,7 @@ class Project: filename = relpath(filename, self.srcdir) for suffix in self.source_suffix: if filename.endswith(suffix): + filename = path_stabilize(filename) return filename[:-len(suffix)] # the file does not have docname From d0fa844f9198cfdcd2998aa9b07ed454c6618fb0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Nov 2019 11:12:33 +0900 Subject: [PATCH 06/28] Fix #6806: linkcheck: Failure on parsing content --- CHANGES | 1 + sphinx/builders/linkcheck.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index a1676d5d6..dc56e3cf9 100644 --- a/CHANGES +++ b/CHANGES @@ -48,6 +48,7 @@ Bugs fixed supported LaTeX engines: ¶, §, €, ∞, ±, →, ‣, –, superscript and subscript digits go through "as is" (as default OpenType font supports them) * #6704: linkcheck: Be defensive and handle newly defined HTTP error code +* #6806: linkcheck: Failure on parsing content * #6655: image URLs containing ``data:`` causes gettext builder crashed * #6584: i18n: Error when compiling message catalogs on Hindi * #6718: i18n: KeyError is raised if section title and table title are same diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 635d9df98..737079a02 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -59,6 +59,9 @@ def check_anchor(response: requests.requests.Response, anchor: str) -> bool: # Read file in chunks. If we find a matching anchor, we break # the loop early in hopes not to have to download the whole thing. for chunk in response.iter_content(chunk_size=4096, decode_unicode=True): + if isinstance(chunk, bytes): # requests failed to decode + chunk = chunk.decode() # manually try to decode it + parser.feed(chunk) if parser.found: break From c6f0eb215a234eef4163d20477a49877eb8fe11e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Nov 2019 17:37:48 +0900 Subject: [PATCH 07/28] Fix #4186: LaTeX: Support upLaTeX as a new latex_engine (experimental) --- CHANGES | 1 + doc/usage/configuration.rst | 5 +++++ sphinx/builders/latex/__init__.py | 10 +++++++--- sphinx/texinputs/Makefile_t | 6 +++--- sphinx/texinputs/{latexmkjarc => latexmkjarc_t} | 2 +- sphinx/writers/latex.py | 9 +++++++++ 6 files changed, 26 insertions(+), 7 deletions(-) rename sphinx/texinputs/{latexmkjarc => latexmkjarc_t} (89%) diff --git a/CHANGES b/CHANGES index a1676d5d6..def0e7055 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ Features added * #1331: Add new config variable: :confval:`user_agent` * #6000: LaTeX: have backslash also be an inline literal word wrap break character +* #4186: LaTeX: Support upLaTeX as a new :confval:`latex_engine` (experimental) * #6812: Improve a warning message when extensions are not parallel safe * #6818: Improve Intersphinx performance for multiple remote inventories. * #2546: apidoc: .so file support diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index e61c09cb2..bb1c639f9 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -1836,6 +1836,7 @@ These options influence LaTeX output. * ``'xelatex'`` -- XeLaTeX * ``'lualatex'`` -- LuaLaTeX * ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``) + * ``'uplatex'`` -- upLaTeX (experimental) ``'pdflatex'``\ 's support for Unicode characters is limited. @@ -1861,6 +1862,10 @@ These options influence LaTeX output. Use ``xelatex`` by default for Greek documents. + .. versionchanged:: 2.3 + + Add ``uplatex`` support. + Contrarily to :ref:`MathJaX math rendering in HTML output `, LaTeX requires some extra configuration to support Unicode literals in :rst:dir:`math`: the only comprehensive solution (as far as we know) is to diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index 9c34b5568..87d3afd96 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -427,8 +427,12 @@ def default_latex_engine(config: Config) -> str: def default_latex_docclass(config: Config) -> Dict[str, str]: """ Better default latex_docclass settings for specific languages. """ if config.language == 'ja': - return {'manual': 'jsbook', - 'howto': 'jreport'} + if config.latex_engine == 'uplatex': + return {'manual': 'ujbook', + 'howto': 'ujreport'} + else: + return {'manual': 'jsbook', + 'howto': 'jreport'} else: return {} @@ -454,7 +458,7 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.connect('config-inited', validate_config_values) app.add_config_value('latex_engine', default_latex_engine, None, - ENUM('pdflatex', 'xelatex', 'lualatex', 'platex')) + ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex')) app.add_config_value('latex_documents', default_latex_documents, None) app.add_config_value('latex_logo', None, None, [str]) app.add_config_value('latex_appendices', [], None) diff --git a/sphinx/texinputs/Makefile_t b/sphinx/texinputs/Makefile_t index 2afabb360..405b34a58 100644 --- a/sphinx/texinputs/Makefile_t +++ b/sphinx/texinputs/Makefile_t @@ -37,7 +37,7 @@ XINDYOPTS += -M LatinRules.xdy # format: pdf or dvi (used only by archive targets) FMT = pdf -{% if latex_engine == 'platex' -%} +{% if latex_engine in ('platex', 'uplatex') -%} # latexmkrc is read then overridden by latexmkjarc LATEX = latexmk -r latexmkjarc -dvi PDFLATEX = latexmk -r latexmkjarc -pdfdvi -dvi- -ps- @@ -49,7 +49,7 @@ PDFLATEX = latexmk -pdf -dvi- -ps- %.png %.gif %.jpg %.jpeg: FORCE_MAKE extractbb '$@' -{% if latex_engine == 'platex' -%} +{% if latex_engine in ('platex', 'uplatex') -%} %.dvi: %.tex $(ALLIMGS) FORCE_MAKE for f in *.pdf; do extractbb "$$f"; done $(LATEX) $(LATEXMKOPTS) '$<' @@ -62,7 +62,7 @@ PDFLATEX = latexmk -pdf -dvi- -ps- %.ps: %.dvi dvips '$<' -{% if latex_engine == 'platex' -%} +{% if latex_engine in ('platex', 'uplatex') -%} %.pdf: %.tex $(ALLIMGS) FORCE_MAKE for f in *.pdf; do extractbb "$$f"; done {%- else -%} diff --git a/sphinx/texinputs/latexmkjarc b/sphinx/texinputs/latexmkjarc_t similarity index 89% rename from sphinx/texinputs/latexmkjarc rename to sphinx/texinputs/latexmkjarc_t index 5b315d6c9..c7403a90b 100644 --- a/sphinx/texinputs/latexmkjarc +++ b/sphinx/texinputs/latexmkjarc_t @@ -1,4 +1,4 @@ -$latex = 'platex ' . $ENV{'LATEXOPTS'} . ' -kanji=utf8 %O %S'; +$latex = '{{ latex_engine }} ' . $ENV{'LATEXOPTS'} . ' -kanji=utf8 %O %S'; $dvipdf = 'dvipdfmx %O -o %D %S'; $makeindex = 'internal mendex %S %B %D'; sub mendex { diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 5facdc40c..8e5056257 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -221,6 +221,15 @@ ADDITIONAL_SETTINGS = { 'fncychap': '', 'geometry': '\\usepackage[dvipdfm]{geometry}', }, + 'uplatex': { + 'latex_engine': 'uplatex', + 'babel': '', + 'classoptions': ',dvipdfmx', + 'fontpkg': '\\usepackage{times}', + 'textgreek': '', + 'fncychap': '', + 'geometry': '\\usepackage[dvipdfm]{geometry}', + }, # special settings for latex_engine + language_code ('xelatex', 'fr'): { From e720f0a1a237d1fe9251efa1f493cc7cee524a86 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Nov 2019 01:10:57 +0100 Subject: [PATCH 08/28] LaTeX: stop escaping | to LaTeX macro, except if in an index entry --- sphinx/texinputs/sphinx.sty | 3 ++- sphinx/texinputs/sphinx.xdy | 2 +- sphinx/util/texescape.py | 2 -- sphinx/writers/latex.py | 1 + tests/test_build_latex.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 5d9adb5bb..7e8421aed 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1881,9 +1881,10 @@ \let\sphinxtermref \@firstofone }} -% For curly braces inside \index macro +% For curly braces and vertical bar inside \index macro \def\sphinxleftcurlybrace{\{} \def\sphinxrightcurlybrace{\}} +\def\sphinxverticalbar{|} % Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x \def\spx@bd#1#2{% diff --git a/sphinx/texinputs/sphinx.xdy b/sphinx/texinputs/sphinx.xdy index 1c0794cd9..0efbdef2f 100644 --- a/sphinx/texinputs/sphinx.xdy +++ b/sphinx/texinputs/sphinx.xdy @@ -109,6 +109,7 @@ (merge-rule "\sphinxleftcurlybrace{}" "{" :string) (merge-rule "\sphinxrightcurlybrace{}" "}" :string) +(merge-rule "\sphinxverticalbar{}" "|" :string) (merge-rule "\_" "_" :string) (merge-rule "{[}" "[" :string) (merge-rule "{]}" "]" :string) @@ -126,7 +127,6 @@ (merge-rule "\(\rightarrow\)" "→" :string) (merge-rule "\(\checkmark\)" "✓" :string) (merge-rule "\textendash{}" "–" :string) -(merge-rule "\textbar{}" "|" :string) (merge-rule "\(\sp{\text{0}}\)" "⁰" :string) (merge-rule "\(\sp{\text{1}}\)" "¹" :string) (merge-rule "\(\sp{\text{2}}\)" "²" :string) diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py index e3c45adb4..5daaf137a 100644 --- a/sphinx/util/texescape.py +++ b/sphinx/util/texescape.py @@ -32,8 +32,6 @@ tex_replacements = [ ('`', r'{}`'), ('<', r'\textless{}'), ('>', r'\textgreater{}'), - # map char for some unknown reason. TODO: remove this? - ('|', r'\textbar{}'), # map special Unicode characters to TeX commands ('✓', r'\(\checkmark\)'), ('✔', r'\(\pmb{\checkmark}\)'), diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 5facdc40c..7e79385f1 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1816,6 +1816,7 @@ class LaTeXTranslator(SphinxTranslator): value = value.replace('"', '""') value = value.replace('@', '"@') value = value.replace('!', '"!') + value = value.replace('|', r'\sphinxverticalbar{}') return value def style(string): diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index 0ebcd0b62..dc91a51a0 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -315,7 +315,7 @@ def test_numref_with_prefix2(app, status, warning): assert ('\\hyperref[\\detokenize{baz:table22}]' '{Table:\\ref{\\detokenize{baz:table22}}}') in result assert ('\\hyperref[\\detokenize{index:code-1}]{Code-\\ref{\\detokenize{index:code-1}} ' - '\\textbar{} }') in result + '| }') in result assert ('\\hyperref[\\detokenize{baz:code22}]' '{Code-\\ref{\\detokenize{baz:code22}}}') in result assert ('\\hyperref[\\detokenize{foo:foo}]' From cf376bb45592bd0cba3b793249a13fc5903811f3 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Nov 2019 14:48:18 +0100 Subject: [PATCH 09/28] =?UTF-8?q?LaTeX:=20Do=20not=20escape=20=E2=82=AC=20?= =?UTF-8?q?wrongly=20(refs:=200103ff2a2b6,=20#6835)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sphinx/writers/latex.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 5facdc40c..db29b40ec 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -2164,8 +2164,6 @@ class LaTeXTranslator(SphinxTranslator): node.rawsource, lang, opts=opts, linenos=linenos, location=(self.curfilestack[-1], node.line), **highlight_args ) - # workaround for Unicode issue - hlcode = hlcode.replace('€', '@texteuro[]') if self.in_footnote: self.body.append('\n\\sphinxSetupCodeBlockInFootnote') hlcode = hlcode.replace('\\begin{Verbatim}', From 30c7af788ca52bb484a6c576dbfa3b7c446000bf Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Nov 2019 21:15:35 +0100 Subject: [PATCH 10/28] LaTeX: revert in index entries to \textbar{} not \sphinxtextbar{} This is because of case of an index directive or role in a table cell. For the same reason tabulary is not compatible with code-cells, it affects index entries. The escaping of | char by a LaTeX macro needed to be by a "robus" or "protected" one, or by string like {"|}. This was not the choice of previous commit, by oversight. By reverting to \textbar{} (which is a "robust" command) we also maintain maximal backwards compatibility for the sorting in the index done by the makeindex program. --- sphinx/texinputs/sphinx.sty | 3 +-- sphinx/texinputs/sphinx.xdy | 2 +- sphinx/writers/latex.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 7e8421aed..5d9adb5bb 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1881,10 +1881,9 @@ \let\sphinxtermref \@firstofone }} -% For curly braces and vertical bar inside \index macro +% For curly braces inside \index macro \def\sphinxleftcurlybrace{\{} \def\sphinxrightcurlybrace{\}} -\def\sphinxverticalbar{|} % Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x \def\spx@bd#1#2{% diff --git a/sphinx/texinputs/sphinx.xdy b/sphinx/texinputs/sphinx.xdy index 0efbdef2f..1c0794cd9 100644 --- a/sphinx/texinputs/sphinx.xdy +++ b/sphinx/texinputs/sphinx.xdy @@ -109,7 +109,6 @@ (merge-rule "\sphinxleftcurlybrace{}" "{" :string) (merge-rule "\sphinxrightcurlybrace{}" "}" :string) -(merge-rule "\sphinxverticalbar{}" "|" :string) (merge-rule "\_" "_" :string) (merge-rule "{[}" "[" :string) (merge-rule "{]}" "]" :string) @@ -127,6 +126,7 @@ (merge-rule "\(\rightarrow\)" "→" :string) (merge-rule "\(\checkmark\)" "✓" :string) (merge-rule "\textendash{}" "–" :string) +(merge-rule "\textbar{}" "|" :string) (merge-rule "\(\sp{\text{0}}\)" "⁰" :string) (merge-rule "\(\sp{\text{1}}\)" "¹" :string) (merge-rule "\(\sp{\text{2}}\)" "²" :string) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 7e79385f1..7695b31a9 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1816,7 +1816,7 @@ class LaTeXTranslator(SphinxTranslator): value = value.replace('"', '""') value = value.replace('@', '"@') value = value.replace('!', '"!') - value = value.replace('|', r'\sphinxverticalbar{}') + value = value.replace('|', r'\textbar{}') return value def style(string): From 182b11e68db02cd0de84a80f9830afbdbd35bca8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Nov 2019 23:52:19 +0900 Subject: [PATCH 11/28] Fix #6848: config.py shouldn't pop extensions from overrides --- CHANGES | 1 + sphinx/config.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 495d47199..9f03d9a92 100644 --- a/CHANGES +++ b/CHANGES @@ -67,6 +67,7 @@ Bugs fixed * #6793: texinfo: Code examples broken following "sidebar" * #6813: An orphan warning is emitted for included document on Windows. Thanks to @drillan +* #6848: config.py shouldn't pop extensions from overrides Testing -------- diff --git a/sphinx/config.py b/sphinx/config.py index d8cce1b3d..cbe04b3ee 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -177,16 +177,16 @@ class Config: else: config, overrides = args[:2] - self.overrides = overrides + self.overrides = dict(overrides) self.values = Config.config_values.copy() self._raw_config = config self.setup = config.get('setup', None) # type: Callable - if 'extensions' in overrides: - if isinstance(overrides['extensions'], str): - config['extensions'] = overrides.pop('extensions').split(',') + if 'extensions' in self.overrides: + if isinstance(self.overrides['extensions'], str): + config['extensions'] = self.overrides.pop('extensions').split(',') else: - config['extensions'] = overrides.pop('extensions') + config['extensions'] = self.overrides.pop('extensions') self.extensions = config.get('extensions', []) # type: List[str] @classmethod From 68729fb975d38000d304e2db1eb121fb194a0e04 Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Wed, 20 Nov 2019 11:34:03 +0100 Subject: [PATCH 12/28] Fix misplaced flags in re.sub() call The 4th argument of re.sub() is maximum number of substitutions, not flags. --- sphinx/util/smartypants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/util/smartypants.py b/sphinx/util/smartypants.py index 47f8b59b2..43f8bc724 100644 --- a/sphinx/util/smartypants.py +++ b/sphinx/util/smartypants.py @@ -155,7 +155,7 @@ def educateQuotes(text: str, language: str = 'en') -> str: # Special case for decade abbreviations (the '80s): if language.startswith('en'): # TODO similar cases in other languages? - text = re.sub(r"""'(?=\d{2}s)""", apostrophe, text, re.UNICODE) + text = re.sub(r"""'(?=\d{2}s)""", apostrophe, text, flags=re.UNICODE) close_class = r"""[^\ \t\r\n\[\{\(\-]""" dec_dashes = r"""–|—""" From c9236df8f1d370d92f7435832e0a0be352dfecea Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 21 Nov 2019 00:37:13 +0900 Subject: [PATCH 13/28] Update CHANGES for PR #6850 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 495d47199..c81b051c5 100644 --- a/CHANGES +++ b/CHANGES @@ -67,6 +67,7 @@ Bugs fixed * #6793: texinfo: Code examples broken following "sidebar" * #6813: An orphan warning is emitted for included document on Windows. Thanks to @drillan +* #6850: Fix smartypants module calls re.sub() with wrong options Testing -------- From a0b05422188d7afd8200f8a541a89d46baff2c20 Mon Sep 17 00:00:00 2001 From: Timotheus Kampik Date: Wed, 20 Nov 2019 21:13:54 +0100 Subject: [PATCH 14/28] 6824 fix search js bug (#6844) * #6824: Fix search logic (front end) Prevent duplicate additions of terms to a file in ``fileMap``, document search fix in change log --- CHANGES | 3 +++ sphinx/themes/basic/static/searchtools.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 9780573c9..9e3550e1d 100644 --- a/CHANGES +++ b/CHANGES @@ -70,6 +70,9 @@ Bugs fixed * #6813: An orphan warning is emitted for included document on Windows. Thanks to @drillan * #6850: Fix smartypants module calls re.sub() with wrong options +* #6824: HTML search: If a search term is partially matched in the title and + fully matched in a text paragraph on the same page, the search does not + include this match. Testing -------- diff --git a/sphinx/themes/basic/static/searchtools.js b/sphinx/themes/basic/static/searchtools.js index 7e0174e1c..ad845872e 100644 --- a/sphinx/themes/basic/static/searchtools.js +++ b/sphinx/themes/basic/static/searchtools.js @@ -424,7 +424,7 @@ var Search = { for (j = 0; j < _files.length; j++) { file = _files[j]; if (!(file in scoreMap)) - scoreMap[file] = {} + scoreMap[file] = {}; scoreMap[file][word] = o.score; } }); @@ -432,7 +432,7 @@ var Search = { // create the mapping for (j = 0; j < files.length; j++) { file = files[j]; - if (file in fileMap) + if (file in fileMap && fileMap[file].indexOf(word) === -1) fileMap[file].push(word); else fileMap[file] = [word]; From 70f087990b48197a67f302b610e92c7879a2af75 Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 22 Nov 2019 19:15:59 +0100 Subject: [PATCH 15/28] DOC: add Greek to list of supported languages --- doc/usage/configuration.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index e61c09cb2..a888be120 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -667,6 +667,7 @@ documentation on :ref:`intl` for details. * ``cs`` -- Czech * ``da`` -- Danish * ``de`` -- German + * ``el`` -- Greek * ``en`` -- English * ``es`` -- Spanish * ``et`` -- Estonian From df2f80c7553714397d5ee09b43025e0df9eefa4a Mon Sep 17 00:00:00 2001 From: Jonas Haag Date: Wed, 13 Nov 2019 15:39:47 +0100 Subject: [PATCH 16/28] Add linkcheck_auth option --- CHANGES | 2 ++ doc/usage/configuration.rst | 30 +++++++++++++++++++++++++++++- sphinx/builders/linkcheck.py | 17 ++++++++++++++--- tests/test_build_linkcheck.py | 23 +++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index cf7231b7d..8256a8a5d 100644 --- a/CHANGES +++ b/CHANGES @@ -39,6 +39,8 @@ Features added * #2546: apidoc: .so file support * #6798: autosummary: emit ``autodoc-skip-member`` event on generating stub file * #6483: i18n: make explicit titles in toctree translatable +* #6816: linkcheck: Add :confval:`linkcheck_auth` option to provide + authentication information when doing ``linkcheck`` builds Bugs fixed ---------- diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index bb1c639f9..8a253d8ce 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -538,7 +538,7 @@ General configuration directory pointed ``REQUESTS_CA_BUNDLE`` environment variable if ``tls_cacerts`` not set. - .. _requests: http://docs.python-requests.org/en/master/ + .. _requests: https://requests.readthedocs.io/en/master/ .. confval:: today today_fmt @@ -2369,6 +2369,34 @@ Options for the linkcheck builder .. versionadded:: 1.5 +.. confval:: linkcheck_auth + + Pass authentication information when doing a ``linkcheck`` build. + + A list of ``(regex_pattern, auth_info)`` tuples where the items are: + + *regex_pattern* + A regular expression that matches a URI. + *auth_info* + Authentication information to use for that URI. The value can be anything + that is understood by the ``requests`` library (see `requests + Authentication `_ for details). + + .. _requests-auth: https://requests.readthedocs.io/en/master/user/authentication/ + + The ``linkcheck`` builder will use the first matching ``auth_info`` value + it can find in the :confval:`linkcheck_auth` list, so values earlier in the + list have higher priority. + + Example:: + + linkcheck_auth = [ + ('https://foo\.yourcompany\.com/.+', ('johndoe', 'secret')), + ('https://.+\.yourcompany\.com/.+', HTTPDigestAuth(...)), + ] + + .. versionadded:: 2.3 + Options for the XML builder --------------------------- diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 737079a02..acca8998a 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -81,6 +81,8 @@ class CheckExternalLinksBuilder(Builder): self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore] self.anchors_ignore = [re.compile(x) for x in self.app.config.linkcheck_anchors_ignore] + self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info + in self.app.config.linkcheck_auth] self.good = set() # type: Set[str] self.broken = {} # type: Dict[str, str] self.redirected = {} # type: Dict[str, Tuple[str, int]] @@ -127,11 +129,18 @@ class CheckExternalLinksBuilder(Builder): except UnicodeError: req_url = encode_uri(req_url) + # Get auth info, if any + for pattern, auth_info in self.auth: + if pattern.match(uri): + break + else: + auth_info = None + try: if anchor and self.app.config.linkcheck_anchors: # Read the whole document and see if #anchor exists response = requests.get(req_url, stream=True, config=self.app.config, - **kwargs) + auth=auth_info, **kwargs) found = check_anchor(response, unquote(anchor)) if not found: @@ -140,13 +149,14 @@ class CheckExternalLinksBuilder(Builder): try: # try a HEAD request first, which should be easier on # the server and the network - response = requests.head(req_url, config=self.app.config, **kwargs) + response = requests.head(req_url, config=self.app.config, + auth=auth_info, **kwargs) response.raise_for_status() except HTTPError: # retry with GET request if that fails, some servers # don't like HEAD requests. response = requests.get(req_url, stream=True, config=self.app.config, - **kwargs) + auth=auth_info, **kwargs) response.raise_for_status() except HTTPError as err: if err.response.status_code == 401: @@ -305,6 +315,7 @@ def setup(app: Sphinx) -> Dict[str, Any]: app.add_builder(CheckExternalLinksBuilder) app.add_config_value('linkcheck_ignore', [], None) + app.add_config_value('linkcheck_auth', [], None) app.add_config_value('linkcheck_retries', 1, None) app.add_config_value('linkcheck_timeout', None, None, [int]) app.add_config_value('linkcheck_workers', 5, None) diff --git a/tests/test_build_linkcheck.py b/tests/test_build_linkcheck.py index 4bf47a962..22866b27b 100644 --- a/tests/test_build_linkcheck.py +++ b/tests/test_build_linkcheck.py @@ -8,6 +8,7 @@ :license: BSD, see LICENSE for details. """ +from unittest import mock import pytest @@ -47,3 +48,25 @@ def test_anchors_ignored(app, status, warning): # expect all ok when excluding #top assert not content + + +@pytest.mark.sphinx( + 'linkcheck', testroot='linkcheck', freshenv=True, + confoverrides={'linkcheck_auth': [ + (r'.+google\.com/image.+', 'authinfo1'), + (r'.+google\.com.+', 'authinfo2'), + ] + }) +def test_auth(app, status, warning): + mock_req = mock.MagicMock() + mock_req.return_value = 'fake-response' + + with mock.patch.multiple('requests', get=mock_req, head=mock_req): + app.builder.build_all() + for c_args, c_kwargs in mock_req.call_args_list: + if 'google.com/image' in c_args[0]: + assert c_kwargs['auth'] == 'authinfo1' + elif 'google.com' in c_args[0]: + assert c_kwargs['auth'] == 'authinfo2' + else: + assert not c_kwargs['auth'] From 1faf14d411f965e54074f2aafd00c41e50ea02c7 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 26 Nov 2019 01:22:14 +0900 Subject: [PATCH 17/28] Update supported languages (refs: #6854) --- doc/usage/configuration.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 3c3dbf1ad..cfea84373 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -662,13 +662,17 @@ documentation on :ref:`intl` for details. Currently supported languages by Sphinx are: + * ``ar`` -- Arabic * ``bn`` -- Bengali * ``ca`` -- Catalan + * ``cak`` -- Kaqchikel * ``cs`` -- Czech + * ``cy`` -- Welsh * ``da`` -- Danish * ``de`` -- German * ``el`` -- Greek * ``en`` -- English + * ``eo`` -- Esperanto * ``es`` -- Spanish * ``et`` -- Estonian * ``eu`` -- Basque @@ -676,6 +680,7 @@ documentation on :ref:`intl` for details. * ``fi`` -- Finnish * ``fr`` -- French * ``he`` -- Hebrew + * ``hi`` -- Hindi * ``hr`` -- Croatian * ``hu`` -- Hungarian * ``id`` -- Indonesian @@ -689,15 +694,20 @@ documentation on :ref:`intl` for details. * ``ne`` -- Nepali * ``nl`` -- Dutch * ``pl`` -- Polish + * ``pt`` -- Portuguese * ``pt_BR`` -- Brazilian Portuguese * ``pt_PT`` -- European Portuguese + * ``ro`` -- Romanian * ``ru`` -- Russian * ``si`` -- Sinhala * ``sk`` -- Slovak * ``sl`` -- Slovenian + * ``sr`` -- Serbian * ``sv`` -- Swedish + * ``ta`` -- Tamil * ``tr`` -- Turkish * ``uk_UA`` -- Ukrainian + * ``ur`` -- Urdu * ``vi`` -- Vietnamese * ``zh_CN`` -- Simplified Chinese * ``zh_TW`` -- Traditional Chinese From ede4182c5202899231b47094112022fca0cddb3d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 15 Jul 2019 20:52:44 +0900 Subject: [PATCH 18/28] Migrate to py3 style type annotation: sphinx.writers.texinfo --- sphinx/writers/texinfo.py | 688 +++++++++++++------------------------- 1 file changed, 233 insertions(+), 455 deletions(-) diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index b7a590cad..757519740 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -12,12 +12,15 @@ import re import textwrap import warnings from os import path -from typing import Iterable, cast +from typing import Any, Callable, Dict, Iterable, Iterator, List, Pattern, Set, Tuple, Union +from typing import cast from docutils import nodes, writers +from docutils.nodes import Element, Node, Text from sphinx import addnodes, __display_version__ from sphinx.deprecation import RemovedInSphinx30Warning +from sphinx.domains import IndexEntry from sphinx.errors import ExtensionError from sphinx.locale import admonitionlabels, _, __ from sphinx.util import logging @@ -27,9 +30,8 @@ from sphinx.writers.latex import collected_footnote if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Pattern, Set, Tuple, Union # NOQA - from sphinx.builders.texinfo import TexinfoBuilder # NOQA - from sphinx.domains import IndexEntry # NOQA + from sphinx.builders.texinfo import TexinfoBuilder + logger = logging.getLogger(__name__) @@ -89,8 +91,7 @@ TEMPLATE = """\ """ -def find_subsections(section): - # type: (nodes.Element) -> List[nodes.section] +def find_subsections(section: Element) -> List[nodes.section]: """Return a list of subsections for the given ``section``.""" result = [] for child in section: @@ -102,8 +103,7 @@ def find_subsections(section): return result -def smart_capwords(s, sep=None): - # type: (str, str) -> str +def smart_capwords(s: str, sep: str = None) -> str: """Like string.capwords() but does not capitalize words that already contain a capital letter.""" words = s.split(sep) @@ -131,13 +131,11 @@ class TexinfoWriter(writers.Writer): visitor_attributes = ('output', 'fragment') - def __init__(self, builder): - # type: (TexinfoBuilder) -> None + def __init__(self, builder: "TexinfoBuilder") -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: visitor = self.builder.create_translator(self.document, self.builder) self.visitor = cast(TexinfoTranslator, visitor) self.document.walkabout(visitor) @@ -166,8 +164,7 @@ class TexinfoTranslator(SphinxTranslator): 'title': '', } - def __init__(self, document, builder): - # type: (nodes.document, TexinfoBuilder) -> None + def __init__(self, document: nodes.document, builder: "TexinfoBuilder") -> None: super().__init__(document, builder) self.init_settings() @@ -205,8 +202,7 @@ class TexinfoTranslator(SphinxTranslator): self.handled_abbrs = set() # type: Set[str] self.colwidths = None # type: List[int] - def finish(self): - # type: () -> None + def finish(self) -> None: if self.previous_section is None: self.add_menu('Top') for index in self.indices: @@ -227,8 +223,7 @@ class TexinfoTranslator(SphinxTranslator): # -- Helper routines - def init_settings(self): - # type: () -> None + def init_settings(self) -> None: elements = self.elements = self.default_elements.copy() elements.update({ # if empty, the title is set to the first section title @@ -270,14 +265,12 @@ class TexinfoTranslator(SphinxTranslator): # allow the user to override them all elements.update(self.settings.texinfo_elements) - def collect_node_names(self): - # type: () -> None + def collect_node_names(self) -> None: """Generates a unique id for each section. Assigns the attribute ``node_name`` to each section.""" - def add_node_name(name): - # type: (str) -> str + def add_node_name(name: str) -> str: node_id = self.escape_id(name) nth, suffix = 1, '' while node_id + suffix in self.written_ids or \ @@ -302,11 +295,10 @@ class TexinfoTranslator(SphinxTranslator): name = (title and title.astext()) or '' section['node_name'] = add_node_name(name) - def collect_node_menus(self): - # type: () -> None + def collect_node_menus(self) -> None: """Collect the menu entries for each "node" section.""" node_menus = self.node_menus - targets = [self.document] # type: List[nodes.Element] + targets = [self.document] # type: List[Element] targets.extend(self.document.traverse(nodes.section)) for node in targets: assert 'node_name' in node and node['node_name'] @@ -328,8 +320,7 @@ class TexinfoTranslator(SphinxTranslator): node_menus[name] = [] node_menus['Top'].append(name) - def collect_rellinks(self): - # type: () -> None + def collect_rellinks(self) -> None: """Collect the relative links (next, previous, up) for each "node".""" rellinks = self.rellinks node_menus = self.node_menus @@ -362,8 +353,7 @@ class TexinfoTranslator(SphinxTranslator): # namely menus and node names, it's not possible to escape certain # characters. - def escape(self, s): - # type: (str) -> str + def escape(self, s: str) -> str: """Return a string with Texinfo command characters escaped.""" s = s.replace('@', '@@') s = s.replace('{', '@{') @@ -373,8 +363,7 @@ class TexinfoTranslator(SphinxTranslator): s = s.replace("''", "'@w{'}") return s - def escape_arg(self, s): - # type: (str) -> str + def escape_arg(self, s: str) -> str: """Return an escaped string suitable for use as an argument to a Texinfo command.""" s = self.escape(s) @@ -384,8 +373,7 @@ class TexinfoTranslator(SphinxTranslator): s = ' '.join(s.split()).strip() return s - def escape_id(self, s): - # type: (str) -> str + def escape_id(self, s: str) -> str: """Return an escaped string suitable for node names and anchors.""" bad_chars = ',:()' for bc in bad_chars: @@ -396,22 +384,19 @@ class TexinfoTranslator(SphinxTranslator): s = ' '.join(s.split()).strip() return self.escape(s) - def escape_menu(self, s): - # type: (str) -> str + def escape_menu(self, s: str) -> str: """Return an escaped string suitable for menu entries.""" s = self.escape_arg(s) s = s.replace(':', ';') s = ' '.join(s.split()).strip() return s - def ensure_eol(self): - # type: () -> None + def ensure_eol(self) -> None: """Ensure the last line in body is terminated by new line.""" if self.body and self.body[-1][-1:] != '\n': self.body.append('\n') - def format_menu_entry(self, name, node_name, desc): - # type: (str, str, str) -> str + def format_menu_entry(self, name: str, node_name: str, desc: str) -> str: if name == node_name: s = '* %s:: ' % (name,) else: @@ -421,8 +406,8 @@ class TexinfoTranslator(SphinxTranslator): textwrap.wrap(desc, width=78 - offset)) return s + wdesc.strip() + '\n' - def add_menu_entries(self, entries, reg=re.compile(r'\s+---?\s+')): - # type: (List[str], Pattern) -> None + def add_menu_entries(self, entries: List[str], reg: Pattern = re.compile(r'\s+---?\s+') + ) -> None: for entry in entries: name = self.node_names[entry] # special formatting for entries that are divided by an em-dash @@ -439,8 +424,7 @@ class TexinfoTranslator(SphinxTranslator): desc = self.escape(desc) self.body.append(self.format_menu_entry(name, entry, desc)) - def add_menu(self, node_name): - # type: (str) -> None + def add_menu(self, node_name: str) -> None: entries = self.node_menus[node_name] if not entries: return @@ -452,8 +436,7 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n@end menu\n') return - def _add_detailed_menu(name): - # type: (str) -> None + def _add_detailed_menu(name: str) -> None: entries = self.node_menus[name] if not entries: return @@ -469,8 +452,7 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n@end detailmenu\n' '@end menu\n') - def tex_image_length(self, width_str): - # type: (str) -> str + def tex_image_length(self, width_str: str) -> str: match = re.match(r'(\d*\.?\d*)\s*(\S*)', width_str) if not match: # fallback @@ -485,10 +467,8 @@ class TexinfoTranslator(SphinxTranslator): res = "%d.0pt" % (float(amount) * 4.1825368) return res - def collect_indices(self): - # type: () -> None - def generate(content, collapsed): - # type: (List[Tuple[str, List[IndexEntry]]], bool) -> str + def collect_indices(self) -> None: + def generate(content: List[Tuple[str, List[IndexEntry]]], collapsed: bool) -> str: ret = ['\n@menu\n'] for letter, entries in content: for entry in entries: @@ -525,10 +505,8 @@ class TexinfoTranslator(SphinxTranslator): # this is copied from the latex writer # TODO: move this to sphinx.util - def collect_footnotes(self, node): - # type: (nodes.Element) -> Dict[str, List[Union[collected_footnote, bool]]] - def footnotes_under(n): - # type: (nodes.Element) -> Iterator[nodes.footnote] + def collect_footnotes(self, node: Element) -> Dict[str, List[Union[collected_footnote, bool]]]: # NOQA + def footnotes_under(n: Element) -> Iterator[nodes.footnote]: if isinstance(n, nodes.footnote): yield n else: @@ -546,8 +524,7 @@ class TexinfoTranslator(SphinxTranslator): # -- xref handling - def get_short_id(self, id): - # type: (str) -> str + def get_short_id(self, id: str) -> str: """Return a shorter 'id' associated with ``id``.""" # Shorter ids improve paragraph filling in places # that the id is hidden by Emacs. @@ -558,8 +535,7 @@ class TexinfoTranslator(SphinxTranslator): self.short_ids[id] = sid return sid - def add_anchor(self, id, node): - # type: (str, nodes.Node) -> None + def add_anchor(self, id: str, node: Node) -> None: if id.startswith('index-'): return id = self.curfilestack[-1] + ':' + id @@ -570,8 +546,7 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('@anchor{%s}' % id) self.written_ids.add(id) - def add_xref(self, id, name, node): - # type: (str, str, nodes.Node) -> None + def add_xref(self, id: str, name: str, node: Node) -> None: name = self.escape_menu(name) sid = self.get_short_id(id) self.body.append('@ref{%s,,%s}' % (sid, name)) @@ -580,20 +555,17 @@ class TexinfoTranslator(SphinxTranslator): # -- Visiting - def visit_document(self, node): - # type: (nodes.Element) -> None + def visit_document(self, node: Element) -> None: self.footnotestack.append(self.collect_footnotes(node)) self.curfilestack.append(node.get('docname', '')) if 'docname' in node: self.add_anchor(':doc', node) - def depart_document(self, node): - # type: (nodes.Element) -> None + def depart_document(self, node: Element) -> None: self.footnotestack.pop() self.curfilestack.pop() - def visit_Text(self, node): - # type: (nodes.Text) -> None + def visit_Text(self, node: Text) -> None: s = self.escape(node.astext()) if self.escape_newlines: s = s.replace('\n', ' ') @@ -602,12 +574,10 @@ class TexinfoTranslator(SphinxTranslator): s = s.replace('-', '@w{-}') self.body.append(s) - def depart_Text(self, node): - # type: (nodes.Text) -> None + def depart_Text(self, node: Text) -> None: pass - def visit_section(self, node): - # type: (nodes.Element) -> None + def visit_section(self, node: Element) -> None: self.next_section_ids.update(node.get('ids', [])) if not self.seen_title: return @@ -626,8 +596,7 @@ class TexinfoTranslator(SphinxTranslator): self.previous_section = cast(nodes.section, node) self.section_level += 1 - def depart_section(self, node): - # type: (nodes.Element) -> None + def depart_section(self, node: Element) -> None: self.section_level -= 1 headings = ( @@ -644,8 +613,7 @@ class TexinfoTranslator(SphinxTranslator): '@subsubheading', ) - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: if not self.seen_title: self.seen_title = True raise nodes.SkipNode @@ -666,12 +634,10 @@ class TexinfoTranslator(SphinxTranslator): heading = self.headings[-1] self.body.append('\n%s ' % heading) - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: self.body.append('\n\n') - def visit_rubric(self, node): - # type: (nodes.Element) -> None + def visit_rubric(self, node: Element) -> None: if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')): raise nodes.SkipNode try: @@ -681,23 +647,19 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n%s ' % rubric) self.escape_newlines += 1 - def depart_rubric(self, node): - # type: (nodes.Element) -> None + def depart_rubric(self, node: Element) -> None: self.escape_newlines -= 1 self.body.append('\n\n') - def visit_subtitle(self, node): - # type: (nodes.Element) -> None + def visit_subtitle(self, node: Element) -> None: self.body.append('\n\n@noindent\n') - def depart_subtitle(self, node): - # type: (nodes.Element) -> None + def depart_subtitle(self, node: Element) -> None: self.body.append('\n\n') # -- References - def visit_target(self, node): - # type: (nodes.Element) -> None + def visit_target(self, node: Element) -> None: # postpone the labels until after the sectioning command parindex = node.parent.index(node) try: @@ -721,12 +683,10 @@ class TexinfoTranslator(SphinxTranslator): for id in node['ids']: self.add_anchor(id, node) - def depart_target(self, node): - # type: (nodes.Element) -> None + def depart_target(self, node: Element) -> None: pass - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: # an xref's target is displayed in Info so we ignore a few # cases for the sake of appearance if isinstance(node.parent, (nodes.title, addnodes.desc_type)): @@ -789,134 +749,107 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('%s@footnote{%s}' % (name, uri)) raise nodes.SkipNode - def depart_reference(self, node): - # type: (nodes.Element) -> None + def depart_reference(self, node: Element) -> None: pass - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: text = nodes.Text(node.get('title', '#')) self.visit_Text(text) raise nodes.SkipNode - def visit_title_reference(self, node): - # type: (nodes.Element) -> None + def visit_title_reference(self, node: Element) -> None: text = node.astext() self.body.append('@cite{%s}' % self.escape_arg(text)) raise nodes.SkipNode # -- Blocks - def visit_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_paragraph(self, node: Element) -> None: self.body.append('\n') - def depart_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_paragraph(self, node: Element) -> None: self.body.append('\n') - def visit_block_quote(self, node): - # type: (nodes.Element) -> None + def visit_block_quote(self, node: Element) -> None: self.body.append('\n@quotation\n') - def depart_block_quote(self, node): - # type: (nodes.Element) -> None + def depart_block_quote(self, node: Element) -> None: self.ensure_eol() self.body.append('@end quotation\n') - def visit_literal_block(self, node): - # type: (nodes.Element) -> None + def visit_literal_block(self, node: Element) -> None: self.body.append('\n@example\n') - def depart_literal_block(self, node): - # type: (nodes.Element) -> None + def depart_literal_block(self, node: Element) -> None: self.ensure_eol() self.body.append('@end example\n') visit_doctest_block = visit_literal_block depart_doctest_block = depart_literal_block - def visit_line_block(self, node): - # type: (nodes.Element) -> None + def visit_line_block(self, node: Element) -> None: if not isinstance(node.parent, nodes.line_block): self.body.append('\n\n') self.body.append('@display\n') - def depart_line_block(self, node): - # type: (nodes.Element) -> None + def depart_line_block(self, node: Element) -> None: self.body.append('@end display\n') if not isinstance(node.parent, nodes.line_block): self.body.append('\n\n') - def visit_line(self, node): - # type: (nodes.Element) -> None + def visit_line(self, node: Element) -> None: self.escape_newlines += 1 - def depart_line(self, node): - # type: (nodes.Element) -> None + def depart_line(self, node: Element) -> None: self.body.append('@w{ }\n') self.escape_newlines -= 1 # -- Inline - def visit_strong(self, node): - # type: (nodes.Element) -> None + def visit_strong(self, node: Element) -> None: self.body.append('@strong{') - def depart_strong(self, node): - # type: (nodes.Element) -> None + def depart_strong(self, node: Element) -> None: self.body.append('}') - def visit_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_emphasis(self, node: Element) -> None: self.body.append('@emph{') - def depart_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_emphasis(self, node: Element) -> None: self.body.append('}') - def visit_literal(self, node): - # type: (nodes.Element) -> None + def visit_literal(self, node: Element) -> None: self.body.append('@code{') - def depart_literal(self, node): - # type: (nodes.Element) -> None + def depart_literal(self, node: Element) -> None: self.body.append('}') - def visit_superscript(self, node): - # type: (nodes.Element) -> None + def visit_superscript(self, node: Element) -> None: self.body.append('@w{^') - def depart_superscript(self, node): - # type: (nodes.Element) -> None + def depart_superscript(self, node: Element) -> None: self.body.append('}') - def visit_subscript(self, node): - # type: (nodes.Element) -> None + def visit_subscript(self, node: Element) -> None: self.body.append('@w{[') - def depart_subscript(self, node): - # type: (nodes.Element) -> None + def depart_subscript(self, node: Element) -> None: self.body.append(']}') # -- Footnotes - def visit_footnote(self, node): - # type: (nodes.Element) -> None + def visit_footnote(self, node: Element) -> None: raise nodes.SkipNode - def visit_collected_footnote(self, node): - # type: (nodes.Element) -> None + def visit_collected_footnote(self, node: Element) -> None: self.in_footnote += 1 self.body.append('@footnote{') - def depart_collected_footnote(self, node): - # type: (nodes.Element) -> None + def depart_collected_footnote(self, node: Element) -> None: self.body.append('}') self.in_footnote -= 1 - def visit_footnote_reference(self, node): - # type: (nodes.Element) -> None + def visit_footnote_reference(self, node: Element) -> None: num = node.astext().strip() try: footnode, used = self.footnotestack[-1][num] @@ -926,39 +859,32 @@ class TexinfoTranslator(SphinxTranslator): footnode.walkabout(self) # type: ignore raise nodes.SkipChildren - def visit_citation(self, node): - # type: (nodes.Element) -> None + def visit_citation(self, node: Element) -> None: self.body.append('\n') for id in node.get('ids'): self.add_anchor(id, node) self.escape_newlines += 1 - def depart_citation(self, node): - # type: (nodes.Element) -> None + def depart_citation(self, node: Element) -> None: self.escape_newlines -= 1 - def visit_citation_reference(self, node): - # type: (nodes.Element) -> None + def visit_citation_reference(self, node: Element) -> None: self.body.append('@w{[') - def depart_citation_reference(self, node): - # type: (nodes.Element) -> None + def depart_citation_reference(self, node: Element) -> None: self.body.append(']}') # -- Lists - def visit_bullet_list(self, node): - # type: (nodes.Element) -> None + def visit_bullet_list(self, node: Element) -> None: bullet = node.get('bullet', '*') self.body.append('\n\n@itemize %s\n' % bullet) - def depart_bullet_list(self, node): - # type: (nodes.Element) -> None + def depart_bullet_list(self, node: Element) -> None: self.ensure_eol() self.body.append('@end itemize\n') - def visit_enumerated_list(self, node): - # type: (nodes.Element) -> None + def visit_enumerated_list(self, node: Element) -> None: # doesn't support Roman numerals enum = node.get('enumtype', 'arabic') starters = {'arabic': '', @@ -967,101 +893,79 @@ class TexinfoTranslator(SphinxTranslator): start = node.get('start', starters.get(enum, '')) self.body.append('\n\n@enumerate %s\n' % start) - def depart_enumerated_list(self, node): - # type: (nodes.Element) -> None + def depart_enumerated_list(self, node: Element) -> None: self.ensure_eol() self.body.append('@end enumerate\n') - def visit_list_item(self, node): - # type: (nodes.Element) -> None + def visit_list_item(self, node: Element) -> None: self.body.append('\n@item ') - def depart_list_item(self, node): - # type: (nodes.Element) -> None + def depart_list_item(self, node: Element) -> None: pass # -- Option List - def visit_option_list(self, node): - # type: (nodes.Element) -> None + def visit_option_list(self, node: Element) -> None: self.body.append('\n\n@table @option\n') - def depart_option_list(self, node): - # type: (nodes.Element) -> None + def depart_option_list(self, node: Element) -> None: self.ensure_eol() self.body.append('@end table\n') - def visit_option_list_item(self, node): - # type: (nodes.Element) -> None + def visit_option_list_item(self, node: Element) -> None: pass - def depart_option_list_item(self, node): - # type: (nodes.Element) -> None + def depart_option_list_item(self, node: Element) -> None: pass - def visit_option_group(self, node): - # type: (nodes.Element) -> None + def visit_option_group(self, node: Element) -> None: self.at_item_x = '@item' - def depart_option_group(self, node): - # type: (nodes.Element) -> None + def depart_option_group(self, node: Element) -> None: pass - def visit_option(self, node): - # type: (nodes.Element) -> None + def visit_option(self, node: Element) -> None: self.escape_hyphens += 1 self.body.append('\n%s ' % self.at_item_x) self.at_item_x = '@itemx' - def depart_option(self, node): - # type: (nodes.Element) -> None + def depart_option(self, node: Element) -> None: self.escape_hyphens -= 1 - def visit_option_string(self, node): - # type: (nodes.Element) -> None + def visit_option_string(self, node: Element) -> None: pass - def depart_option_string(self, node): - # type: (nodes.Element) -> None + def depart_option_string(self, node: Element) -> None: pass - def visit_option_argument(self, node): - # type: (nodes.Element) -> None + def visit_option_argument(self, node: Element) -> None: self.body.append(node.get('delimiter', ' ')) - def depart_option_argument(self, node): - # type: (nodes.Element) -> None + def depart_option_argument(self, node: Element) -> None: pass - def visit_description(self, node): - # type: (nodes.Element) -> None + def visit_description(self, node: Element) -> None: self.body.append('\n') - def depart_description(self, node): - # type: (nodes.Element) -> None + def depart_description(self, node: Element) -> None: pass # -- Definitions - def visit_definition_list(self, node): - # type: (nodes.Element) -> None + def visit_definition_list(self, node: Element) -> None: self.body.append('\n\n@table @asis\n') - def depart_definition_list(self, node): - # type: (nodes.Element) -> None + def depart_definition_list(self, node: Element) -> None: self.ensure_eol() self.body.append('@end table\n') - def visit_definition_list_item(self, node): - # type: (nodes.Element) -> None + def visit_definition_list_item(self, node: Element) -> None: self.at_item_x = '@item' - def depart_definition_list_item(self, node): - # type: (nodes.Element) -> None + def depart_definition_list_item(self, node: Element) -> None: pass - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: for id in node.get('ids'): self.add_anchor(id, node) # anchors and indexes need to go in front @@ -1072,46 +976,36 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n%s ' % self.at_item_x) self.at_item_x = '@itemx' - def depart_term(self, node): - # type: (nodes.Element) -> None + def depart_term(self, node: Element) -> None: pass - def visit_classifier(self, node): - # type: (nodes.Element) -> None + def visit_classifier(self, node: Element) -> None: self.body.append(' : ') - def depart_classifier(self, node): - # type: (nodes.Element) -> None + def depart_classifier(self, node: Element) -> None: pass - def visit_definition(self, node): - # type: (nodes.Element) -> None + def visit_definition(self, node: Element) -> None: self.body.append('\n') - def depart_definition(self, node): - # type: (nodes.Element) -> None + def depart_definition(self, node: Element) -> None: pass # -- Tables - def visit_table(self, node): - # type: (nodes.Element) -> None + def visit_table(self, node: Element) -> None: self.entry_sep = '@item' - def depart_table(self, node): - # type: (nodes.Element) -> None + def depart_table(self, node: Element) -> None: self.body.append('\n@end multitable\n\n') - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: pass - def depart_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def depart_tabular_col_spec(self, node: Element) -> None: pass - def visit_colspec(self, node): - # type: (nodes.Element) -> None + def visit_colspec(self, node: Element) -> None: self.colwidths.append(node['colwidth']) if len(self.colwidths) != self.n_cols: return @@ -1119,104 +1013,82 @@ class TexinfoTranslator(SphinxTranslator): for i, n in enumerate(self.colwidths): self.body.append('{%s} ' % ('x' * (n + 2))) - def depart_colspec(self, node): - # type: (nodes.Element) -> None + def depart_colspec(self, node: Element) -> None: pass - def visit_tgroup(self, node): - # type: (nodes.Element) -> None + def visit_tgroup(self, node: Element) -> None: self.colwidths = [] self.n_cols = node['cols'] - def depart_tgroup(self, node): - # type: (nodes.Element) -> None + def depart_tgroup(self, node: Element) -> None: pass - def visit_thead(self, node): - # type: (nodes.Element) -> None + def visit_thead(self, node: Element) -> None: self.entry_sep = '@headitem' - def depart_thead(self, node): - # type: (nodes.Element) -> None + def depart_thead(self, node: Element) -> None: pass - def visit_tbody(self, node): - # type: (nodes.Element) -> None + def visit_tbody(self, node: Element) -> None: pass - def depart_tbody(self, node): - # type: (nodes.Element) -> None + def depart_tbody(self, node: Element) -> None: pass - def visit_row(self, node): - # type: (nodes.Element) -> None + def visit_row(self, node: Element) -> None: pass - def depart_row(self, node): - # type: (nodes.Element) -> None + def depart_row(self, node: Element) -> None: self.entry_sep = '@item' - def visit_entry(self, node): - # type: (nodes.Element) -> None + def visit_entry(self, node: Element) -> None: self.body.append('\n%s\n' % self.entry_sep) self.entry_sep = '@tab' - def depart_entry(self, node): - # type: (nodes.Element) -> None + def depart_entry(self, node: Element) -> None: for i in range(node.get('morecols', 0)): self.body.append('\n@tab\n') # -- Field Lists - def visit_field_list(self, node): - # type: (nodes.Element) -> None + def visit_field_list(self, node: Element) -> None: pass - def depart_field_list(self, node): - # type: (nodes.Element) -> None + def depart_field_list(self, node: Element) -> None: pass - def visit_field(self, node): - # type: (nodes.Element) -> None + def visit_field(self, node: Element) -> None: self.body.append('\n') - def depart_field(self, node): - # type: (nodes.Element) -> None + def depart_field(self, node: Element) -> None: self.body.append('\n') - def visit_field_name(self, node): - # type: (nodes.Element) -> None + def visit_field_name(self, node: Element) -> None: self.ensure_eol() self.body.append('@*') - def depart_field_name(self, node): - # type: (nodes.Element) -> None + def depart_field_name(self, node: Element) -> None: self.body.append(': ') - def visit_field_body(self, node): - # type: (nodes.Element) -> None + def visit_field_body(self, node: Element) -> None: pass - def depart_field_body(self, node): - # type: (nodes.Element) -> None + def depart_field_body(self, node: Element) -> None: pass # -- Admonitions - def visit_admonition(self, node, name=''): - # type: (nodes.Element, str) -> None + def visit_admonition(self, node: Element, name: str = '') -> None: if not name: title = cast(nodes.title, node[0]) name = self.escape(title.astext()) self.body.append('\n@cartouche\n@quotation %s ' % name) - def _visit_named_admonition(self, node): - # type: (nodes.Element) -> None + def _visit_named_admonition(self, node: Element) -> None: label = admonitionlabels[node.tagname] self.body.append('\n@cartouche\n@quotation %s ' % label) - def depart_admonition(self, node): - # type: (nodes.Element) -> None + def depart_admonition(self, node: Element) -> None: self.ensure_eol() self.body.append('@end quotation\n' '@end cartouche\n') @@ -1242,42 +1114,33 @@ class TexinfoTranslator(SphinxTranslator): # -- Misc - def visit_docinfo(self, node): - # type: (nodes.Element) -> None + def visit_docinfo(self, node: Element) -> None: raise nodes.SkipNode - def visit_generated(self, node): - # type: (nodes.Element) -> None + def visit_generated(self, node: Element) -> None: raise nodes.SkipNode - def visit_header(self, node): - # type: (nodes.Element) -> None + def visit_header(self, node: Element) -> None: raise nodes.SkipNode - def visit_footer(self, node): - # type: (nodes.Element) -> None + def visit_footer(self, node: Element) -> None: raise nodes.SkipNode - def visit_container(self, node): - # type: (nodes.Element) -> None + def visit_container(self, node: Element) -> None: if node.get('literal_block'): self.body.append('\n\n@float LiteralBlock\n') - def depart_container(self, node): - # type: (nodes.Element) -> None + def depart_container(self, node: Element) -> None: if node.get('literal_block'): self.body.append('\n@end float\n\n') - def visit_decoration(self, node): - # type: (nodes.Element) -> None + def visit_decoration(self, node: Element) -> None: pass - def depart_decoration(self, node): - # type: (nodes.Element) -> None + def depart_decoration(self, node: Element) -> None: pass - def visit_topic(self, node): - # type: (nodes.Element) -> None + def visit_topic(self, node: Element) -> None: # ignore TOC's since we have to have a "menu" anyway if 'contents' in node.get('classes', []): raise nodes.SkipNode @@ -1286,43 +1149,34 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('%s\n' % self.escape(title.astext())) self.depart_rubric(title) - def depart_topic(self, node): - # type: (nodes.Element) -> None + def depart_topic(self, node: Element) -> None: pass - def visit_transition(self, node): - # type: (nodes.Element) -> None + def visit_transition(self, node: Element) -> None: self.body.append('\n\n%s\n\n' % ('_' * 66)) - def depart_transition(self, node): - # type: (nodes.Element) -> None + def depart_transition(self, node: Element) -> None: pass - def visit_attribution(self, node): - # type: (nodes.Element) -> None + def visit_attribution(self, node: Element) -> None: self.body.append('\n\n@center --- ') - def depart_attribution(self, node): - # type: (nodes.Element) -> None + def depart_attribution(self, node: Element) -> None: self.body.append('\n\n') - def visit_raw(self, node): - # type: (nodes.Element) -> None + def visit_raw(self, node: Element) -> None: format = node.get('format', '').split() if 'texinfo' in format or 'texi' in format: self.body.append(node.astext()) raise nodes.SkipNode - def visit_figure(self, node): - # type: (nodes.Element) -> None + def visit_figure(self, node: Element) -> None: self.body.append('\n\n@float Figure\n') - def depart_figure(self, node): - # type: (nodes.Element) -> None + def depart_figure(self, node: Element) -> None: self.body.append('\n@end float\n\n') - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: if (isinstance(node.parent, nodes.figure) or (isinstance(node.parent, nodes.container) and node.parent.get('literal_block'))): @@ -1331,15 +1185,13 @@ class TexinfoTranslator(SphinxTranslator): logger.warning(__('caption not inside a figure.'), location=(self.curfilestack[-1], node.line)) - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: if (isinstance(node.parent, nodes.figure) or (isinstance(node.parent, nodes.container) and node.parent.get('literal_block'))): self.body.append('}\n') - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: if node['uri'] in self.builder.images: uri = self.builder.images[node['uri']] else: @@ -1360,82 +1212,65 @@ class TexinfoTranslator(SphinxTranslator): self.body.append('\n@image{%s,%s,%s,%s,%s}\n' % (filename, width, height, alt, ext[1:])) - def depart_image(self, node): - # type: (nodes.Element) -> None + def depart_image(self, node: Element) -> None: pass - def visit_compound(self, node): - # type: (nodes.Element) -> None + def visit_compound(self, node: Element) -> None: pass - def depart_compound(self, node): - # type: (nodes.Element) -> None + def depart_compound(self, node: Element) -> None: pass - def visit_sidebar(self, node): - # type: (nodes.Element) -> None + def visit_sidebar(self, node: Element) -> None: self.visit_topic(node) - def depart_sidebar(self, node): - # type: (nodes.Element) -> None + def depart_sidebar(self, node: Element) -> None: self.depart_topic(node) - def visit_label(self, node): - # type: (nodes.Element) -> None + def visit_label(self, node: Element) -> None: self.body.append('@w{(') - def depart_label(self, node): - # type: (nodes.Element) -> None + def depart_label(self, node: Element) -> None: self.body.append(')} ') - def visit_legend(self, node): - # type: (nodes.Element) -> None + def visit_legend(self, node: Element) -> None: pass - def depart_legend(self, node): - # type: (nodes.Element) -> None + def depart_legend(self, node: Element) -> None: pass - def visit_system_message(self, node): - # type: (nodes.Element) -> None + def visit_system_message(self, node: Element) -> None: self.body.append('\n@verbatim\n' '\n' '@end verbatim\n' % node.astext()) raise nodes.SkipNode - def visit_comment(self, node): - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: self.body.append('\n') for line in node.astext().splitlines(): self.body.append('@c %s\n' % line) raise nodes.SkipNode - def visit_problematic(self, node): - # type: (nodes.Element) -> None + def visit_problematic(self, node: Element) -> None: self.body.append('>>') - def depart_problematic(self, node): - # type: (nodes.Element) -> None + def depart_problematic(self, node: Element) -> None: self.body.append('<<') - def unimplemented_visit(self, node): - # type: (nodes.Element) -> None + def unimplemented_visit(self, node: Element) -> None: logger.warning(__("unimplemented node type: %r"), node, location=(self.curfilestack[-1], node.line)) - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: logger.warning(__("unknown node type: %r"), node, location=(self.curfilestack[-1], node.line)) - def unknown_departure(self, node): - # type: (nodes.Node) -> None + def unknown_departure(self, node: Node) -> None: pass # -- Sphinx specific - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.visit_literal_block(None) names = [] productionlist = cast(Iterable[addnodes.production], node) @@ -1454,32 +1289,25 @@ class TexinfoTranslator(SphinxTranslator): self.depart_literal_block(None) raise nodes.SkipNode - def visit_production(self, node): - # type: (nodes.Element) -> None + def visit_production(self, node: Element) -> None: pass - def depart_production(self, node): - # type: (nodes.Element) -> None + def depart_production(self, node: Element) -> None: pass - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: self.body.append('@code{') - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: self.body.append('}') - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: self.body.append('@code{') - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: self.body.append('}') - def visit_index(self, node): - # type: (nodes.Element) -> None + def visit_index(self, node: Element) -> None: # terminate the line but don't prevent paragraph breaks if isinstance(node.parent, nodes.paragraph): self.ensure_eol() @@ -1490,55 +1318,44 @@ class TexinfoTranslator(SphinxTranslator): text = self.escape_menu(text) self.body.append('@geindex %s\n' % text) - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: self.body.append('\n') - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: self.body.append('\n') - def visit_start_of_file(self, node): - # type: (nodes.Element) -> None + def visit_start_of_file(self, node: Element) -> None: # add a document target self.next_section_ids.add(':doc') self.curfilestack.append(node['docname']) self.footnotestack.append(self.collect_footnotes(node)) - def depart_start_of_file(self, node): - # type: (nodes.Element) -> None + def depart_start_of_file(self, node: Element) -> None: self.curfilestack.pop() self.footnotestack.pop() - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: txt = self.escape_arg(node.astext()) self.body.append('\n\n@center %s\n\n' % txt) raise nodes.SkipNode - def visit_seealso(self, node): - # type: (nodes.Element) -> None + def visit_seealso(self, node: Element) -> None: self.body.append('\n\n@subsubheading %s\n\n' % admonitionlabels['seealso']) - def depart_seealso(self, node): - # type: (nodes.Element) -> None + def depart_seealso(self, node: Element) -> None: self.body.append('\n') - def visit_meta(self, node): - # type: (nodes.Element) -> None + def visit_meta(self, node: Element) -> None: raise nodes.SkipNode - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: bullet_list = cast(nodes.bullet_list, node[0]) list_items = cast(Iterable[nodes.list_item], bullet_list) self.body.append('\n\n') @@ -1548,19 +1365,16 @@ class TexinfoTranslator(SphinxTranslator): # -- Desc - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: self.desc = node self.at_deffnx = '@deffn' - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: self.desc = None self.ensure_eol() self.body.append('@end deffn\n') - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: self.escape_hyphens += 1 objtype = node.parent['objtype'] if objtype != 'describe': @@ -1580,55 +1394,43 @@ class TexinfoTranslator(SphinxTranslator): self.at_deffnx = '@deffnx' self.desc_type_name = name - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: self.body.append("\n") self.escape_hyphens -= 1 self.desc_type_name = None - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: pass - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: pass - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: pass - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: pass - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.body.append(' -> ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: pass - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: self.body.append(' (') self.first_param = 1 - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: self.body.append(')') - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if not self.first_param: self.body.append(', ') else: @@ -1639,16 +1441,13 @@ class TexinfoTranslator(SphinxTranslator): self.body.append(text) raise nodes.SkipNode - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.body.append('[') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.body.append(']') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: # Try to avoid duplicating info already displayed by the deffn category. # e.g. # @deffn {Class} Foo @@ -1660,28 +1459,22 @@ class TexinfoTranslator(SphinxTranslator): txt in self.desc_type_name.split(): raise nodes.SkipNode - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: pass - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: pass - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: pass - def visit_inline(self, node): - # type: (nodes.Element) -> None + def visit_inline(self, node: Element) -> None: pass - def depart_inline(self, node): - # type: (nodes.Element) -> None + def depart_inline(self, node: Element) -> None: pass - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: abbr = node.astext() self.body.append('@abbr{') if node.hasattr('explanation') and abbr not in self.handled_abbrs: @@ -1690,69 +1483,54 @@ class TexinfoTranslator(SphinxTranslator): else: self.context.append('}') - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: self.body.append(self.context.pop()) - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: return self.visit_literal_emphasis(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: return self.depart_literal_emphasis(node) - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: pass - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: pass - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: self.visit_bullet_list(node) - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: self.depart_bullet_list(node) - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: pass - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: pass - def visit_pending_xref(self, node): - # type: (nodes.Element) -> None + def visit_pending_xref(self, node: Element) -> None: pass - def depart_pending_xref(self, node): - # type: (nodes.Element) -> None + def depart_pending_xref(self, node: Element) -> None: pass - def visit_math(self, node): - # type: (nodes.Element) -> None + def visit_math(self, node: Element) -> None: self.body.append('@math{' + self.escape_arg(node.astext()) + '}') raise nodes.SkipNode - def visit_math_block(self, node): - # type: (nodes.Element) -> None + def visit_math_block(self, node: Element) -> None: if node.get('label'): self.add_anchor(node['label'], node) self.body.append('\n\n@example\n%s\n@end example\n\n' % self.escape_arg(node.astext())) raise nodes.SkipNode - def _make_visit_admonition(name): # type: ignore - # type: (str) -> Callable[[TexinfoTranslator, nodes.Element], None] + def _make_visit_admonition(name: str) -> Callable[["TexinfoTranslator", Element], None]: # type: ignore # NOQA warnings.warn('TexinfoTranslator._make_visit_admonition() is deprecated.', RemovedInSphinx30Warning) - def visit(self, node): - # type: (TexinfoTranslator, nodes.Element) -> None + def visit(self: "TexinfoTranslator", node: Element) -> None: self.visit_admonition(node, admonitionlabels[name]) return visit From d9def518723fa76428b0f1ec19f50b4a4004c7b3 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 21 Aug 2019 00:58:20 +0900 Subject: [PATCH 19/28] Migrate to py3 style type annotation: sphinx.writers.manpage --- sphinx/writers/manpage.py | 261 +++++++++++++------------------------- 1 file changed, 88 insertions(+), 173 deletions(-) diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 7811ccc5b..c9ae41609 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -9,9 +9,11 @@ """ import warnings -from typing import Iterable, cast +from typing import Any, Dict, Iterable +from typing import cast from docutils import nodes +from docutils.nodes import Element, Node, TextElement from docutils.writers.manpage import ( Writer, Translator as BaseTranslator @@ -26,21 +28,16 @@ from sphinx.util.docutils import SphinxTranslator from sphinx.util.i18n import format_date from sphinx.util.nodes import NodeMatcher -if False: - # For type annotation - from typing import Any, Dict # NOQA logger = logging.getLogger(__name__) class ManualPageWriter(Writer): - def __init__(self, builder): - # type: (Builder) -> None + def __init__(self, builder: Builder) -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: transform = NestedInlineTransform(self.document) transform.apply() visitor = self.builder.create_translator(self.document, self.builder) @@ -60,14 +57,12 @@ class NestedInlineTransform: foo=var &bar=2 """ - def __init__(self, document): - # type: (nodes.document) -> None + def __init__(self, document: nodes.document) -> None: self.document = document - def apply(self, **kwargs): - # type: (Any) -> None + def apply(self, **kwargs) -> None: matcher = NodeMatcher(nodes.literal, nodes.emphasis, nodes.strong) - for node in self.document.traverse(matcher): # type: nodes.TextElement + for node in self.document.traverse(matcher): # type: TextElement if any(matcher(subnode) for subnode in node): pos = node.parent.index(node) for subnode in reversed(node[1:]): @@ -86,8 +81,7 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): _docinfo = {} # type: Dict[str, Any] - def __init__(self, *args): - # type: (Any) -> None + def __init__(self, *args) -> None: if isinstance(args[0], nodes.document) and isinstance(args[1], Builder): document, builder = args else: @@ -126,153 +120,120 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): self.language.labels[label] = self.deunicode(translation) # type: ignore # overwritten -- added quotes around all .TH arguments - def header(self): - # type: () -> str + def header(self) -> str: tmpl = (".TH \"%(title_upper)s\" \"%(manual_section)s\"" " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n" ".SH NAME\n" "%(title)s \\- %(subtitle)s\n") return tmpl % self._docinfo - def visit_start_of_file(self, node): - # type: (nodes.Element) -> None + def visit_start_of_file(self, node: Element) -> None: pass - def depart_start_of_file(self, node): - # type: (nodes.Element) -> None + def depart_start_of_file(self, node: Element) -> None: pass - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: self.visit_definition_list(node) - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: self.depart_definition_list(node) - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: self.visit_definition_list_item(node) self.visit_term(node) - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: self.depart_term(node) - def visit_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature_line(self, node: Element) -> None: pass - def depart_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature_line(self, node: Element) -> None: self.body.append(' ') - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: pass - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: pass - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.body.append(' -> ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: pass - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: pass - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: pass - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: self.body.append('(') self.first_param = 1 - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: self.body.append(')') - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if not self.first_param: self.body.append(', ') else: self.first_param = 0 - def depart_desc_parameter(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameter(self, node: Element) -> None: pass - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.body.append('[') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.body.append(']') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: pass - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: pass - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: self.visit_definition(node) - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: self.depart_definition(node) - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: self.visit_paragraph(node) - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: self.depart_paragraph(node) # overwritten -- don't make whole of term bold if it includes strong node - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: if node.traverse(nodes.strong): self.body.append('\n') else: super().visit_term(node) # overwritten -- we don't want source comments to show up - def visit_comment(self, node): # type: ignore - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: # type: ignore raise nodes.SkipNode # overwritten -- added ensure_eol() - def visit_footnote(self, node): - # type: (nodes.Element) -> None + def visit_footnote(self, node: Element) -> None: self.ensure_eol() super().visit_footnote(node) # overwritten -- handle footnotes rubric - def visit_rubric(self, node): - # type: (nodes.Element) -> None + def visit_rubric(self, node: Element) -> None: self.ensure_eol() if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')): self.body.append('.SH ' + self.deunicode(node.astext()).upper() + '\n') @@ -280,20 +241,16 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): else: self.body.append('.sp\n') - def depart_rubric(self, node): - # type: (nodes.Element) -> None + def depart_rubric(self, node: Element) -> None: self.body.append('\n') - def visit_seealso(self, node): - # type: (nodes.Element) -> None + def visit_seealso(self, node: Element) -> None: self.visit_admonition(node, 'seealso') - def depart_seealso(self, node): - # type: (nodes.Element) -> None + def depart_seealso(self, node: Element) -> None: self.depart_admonition(node) - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.ensure_eol() names = [] self.in_productionlist += 1 @@ -318,25 +275,21 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): self.in_productionlist -= 1 raise nodes.SkipNode - def visit_production(self, node): - # type: (nodes.Element) -> None + def visit_production(self, node: Element) -> None: pass - def depart_production(self, node): - # type: (nodes.Element) -> None + def depart_production(self, node: Element) -> None: pass # overwritten -- don't emit a warning for images - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: if 'alt' in node.attributes: self.body.append(_('[image: %s]') % node['alt'] + '\n') self.body.append(_('[image]') + '\n') raise nodes.SkipNode # overwritten -- don't visit inner marked up nodes - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: self.body.append(self.defs['reference'][0]) # avoid repeating escaping code... fine since # visit_Text calls astext() and only works on that afterwards @@ -357,59 +310,46 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): '>']) raise nodes.SkipNode - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: text = nodes.Text(node.get('title', '#')) self.visit_Text(text) raise nodes.SkipNode - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: self.ensure_eol() self.body.append('.sp\n.ce\n') - def depart_centered(self, node): - # type: (nodes.Element) -> None + def depart_centered(self, node: Element) -> None: self.body.append('\n.ce 0\n') - def visit_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_compact_paragraph(self, node: Element) -> None: pass - def depart_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_compact_paragraph(self, node: Element) -> None: pass - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: pass - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: pass - def visit_toctree(self, node): - # type: (nodes.Element) -> None + def visit_toctree(self, node: Element) -> None: raise nodes.SkipNode - def visit_index(self, node): - # type: (nodes.Element) -> None + def visit_index(self, node: Element) -> None: raise nodes.SkipNode - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: raise nodes.SkipNode - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: bullet_list = cast(nodes.bullet_list, node[0]) list_items = cast(Iterable[nodes.list_item], bullet_list) self.ensure_eol() @@ -419,72 +359,57 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): self.body.append('\n') raise nodes.SkipNode - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: self.visit_bullet_list(node) - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: self.depart_bullet_list(node) - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: pass - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: pass - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: return self.visit_emphasis(node) - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: return self.depart_emphasis(node) - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: return self.visit_strong(node) - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: return self.depart_strong(node) - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: pass - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: pass - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: return self.visit_strong(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: return self.depart_strong(node) # overwritten: handle section titles better than in 0.6 release - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'): self.body.append('.sp\n') else: super().visit_caption(node) - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'): self.body.append('\n') else: super().depart_caption(node) # overwritten: handle section titles better than in 0.6 release - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: if isinstance(node.parent, addnodes.seealso): self.body.append('.IP "') return @@ -498,47 +423,37 @@ class ManualPageTranslator(SphinxTranslator, BaseTranslator): raise nodes.SkipNode return super().visit_title(node) - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: if isinstance(node.parent, addnodes.seealso): self.body.append('"\n') return return super().depart_title(node) - def visit_raw(self, node): - # type: (nodes.Element) -> None + def visit_raw(self, node: Element) -> None: if 'manpage' in node.get('format', '').split(): self.body.append(node.astext()) raise nodes.SkipNode - def visit_meta(self, node): - # type: (nodes.Element) -> None + def visit_meta(self, node: Element) -> None: raise nodes.SkipNode - def visit_inline(self, node): - # type: (nodes.Element) -> None + def visit_inline(self, node: Element) -> None: pass - def depart_inline(self, node): - # type: (nodes.Element) -> None + def depart_inline(self, node: Element) -> None: pass - def visit_math(self, node): - # type: (nodes.Element) -> None + def visit_math(self, node: Element) -> None: pass - def depart_math(self, node): - # type: (nodes.Element) -> None + def depart_math(self, node: Element) -> None: pass - def visit_math_block(self, node): - # type: (nodes.Element) -> None + def visit_math_block(self, node: Element) -> None: self.visit_centered(node) - def depart_math_block(self, node): - # type: (nodes.Element) -> None + def depart_math_block(self, node: Element) -> None: self.depart_centered(node) - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: raise NotImplementedError('Unknown node: ' + node.__class__.__name__) From 5466906c7b1ed24f0c138803fd141c5b9f995e6f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 21 Aug 2019 00:58:36 +0900 Subject: [PATCH 20/28] Migrate to py3 style type annotation: sphinx.writers.html5 --- sphinx/writers/html5.py | 374 ++++++++++++++-------------------------- 1 file changed, 127 insertions(+), 247 deletions(-) diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index e412ea167..26dc2e816 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -12,9 +12,11 @@ import os import posixpath import sys import warnings -from typing import Iterable, cast +from typing import cast +from typing import Iterable from docutils import nodes +from docutils.nodes import Element, Node, Text from docutils.writers.html5_polyglot import HTMLTranslator as BaseTranslator from sphinx import addnodes @@ -27,8 +29,7 @@ from sphinx.util.images import get_image_size if False: # For type annotation - from typing import Any # NOQA - from sphinx.builders.html import StandaloneHTMLBuilder # NOQA + from sphinx.builders.html import StandaloneHTMLBuilder logger = logging.getLogger(__name__) @@ -44,8 +45,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): builder = None # type: StandaloneHTMLBuilder - def __init__(self, *args): - # type: (Any) -> None + def __init__(self, *args) -> None: if isinstance(args[0], nodes.document) and isinstance(args[1], Builder): document, builder = args else: @@ -71,26 +71,21 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self._fieldlist_row_index = 0 self.required_params_left = 0 - def visit_start_of_file(self, node): - # type: (nodes.Element) -> None + def visit_start_of_file(self, node: Element) -> None: # only occurs in the single-file builder self.docnames.append(node['docname']) self.body.append('' % node['docname']) - def depart_start_of_file(self, node): - # type: (nodes.Element) -> None + def depart_start_of_file(self, node: Element) -> None: self.docnames.pop() - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: self.body.append(self.starttag(node, 'dl', CLASS=node['objtype'])) - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: self.body.append('\n\n') - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: # the id is set automatically self.body.append(self.starttag(node, 'dt')) # anchor for per-desc interactive data @@ -98,57 +93,45 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): and node['ids'] and node['first']: self.body.append('' % node['ids'][0]) - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: if not node.get('is_multiline'): self.add_permalink_ref(node, _('Permalink to this definition')) self.body.append('\n') - def visit_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature_line(self, node: Element) -> None: pass - def depart_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature_line(self, node: Element) -> None: if node.get('add_permalink'): # the permalink info is on the parent desc_signature node self.add_permalink_ref(node.parent, _('Permalink to this definition')) self.body.append('
') - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: self.body.append(self.starttag(node, 'code', '', CLASS='sig-prename descclassname')) - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: self.body.append('') - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.body.append(' → ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: pass - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: self.body.append(self.starttag(node, 'code', '', CLASS='sig-name descname')) - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: self.body.append('') - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: self.body.append('(') self.first_param = 1 self.optional_param_level = 0 @@ -157,8 +140,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): for c in node.children]) self.param_separator = node.child_text_separator - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: self.body.append(')') # If required parameters are still to come, then put the comma after @@ -167,8 +149,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): # # foo([a, ]b, c[, d]) # - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if self.first_param: self.first_param = 0 elif not self.required_params_left: @@ -178,50 +159,40 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): if not node.hasattr('noemph'): self.body.append('') - def depart_desc_parameter(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameter(self, node: Element) -> None: if not node.hasattr('noemph'): self.body.append('') if self.required_params_left: self.body.append(self.param_separator) - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.optional_param_level += 1 self.body.append('[') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.optional_param_level -= 1 self.body.append(']') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: self.body.append(self.starttag(node, 'em', '', CLASS='property')) - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: self.body.append('') - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: self.body.append(self.starttag(node, 'dd', '')) - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: self.body.append('') - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: self.body.append(self.starttag(node, 'div', CLASS=node['type'])) - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: self.body.append('\n') # overwritten - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: atts = {'class': 'reference'} if node.get('internal') or 'refuri' not in node: atts['class'] += ' internal' @@ -249,37 +220,30 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append(('%s' + self.secnumber_suffix) % '.'.join(map(str, node['secnumber']))) - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: self.visit_reference(node) - def depart_number_reference(self, node): - # type: (nodes.Element) -> None + def depart_number_reference(self, node: Element) -> None: self.depart_reference(node) # overwritten -- we don't want source comments to show up in the HTML - def visit_comment(self, node): # type: ignore - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: # type: ignore raise nodes.SkipNode # overwritten - def visit_admonition(self, node, name=''): - # type: (nodes.Element, str) -> None + def visit_admonition(self, node: Element, name: str = '') -> None: self.body.append(self.starttag( node, 'div', CLASS=('admonition ' + name))) if name: node.insert(0, nodes.title(name, admonitionlabels[name])) - def visit_seealso(self, node): - # type: (nodes.Element) -> None + def visit_seealso(self, node: Element) -> None: self.visit_admonition(node, 'seealso') - def depart_seealso(self, node): - # type: (nodes.Element) -> None + def depart_seealso(self, node: Element) -> None: self.depart_admonition(node) - def add_secnumber(self, node): - # type: (nodes.Element) -> None + def add_secnumber(self, node: Element) -> None: if node.get('secnumber'): self.body.append('.'.join(map(str, node['secnumber'])) + self.secnumber_suffix) @@ -298,10 +262,8 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append('.'.join(map(str, numbers)) + self.secnumber_suffix) - def add_fignumber(self, node): - # type: (nodes.Element) -> None - def append_fignumber(figtype, figure_id): - # type: (str, str) -> None + def add_fignumber(self, node: Element) -> None: + def append_fignumber(figtype: str, figure_id: str) -> None: if self.builder.name == 'singlehtml': key = "%s/%s" % (self.docnames[-1], figtype) else: @@ -326,55 +288,47 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): else: append_fignumber(figtype, node['ids'][0]) - def add_permalink_ref(self, node, title): - # type: (nodes.Element, str) -> None + def add_permalink_ref(self, node: Element, title: str) -> None: if node['ids'] and self.permalink_text and self.builder.add_permalinks: format = '%s' self.body.append(format % (node['ids'][0], title, self.permalink_text)) # overwritten - def visit_bullet_list(self, node): - # type: (nodes.Element) -> None + def visit_bullet_list(self, node: Element) -> None: if len(node) == 1 and isinstance(node[0], addnodes.toctree): # avoid emitting empty
    raise nodes.SkipNode super().visit_bullet_list(node) # overwritten - def visit_definition(self, node): - # type: (nodes.Element) -> None + def visit_definition(self, node: Element) -> None: # don't insert here. self.body.append(self.starttag(node, 'dd', '')) # overwritten - def depart_definition(self, node): - # type: (nodes.Element) -> None + def depart_definition(self, node: Element) -> None: self.body.append('\n') # overwritten - def visit_classifier(self, node): - # type: (nodes.Element) -> None + def visit_classifier(self, node: Element) -> None: self.body.append(self.starttag(node, 'span', '', CLASS='classifier')) # overwritten - def depart_classifier(self, node): - # type: (nodes.Element) -> None + def depart_classifier(self, node: Element) -> None: self.body.append('') - next_node = node.next_node(descend=False, siblings=True) # type: nodes.Node + next_node = node.next_node(descend=False, siblings=True) # type: Node if not isinstance(next_node, nodes.classifier): # close `
    ` tag at the tail of classifiers self.body.append('
    ') # overwritten - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: self.body.append(self.starttag(node, 'dt', '')) # overwritten - def depart_term(self, node): - # type: (nodes.Element) -> None - next_node = node.next_node(descend=False, siblings=True) # type: nodes.Node + def depart_term(self, node: Element) -> None: + next_node = node.next_node(descend=False, siblings=True) # type: Node if isinstance(next_node, nodes.classifier): # Leave the end tag to `self.depart_classifier()`, in case # there's a classifier. @@ -383,16 +337,14 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append('') # overwritten - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: super().visit_title(node) self.add_secnumber(node) self.add_fignumber(node.parent) if isinstance(node.parent, nodes.table): self.body.append('') - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: close_tag = self.context[-1] if (self.permalink_text and self.builder.add_permalinks and node.parent.hasattr('ids') and node.parent['ids']): @@ -414,8 +366,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): super().depart_title(node) # overwritten - def visit_literal_block(self, node): - # type: (nodes.Element) -> None + def visit_literal_block(self, node: Element) -> None: if node.rawsource != node.astext(): # most probably a parsed-literal block -- don't highlight return super().visit_literal_block(node) @@ -439,8 +390,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append(starttag + highlighted + '\n') raise nodes.SkipNode - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'): self.body.append('
    ') else: @@ -448,8 +398,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.add_fignumber(node.parent) self.body.append(self.starttag(node, 'span', '', CLASS='caption-text')) - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: self.body.append('') # append permalink if available @@ -465,22 +414,18 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): else: super().depart_caption(node) - def visit_doctest_block(self, node): - # type: (nodes.Element) -> None + def visit_doctest_block(self, node: Element) -> None: self.visit_literal_block(node) # overwritten to add the
    (for XHTML compliance) - def visit_block_quote(self, node): - # type: (nodes.Element) -> None + def visit_block_quote(self, node: Element) -> None: self.body.append(self.starttag(node, 'blockquote') + '
    ') - def depart_block_quote(self, node): - # type: (nodes.Element) -> None + def depart_block_quote(self, node: Element) -> None: self.body.append('
    \n') # overwritten - def visit_literal(self, node): - # type: (nodes.Element) -> None + def visit_literal(self, node: Element) -> None: if 'kbd' in node['classes']: self.body.append(self.starttag(node, 'kbd', '', CLASS='docutils literal notranslate')) @@ -489,16 +434,14 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): CLASS='docutils literal notranslate')) self.protect_literal_text += 1 - def depart_literal(self, node): - # type: (nodes.Element) -> None + def depart_literal(self, node: Element) -> None: if 'kbd' in node['classes']: self.body.append('') else: self.protect_literal_text -= 1 self.body.append('') - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.body.append(self.starttag(node, 'pre')) names = [] productionlist = cast(Iterable[addnodes.production], node) @@ -518,37 +461,29 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append('\n') raise nodes.SkipNode - def depart_productionlist(self, node): - # type: (nodes.Element) -> None + def depart_productionlist(self, node: Element) -> None: pass - def visit_production(self, node): - # type: (nodes.Element) -> None + def visit_production(self, node: Element) -> None: pass - def depart_production(self, node): - # type: (nodes.Element) -> None + def depart_production(self, node: Element) -> None: pass - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: self.body.append(self.starttag(node, 'p', CLASS="centered") + '') - def depart_centered(self, node): - # type: (nodes.Element) -> None + def depart_centered(self, node: Element) -> None: self.body.append('

    ') - def visit_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_compact_paragraph(self, node: Element) -> None: pass - def depart_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_compact_paragraph(self, node: Element) -> None: pass - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: atts = {'class': 'reference download', 'download': ''} @@ -567,13 +502,11 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): else: self.context.append('') - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: self.body.append(self.context.pop()) # overwritten - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: olduri = node['uri'] # rewrite the URI if the environment knows about it if olduri in self.builder.images: @@ -614,62 +547,49 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): super().visit_image(node) # overwritten - def depart_image(self, node): - # type: (nodes.Element) -> None + def depart_image(self, node: Element) -> None: if node['uri'].lower().endswith(('svg', 'svgz')): self.body.append(self.context.pop()) else: super().depart_image(node) - def visit_toctree(self, node): - # type: (nodes.Element) -> None + def visit_toctree(self, node: Element) -> None: # this only happens when formatting a toc from env.tocs -- in this # case we don't want to include the subtree raise nodes.SkipNode - def visit_index(self, node): - # type: (nodes.Element) -> None + def visit_index(self, node: Element) -> None: raise nodes.SkipNode - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: raise nodes.SkipNode - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: pass - def depart_acks(self, node): - # type: (nodes.Element) -> None + def depart_acks(self, node: Element) -> None: pass - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: self.body.append('') - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: self.body.append('
    \n') - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: self.body.append('') - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: self.body.append('') # overwritten - def visit_Text(self, node): - # type: (nodes.Text) -> None + def visit_Text(self, node: Text) -> None: text = node.astext() encoded = self.encode(text) if self.protect_literal_text: @@ -690,122 +610,95 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): encoded = self.cloak_email(encoded) self.body.append(encoded) - def visit_note(self, node): - # type: (nodes.Element) -> None + def visit_note(self, node: Element) -> None: self.visit_admonition(node, 'note') - def depart_note(self, node): - # type: (nodes.Element) -> None + def depart_note(self, node: Element) -> None: self.depart_admonition(node) - def visit_warning(self, node): - # type: (nodes.Element) -> None + def visit_warning(self, node: Element) -> None: self.visit_admonition(node, 'warning') - def depart_warning(self, node): - # type: (nodes.Element) -> None + def depart_warning(self, node: Element) -> None: self.depart_admonition(node) - def visit_attention(self, node): - # type: (nodes.Element) -> None + def visit_attention(self, node: Element) -> None: self.visit_admonition(node, 'attention') - def depart_attention(self, node): - # type: (nodes.Element) -> None + def depart_attention(self, node: Element) -> None: self.depart_admonition(node) - def visit_caution(self, node): - # type: (nodes.Element) -> None + def visit_caution(self, node: Element) -> None: self.visit_admonition(node, 'caution') - def depart_caution(self, node): - # type: (nodes.Element) -> None + def depart_caution(self, node: Element) -> None: self.depart_admonition(node) - def visit_danger(self, node): - # type: (nodes.Element) -> None + def visit_danger(self, node: Element) -> None: self.visit_admonition(node, 'danger') - def depart_danger(self, node): - # type: (nodes.Element) -> None + def depart_danger(self, node: Element) -> None: self.depart_admonition(node) - def visit_error(self, node): - # type: (nodes.Element) -> None + def visit_error(self, node: Element) -> None: self.visit_admonition(node, 'error') - def depart_error(self, node): - # type: (nodes.Element) -> None + def depart_error(self, node: Element) -> None: self.depart_admonition(node) - def visit_hint(self, node): - # type: (nodes.Element) -> None + def visit_hint(self, node: Element) -> None: self.visit_admonition(node, 'hint') - def depart_hint(self, node): - # type: (nodes.Element) -> None + def depart_hint(self, node: Element) -> None: self.depart_admonition(node) - def visit_important(self, node): - # type: (nodes.Element) -> None + def visit_important(self, node: Element) -> None: self.visit_admonition(node, 'important') - def depart_important(self, node): - # type: (nodes.Element) -> None + def depart_important(self, node: Element) -> None: self.depart_admonition(node) - def visit_tip(self, node): - # type: (nodes.Element) -> None + def visit_tip(self, node: Element) -> None: self.visit_admonition(node, 'tip') - def depart_tip(self, node): - # type: (nodes.Element) -> None + def depart_tip(self, node: Element) -> None: self.depart_admonition(node) - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: return self.visit_emphasis(node) - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: return self.depart_emphasis(node) - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: return self.visit_strong(node) - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: return self.depart_strong(node) - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: attrs = {} if node.hasattr('explanation'): attrs['title'] = node['explanation'] self.body.append(self.starttag(node, 'abbr', '', **attrs)) - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: self.body.append('') - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: self.visit_literal_emphasis(node) if self.manpages_url: node['refuri'] = self.manpages_url.format(**node.attributes) self.visit_reference(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: if self.manpages_url: self.depart_reference(node) self.depart_literal_emphasis(node) # overwritten to add even/odd classes - def generate_targets_for_table(self, node): - # type: (nodes.Element) -> None + def generate_targets_for_table(self, node: Element) -> None: """Generate hyperlink targets for tables. Original visit_table() generates hyperlink targets inside table tags @@ -818,8 +711,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append('' % id) node['ids'].remove(id) - def visit_table(self, node): - # type: (nodes.Element) -> None + def visit_table(self, node: Element) -> None: self.generate_targets_for_table(node) self._table_row_index = 0 @@ -831,8 +723,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): tag = self.starttag(node, 'table', CLASS=' '.join(classes)) self.body.append(tag) - def visit_row(self, node): - # type: (nodes.Element) -> None + def visit_row(self, node: Element) -> None: self._table_row_index += 1 if self._table_row_index % 2 == 0: node['classes'].append('row-even') @@ -841,75 +732,64 @@ class HTML5Translator(SphinxTranslator, BaseTranslator): self.body.append(self.starttag(node, 'tr', '')) node.column = 0 # type: ignore - def visit_field_list(self, node): - # type: (nodes.Element) -> None + def visit_field_list(self, node: Element) -> None: self._fieldlist_row_index = 0 return super().visit_field_list(node) - def visit_field(self, node): - # type: (nodes.Element) -> None + def visit_field(self, node: Element) -> None: self._fieldlist_row_index += 1 if self._fieldlist_row_index % 2 == 0: node['classes'].append('field-even') else: node['classes'].append('field-odd') - def visit_math(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def visit_math(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name visit, _ = self.builder.app.registry.html_inline_math_renderers[name] visit(self, node) - def depart_math(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def depart_math(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name _, depart = self.builder.app.registry.html_inline_math_renderers[name] if depart: depart(self, node) - def visit_math_block(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def visit_math_block(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name visit, _ = self.builder.app.registry.html_block_math_renderers[name] visit(self, node) - def depart_math_block(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def depart_math_block(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name _, depart = self.builder.app.registry.html_block_math_renderers[name] if depart: depart(self, node) - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: raise NotImplementedError('Unknown node: ' + node.__class__.__name__) # --------- METHODS FOR COMPATIBILITY -------------------------------------- @property - def highlightlang(self): - # type: () -> str + def highlightlang(self) -> str: warnings.warn('HTMLTranslator.highlightlang is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return self.builder.config.highlight_language @property - def highlightlang_base(self): - # type: () -> str + def highlightlang_base(self) -> str: warnings.warn('HTMLTranslator.highlightlang_base is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return self.builder.config.highlight_language @property - def highlightopts(self): - # type: () -> str + def highlightopts(self) -> str: warnings.warn('HTMLTranslator.highlightopts is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return self.builder.config.highlight_options @property - def highlightlinenothreshold(self): - # type: () -> int + def highlightlinenothreshold(self) -> int: warnings.warn('HTMLTranslator.highlightlinenothreshold is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return sys.maxsize From ab1369a837c0e0868928c9c71fb00b0d2b64b075 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 14 Oct 2019 18:37:23 +0900 Subject: [PATCH 21/28] Migrate to py3 style type annotation: sphinx.writers.html --- sphinx/writers/html.py | 395 ++++++++++++++--------------------------- 1 file changed, 134 insertions(+), 261 deletions(-) diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 381457926..d283398f0 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -13,9 +13,11 @@ import os import posixpath import sys import warnings -from typing import Iterable, cast +from typing import cast +from typing import Iterable from docutils import nodes +from docutils.nodes import Element, Node, Text from docutils.writers.html4css1 import Writer, HTMLTranslator as BaseTranslator from sphinx import addnodes @@ -28,8 +30,7 @@ from sphinx.util.images import get_image_size if False: # For type annotation - from typing import Any # NOQA - from sphinx.builders.html import StandaloneHTMLBuilder # NOQA + from sphinx.builders.html import StandaloneHTMLBuilder logger = logging.getLogger(__name__) @@ -46,13 +47,11 @@ class HTMLWriter(Writer): if '--embed-stylesheet' in _setting[1]: _setting[2]['default'] = 0 - def __init__(self, builder): - # type: (StandaloneHTMLBuilder) -> None + def __init__(self, builder: "StandaloneHTMLBuilder") -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: # sadly, this is mostly copied from parent class visitor = self.builder.create_translator(self.document, self.builder) self.visitor = cast(HTMLTranslator, visitor) @@ -74,8 +73,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): builder = None # type: StandaloneHTMLBuilder - def __init__(self, *args): - # type: (Any) -> None + def __init__(self, *args) -> None: if isinstance(args[0], nodes.document) and isinstance(args[1], Builder): document, builder = args else: @@ -101,26 +99,21 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self._fieldlist_row_index = 0 self.required_params_left = 0 - def visit_start_of_file(self, node): - # type: (nodes.Element) -> None + def visit_start_of_file(self, node: Element) -> None: # only occurs in the single-file builder self.docnames.append(node['docname']) self.body.append('' % node['docname']) - def depart_start_of_file(self, node): - # type: (nodes.Element) -> None + def depart_start_of_file(self, node: Element) -> None: self.docnames.pop() - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: self.body.append(self.starttag(node, 'dl', CLASS=node['objtype'])) - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: self.body.append('\n\n') - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: # the id is set automatically self.body.append(self.starttag(node, 'dt')) # anchor for per-desc interactive data @@ -128,57 +121,45 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): and node['ids'] and node['first']: self.body.append('' % node['ids'][0]) - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: if not node.get('is_multiline'): self.add_permalink_ref(node, _('Permalink to this definition')) self.body.append('\n') - def visit_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature_line(self, node: Element) -> None: pass - def depart_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature_line(self, node: Element) -> None: if node.get('add_permalink'): # the permalink info is on the parent desc_signature node self.add_permalink_ref(node.parent, _('Permalink to this definition')) self.body.append('
    ') - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: self.body.append(self.starttag(node, 'code', '', CLASS='descclassname')) - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: self.body.append('') - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.body.append(' → ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: pass - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: self.body.append(self.starttag(node, 'code', '', CLASS='descname')) - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: self.body.append('') - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: self.body.append('(') self.first_param = 1 self.optional_param_level = 0 @@ -187,8 +168,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): for c in node.children]) self.param_separator = node.child_text_separator - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: self.body.append(')') # If required parameters are still to come, then put the comma after @@ -197,8 +177,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): # # foo([a, ]b, c[, d]) # - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if self.first_param: self.first_param = 0 elif not self.required_params_left: @@ -208,50 +187,40 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): if not node.hasattr('noemph'): self.body.append('') - def depart_desc_parameter(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameter(self, node: Element) -> None: if not node.hasattr('noemph'): self.body.append('') if self.required_params_left: self.body.append(self.param_separator) - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.optional_param_level += 1 self.body.append('[') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.optional_param_level -= 1 self.body.append(']') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: self.body.append(self.starttag(node, 'em', '', CLASS='property')) - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: self.body.append('') - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: self.body.append(self.starttag(node, 'dd', '')) - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: self.body.append('') - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: self.body.append(self.starttag(node, 'div', CLASS=node['type'])) - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: self.body.append('
    \n') # overwritten - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: atts = {'class': 'reference'} if node.get('internal') or 'refuri' not in node: atts['class'] += ' internal' @@ -279,38 +248,31 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append(('%s' + self.secnumber_suffix) % '.'.join(map(str, node['secnumber']))) - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: self.visit_reference(node) - def depart_number_reference(self, node): - # type: (nodes.Element) -> None + def depart_number_reference(self, node: Element) -> None: self.depart_reference(node) # overwritten -- we don't want source comments to show up in the HTML - def visit_comment(self, node): # type: ignore - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: # type: ignore raise nodes.SkipNode # overwritten - def visit_admonition(self, node, name=''): - # type: (nodes.Element, str) -> None + def visit_admonition(self, node: Element, name: str = '') -> None: self.body.append(self.starttag( node, 'div', CLASS=('admonition ' + name))) if name: node.insert(0, nodes.title(name, admonitionlabels[name])) self.set_first_last(node) - def visit_seealso(self, node): - # type: (nodes.Element) -> None + def visit_seealso(self, node: Element) -> None: self.visit_admonition(node, 'seealso') - def depart_seealso(self, node): - # type: (nodes.Element) -> None + def depart_seealso(self, node: Element) -> None: self.depart_admonition(node) - def add_secnumber(self, node): - # type: (nodes.Element) -> None + def add_secnumber(self, node: Element) -> None: if node.get('secnumber'): self.body.append('.'.join(map(str, node['secnumber'])) + self.secnumber_suffix) @@ -329,10 +291,8 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append('.'.join(map(str, numbers)) + self.secnumber_suffix) - def add_fignumber(self, node): - # type: (nodes.Element) -> None - def append_fignumber(figtype, figure_id): - # type: (str, str) -> None + def add_fignumber(self, node: Element) -> None: + def append_fignumber(figtype: str, figure_id: str) -> None: if self.builder.name == 'singlehtml': key = "%s/%s" % (self.docnames[-1], figtype) else: @@ -357,14 +317,12 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): else: append_fignumber(figtype, node['ids'][0]) - def add_permalink_ref(self, node, title): - # type: (nodes.Element, str) -> None + def add_permalink_ref(self, node: Element, title: str) -> None: if node['ids'] and self.permalink_text and self.builder.add_permalinks: format = '%s' self.body.append(format % (node['ids'][0], title, self.permalink_text)) - def generate_targets_for_listing(self, node): - # type: (nodes.Element) -> None + def generate_targets_for_listing(self, node: Element) -> None: """Generate hyperlink targets for listings. Original visit_bullet_list(), visit_definition_list() and visit_enumerated_list() @@ -379,8 +337,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): node['ids'].remove(id) # overwritten - def visit_bullet_list(self, node): - # type: (nodes.Element) -> None + def visit_bullet_list(self, node: Element) -> None: if len(node) == 1 and isinstance(node[0], addnodes.toctree): # avoid emitting empty
      raise nodes.SkipNode @@ -388,46 +345,39 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): super().visit_bullet_list(node) # overwritten - def visit_enumerated_list(self, node): - # type: (nodes.Element) -> None + def visit_enumerated_list(self, node: Element) -> None: self.generate_targets_for_listing(node) super().visit_enumerated_list(node) # overwritten - def visit_definition(self, node): - # type: (nodes.Element) -> None + def visit_definition(self, node: Element) -> None: # don't insert here. self.body.append(self.starttag(node, 'dd', '')) # overwritten - def depart_definition(self, node): - # type: (nodes.Element) -> None + def depart_definition(self, node: Element) -> None: self.body.append('\n') # overwritten - def visit_classifier(self, node): - # type: (nodes.Element) -> None + def visit_classifier(self, node: Element) -> None: self.body.append(self.starttag(node, 'span', '', CLASS='classifier')) # overwritten - def depart_classifier(self, node): - # type: (nodes.Element) -> None + def depart_classifier(self, node: Element) -> None: self.body.append('') - next_node = node.next_node(descend=False, siblings=True) # type: nodes.Node + next_node = node.next_node(descend=False, siblings=True) # type: Node if not isinstance(next_node, nodes.classifier): # close `
      ` tag at the tail of classifiers self.body.append('
      ') # overwritten - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: self.body.append(self.starttag(node, 'dt', '')) # overwritten - def depart_term(self, node): - # type: (nodes.Element) -> None - next_node = node.next_node(descend=False, siblings=True) # type: nodes.Node + def depart_term(self, node: Element) -> None: + next_node = node.next_node(descend=False, siblings=True) # type: Node if isinstance(next_node, nodes.classifier): # Leave the end tag to `self.depart_classifier()`, in case # there's a classifier. @@ -436,16 +386,14 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append('') # overwritten - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: super().visit_title(node) self.add_secnumber(node) self.add_fignumber(node.parent) if isinstance(node.parent, nodes.table): self.body.append('') - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: close_tag = self.context[-1] if (self.permalink_text and self.builder.add_permalinks and node.parent.hasattr('ids') and node.parent['ids']): @@ -467,8 +415,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): super().depart_title(node) # overwritten - def visit_literal_block(self, node): - # type: (nodes.Element) -> None + def visit_literal_block(self, node: Element) -> None: if node.rawsource != node.astext(): # most probably a parsed-literal block -- don't highlight return super().visit_literal_block(node) @@ -492,8 +439,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append(starttag + highlighted + '
      \n') raise nodes.SkipNode - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: if isinstance(node.parent, nodes.container) and node.parent.get('literal_block'): self.body.append('
      ') else: @@ -501,8 +447,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.add_fignumber(node.parent) self.body.append(self.starttag(node, 'span', '', CLASS='caption-text')) - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: self.body.append('') # append permalink if available @@ -518,22 +463,18 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): else: super().depart_caption(node) - def visit_doctest_block(self, node): - # type: (nodes.Element) -> None + def visit_doctest_block(self, node: Element) -> None: self.visit_literal_block(node) # overwritten to add the
      (for XHTML compliance) - def visit_block_quote(self, node): - # type: (nodes.Element) -> None + def visit_block_quote(self, node: Element) -> None: self.body.append(self.starttag(node, 'blockquote') + '
      ') - def depart_block_quote(self, node): - # type: (nodes.Element) -> None + def depart_block_quote(self, node: Element) -> None: self.body.append('
      \n') # overwritten - def visit_literal(self, node): - # type: (nodes.Element) -> None + def visit_literal(self, node: Element) -> None: if 'kbd' in node['classes']: self.body.append(self.starttag(node, 'kbd', '', CLASS='docutils literal notranslate')) @@ -542,16 +483,14 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): CLASS='docutils literal notranslate')) self.protect_literal_text += 1 - def depart_literal(self, node): - # type: (nodes.Element) -> None + def depart_literal(self, node: Element) -> None: if 'kbd' in node['classes']: self.body.append('') else: self.protect_literal_text -= 1 self.body.append('') - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.body.append(self.starttag(node, 'pre')) names = [] productionlist = cast(Iterable[addnodes.production], node) @@ -571,30 +510,24 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append('\n') raise nodes.SkipNode - def depart_productionlist(self, node): - # type: (nodes.Element) -> None + def depart_productionlist(self, node: Element) -> None: pass - def visit_production(self, node): - # type: (nodes.Element) -> None + def visit_production(self, node: Element) -> None: pass - def depart_production(self, node): - # type: (nodes.Element) -> None + def depart_production(self, node: Element) -> None: pass - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: self.body.append(self.starttag(node, 'p', CLASS="centered") + '') - def depart_centered(self, node): - # type: (nodes.Element) -> None + def depart_centered(self, node: Element) -> None: self.body.append('

      ') # overwritten - def should_be_compact_paragraph(self, node): - # type: (nodes.Node) -> bool + def should_be_compact_paragraph(self, node: Node) -> bool: """Determine if the

      tags around paragraph can be omitted.""" if isinstance(node.parent, addnodes.desc_content): # Never compact desc_content items. @@ -604,16 +537,13 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): return False return super().should_be_compact_paragraph(node) - def visit_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_compact_paragraph(self, node: Element) -> None: pass - def depart_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_compact_paragraph(self, node: Element) -> None: pass - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: atts = {'class': 'reference download', 'download': ''} @@ -632,13 +562,11 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): else: self.context.append('') - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: self.body.append(self.context.pop()) # overwritten - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: olduri = node['uri'] # rewrite the URI if the environment knows about it if olduri in self.builder.images: @@ -679,67 +607,53 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): super().visit_image(node) # overwritten - def depart_image(self, node): - # type: (nodes.Element) -> None + def depart_image(self, node: Element) -> None: if node['uri'].lower().endswith(('svg', 'svgz')): self.body.append(self.context.pop()) else: super().depart_image(node) - def visit_toctree(self, node): - # type: (nodes.Element) -> None + def visit_toctree(self, node: Element) -> None: # this only happens when formatting a toc from env.tocs -- in this # case we don't want to include the subtree raise nodes.SkipNode - def visit_index(self, node): - # type: (nodes.Element) -> None + def visit_index(self, node: Element) -> None: raise nodes.SkipNode - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: raise nodes.SkipNode - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: pass - def depart_acks(self, node): - # type: (nodes.Element) -> None + def depart_acks(self, node: Element) -> None: pass - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: self.body.append('') - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: self.body.append('
      \n') - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: self.body.append('') - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: self.body.append('') - def visit_option_group(self, node): - # type: (nodes.Element) -> None + def visit_option_group(self, node: Element) -> None: super().visit_option_group(node) self.context[-2] = self.context[-2].replace(' ', ' ') # overwritten - def visit_Text(self, node): - # type: (nodes.Text) -> None + def visit_Text(self, node: Text) -> None: text = node.astext() encoded = self.encode(text) if self.protect_literal_text: @@ -760,127 +674,99 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): encoded = self.cloak_email(encoded) self.body.append(encoded) - def visit_note(self, node): - # type: (nodes.Element) -> None + def visit_note(self, node: Element) -> None: self.visit_admonition(node, 'note') - def depart_note(self, node): - # type: (nodes.Element) -> None + def depart_note(self, node: Element) -> None: self.depart_admonition(node) - def visit_warning(self, node): - # type: (nodes.Element) -> None + def visit_warning(self, node: Element) -> None: self.visit_admonition(node, 'warning') - def depart_warning(self, node): - # type: (nodes.Element) -> None + def depart_warning(self, node: Element) -> None: self.depart_admonition(node) - def visit_attention(self, node): - # type: (nodes.Element) -> None + def visit_attention(self, node: Element) -> None: self.visit_admonition(node, 'attention') - def depart_attention(self, node): - # type: (nodes.Element) -> None + def depart_attention(self, node: Element) -> None: self.depart_admonition(node) - def visit_caution(self, node): - # type: (nodes.Element) -> None + def visit_caution(self, node: Element) -> None: self.visit_admonition(node, 'caution') - def depart_caution(self, node): - # type: (nodes.Element) -> None + def depart_caution(self, node: Element) -> None: self.depart_admonition(node) - def visit_danger(self, node): - # type: (nodes.Element) -> None + def visit_danger(self, node: Element) -> None: self.visit_admonition(node, 'danger') - def depart_danger(self, node): - # type: (nodes.Element) -> None + def depart_danger(self, node: Element) -> None: self.depart_admonition(node) - def visit_error(self, node): - # type: (nodes.Element) -> None + def visit_error(self, node: Element) -> None: self.visit_admonition(node, 'error') - def depart_error(self, node): - # type: (nodes.Element) -> None + def depart_error(self, node: Element) -> None: self.depart_admonition(node) - def visit_hint(self, node): - # type: (nodes.Element) -> None + def visit_hint(self, node: Element) -> None: self.visit_admonition(node, 'hint') - def depart_hint(self, node): - # type: (nodes.Element) -> None + def depart_hint(self, node: Element) -> None: self.depart_admonition(node) - def visit_important(self, node): - # type: (nodes.Element) -> None + def visit_important(self, node: Element) -> None: self.visit_admonition(node, 'important') - def depart_important(self, node): - # type: (nodes.Element) -> None + def depart_important(self, node: Element) -> None: self.depart_admonition(node) - def visit_tip(self, node): - # type: (nodes.Element) -> None + def visit_tip(self, node: Element) -> None: self.visit_admonition(node, 'tip') - def depart_tip(self, node): - # type: (nodes.Element) -> None + def depart_tip(self, node: Element) -> None: self.depart_admonition(node) - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: return self.visit_emphasis(node) - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: return self.depart_emphasis(node) - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: return self.visit_strong(node) - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: return self.depart_strong(node) - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: attrs = {} if node.hasattr('explanation'): attrs['title'] = node['explanation'] self.body.append(self.starttag(node, 'abbr', '', **attrs)) - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: self.body.append('') - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: self.visit_literal_emphasis(node) if self.manpages_url: node['refuri'] = self.manpages_url.format(**node.attributes) self.visit_reference(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: if self.manpages_url: self.depart_reference(node) self.depart_literal_emphasis(node) # overwritten to add even/odd classes - def visit_table(self, node): - # type: (nodes.Element) -> None + def visit_table(self, node: Element) -> None: self._table_row_index = 0 return super().visit_table(node) - def visit_row(self, node): - # type: (nodes.Element) -> None + def visit_row(self, node: Element) -> None: self._table_row_index += 1 if self._table_row_index % 2 == 0: node['classes'].append('row-even') @@ -889,19 +775,16 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): self.body.append(self.starttag(node, 'tr', '')) node.column = 0 # type: ignore - def visit_entry(self, node): - # type: (nodes.Element) -> None + def visit_entry(self, node: Element) -> None: super().visit_entry(node) if self.body[-1] == ' ': self.body[-1] = ' ' - def visit_field_list(self, node): - # type: (nodes.Element) -> None + def visit_field_list(self, node: Element) -> None: self._fieldlist_row_index = 0 return super().visit_field_list(node) - def visit_field(self, node): - # type: (nodes.Element) -> None + def visit_field(self, node: Element) -> None: self._fieldlist_row_index += 1 if self._fieldlist_row_index % 2 == 0: node['classes'].append('field-even') @@ -909,69 +792,59 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator): node['classes'].append('field-odd') self.body.append(self.starttag(node, 'tr', '', CLASS='field')) - def visit_field_name(self, node): - # type: (nodes.Element) -> None + def visit_field_name(self, node: Element) -> None: context_count = len(self.context) super().visit_field_name(node) if context_count != len(self.context): self.context[-1] = self.context[-1].replace(' ', ' ') - def visit_math(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def visit_math(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name visit, _ = self.builder.app.registry.html_inline_math_renderers[name] visit(self, node) - def depart_math(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def depart_math(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name _, depart = self.builder.app.registry.html_inline_math_renderers[name] if depart: depart(self, node) - def visit_math_block(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def visit_math_block(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name visit, _ = self.builder.app.registry.html_block_math_renderers[name] visit(self, node) - def depart_math_block(self, node, math_env=''): - # type: (nodes.Element, str) -> None + def depart_math_block(self, node: Element, math_env: str = '') -> None: name = self.builder.math_renderer_name _, depart = self.builder.app.registry.html_block_math_renderers[name] if depart: depart(self, node) - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: raise NotImplementedError('Unknown node: ' + node.__class__.__name__) # --------- METHODS FOR COMPATIBILITY -------------------------------------- @property - def highlightlang(self): - # type: () -> str + def highlightlang(self) -> str: warnings.warn('HTMLTranslator.highlightlang is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return self.builder.config.highlight_language @property - def highlightlang_base(self): - # type: () -> str + def highlightlang_base(self) -> str: warnings.warn('HTMLTranslator.highlightlang_base is deprecated.', RemovedInSphinx30Warning) return self.builder.config.highlight_language @property - def highlightopts(self): - # type: () -> str + def highlightopts(self) -> str: warnings.warn('HTMLTranslator.highlightopts is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return self.builder.config.highlight_options @property - def highlightlinenothreshold(self): - # type: () -> int + def highlightlinenothreshold(self) -> int: warnings.warn('HTMLTranslator.highlightlinenothreshold is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return sys.maxsize From a7f86954a8dab604242616974cac3bfa5f0019a3 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 14 Oct 2019 15:04:39 +0900 Subject: [PATCH 22/28] Migrate to py3 style type annotation: sphinx.writers.xml --- sphinx/writers/xml.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/sphinx/writers/xml.py b/sphinx/writers/xml.py index 8f6d393e2..64da854e5 100644 --- a/sphinx/writers/xml.py +++ b/sphinx/writers/xml.py @@ -10,22 +10,16 @@ from docutils.writers.docutils_xml import Writer as BaseXMLWriter -if False: - # For type annotation - from typing import Any # NOQA - from sphinx.builders import Builder # NOQA +from sphinx.builders import Builder class XMLWriter(BaseXMLWriter): - - def __init__(self, builder): - # type: (Builder) -> None + def __init__(self, builder: Builder) -> None: super().__init__() self.builder = builder self.translator_class = self.builder.get_translator_class() - def translate(self, *args, **kwargs): - # type: (Any, Any) -> None + def translate(self, *args, **kwargs) -> None: self.document.settings.newlines = \ self.document.settings.indents = \ self.builder.env.config.xml_pretty @@ -45,16 +39,13 @@ class PseudoXMLWriter(BaseXMLWriter): output = None """Final translated form of `document`.""" - def __init__(self, builder): - # type: (Builder) -> None + def __init__(self, builder: Builder) -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: self.output = self.document.pformat() - def supports(self, format): - # type: (str) -> bool + def supports(self, format: str) -> bool: """This writer supports all format-specific elements.""" return True From 67c133aa77c73f8090d63317138669b27397535e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 14 Oct 2019 15:13:55 +0900 Subject: [PATCH 23/28] Migrate to py3 style type annotation: sphinx.writers.text --- sphinx/writers/text.py | 614 ++++++++++++++--------------------------- 1 file changed, 207 insertions(+), 407 deletions(-) diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 7a9cf5a1b..879ce5ada 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -13,9 +13,11 @@ import re import textwrap import warnings from itertools import groupby, chain -from typing import Iterable, cast +from typing import Callable, Dict, List, Iterable, Optional, Set, Tuple, Union +from typing import cast from docutils import nodes, writers +from docutils.nodes import Element, Node, Text from docutils.utils import column_width from sphinx import addnodes @@ -25,8 +27,7 @@ from sphinx.util.docutils import SphinxTranslator if False: # For type annotation - from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Union # NOQA - from sphinx.builders.text import TextBuilder # NOQA + from sphinx.builders.text import TextBuilder class Cell: @@ -203,8 +204,7 @@ class Table: out = [] self.rewrap() - def writesep(char="-", lineno=None): - # type: (str, Optional[int]) -> str + def writesep(char: str = "-", lineno: Optional[int] = None) -> str: """Called on the line *before* lineno. Called with no *lineno* for the last sep. """ @@ -264,8 +264,7 @@ class TextWrapper(textwrap.TextWrapper): r'[^\s\w]*\w+[a-zA-Z]-(?=\w+[a-zA-Z])|' # hyphenated words r'(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') # em-dash - def _wrap_chunks(self, chunks): - # type: (List[str]) -> List[str] + def _wrap_chunks(self, chunks: List[str]) -> List[str]: """_wrap_chunks(chunks : [string]) -> [string] The original _wrap_chunks uses len() to calculate width. @@ -312,8 +311,7 @@ class TextWrapper(textwrap.TextWrapper): return lines - def _break_word(self, word, space_left): - # type: (str, int) -> Tuple[str, str] + def _break_word(self, word: str, space_left: int) -> Tuple[str, str]: """_break_word(word : string, space_left : int) -> (string, string) Break line by unicode width instead of len(word). @@ -325,15 +323,13 @@ class TextWrapper(textwrap.TextWrapper): return word[:i - 1], word[i - 1:] return word, '' - def _split(self, text): - # type: (str) -> List[str] + def _split(self, text: str) -> List[str]: """_split(text : string) -> [string] Override original method that only split by 'wordsep_re'. This '_split' split wide-characters into chunk by one character. """ - def split(t): - # type: (str) -> List[str] + def split(t: str) -> List[str]: return super(TextWrapper, self)._split(t) chunks = [] # type: List[str] for chunk in split(text): @@ -344,8 +340,8 @@ class TextWrapper(textwrap.TextWrapper): chunks.extend(list(g)) return chunks - def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): - # type: (List[str], List[str], int, int) -> None + def _handle_long_word(self, reversed_chunks: List[str], cur_line: List[str], + cur_len: int, width: int) -> None: """_handle_long_word(chunks : [string], cur_line : [string], cur_len : int, width : int) @@ -366,8 +362,7 @@ MAXWIDTH = 70 STDINDENT = 3 -def my_wrap(text, width=MAXWIDTH, **kwargs): - # type: (str, int, Any) -> List[str] +def my_wrap(text: str, width: int = MAXWIDTH, **kwargs) -> List[str]: w = TextWrapper(width=width, **kwargs) return w.wrap(text) @@ -379,13 +374,11 @@ class TextWriter(writers.Writer): output = None # type: str - def __init__(self, builder): - # type: (TextBuilder) -> None + def __init__(self, builder: "TextBuilder") -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: visitor = self.builder.create_translator(self.document, self.builder) self.document.walkabout(visitor) self.output = cast(TextTranslator, visitor).body @@ -394,8 +387,7 @@ class TextWriter(writers.Writer): class TextTranslator(SphinxTranslator): builder = None # type: TextBuilder - def __init__(self, document, builder): - # type: (nodes.document, TextBuilder) -> None + def __init__(self, document: nodes.document, builder: "TextBuilder") -> None: super().__init__(document, builder) newlines = self.config.text_newlines @@ -415,25 +407,21 @@ class TextTranslator(SphinxTranslator): self.lineblocklevel = 0 self.table = None # type: Table - def add_text(self, text): - # type: (str) -> None + def add_text(self, text: str) -> None: self.states[-1].append((-1, text)) - def new_state(self, indent=STDINDENT): - # type: (int) -> None + def new_state(self, indent: int = STDINDENT) -> None: self.states.append([]) self.stateindent.append(indent) - def end_state(self, wrap=True, end=[''], first=None): - # type: (bool, List[str], str) -> None + def end_state(self, wrap: bool = True, end: List[str] = [''], first: str = None) -> None: content = self.states.pop() maxindent = sum(self.stateindent) indent = self.stateindent.pop() result = [] # type: List[Tuple[int, List[str]]] toformat = [] # type: List[str] - def do_format(): - # type: () -> None + def do_format() -> None: if not toformat: return if wrap: @@ -463,73 +451,59 @@ class TextTranslator(SphinxTranslator): result.extend(result_rest) self.states[-1].extend(result) - def visit_document(self, node): - # type: (nodes.Element) -> None + def visit_document(self, node: Element) -> None: self.new_state(0) - def depart_document(self, node): - # type: (nodes.Element) -> None + def depart_document(self, node: Element) -> None: self.end_state() self.body = self.nl.join(line and (' ' * indent + line) for indent, lines in self.states[0] for line in lines) # XXX header/footer? - def visit_section(self, node): - # type: (nodes.Element) -> None + def visit_section(self, node: Element) -> None: self._title_char = self.sectionchars[self.sectionlevel] self.sectionlevel += 1 - def depart_section(self, node): - # type: (nodes.Element) -> None + def depart_section(self, node: Element) -> None: self.sectionlevel -= 1 - def visit_topic(self, node): - # type: (nodes.Element) -> None + def visit_topic(self, node: Element) -> None: self.new_state(0) - def depart_topic(self, node): - # type: (nodes.Element) -> None + def depart_topic(self, node: Element) -> None: self.end_state() visit_sidebar = visit_topic depart_sidebar = depart_topic - def visit_rubric(self, node): - # type: (nodes.Element) -> None + def visit_rubric(self, node: Element) -> None: self.new_state(0) self.add_text('-[ ') - def depart_rubric(self, node): - # type: (nodes.Element) -> None + def depart_rubric(self, node: Element) -> None: self.add_text(' ]-') self.end_state() - def visit_compound(self, node): - # type: (nodes.Element) -> None + def visit_compound(self, node: Element) -> None: pass - def depart_compound(self, node): - # type: (nodes.Element) -> None + def depart_compound(self, node: Element) -> None: pass - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: if isinstance(node.parent, nodes.Admonition): self.add_text(node.astext() + ': ') raise nodes.SkipNode self.new_state(0) - def get_section_number_string(self, node): - # type: (nodes.Element) -> str + def get_section_number_string(self, node: Element) -> str: if isinstance(node.parent, nodes.section): anchorname = '#' + node.parent['ids'][0] numbers = self.builder.secnumbers.get(anchorname) @@ -539,8 +513,7 @@ class TextTranslator(SphinxTranslator): return '.'.join(map(str, numbers)) + self.secnumber_suffix return '' - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: if isinstance(node.parent, nodes.section): char = self._title_char else: @@ -556,90 +529,69 @@ class TextTranslator(SphinxTranslator): title.pop(0) self.states[-1].append((0, title)) - def visit_subtitle(self, node): - # type: (nodes.Element) -> None + def visit_subtitle(self, node: Element) -> None: pass - def depart_subtitle(self, node): - # type: (nodes.Element) -> None + def depart_subtitle(self, node: Element) -> None: pass - def visit_attribution(self, node): - # type: (nodes.Element) -> None + def visit_attribution(self, node: Element) -> None: self.add_text('-- ') - def depart_attribution(self, node): - # type: (nodes.Element) -> None + def depart_attribution(self, node: Element) -> None: pass - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: pass - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: pass - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: self.new_state(0) - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: # XXX: wrap signatures in a way that makes sense self.end_state(wrap=False, end=None) - def visit_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature_line(self, node: Element) -> None: pass - def depart_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature_line(self, node: Element) -> None: self.add_text('\n') - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: pass - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: pass - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: pass - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: pass - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.add_text(' -> ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: pass - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: self.add_text('(') self.first_param = 1 - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: self.add_text(')') - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if not self.first_param: self.add_text(', ') else: @@ -647,49 +599,38 @@ class TextTranslator(SphinxTranslator): self.add_text(node.astext()) raise nodes.SkipNode - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.add_text('[') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.add_text(']') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: pass - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: pass - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: self.new_state() self.add_text(self.nl) - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: self.end_state() - def visit_figure(self, node): - # type: (nodes.Element) -> None + def visit_figure(self, node: Element) -> None: self.new_state() - def depart_figure(self, node): - # type: (nodes.Element) -> None + def depart_figure(self, node: Element) -> None: self.end_state() - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: pass - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: pass - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.new_state() names = [] productionlist = cast(Iterable[addnodes.production], node) @@ -707,173 +648,137 @@ class TextTranslator(SphinxTranslator): self.end_state(wrap=False) raise nodes.SkipNode - def visit_footnote(self, node): - # type: (nodes.Element) -> None + def visit_footnote(self, node: Element) -> None: label = cast(nodes.label, node[0]) self._footnote = label.astext().strip() self.new_state(len(self._footnote) + 3) - def depart_footnote(self, node): - # type: (nodes.Element) -> None + def depart_footnote(self, node: Element) -> None: self.end_state(first='[%s] ' % self._footnote) - def visit_citation(self, node): - # type: (nodes.Element) -> None + def visit_citation(self, node: Element) -> None: if len(node) and isinstance(node[0], nodes.label): self._citlabel = node[0].astext() else: self._citlabel = '' self.new_state(len(self._citlabel) + 3) - def depart_citation(self, node): - # type: (nodes.Element) -> None + def depart_citation(self, node: Element) -> None: self.end_state(first='[%s] ' % self._citlabel) - def visit_label(self, node): - # type: (nodes.Element) -> None + def visit_label(self, node: Element) -> None: raise nodes.SkipNode - def visit_legend(self, node): - # type: (nodes.Element) -> None + def visit_legend(self, node: Element) -> None: pass - def depart_legend(self, node): - # type: (nodes.Element) -> None + def depart_legend(self, node: Element) -> None: pass # XXX: option list could use some better styling - def visit_option_list(self, node): - # type: (nodes.Element) -> None + def visit_option_list(self, node: Element) -> None: pass - def depart_option_list(self, node): - # type: (nodes.Element) -> None + def depart_option_list(self, node: Element) -> None: pass - def visit_option_list_item(self, node): - # type: (nodes.Element) -> None + def visit_option_list_item(self, node: Element) -> None: self.new_state(0) - def depart_option_list_item(self, node): - # type: (nodes.Element) -> None + def depart_option_list_item(self, node: Element) -> None: self.end_state() - def visit_option_group(self, node): - # type: (nodes.Element) -> None + def visit_option_group(self, node: Element) -> None: self._firstoption = True - def depart_option_group(self, node): - # type: (nodes.Element) -> None + def depart_option_group(self, node: Element) -> None: self.add_text(' ') - def visit_option(self, node): - # type: (nodes.Element) -> None + def visit_option(self, node: Element) -> None: if self._firstoption: self._firstoption = False else: self.add_text(', ') - def depart_option(self, node): - # type: (nodes.Element) -> None + def depart_option(self, node: Element) -> None: pass - def visit_option_string(self, node): - # type: (nodes.Element) -> None + def visit_option_string(self, node: Element) -> None: pass - def depart_option_string(self, node): - # type: (nodes.Element) -> None + def depart_option_string(self, node: Element) -> None: pass - def visit_option_argument(self, node): - # type: (nodes.Element) -> None + def visit_option_argument(self, node: Element) -> None: self.add_text(node['delimiter']) - def depart_option_argument(self, node): - # type: (nodes.Element) -> None + def depart_option_argument(self, node: Element) -> None: pass - def visit_description(self, node): - # type: (nodes.Element) -> None + def visit_description(self, node: Element) -> None: pass - def depart_description(self, node): - # type: (nodes.Element) -> None + def depart_description(self, node: Element) -> None: pass - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: raise nodes.SkipNode - def visit_colspec(self, node): - # type: (nodes.Element) -> None + def visit_colspec(self, node: Element) -> None: self.table.colwidth.append(node["colwidth"]) raise nodes.SkipNode - def visit_tgroup(self, node): - # type: (nodes.Element) -> None + def visit_tgroup(self, node: Element) -> None: pass - def depart_tgroup(self, node): - # type: (nodes.Element) -> None + def depart_tgroup(self, node: Element) -> None: pass - def visit_thead(self, node): - # type: (nodes.Element) -> None + def visit_thead(self, node: Element) -> None: pass - def depart_thead(self, node): - # type: (nodes.Element) -> None + def depart_thead(self, node: Element) -> None: pass - def visit_tbody(self, node): - # type: (nodes.Element) -> None + def visit_tbody(self, node: Element) -> None: self.table.set_separator() - def depart_tbody(self, node): - # type: (nodes.Element) -> None + def depart_tbody(self, node: Element) -> None: pass - def visit_row(self, node): - # type: (nodes.Element) -> None + def visit_row(self, node: Element) -> None: if self.table.lines: self.table.add_row() - def depart_row(self, node): - # type: (nodes.Element) -> None + def depart_row(self, node: Element) -> None: pass - def visit_entry(self, node): - # type: (nodes.Element) -> None + def visit_entry(self, node: Element) -> None: self.entry = Cell( rowspan=node.get("morerows", 0) + 1, colspan=node.get("morecols", 0) + 1 ) self.new_state(0) - def depart_entry(self, node): - # type: (nodes.Element) -> None + def depart_entry(self, node: Element) -> None: text = self.nl.join(self.nl.join(x[1]) for x in self.states.pop()) self.stateindent.pop() self.entry.text = text self.table.add_cell(self.entry) self.entry = None - def visit_table(self, node): - # type: (nodes.Element) -> None + def visit_table(self, node: Element) -> None: if self.table: raise NotImplementedError('Nested tables are not supported.') self.new_state(0) self.table = Table() - def depart_table(self, node): - # type: (nodes.Element) -> None + def depart_table(self, node: Element) -> None: self.add_text(str(self.table)) self.table = None self.end_state(wrap=False) - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: bullet_list = cast(nodes.bullet_list, node[0]) list_items = cast(Iterable[nodes.list_item], bullet_list) self.new_state(0) @@ -881,47 +786,38 @@ class TextTranslator(SphinxTranslator): self.end_state() raise nodes.SkipNode - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: if 'alt' in node.attributes: self.add_text(_('[image: %s]') % node['alt']) self.add_text(_('[image]')) raise nodes.SkipNode - def visit_transition(self, node): - # type: (nodes.Element) -> None + def visit_transition(self, node: Element) -> None: indent = sum(self.stateindent) self.new_state(0) self.add_text('=' * (MAXWIDTH - indent)) self.end_state() raise nodes.SkipNode - def visit_bullet_list(self, node): - # type: (nodes.Element) -> None + def visit_bullet_list(self, node: Element) -> None: self.list_counter.append(-1) - def depart_bullet_list(self, node): - # type: (nodes.Element) -> None + def depart_bullet_list(self, node: Element) -> None: self.list_counter.pop() - def visit_enumerated_list(self, node): - # type: (nodes.Element) -> None + def visit_enumerated_list(self, node: Element) -> None: self.list_counter.append(node.get('start', 1) - 1) - def depart_enumerated_list(self, node): - # type: (nodes.Element) -> None + def depart_enumerated_list(self, node: Element) -> None: self.list_counter.pop() - def visit_definition_list(self, node): - # type: (nodes.Element) -> None + def visit_definition_list(self, node: Element) -> None: self.list_counter.append(-2) - def depart_definition_list(self, node): - # type: (nodes.Element) -> None + def depart_definition_list(self, node: Element) -> None: self.list_counter.pop() - def visit_list_item(self, node): - # type: (nodes.Element) -> None + def visit_list_item(self, node: Element) -> None: if self.list_counter[-1] == -1: # bullet list self.new_state(2) @@ -933,8 +829,7 @@ class TextTranslator(SphinxTranslator): self.list_counter[-1] += 1 self.new_state(len(str(self.list_counter[-1])) + 2) - def depart_list_item(self, node): - # type: (nodes.Element) -> None + def depart_list_item(self, node: Element) -> None: if self.list_counter[-1] == -1: self.end_state(first='* ') elif self.list_counter[-1] == -2: @@ -942,115 +837,89 @@ class TextTranslator(SphinxTranslator): else: self.end_state(first='%s. ' % self.list_counter[-1]) - def visit_definition_list_item(self, node): - # type: (nodes.Element) -> None + def visit_definition_list_item(self, node: Element) -> None: self._classifier_count_in_li = len(node.traverse(nodes.classifier)) - def depart_definition_list_item(self, node): - # type: (nodes.Element) -> None + def depart_definition_list_item(self, node: Element) -> None: pass - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: self.new_state(0) - def depart_term(self, node): - # type: (nodes.Element) -> None + def depart_term(self, node: Element) -> None: if not self._classifier_count_in_li: self.end_state(end=None) - def visit_classifier(self, node): - # type: (nodes.Element) -> None + def visit_classifier(self, node: Element) -> None: self.add_text(' : ') - def depart_classifier(self, node): - # type: (nodes.Element) -> None + def depart_classifier(self, node: Element) -> None: self._classifier_count_in_li -= 1 if not self._classifier_count_in_li: self.end_state(end=None) - def visit_definition(self, node): - # type: (nodes.Element) -> None + def visit_definition(self, node: Element) -> None: self.new_state() - def depart_definition(self, node): - # type: (nodes.Element) -> None + def depart_definition(self, node: Element) -> None: self.end_state() - def visit_field_list(self, node): - # type: (nodes.Element) -> None + def visit_field_list(self, node: Element) -> None: pass - def depart_field_list(self, node): - # type: (nodes.Element) -> None + def depart_field_list(self, node: Element) -> None: pass - def visit_field(self, node): - # type: (nodes.Element) -> None + def visit_field(self, node: Element) -> None: pass - def depart_field(self, node): - # type: (nodes.Element) -> None + def depart_field(self, node: Element) -> None: pass - def visit_field_name(self, node): - # type: (nodes.Element) -> None + def visit_field_name(self, node: Element) -> None: self.new_state(0) - def depart_field_name(self, node): - # type: (nodes.Element) -> None + def depart_field_name(self, node: Element) -> None: self.add_text(':') self.end_state(end=None) - def visit_field_body(self, node): - # type: (nodes.Element) -> None + def visit_field_body(self, node: Element) -> None: self.new_state() - def depart_field_body(self, node): - # type: (nodes.Element) -> None + def depart_field_body(self, node: Element) -> None: self.end_state() - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: pass - def depart_centered(self, node): - # type: (nodes.Element) -> None + def depart_centered(self, node: Element) -> None: pass - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: pass - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: pass - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: pass - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: pass - def visit_admonition(self, node): - # type: (nodes.Element) -> None + def visit_admonition(self, node: Element) -> None: self.new_state(0) - def depart_admonition(self, node): - # type: (nodes.Element) -> None + def depart_admonition(self, node: Element) -> None: self.end_state() - def _visit_admonition(self, node): - # type: (nodes.Element) -> None + def _visit_admonition(self, node: Element) -> None: self.new_state(2) if isinstance(node.children[0], nodes.Sequential): self.add_text(self.nl) - def _depart_admonition(self, node): - # type: (nodes.Element) -> None + def _depart_admonition(self, node: Element) -> None: label = admonitionlabels[node.tagname] self.end_state(first=label + ': ') @@ -1075,306 +944,237 @@ class TextTranslator(SphinxTranslator): visit_seealso = _visit_admonition depart_seealso = _depart_admonition - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: self.new_state(0) - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: self.end_state() - def visit_literal_block(self, node): - # type: (nodes.Element) -> None + def visit_literal_block(self, node: Element) -> None: self.new_state() - def depart_literal_block(self, node): - # type: (nodes.Element) -> None + def depart_literal_block(self, node: Element) -> None: self.end_state(wrap=False) - def visit_doctest_block(self, node): - # type: (nodes.Element) -> None + def visit_doctest_block(self, node: Element) -> None: self.new_state(0) - def depart_doctest_block(self, node): - # type: (nodes.Element) -> None + def depart_doctest_block(self, node: Element) -> None: self.end_state(wrap=False) - def visit_line_block(self, node): - # type: (nodes.Element) -> None + def visit_line_block(self, node: Element) -> None: self.new_state() self.lineblocklevel += 1 - def depart_line_block(self, node): - # type: (nodes.Element) -> None + def depart_line_block(self, node: Element) -> None: self.lineblocklevel -= 1 self.end_state(wrap=False, end=None) if not self.lineblocklevel: self.add_text('\n') - def visit_line(self, node): - # type: (nodes.Element) -> None + def visit_line(self, node: Element) -> None: pass - def depart_line(self, node): - # type: (nodes.Element) -> None + def depart_line(self, node: Element) -> None: self.add_text('\n') - def visit_block_quote(self, node): - # type: (nodes.Element) -> None + def visit_block_quote(self, node: Element) -> None: self.new_state() - def depart_block_quote(self, node): - # type: (nodes.Element) -> None + def depart_block_quote(self, node: Element) -> None: self.end_state() - def visit_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_compact_paragraph(self, node: Element) -> None: pass - def depart_compact_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_compact_paragraph(self, node: Element) -> None: pass - def visit_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_paragraph(self, node: Element) -> None: if not isinstance(node.parent, nodes.Admonition) or \ isinstance(node.parent, addnodes.seealso): self.new_state(0) - def depart_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_paragraph(self, node: Element) -> None: if not isinstance(node.parent, nodes.Admonition) or \ isinstance(node.parent, addnodes.seealso): self.end_state() - def visit_target(self, node): - # type: (nodes.Element) -> None + def visit_target(self, node: Element) -> None: raise nodes.SkipNode - def visit_index(self, node): - # type: (nodes.Element) -> None + def visit_index(self, node: Element) -> None: raise nodes.SkipNode - def visit_toctree(self, node): - # type: (nodes.Element) -> None + def visit_toctree(self, node: Element) -> None: raise nodes.SkipNode - def visit_pending_xref(self, node): - # type: (nodes.Element) -> None + def visit_pending_xref(self, node: Element) -> None: pass - def depart_pending_xref(self, node): - # type: (nodes.Element) -> None + def depart_pending_xref(self, node: Element) -> None: pass - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: if self.add_secnumbers: numbers = node.get("secnumber") if numbers is not None: self.add_text('.'.join(map(str, numbers)) + self.secnumber_suffix) - def depart_reference(self, node): - # type: (nodes.Element) -> None + def depart_reference(self, node: Element) -> None: pass - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: text = nodes.Text(node.get('title', '#')) self.visit_Text(text) raise nodes.SkipNode - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: pass - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: pass - def visit_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_emphasis(self, node: Element) -> None: self.add_text('*') - def depart_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_emphasis(self, node: Element) -> None: self.add_text('*') - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: self.add_text('*') - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: self.add_text('*') - def visit_strong(self, node): - # type: (nodes.Element) -> None + def visit_strong(self, node: Element) -> None: self.add_text('**') - def depart_strong(self, node): - # type: (nodes.Element) -> None + def depart_strong(self, node: Element) -> None: self.add_text('**') - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: self.add_text('**') - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: self.add_text('**') - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: self.add_text('') - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: if node.hasattr('explanation'): self.add_text(' (%s)' % node['explanation']) - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: return self.visit_literal_emphasis(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: return self.depart_literal_emphasis(node) - def visit_title_reference(self, node): - # type: (nodes.Element) -> None + def visit_title_reference(self, node: Element) -> None: self.add_text('*') - def depart_title_reference(self, node): - # type: (nodes.Element) -> None + def depart_title_reference(self, node: Element) -> None: self.add_text('*') - def visit_literal(self, node): - # type: (nodes.Element) -> None + def visit_literal(self, node: Element) -> None: self.add_text('"') - def depart_literal(self, node): - # type: (nodes.Element) -> None + def depart_literal(self, node: Element) -> None: self.add_text('"') - def visit_subscript(self, node): - # type: (nodes.Element) -> None + def visit_subscript(self, node: Element) -> None: self.add_text('_') - def depart_subscript(self, node): - # type: (nodes.Element) -> None + def depart_subscript(self, node: Element) -> None: pass - def visit_superscript(self, node): - # type: (nodes.Element) -> None + def visit_superscript(self, node: Element) -> None: self.add_text('^') - def depart_superscript(self, node): - # type: (nodes.Element) -> None + def depart_superscript(self, node: Element) -> None: pass - def visit_footnote_reference(self, node): - # type: (nodes.Element) -> None + def visit_footnote_reference(self, node: Element) -> None: self.add_text('[%s]' % node.astext()) raise nodes.SkipNode - def visit_citation_reference(self, node): - # type: (nodes.Element) -> None + def visit_citation_reference(self, node: Element) -> None: self.add_text('[%s]' % node.astext()) raise nodes.SkipNode - def visit_Text(self, node): - # type: (nodes.Text) -> None + def visit_Text(self, node: Text) -> None: self.add_text(node.astext()) - def depart_Text(self, node): - # type: (nodes.Text) -> None + def depart_Text(self, node: Text) -> None: pass - def visit_generated(self, node): - # type: (nodes.Element) -> None + def visit_generated(self, node: Element) -> None: pass - def depart_generated(self, node): - # type: (nodes.Element) -> None + def depart_generated(self, node: Element) -> None: pass - def visit_inline(self, node): - # type: (nodes.Element) -> None + def visit_inline(self, node: Element) -> None: if 'xref' in node['classes'] or 'term' in node['classes']: self.add_text('*') - def depart_inline(self, node): - # type: (nodes.Element) -> None + def depart_inline(self, node: Element) -> None: if 'xref' in node['classes'] or 'term' in node['classes']: self.add_text('*') - def visit_container(self, node): - # type: (nodes.Element) -> None + def visit_container(self, node: Element) -> None: pass - def depart_container(self, node): - # type: (nodes.Element) -> None + def depart_container(self, node: Element) -> None: pass - def visit_problematic(self, node): - # type: (nodes.Element) -> None + def visit_problematic(self, node: Element) -> None: self.add_text('>>') - def depart_problematic(self, node): - # type: (nodes.Element) -> None + def depart_problematic(self, node: Element) -> None: self.add_text('<<') - def visit_system_message(self, node): - # type: (nodes.Element) -> None + def visit_system_message(self, node: Element) -> None: self.new_state(0) self.add_text('' % node.astext()) self.end_state() raise nodes.SkipNode - def visit_comment(self, node): - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: raise nodes.SkipNode - def visit_meta(self, node): - # type: (nodes.Element) -> None + def visit_meta(self, node: Element) -> None: # only valid for HTML raise nodes.SkipNode - def visit_raw(self, node): - # type: (nodes.Element) -> None + def visit_raw(self, node: Element) -> None: if 'text' in node.get('format', '').split(): self.new_state(0) self.add_text(node.astext()) self.end_state(wrap = False) raise nodes.SkipNode - def visit_math(self, node): - # type: (nodes.Element) -> None + def visit_math(self, node: Element) -> None: pass - def depart_math(self, node): - # type: (nodes.Element) -> None + def depart_math(self, node: Element) -> None: pass - def visit_math_block(self, node): - # type: (nodes.Element) -> None + def visit_math_block(self, node: Element) -> None: self.new_state() - def depart_math_block(self, node): - # type: (nodes.Element) -> None + def depart_math_block(self, node: Element) -> None: self.end_state() - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: raise NotImplementedError('Unknown node: ' + node.__class__.__name__) - def _make_depart_admonition(name): # type: ignore - # type: (str) -> Callable[[TextTranslator, nodes.Element], None] + def _make_depart_admonition(name: str) -> Callable[["TextTranslator", Element], None]: # type: ignore # NOQA warnings.warn('TextTranslator._make_depart_admonition() is deprecated.', RemovedInSphinx30Warning) - def depart_admonition(self, node): - # type: (TextTranslator, nodes.Element) -> None + def depart_admonition(self, node: Element) -> None: self.end_state(first=admonitionlabels[name] + ': ') return depart_admonition From f7425c9c3ee3efdf942febad90cde267ef5e7eae Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 14 Oct 2019 18:37:26 +0900 Subject: [PATCH 24/28] Migrate to py3 style type annotation: sphinx.writers.latex --- sphinx/writers/latex.py | 784 ++++++++++++++-------------------------- 1 file changed, 263 insertions(+), 521 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 4b48e5ff3..4c07e552d 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -16,15 +16,18 @@ import sys import warnings from collections import defaultdict from os import path -from typing import Iterable, cast +from typing import Any, Callable, Dict, Iterable, Iterator, List, Pattern, Tuple, Set, Union +from typing import cast from docutils import nodes, writers +from docutils.nodes import Element, Node, Text from sphinx import addnodes from sphinx import highlighting from sphinx.deprecation import ( RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias ) +from sphinx.domains import IndexEntry from sphinx.domains.std import StandardDomain from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, _, __ @@ -42,12 +45,8 @@ except ImportError: if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Pattern, Tuple, Set, Union # NOQA - from sphinx.builders.latex import LaTeXBuilder # NOQA - from sphinx.builders.latex.nodes import ( # NOQA - captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography - ) - from sphinx.domains import IndexEntry # NOQA + from sphinx.builders.latex import LaTeXBuilder + logger = logging.getLogger(__name__) @@ -269,13 +268,11 @@ class LaTeXWriter(writers.Writer): output = None - def __init__(self, builder): - # type: (LaTeXBuilder) -> None + def __init__(self, builder: "LaTeXBuilder") -> None: super().__init__() self.builder = builder - def translate(self): - # type: () -> None + def translate(self) -> None: visitor = self.builder.create_translator(self.document, self.builder) self.document.walkabout(visitor) self.output = cast(LaTeXTranslator, visitor).astext() @@ -286,8 +283,7 @@ class LaTeXWriter(writers.Writer): class Table: """A table data""" - def __init__(self, node): - # type: (nodes.Element) -> None + def __init__(self, node: Element) -> None: self.header = [] # type: List[str] self.body = [] # type: List[str] self.align = node.get('align') @@ -312,26 +308,22 @@ class Table: self.cell_id = 0 # last assigned cell_id @property - def caption_footnotetexts(self): - # type: () -> List[str] + def caption_footnotetexts(self) -> List[str]: warnings.warn('table.caption_footnotetexts is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return [] @property - def header_footnotetexts(self): - # type: () -> List[str] + def header_footnotetexts(self) -> List[str]: warnings.warn('table.header_footnotetexts is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return [] - def is_longtable(self): - # type: () -> bool + def is_longtable(self) -> bool: """True if and only if table uses longtable environment.""" return self.row > 30 or 'longtable' in self.classes - def get_table_type(self): - # type: () -> str + def get_table_type(self) -> str: """Returns the LaTeX environment name for the table. The class currently supports: @@ -351,8 +343,7 @@ class Table: else: return 'tabulary' - def get_colspec(self): - # type: () -> str + def get_colspec(self) -> str: """Returns a column spec of table. This is what LaTeX calls the 'preamble argument' of the used table environment. @@ -375,8 +366,7 @@ class Table: else: return '{|' + ('l|' * self.colcount) + '}\n' - def add_cell(self, height, width): - # type: (int, int) -> None + def add_cell(self, height: int, width: int) -> None: """Adds a new cell to a table. It will be located at current position: (``self.row``, ``self.col``). @@ -387,8 +377,7 @@ class Table: assert self.cells[(self.row + row, self.col + col)] == 0 self.cells[(self.row + row, self.col + col)] = self.cell_id - def cell(self, row=None, col=None): - # type: (int, int) -> TableCell + def cell(self, row: int = None, col: int = None) -> "TableCell": """Returns a cell object (i.e. rectangular area) containing given position. If no option arguments: ``row`` or ``col`` are given, the current position; @@ -407,8 +396,7 @@ class Table: class TableCell: """A cell data of tables.""" - def __init__(self, table, row, col): - # type: (Table, int, int) -> None + def __init__(self, table: Table, row: int, col: int) -> None: if table.cells[(row, col)] == 0: raise IndexError @@ -424,8 +412,7 @@ class TableCell: self.col -= 1 @property - def width(self): - # type: () -> int + def width(self) -> int: """Returns the cell width.""" width = 0 while self.table.cells[(self.row, self.col + width)] == self.cell_id: @@ -433,8 +420,7 @@ class TableCell: return width @property - def height(self): - # type: () -> int + def height(self) -> int: """Returns the cell height.""" height = 0 while self.table.cells[(self.row + height, self.col)] == self.cell_id: @@ -442,14 +428,12 @@ class TableCell: return height -def escape_abbr(text): - # type: (str) -> str +def escape_abbr(text: str) -> str: """Adjust spacing after abbreviations.""" return re.sub(r'\.(?=\s|$)', r'.\@', text) -def rstdim_to_latexdim(width_str, scale = 100): - # type: (str, int) -> str +def rstdim_to_latexdim(width_str: str, scale: int = 100) -> str: """Convert `width_str` with rst length to LaTeX length.""" match = re.match(r'^(\d*\.?\d*)\s*(\S*)$', width_str) if not match: @@ -487,8 +471,7 @@ class LaTeXTranslator(SphinxTranslator): # sphinx specific document classes docclasses = ('howto', 'manual') - def __init__(self, document, builder): - # type: (nodes.document, LaTeXBuilder) -> None + def __init__(self, document: nodes.document, builder: "LaTeXBuilder") -> None: super().__init__(document, builder) self.body = [] # type: List[str] @@ -671,19 +654,16 @@ class LaTeXTranslator(SphinxTranslator): self.curfilestack = [] # type: List[str] self.handled_abbrs = set() # type: Set[str] - def pushbody(self, newbody): - # type: (List[str]) -> None + def pushbody(self, newbody: List[str]) -> None: self.bodystack.append(self.body) self.body = newbody - def popbody(self): - # type: () -> List[str] + def popbody(self) -> List[str]: body = self.body self.body = self.bodystack.pop() return body - def restrict_footnote(self, node): - # type: (nodes.Element) -> None + def restrict_footnote(self, node: Element) -> None: warnings.warn('LaTeXWriter.restrict_footnote() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) @@ -691,8 +671,7 @@ class LaTeXTranslator(SphinxTranslator): self.footnote_restricted = node self.pending_footnotes = [] - def unrestrict_footnote(self, node): - # type: (nodes.Element) -> None + def unrestrict_footnote(self, node: Element) -> None: warnings.warn('LaTeXWriter.unrestrict_footnote() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) @@ -703,56 +682,48 @@ class LaTeXTranslator(SphinxTranslator): footnode.walkabout(self) self.pending_footnotes = [] - def format_docclass(self, docclass): - # type: (str) -> str + def format_docclass(self, docclass: str) -> str: """ prepends prefix to sphinx document classes """ if docclass in self.docclasses: docclass = 'sphinx' + docclass return docclass - def astext(self): - # type: () -> str + def astext(self) -> str: self.elements.update({ 'body': ''.join(self.body), 'indices': self.generate_indices() }) return self.render('latex.tex_t', self.elements) - def hypertarget(self, id, withdoc=True, anchor=True): - # type: (str, bool, bool) -> str + def hypertarget(self, id: str, withdoc: bool = True, anchor: bool = True) -> str: if withdoc: id = self.curfilestack[-1] + ':' + id return (anchor and '\\phantomsection' or '') + \ '\\label{%s}' % self.idescape(id) - def hypertarget_to(self, node, anchor=False): - # type: (nodes.Element, bool) -> str + def hypertarget_to(self, node: Element, anchor: bool = False) -> str: labels = ''.join(self.hypertarget(node_id, anchor=False) for node_id in node['ids']) if anchor: return r'\phantomsection' + labels else: return labels - def hyperlink(self, id): - # type: (str) -> str + def hyperlink(self, id: str) -> str: return '{\\hyperref[%s]{' % self.idescape(id) - def hyperpageref(self, id): - # type: (str) -> str + def hyperpageref(self, id: str) -> str: return '\\autopageref*{%s}' % self.idescape(id) def escape(self, s: str) -> str: return texescape.escape(s, self.config.latex_engine) - def idescape(self, id): - # type: (str) -> str + def idescape(self, id: str) -> str: return '\\detokenize{%s}' % str(id).translate(tex_replace_map).\ encode('ascii', 'backslashreplace').decode('ascii').\ replace('\\', '_') - def babel_renewcommand(self, command, definition): - # type: (str, str) -> str + def babel_renewcommand(self, command: str, definition: str) -> str: if self.elements['multilingual']: prefix = '\\addto\\captions%s{' % self.babel.get_language() suffix = '}' @@ -762,10 +733,8 @@ class LaTeXTranslator(SphinxTranslator): return ('%s\\renewcommand{%s}{%s}%s\n' % (prefix, command, definition, suffix)) - def generate_indices(self): - # type: () -> str - def generate(content, collapsed): - # type: (List[Tuple[str, List[IndexEntry]]], bool) -> None + def generate_indices(self) -> str: + def generate(content: List[Tuple[str, List[IndexEntry]]], collapsed: bool) -> None: ret.append('\\begin{sphinxtheindex}\n') ret.append('\\let\\bigletter\\sphinxstyleindexlettergroup\n') for i, (letter, entries) in enumerate(content): @@ -804,8 +773,7 @@ class LaTeXTranslator(SphinxTranslator): return ''.join(ret) - def render(self, template_name, variables): - # type: (str, Dict) -> str + def render(self, template_name: str, variables: Dict) -> str: renderer = LaTeXRenderer(latex_engine=self.config.latex_engine) for template_dir in self.builder.config.templates_path: template = path.join(self.builder.confdir, template_dir, @@ -815,8 +783,7 @@ class LaTeXTranslator(SphinxTranslator): return renderer.render(template_name, variables) - def visit_document(self, node): - # type: (nodes.Element) -> None + def visit_document(self, node: Element) -> None: self.curfilestack.append(node.get('docname', '')) if self.first_document == 1: # the first document is all the regular content ... @@ -830,69 +797,55 @@ class LaTeXTranslator(SphinxTranslator): # "- 1" because the level is increased before the title is visited self.sectionlevel = self.top_sectionlevel - 1 - def depart_document(self, node): - # type: (nodes.Element) -> None + def depart_document(self, node: Element) -> None: pass - def visit_start_of_file(self, node): - # type: (nodes.Element) -> None + def visit_start_of_file(self, node: Element) -> None: self.curfilestack.append(node['docname']) - def depart_start_of_file(self, node): - # type: (nodes.Element) -> None + def depart_start_of_file(self, node: Element) -> None: self.curfilestack.pop() - def visit_section(self, node): - # type: (nodes.Element) -> None + def visit_section(self, node: Element) -> None: if not self.this_is_the_title: self.sectionlevel += 1 self.body.append('\n\n') - def depart_section(self, node): - # type: (nodes.Element) -> None + def depart_section(self, node: Element) -> None: self.sectionlevel = max(self.sectionlevel - 1, self.top_sectionlevel - 1) - def visit_problematic(self, node): - # type: (nodes.Element) -> None + def visit_problematic(self, node: Element) -> None: self.body.append(r'{\color{red}\bfseries{}') - def depart_problematic(self, node): - # type: (nodes.Element) -> None + def depart_problematic(self, node: Element) -> None: self.body.append('}') - def visit_topic(self, node): - # type: (nodes.Element) -> None + def visit_topic(self, node: Element) -> None: self.in_minipage = 1 self.body.append('\n\\begin{sphinxShadowBox}\n') - def depart_topic(self, node): - # type: (nodes.Element) -> None + def depart_topic(self, node: Element) -> None: self.in_minipage = 0 self.body.append('\\end{sphinxShadowBox}\n') visit_sidebar = visit_topic depart_sidebar = depart_topic - def visit_glossary(self, node): - # type: (nodes.Element) -> None + def visit_glossary(self, node: Element) -> None: pass - def depart_glossary(self, node): - # type: (nodes.Element) -> None + def depart_glossary(self, node: Element) -> None: pass - def visit_productionlist(self, node): - # type: (nodes.Element) -> None + def visit_productionlist(self, node: Element) -> None: self.body.append('\n\n\\begin{productionlist}\n') self.in_production_list = 1 - def depart_productionlist(self, node): - # type: (nodes.Element) -> None + def depart_productionlist(self, node: Element) -> None: self.body.append('\\end{productionlist}\n\n') self.in_production_list = 0 - def visit_production(self, node): - # type: (nodes.Element) -> None + def visit_production(self, node: Element) -> None: if node['tokenname']: tn = node['tokenname'] self.body.append(self.hypertarget('grammar-token-' + tn)) @@ -900,20 +853,16 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append('\\productioncont{') - def depart_production(self, node): - # type: (nodes.Element) -> None + def depart_production(self, node: Element) -> None: self.body.append('}\n') - def visit_transition(self, node): - # type: (nodes.Element) -> None + def visit_transition(self, node: Element) -> None: self.body.append(self.elements['transition']) - def depart_transition(self, node): - # type: (nodes.Element) -> None + def depart_transition(self, node: Element) -> None: pass - def visit_title(self, node): - # type: (nodes.Element) -> None + def visit_title(self, node: Element) -> None: parent = node.parent if isinstance(parent, addnodes.seealso): # the environment already handles this @@ -961,38 +910,32 @@ class LaTeXTranslator(SphinxTranslator): self.context.append('}\n') self.in_title = 1 - def depart_title(self, node): - # type: (nodes.Element) -> None + def depart_title(self, node: Element) -> None: self.in_title = 0 if isinstance(node.parent, nodes.table): self.table.caption = self.popbody() else: self.body.append(self.context.pop()) - def visit_subtitle(self, node): - # type: (nodes.Element) -> None + def visit_subtitle(self, node: Element) -> None: if isinstance(node.parent, nodes.sidebar): self.body.append('\\sphinxstylesidebarsubtitle{') self.context.append('}\n') else: self.context.append('') - def depart_subtitle(self, node): - # type: (nodes.Element) -> None + def depart_subtitle(self, node: Element) -> None: self.body.append(self.context.pop()) - def visit_desc(self, node): - # type: (nodes.Element) -> None + def visit_desc(self, node: Element) -> None: self.body.append('\n\n\\begin{fulllineitems}\n') if self.table: self.table.has_problematic = True - def depart_desc(self, node): - # type: (nodes.Element) -> None + def depart_desc(self, node: Element) -> None: self.body.append('\n\\end{fulllineitems}\n\n') - def _visit_signature_line(self, node): - # type: (nodes.Element) -> None + def _visit_signature_line(self, node: Element) -> None: for child in node: if isinstance(child, addnodes.desc_parameterlist): self.body.append(r'\pysiglinewithargsret{') @@ -1000,12 +943,10 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append(r'\pysigline{') - def _depart_signature_line(self, node): - # type: (nodes.Element) -> None + def _depart_signature_line(self, node: Element) -> None: self.body.append('}') - def visit_desc_signature(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature(self, node: Element) -> None: if node.parent['objtype'] != 'describe' and node['ids']: hyper = self.hypertarget(node['ids'][0]) else: @@ -1016,72 +957,58 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append('%\n\\pysigstartmultiline\n') - def depart_desc_signature(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature(self, node: Element) -> None: if not node.get('is_multiline'): self._depart_signature_line(node) else: self.body.append('%\n\\pysigstopmultiline') - def visit_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def visit_desc_signature_line(self, node: Element) -> None: self._visit_signature_line(node) - def depart_desc_signature_line(self, node): - # type: (nodes.Element) -> None + def depart_desc_signature_line(self, node: Element) -> None: self._depart_signature_line(node) - def visit_desc_addname(self, node): - # type: (nodes.Element) -> None + def visit_desc_addname(self, node: Element) -> None: self.body.append(r'\sphinxcode{\sphinxupquote{') self.literal_whitespace += 1 - def depart_desc_addname(self, node): - # type: (nodes.Element) -> None + def depart_desc_addname(self, node: Element) -> None: self.body.append('}}') self.literal_whitespace -= 1 - def visit_desc_type(self, node): - # type: (nodes.Element) -> None + def visit_desc_type(self, node: Element) -> None: pass - def depart_desc_type(self, node): - # type: (nodes.Element) -> None + def depart_desc_type(self, node: Element) -> None: pass - def visit_desc_returns(self, node): - # type: (nodes.Element) -> None + def visit_desc_returns(self, node: Element) -> None: self.body.append(r'{ $\rightarrow$ ') - def depart_desc_returns(self, node): - # type: (nodes.Element) -> None + def depart_desc_returns(self, node: Element) -> None: self.body.append(r'}') - def visit_desc_name(self, node): - # type: (nodes.Element) -> None + def visit_desc_name(self, node: Element) -> None: self.body.append(r'\sphinxbfcode{\sphinxupquote{') self.no_contractions += 1 self.literal_whitespace += 1 - def depart_desc_name(self, node): - # type: (nodes.Element) -> None + def depart_desc_name(self, node: Element) -> None: self.body.append('}}') self.literal_whitespace -= 1 self.no_contractions -= 1 - def visit_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameterlist(self, node: Element) -> None: # close name, open parameterlist self.body.append('}{') self.first_param = 1 - def depart_desc_parameterlist(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameterlist(self, node: Element) -> None: # close parameterlist, open return annotation self.body.append('}{') - def visit_desc_parameter(self, node): - # type: (nodes.Element) -> None + def visit_desc_parameter(self, node: Element) -> None: if not self.first_param: self.body.append(', ') else: @@ -1089,60 +1016,48 @@ class LaTeXTranslator(SphinxTranslator): if not node.hasattr('noemph'): self.body.append(r'\emph{') - def depart_desc_parameter(self, node): - # type: (nodes.Element) -> None + def depart_desc_parameter(self, node: Element) -> None: if not node.hasattr('noemph'): self.body.append('}') - def visit_desc_optional(self, node): - # type: (nodes.Element) -> None + def visit_desc_optional(self, node: Element) -> None: self.body.append(r'\sphinxoptional{') - def depart_desc_optional(self, node): - # type: (nodes.Element) -> None + def depart_desc_optional(self, node: Element) -> None: self.body.append('}') - def visit_desc_annotation(self, node): - # type: (nodes.Element) -> None + def visit_desc_annotation(self, node: Element) -> None: self.body.append(r'\sphinxbfcode{\sphinxupquote{') - def depart_desc_annotation(self, node): - # type: (nodes.Element) -> None + def depart_desc_annotation(self, node: Element) -> None: self.body.append('}}') - def visit_desc_content(self, node): - # type: (nodes.Element) -> None + def visit_desc_content(self, node: Element) -> None: if node.children and not isinstance(node.children[0], nodes.paragraph): # avoid empty desc environment which causes a formatting bug self.body.append('~') - def depart_desc_content(self, node): - # type: (nodes.Element) -> None + def depart_desc_content(self, node: Element) -> None: pass - def visit_seealso(self, node): - # type: (nodes.Element) -> None + def visit_seealso(self, node: Element) -> None: self.body.append('\n\n\\sphinxstrong{%s:}\n\n' % admonitionlabels['seealso']) - def depart_seealso(self, node): - # type: (nodes.Element) -> None + def depart_seealso(self, node: Element) -> None: self.body.append("\n\n") - def visit_rubric(self, node): - # type: (nodes.Element) -> None + def visit_rubric(self, node: Element) -> None: if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')): raise nodes.SkipNode self.body.append('\\subsubsection*{') self.context.append('}\n') self.in_title = 1 - def depart_rubric(self, node): - # type: (nodes.Element) -> None + def depart_rubric(self, node: Element) -> None: self.in_title = 0 self.body.append(self.context.pop()) - def visit_footnote(self, node): - # type: (nodes.Element) -> None + def visit_footnote(self, node: Element) -> None: self.in_footnote += 1 label = cast(nodes.label, node[0]) if self.in_parsed_literal: @@ -1151,25 +1066,21 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('%%\n\\begin{footnote}[%s]' % label.astext()) self.body.append('\\sphinxAtStartFootnote\n') - def depart_footnote(self, node): - # type: (nodes.Element) -> None + def depart_footnote(self, node: Element) -> None: if self.in_parsed_literal: self.body.append('\\end{footnote}') else: self.body.append('%\n\\end{footnote}') self.in_footnote -= 1 - def visit_label(self, node): - # type: (nodes.Element) -> None + def visit_label(self, node: Element) -> None: raise nodes.SkipNode - def visit_tabular_col_spec(self, node): - # type: (nodes.Element) -> None + def visit_tabular_col_spec(self, node: Element) -> None: self.next_table_colspec = node['spec'] raise nodes.SkipNode - def visit_table(self, node): - # type: (nodes.Element) -> None + def visit_table(self, node: Element) -> None: if self.table: raise UnsupportedError( '%s:%s: nested tables are not yet implemented.' % @@ -1182,8 +1093,7 @@ class LaTeXTranslator(SphinxTranslator): ':widths: is ignored.'), location=node) self.next_table_colspec = None - def depart_table(self, node): - # type: (nodes.Element) -> None + def depart_table(self, node: Element) -> None: labels = self.hypertarget_to(node) table_type = self.table.get_table_type() table = self.render(table_type + '.tex_t', @@ -1194,46 +1104,37 @@ class LaTeXTranslator(SphinxTranslator): self.table = None - def visit_colspec(self, node): - # type: (nodes.Element) -> None + def visit_colspec(self, node: Element) -> None: self.table.colcount += 1 if 'colwidth' in node: self.table.colwidths.append(node['colwidth']) if 'stub' in node: self.table.stubs.append(self.table.colcount - 1) - def depart_colspec(self, node): - # type: (nodes.Element) -> None + def depart_colspec(self, node: Element) -> None: pass - def visit_tgroup(self, node): - # type: (nodes.Element) -> None + def visit_tgroup(self, node: Element) -> None: pass - def depart_tgroup(self, node): - # type: (nodes.Element) -> None + def depart_tgroup(self, node: Element) -> None: pass - def visit_thead(self, node): - # type: (nodes.Element) -> None + def visit_thead(self, node: Element) -> None: # Redirect head output until header is finished. self.pushbody(self.table.header) - def depart_thead(self, node): - # type: (nodes.Element) -> None + def depart_thead(self, node: Element) -> None: self.popbody() - def visit_tbody(self, node): - # type: (nodes.Element) -> None + def visit_tbody(self, node: Element) -> None: # Redirect body output until table is finished. self.pushbody(self.table.body) - def depart_tbody(self, node): - # type: (nodes.Element) -> None + def depart_tbody(self, node: Element) -> None: self.popbody() - def visit_row(self, node): - # type: (nodes.Element) -> None + def visit_row(self, node: Element) -> None: self.table.col = 0 # fill columns if the row starts with the bottom of multirow cell @@ -1253,8 +1154,7 @@ class LaTeXTranslator(SphinxTranslator): '{\\sphinxtablestrut{%d}}' % (cell.width, cell.cell_id)) - def depart_row(self, node): - # type: (nodes.Element) -> None + def depart_row(self, node: Element) -> None: self.body.append('\\\\\n') cells = [self.table.cell(self.table.row, i) for i in range(self.table.colcount)] underlined = [cell.row + cell.height == self.table.row + 1 for cell in cells] @@ -1271,8 +1171,7 @@ class LaTeXTranslator(SphinxTranslator): i += 1 self.table.row += 1 - def visit_entry(self, node): - # type: (nodes.Element) -> None + def visit_entry(self, node: Element) -> None: if self.table.col > 0: self.body.append('&') self.table.add_cell(node.get('morerows', 0) + 1, node.get('morecols', 0) + 1) @@ -1309,8 +1208,7 @@ class LaTeXTranslator(SphinxTranslator): self.pushbody([]) self.context.append(context) - def depart_entry(self, node): - # type: (nodes.Element) -> None + def depart_entry(self, node: Element) -> None: if self.needs_linetrimming: self.needs_linetrimming = 0 body = self.popbody() @@ -1343,8 +1241,7 @@ class LaTeXTranslator(SphinxTranslator): '{\\sphinxtablestrut{%d}}' % (nextcell.width, nextcell.cell_id)) - def visit_acks(self, node): - # type: (nodes.Element) -> None + def visit_acks(self, node: Element) -> None: # this is a list in the source, but should be rendered as a # comma-separated list here bullet_list = cast(nodes.bullet_list, node[0]) @@ -1354,22 +1251,18 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\n\n') raise nodes.SkipNode - def visit_bullet_list(self, node): - # type: (nodes.Element) -> None + def visit_bullet_list(self, node: Element) -> None: if not self.compact_list: self.body.append('\\begin{itemize}\n') if self.table: self.table.has_problematic = True - def depart_bullet_list(self, node): - # type: (nodes.Element) -> None + def depart_bullet_list(self, node: Element) -> None: if not self.compact_list: self.body.append('\\end{itemize}\n') - def visit_enumerated_list(self, node): - # type: (nodes.Element) -> None - def get_enumtype(node): - # type: (nodes.Element) -> str + def visit_enumerated_list(self, node: Element) -> None: + def get_enumtype(node: Element) -> str: enumtype = node.get('enumtype', 'arabic') if 'alpha' in enumtype and 26 < node.get('start', 0) + len(node): # fallback to arabic if alphabet counter overflows @@ -1377,8 +1270,7 @@ class LaTeXTranslator(SphinxTranslator): return enumtype - def get_nested_level(node): - # type: (nodes.Element) -> int + def get_nested_level(node: Element) -> int: if node is None: return 0 elif isinstance(node, nodes.enumerated_list): @@ -1400,40 +1292,32 @@ class LaTeXTranslator(SphinxTranslator): if self.table: self.table.has_problematic = True - def depart_enumerated_list(self, node): - # type: (nodes.Element) -> None + def depart_enumerated_list(self, node: Element) -> None: self.body.append('\\end{enumerate}\n') - def visit_list_item(self, node): - # type: (nodes.Element) -> None + def visit_list_item(self, node: Element) -> None: # Append "{}" in case the next character is "[", which would break # LaTeX's list environment (no numbering and the "[" is not printed). self.body.append(r'\item {} ') - def depart_list_item(self, node): - # type: (nodes.Element) -> None + def depart_list_item(self, node: Element) -> None: self.body.append('\n') - def visit_definition_list(self, node): - # type: (nodes.Element) -> None + def visit_definition_list(self, node: Element) -> None: self.body.append('\\begin{description}\n') if self.table: self.table.has_problematic = True - def depart_definition_list(self, node): - # type: (nodes.Element) -> None + def depart_definition_list(self, node: Element) -> None: self.body.append('\\end{description}\n') - def visit_definition_list_item(self, node): - # type: (nodes.Element) -> None + def visit_definition_list_item(self, node: Element) -> None: pass - def depart_definition_list_item(self, node): - # type: (nodes.Element) -> None + def depart_definition_list_item(self, node: Element) -> None: pass - def visit_term(self, node): - # type: (nodes.Element) -> None + def visit_term(self, node: Element) -> None: self.in_term += 1 ctx = '' if node.get('ids'): @@ -1444,43 +1328,34 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\\item[{') self.context.append(ctx) - def depart_term(self, node): - # type: (nodes.Element) -> None + def depart_term(self, node: Element) -> None: self.body.append(self.context.pop()) self.in_term -= 1 - def visit_classifier(self, node): - # type: (nodes.Element) -> None + def visit_classifier(self, node: Element) -> None: self.body.append('{[}') - def depart_classifier(self, node): - # type: (nodes.Element) -> None + def depart_classifier(self, node: Element) -> None: self.body.append('{]}') - def visit_definition(self, node): - # type: (nodes.Element) -> None + def visit_definition(self, node: Element) -> None: pass - def depart_definition(self, node): - # type: (nodes.Element) -> None + def depart_definition(self, node: Element) -> None: self.body.append('\n') - def visit_field_list(self, node): - # type: (nodes.Element) -> None + def visit_field_list(self, node: Element) -> None: self.body.append('\\begin{quote}\\begin{description}\n') if self.table: self.table.has_problematic = True - def depart_field_list(self, node): - # type: (nodes.Element) -> None + def depart_field_list(self, node: Element) -> None: self.body.append('\\end{description}\\end{quote}\n') - def visit_field(self, node): - # type: (nodes.Element) -> None + def visit_field(self, node: Element) -> None: pass - def depart_field(self, node): - # type: (nodes.Element) -> None + def depart_field(self, node: Element) -> None: pass visit_field_name = visit_term @@ -1489,8 +1364,7 @@ class LaTeXTranslator(SphinxTranslator): visit_field_body = visit_definition depart_field_body = depart_definition - def visit_paragraph(self, node): - # type: (nodes.Element) -> None + def visit_paragraph(self, node: Element) -> None: index = node.parent.index(node) if (index > 0 and isinstance(node.parent, nodes.compound) and not isinstance(node.parent[index - 1], nodes.paragraph) and @@ -1504,22 +1378,18 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append('\n') - def depart_paragraph(self, node): - # type: (nodes.Element) -> None + def depart_paragraph(self, node: Element) -> None: self.body.append('\n') - def visit_centered(self, node): - # type: (nodes.Element) -> None + def visit_centered(self, node: Element) -> None: self.body.append('\n\\begin{center}') if self.table: self.table.has_problematic = True - def depart_centered(self, node): - # type: (nodes.Element) -> None + def depart_centered(self, node: Element) -> None: self.body.append('\n\\end{center}') - def visit_hlist(self, node): - # type: (nodes.Element) -> None + def visit_hlist(self, node: Element) -> None: # for now, we don't support a more compact list format # don't add individual itemize environments, but one for all columns self.compact_list += 1 @@ -1528,34 +1398,28 @@ class LaTeXTranslator(SphinxTranslator): if self.table: self.table.has_problematic = True - def depart_hlist(self, node): - # type: (nodes.Element) -> None + def depart_hlist(self, node: Element) -> None: self.compact_list -= 1 self.body.append('\\end{itemize}\n') - def visit_hlistcol(self, node): - # type: (nodes.Element) -> None + def visit_hlistcol(self, node: Element) -> None: pass - def depart_hlistcol(self, node): - # type: (nodes.Element) -> None + def depart_hlistcol(self, node: Element) -> None: pass - def latex_image_length(self, width_str, scale = 100): - # type: (str, int) -> str + def latex_image_length(self, width_str: str, scale: int = 100) -> str: try: return rstdim_to_latexdim(width_str, scale) except ValueError: logger.warning(__('dimension unit %s is invalid. Ignored.'), width_str) return None - def is_inline(self, node): - # type: (nodes.Element) -> bool + def is_inline(self, node: Element) -> bool: """Check whether a node represents an inline element.""" return isinstance(node.parent, nodes.TextElement) - def visit_image(self, node): - # type: (nodes.Element) -> None + def visit_image(self, node: Element) -> None: attrs = node.attributes pre = [] # type: List[str] # in reverse order @@ -1637,12 +1501,10 @@ class LaTeXTranslator(SphinxTranslator): (options, base, ext)) self.body.extend(post) - def depart_image(self, node): - # type: (nodes.Element) -> None + def depart_image(self, node: Element) -> None: pass - def visit_figure(self, node): - # type: (nodes.Element) -> None + def visit_figure(self, node: Element) -> None: align = self.elements['figure_align'] if self.no_latex_floats: align = "H" @@ -1676,12 +1538,10 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\\capstart\n') self.context.append('\\end{figure}\n') - def depart_figure(self, node): - # type: (nodes.Element) -> None + def depart_figure(self, node: Element) -> None: self.body.append(self.context.pop()) - def visit_caption(self, node): - # type: (nodes.Element) -> None + def visit_caption(self, node: Element) -> None: self.in_caption += 1 if isinstance(node.parent, captioned_literal_block): self.body.append('\\sphinxSetupCaptionForVerbatim{') @@ -1692,41 +1552,34 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append('\\caption{') - def depart_caption(self, node): - # type: (nodes.Element) -> None + def depart_caption(self, node: Element) -> None: self.body.append('}') if isinstance(node.parent, nodes.figure): labels = self.hypertarget_to(node.parent) self.body.append(labels) self.in_caption -= 1 - def visit_legend(self, node): - # type: (nodes.Element) -> None + def visit_legend(self, node: Element) -> None: self.body.append('\n\\begin{sphinxlegend}') - def depart_legend(self, node): - # type: (nodes.Element) -> None + def depart_legend(self, node: Element) -> None: self.body.append('\\end{sphinxlegend}\n') - def visit_admonition(self, node): - # type: (nodes.Element) -> None + def visit_admonition(self, node: Element) -> None: self.body.append('\n\\begin{sphinxadmonition}{note}') self.no_latex_floats += 1 - def depart_admonition(self, node): - # type: (nodes.Element) -> None + def depart_admonition(self, node: Element) -> None: self.body.append('\\end{sphinxadmonition}\n') self.no_latex_floats -= 1 - def _visit_named_admonition(self, node): - # type: (nodes.Element) -> None + def _visit_named_admonition(self, node: Element) -> None: label = admonitionlabels[node.tagname] self.body.append('\n\\begin{sphinxadmonition}{%s}{%s:}' % (node.tagname, label)) self.no_latex_floats += 1 - def _depart_named_admonition(self, node): - # type: (nodes.Element) -> None + def _depart_named_admonition(self, node: Element) -> None: self.body.append('\\end{sphinxadmonition}\n') self.no_latex_floats -= 1 @@ -1749,18 +1602,14 @@ class LaTeXTranslator(SphinxTranslator): visit_warning = _visit_named_admonition depart_warning = _depart_named_admonition - def visit_versionmodified(self, node): - # type: (nodes.Element) -> None + def visit_versionmodified(self, node: Element) -> None: pass - def depart_versionmodified(self, node): - # type: (nodes.Element) -> None + def depart_versionmodified(self, node: Element) -> None: pass - def visit_target(self, node): - # type: (nodes.Element) -> None - def add_target(id): - # type: (str) -> None + def visit_target(self, node: Element) -> None: + def add_target(id: str) -> None: # indexing uses standard LaTeX index markup, so the targets # will be generated differently if id.startswith('index-'): @@ -1803,21 +1652,17 @@ class LaTeXTranslator(SphinxTranslator): for id in node['ids']: add_target(id) - def depart_target(self, node): - # type: (nodes.Element) -> None + def depart_target(self, node: Element) -> None: pass - def visit_attribution(self, node): - # type: (nodes.Element) -> None + def visit_attribution(self, node: Element) -> None: self.body.append('\n\\begin{flushright}\n') self.body.append('---') - def depart_attribution(self, node): - # type: (nodes.Element) -> None + def depart_attribution(self, node: Element) -> None: self.body.append('\n\\end{flushright}\n') - def visit_index(self, node, scre = None): - # type: (nodes.Element, Pattern) -> None + def visit_index(self, node: Element, scre: Pattern = None) -> None: def escape(value): value = self.encode(value) value = value.replace(r'\{', r'\sphinxleftcurlybrace{}') @@ -1887,8 +1732,7 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\\ignorespaces ') raise nodes.SkipNode - def visit_raw(self, node): - # type: (nodes.Element) -> None + def visit_raw(self, node: Element) -> None: if not self.is_inline(node): self.body.append('\n') if 'latex' in node.get('format', '').split(): @@ -1897,8 +1741,7 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\n') raise nodes.SkipNode - def visit_reference(self, node): - # type: (nodes.Element) -> None + def visit_reference(self, node: Element) -> None: if not self.in_title: for id in node.get('ids'): anchor = not self.in_caption @@ -1955,14 +1798,12 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\\sphinxhref{%s}{' % self.encode_uri(uri)) self.context.append('}') - def depart_reference(self, node): - # type: (nodes.Element) -> None + def depart_reference(self, node: Element) -> None: self.body.append(self.context.pop()) if not self.is_inline(node): self.body.append('\n') - def visit_number_reference(self, node): - # type: (nodes.Element) -> None + def visit_number_reference(self, node: Element) -> None: if node.get('refid'): id = self.curfilestack[-1] + ':' + node['refid'] else: @@ -1982,60 +1823,47 @@ class LaTeXTranslator(SphinxTranslator): raise nodes.SkipNode - def visit_download_reference(self, node): - # type: (nodes.Element) -> None + def visit_download_reference(self, node: Element) -> None: pass - def depart_download_reference(self, node): - # type: (nodes.Element) -> None + def depart_download_reference(self, node: Element) -> None: pass - def visit_pending_xref(self, node): - # type: (nodes.Element) -> None + def visit_pending_xref(self, node: Element) -> None: pass - def depart_pending_xref(self, node): - # type: (nodes.Element) -> None + def depart_pending_xref(self, node: Element) -> None: pass - def visit_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_emphasis(self, node: Element) -> None: self.body.append(r'\sphinxstyleemphasis{') - def depart_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_emphasis(self, node: Element) -> None: self.body.append('}') - def visit_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def visit_literal_emphasis(self, node: Element) -> None: self.body.append(r'\sphinxstyleliteralemphasis{\sphinxupquote{') self.no_contractions += 1 - def depart_literal_emphasis(self, node): - # type: (nodes.Element) -> None + def depart_literal_emphasis(self, node: Element) -> None: self.body.append('}}') self.no_contractions -= 1 - def visit_strong(self, node): - # type: (nodes.Element) -> None + def visit_strong(self, node: Element) -> None: self.body.append(r'\sphinxstylestrong{') - def depart_strong(self, node): - # type: (nodes.Element) -> None + def depart_strong(self, node: Element) -> None: self.body.append('}') - def visit_literal_strong(self, node): - # type: (nodes.Element) -> None + def visit_literal_strong(self, node: Element) -> None: self.body.append(r'\sphinxstyleliteralstrong{\sphinxupquote{') self.no_contractions += 1 - def depart_literal_strong(self, node): - # type: (nodes.Element) -> None + def depart_literal_strong(self, node: Element) -> None: self.body.append('}}') self.no_contractions -= 1 - def visit_abbreviation(self, node): - # type: (nodes.Element) -> None + def visit_abbreviation(self, node: Element) -> None: abbr = node.astext() self.body.append(r'\sphinxstyleabbreviation{') # spell out the explanation once @@ -2045,28 +1873,22 @@ class LaTeXTranslator(SphinxTranslator): else: self.context.append('}') - def depart_abbreviation(self, node): - # type: (nodes.Element) -> None + def depart_abbreviation(self, node: Element) -> None: self.body.append(self.context.pop()) - def visit_manpage(self, node): - # type: (nodes.Element) -> None + def visit_manpage(self, node: Element) -> None: return self.visit_literal_emphasis(node) - def depart_manpage(self, node): - # type: (nodes.Element) -> None + def depart_manpage(self, node: Element) -> None: return self.depart_literal_emphasis(node) - def visit_title_reference(self, node): - # type: (nodes.Element) -> None + def visit_title_reference(self, node: Element) -> None: self.body.append(r'\sphinxtitleref{') - def depart_title_reference(self, node): - # type: (nodes.Element) -> None + def depart_title_reference(self, node: Element) -> None: self.body.append('}') - def visit_thebibliography(self, node): - # type: (thebibliography) -> None + def visit_thebibliography(self, node: Element) -> None: citations = cast(Iterable[nodes.citation], node) labels = (cast(nodes.label, citation[0]) for citation in citations) longest_label = max((label.astext() for label in labels), key=len) @@ -2077,78 +1899,63 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\n\\begin{sphinxthebibliography}{%s}\n' % self.encode(longest_label)) - def depart_thebibliography(self, node): - # type: (thebibliography) -> None + def depart_thebibliography(self, node: Element) -> None: self.body.append('\\end{sphinxthebibliography}\n') - def visit_citation(self, node): - # type: (nodes.Element) -> None + def visit_citation(self, node: Element) -> None: label = cast(nodes.label, node[0]) self.body.append('\\bibitem[%s]{%s:%s}' % (self.encode(label.astext()), node['docname'], node['ids'][0])) - def depart_citation(self, node): - # type: (nodes.Element) -> None + def depart_citation(self, node: Element) -> None: pass - def visit_citation_reference(self, node): - # type: (nodes.Element) -> None + def visit_citation_reference(self, node: Element) -> None: if self.in_title: pass else: self.body.append('\\sphinxcite{%s:%s}' % (node['docname'], node['refname'])) raise nodes.SkipNode - def depart_citation_reference(self, node): - # type: (nodes.Element) -> None + def depart_citation_reference(self, node: Element) -> None: pass - def visit_literal(self, node): - # type: (nodes.Element) -> None + def visit_literal(self, node: Element) -> None: self.no_contractions += 1 if self.in_title: self.body.append(r'\sphinxstyleliteralintitle{\sphinxupquote{') else: self.body.append(r'\sphinxcode{\sphinxupquote{') - def depart_literal(self, node): - # type: (nodes.Element) -> None + def depart_literal(self, node: Element) -> None: self.no_contractions -= 1 self.body.append('}}') - def visit_footnote_reference(self, node): - # type: (nodes.Element) -> None + def visit_footnote_reference(self, node: Element) -> None: raise nodes.SkipNode - def visit_footnotemark(self, node): - # type: (footnotemark) -> None + def visit_footnotemark(self, node: Element) -> None: self.body.append('\\sphinxfootnotemark[') - def depart_footnotemark(self, node): - # type: (footnotemark) -> None + def depart_footnotemark(self, node: Element) -> None: self.body.append(']') - def visit_footnotetext(self, node): - # type: (footnotetext) -> None + def visit_footnotetext(self, node: Element) -> None: label = cast(nodes.label, node[0]) self.body.append('%%\n\\begin{footnotetext}[%s]' '\\sphinxAtStartFootnote\n' % label.astext()) - def depart_footnotetext(self, node): - # type: (footnotetext) -> None + def depart_footnotetext(self, node: Element) -> None: # the \ignorespaces in particular for after table header use self.body.append('%\n\\end{footnotetext}\\ignorespaces ') - def visit_captioned_literal_block(self, node): - # type: (captioned_literal_block) -> None + def visit_captioned_literal_block(self, node: Element) -> None: pass - def depart_captioned_literal_block(self, node): - # type: (captioned_literal_block) -> None + def depart_captioned_literal_block(self, node: Element) -> None: pass - def visit_literal_block(self, node): - # type: (nodes.Element) -> None + def visit_literal_block(self, node: Element) -> None: if node.rawsource != node.astext(): # most probably a parsed-literal block -- don't highlight self.in_parsed_literal += 1 @@ -2203,23 +2010,19 @@ class LaTeXTranslator(SphinxTranslator): self.body.append('\\sphinxresetverbatimhllines\n') raise nodes.SkipNode - def depart_literal_block(self, node): - # type: (nodes.Element) -> None + def depart_literal_block(self, node: Element) -> None: self.body.append('\n\\end{sphinxalltt}\n') self.in_parsed_literal -= 1 visit_doctest_block = visit_literal_block depart_doctest_block = depart_literal_block - def visit_line(self, node): - # type: (nodes.Element) -> None + def visit_line(self, node: Element) -> None: self.body.append('\\item[] ') - def depart_line(self, node): - # type: (nodes.Element) -> None + def depart_line(self, node: Element) -> None: self.body.append('\n') - def visit_line_block(self, node): - # type: (nodes.Element) -> None + def visit_line_block(self, node: Element) -> None: if isinstance(node.parent, nodes.line_block): self.body.append('\\item[]\n' '\\begin{DUlineblock}{\\DUlineblockindent}\n') @@ -2228,12 +2031,10 @@ class LaTeXTranslator(SphinxTranslator): if self.table: self.table.has_problematic = True - def depart_line_block(self, node): - # type: (nodes.Element) -> None + def depart_line_block(self, node: Element) -> None: self.body.append('\\end{DUlineblock}\n') - def visit_block_quote(self, node): - # type: (nodes.Element) -> None + def visit_block_quote(self, node: Element) -> None: # If the block quote contains a single object and that object # is a list, then generate a list not a block quote. # This lets us indent lists. @@ -2248,8 +2049,7 @@ class LaTeXTranslator(SphinxTranslator): if self.table: self.table.has_problematic = True - def depart_block_quote(self, node): - # type: (nodes.Element) -> None + def depart_block_quote(self, node: Element) -> None: done = 0 if len(node.children) == 1: child = node.children[0] @@ -2261,89 +2061,71 @@ class LaTeXTranslator(SphinxTranslator): # option node handling copied from docutils' latex writer - def visit_option(self, node): - # type: (nodes.Element) -> None + def visit_option(self, node: Element) -> None: if self.context[-1]: # this is not the first option self.body.append(', ') - def depart_option(self, node): - # type: (nodes.Element) -> None + def depart_option(self, node: Element) -> None: # flag that the first option is done. self.context[-1] += 1 - def visit_option_argument(self, node): - # type: (nodes.Element) -> None + def visit_option_argument(self, node: Element) -> None: """The delimiter betweeen an option and its argument.""" self.body.append(node.get('delimiter', ' ')) - def depart_option_argument(self, node): - # type: (nodes.Element) -> None + def depart_option_argument(self, node: Element) -> None: pass - def visit_option_group(self, node): - # type: (nodes.Element) -> None + def visit_option_group(self, node: Element) -> None: self.body.append('\\item [') # flag for first option self.context.append(0) - def depart_option_group(self, node): - # type: (nodes.Element) -> None + def depart_option_group(self, node: Element) -> None: self.context.pop() # the flag self.body.append('] ') - def visit_option_list(self, node): - # type: (nodes.Element) -> None + def visit_option_list(self, node: Element) -> None: self.body.append('\\begin{optionlist}{3cm}\n') if self.table: self.table.has_problematic = True - def depart_option_list(self, node): - # type: (nodes.Element) -> None + def depart_option_list(self, node: Element) -> None: self.body.append('\\end{optionlist}\n') - def visit_option_list_item(self, node): - # type: (nodes.Element) -> None + def visit_option_list_item(self, node: Element) -> None: pass - def depart_option_list_item(self, node): - # type: (nodes.Element) -> None + def depart_option_list_item(self, node: Element) -> None: pass - def visit_option_string(self, node): - # type: (nodes.Element) -> None + def visit_option_string(self, node: Element) -> None: ostring = node.astext() self.no_contractions += 1 self.body.append(self.encode(ostring)) self.no_contractions -= 1 raise nodes.SkipNode - def visit_description(self, node): - # type: (nodes.Element) -> None + def visit_description(self, node: Element) -> None: self.body.append(' ') - def depart_description(self, node): - # type: (nodes.Element) -> None + def depart_description(self, node: Element) -> None: pass - def visit_superscript(self, node): - # type: (nodes.Element) -> None + def visit_superscript(self, node: Element) -> None: self.body.append('$^{\\text{') - def depart_superscript(self, node): - # type: (nodes.Element) -> None + def depart_superscript(self, node: Element) -> None: self.body.append('}}$') - def visit_subscript(self, node): - # type: (nodes.Element) -> None + def visit_subscript(self, node: Element) -> None: self.body.append('$_{\\text{') - def depart_subscript(self, node): - # type: (nodes.Element) -> None + def depart_subscript(self, node: Element) -> None: self.body.append('}}$') - def visit_inline(self, node): - # type: (nodes.Element) -> None + def visit_inline(self, node: Element) -> None: classes = node.get('classes', []) if classes in [['menuselection']]: self.body.append(r'\sphinxmenuselection{') @@ -2360,60 +2142,47 @@ class LaTeXTranslator(SphinxTranslator): else: self.context.append('') - def depart_inline(self, node): - # type: (nodes.Element) -> None + def depart_inline(self, node: Element) -> None: self.body.append(self.context.pop()) - def visit_generated(self, node): - # type: (nodes.Element) -> None + def visit_generated(self, node: Element) -> None: pass - def depart_generated(self, node): - # type: (nodes.Element) -> None + def depart_generated(self, node: Element) -> None: pass - def visit_compound(self, node): - # type: (nodes.Element) -> None + def visit_compound(self, node: Element) -> None: pass - def depart_compound(self, node): - # type: (nodes.Element) -> None + def depart_compound(self, node: Element) -> None: pass - def visit_container(self, node): - # type: (nodes.Element) -> None + def visit_container(self, node: Element) -> None: pass - def depart_container(self, node): - # type: (nodes.Element) -> None + def depart_container(self, node: Element) -> None: pass - def visit_decoration(self, node): - # type: (nodes.Element) -> None + def visit_decoration(self, node: Element) -> None: pass - def depart_decoration(self, node): - # type: (nodes.Element) -> None + def depart_decoration(self, node: Element) -> None: pass # docutils-generated elements that we don't support - def visit_header(self, node): - # type: (nodes.Element) -> None + def visit_header(self, node: Element) -> None: raise nodes.SkipNode - def visit_footer(self, node): - # type: (nodes.Element) -> None + def visit_footer(self, node: Element) -> None: raise nodes.SkipNode - def visit_docinfo(self, node): - # type: (nodes.Element) -> None + def visit_docinfo(self, node: Element) -> None: raise nodes.SkipNode # text handling - def encode(self, text): - # type: (str) -> str + def encode(self, text: str) -> str: text = self.escape(text) if self.literal_whitespace: # Insert a blank before the newline, to avoid @@ -2424,47 +2193,38 @@ class LaTeXTranslator(SphinxTranslator): text = text.replace("''", "'{'}") return text - def encode_uri(self, text): - # type: (str) -> str + def encode_uri(self, text: str) -> str: # in \href, the tilde is allowed and must be represented literally return self.encode(text).replace('\\textasciitilde{}', '~') - def visit_Text(self, node): - # type: (nodes.Text) -> None + def visit_Text(self, node: Text) -> None: text = self.encode(node.astext()) self.body.append(text) - def depart_Text(self, node): - # type: (nodes.Text) -> None + def depart_Text(self, node: Text) -> None: pass - def visit_comment(self, node): - # type: (nodes.Element) -> None + def visit_comment(self, node: Element) -> None: raise nodes.SkipNode - def visit_meta(self, node): - # type: (nodes.Element) -> None + def visit_meta(self, node: Element) -> None: # only valid for HTML raise nodes.SkipNode - def visit_system_message(self, node): - # type: (nodes.Element) -> None + def visit_system_message(self, node: Element) -> None: pass - def depart_system_message(self, node): - # type: (nodes.Element) -> None + def depart_system_message(self, node: Element) -> None: self.body.append('\n') - def visit_math(self, node): - # type: (nodes.Element) -> None + def visit_math(self, node: Element) -> None: if self.in_title: self.body.append(r'\protect\(%s\protect\)' % node.astext()) else: self.body.append(r'\(%s\)' % node.astext()) raise nodes.SkipNode - def visit_math_block(self, node): - # type: (nodes.Element) -> None + def visit_math_block(self, node: Element) -> None: if node.get('label'): label = "equation:%s:%s" % (node['docname'], node['label']) else: @@ -2480,8 +2240,7 @@ class LaTeXTranslator(SphinxTranslator): self.builder.config.math_number_all)) raise nodes.SkipNode - def visit_math_reference(self, node): - # type: (math_reference) -> None + def visit_math_reference(self, node: Element) -> None: label = "equation:%s:%s" % (node['docname'], node['target']) eqref_format = self.builder.config.math_eqref_format if eqref_format: @@ -2495,20 +2254,16 @@ class LaTeXTranslator(SphinxTranslator): else: self.body.append(r'\eqref{%s}' % label) - def depart_math_reference(self, node): - # type: (math_reference) -> None + def depart_math_reference(self, node: Element) -> None: pass - def unknown_visit(self, node): - # type: (nodes.Node) -> None + def unknown_visit(self, node: Node) -> None: raise NotImplementedError('Unknown node: ' + node.__class__.__name__) # --------- METHODS FOR COMPATIBILITY -------------------------------------- - def collect_footnotes(self, node): - # type: (nodes.Element) -> Dict[str, List[Union[collected_footnote, bool]]] - def footnotes_under(n): - # type: (nodes.Element) -> Iterator[nodes.footnote] + def collect_footnotes(self, node: Element) -> Dict[str, List[Union["collected_footnote", bool]]]: # NOQA + def footnotes_under(n: Element) -> Iterator[nodes.footnote]: if isinstance(n, nodes.footnote): yield n else: @@ -2530,61 +2285,52 @@ class LaTeXTranslator(SphinxTranslator): return fnotes @property - def footnotestack(self): - # type: () -> List[Dict[str, List[Union[collected_footnote, bool]]]] + def footnotestack(self) -> List[Dict[str, List[Union[collected_footnote, bool]]]]: warnings.warn('LaTeXWriter.footnotestack is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return [] @property - def bibitems(self): - # type: () -> List[List[str]] + def bibitems(self) -> List[List[str]]: warnings.warn('LaTeXTranslator.bibitems() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return [] @property - def in_container_literal_block(self): - # type: () -> int + def in_container_literal_block(self) -> int: warnings.warn('LaTeXTranslator.in_container_literal_block is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return 0 @property - def next_section_ids(self): - # type: () -> Set[str] + def next_section_ids(self) -> Set[str]: warnings.warn('LaTeXTranslator.next_section_ids is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return set() @property - def next_hyperlink_ids(self): - # type: () -> Dict + def next_hyperlink_ids(self) -> Dict: warnings.warn('LaTeXTranslator.next_hyperlink_ids is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return {} - def push_hyperlink_ids(self, figtype, ids): - # type: (str, Set[str]) -> None + def push_hyperlink_ids(self, figtype: str, ids: Set[str]) -> None: warnings.warn('LaTeXTranslator.push_hyperlink_ids() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) pass - def pop_hyperlink_ids(self, figtype): - # type: (str) -> Set[str] + def pop_hyperlink_ids(self, figtype: str) -> Set[str]: warnings.warn('LaTeXTranslator.pop_hyperlink_ids() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return set() @property - def hlsettingstack(self): - # type: () -> List[List[Union[str, int]]] + def hlsettingstack(self) -> List[List[Union[str, int]]]: warnings.warn('LaTeXTranslator.hlsettingstack is deprecated.', RemovedInSphinx30Warning, stacklevel=2) return [[self.builder.config.highlight_language, sys.maxsize]] - def check_latex_elements(self): - # type: () -> None + def check_latex_elements(self) -> None: warnings.warn('check_latex_elements() is deprecated.', RemovedInSphinx30Warning, stacklevel=2) @@ -2593,8 +2339,7 @@ class LaTeXTranslator(SphinxTranslator): msg = __("Unknown configure key: latex_elements[%r] is ignored.") logger.warning(msg % key) - def babel_defmacro(self, name, definition): - # type: (str, str) -> str + def babel_defmacro(self, name: str, definition: str) -> str: warnings.warn('babel_defmacro() is deprecated.', RemovedInSphinx40Warning) @@ -2607,19 +2352,16 @@ class LaTeXTranslator(SphinxTranslator): return ('%s\\def%s{%s}%s\n' % (prefix, name, definition, suffix)) - def _make_visit_admonition(name): # type: ignore - # type: (str) -> Callable[[LaTeXTranslator, nodes.Element], None] + def _make_visit_admonition(name: str) -> Callable[["LaTeXTranslator", Element], None]: # type: ignore # NOQA warnings.warn('LaTeXTranslator._make_visit_admonition() is deprecated.', RemovedInSphinx30Warning) - def visit_admonition(self, node): - # type: (LaTeXTranslator, nodes.Element) -> None + def visit_admonition(self: "LaTeXTranslator", node: Element) -> None: self.body.append('\n\\begin{sphinxadmonition}{%s}{%s:}' % (name, admonitionlabels[name])) return visit_admonition - def generate_numfig_format(self, builder): - # type: (LaTeXBuilder) -> str + def generate_numfig_format(self, builder: "LaTeXBuilder") -> str: warnings.warn('generate_numfig_format() is deprecated.', RemovedInSphinx40Warning) ret = [] # type: List[str] From 82b2b1752ab652fe59a236649c99c9099d7fe0ce Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 27 Nov 2019 00:12:32 +0900 Subject: [PATCH 25/28] doc: URL of numpydoc has changed --- doc/usage/extensions/napoleon.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/usage/extensions/napoleon.rst b/doc/usage/extensions/napoleon.rst index 0460f1607..b12dd03ba 100644 --- a/doc/usage/extensions/napoleon.rst +++ b/doc/usage/extensions/napoleon.rst @@ -56,7 +56,7 @@ source code files. .. _Google: https://google.github.io/styleguide/pyguide.html#Comments .. _NumPy: - https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt + https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard .. _Khan Academy: https://github.com/Khan/style-guides/blob/master/style/python.md#docstrings From c6d9924735e32e1e81f3732006d3389e9ad6ffd6 Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 4 Jul 2019 09:42:03 -0400 Subject: [PATCH 26/28] Opensearch: Use favicon if available --- sphinx/themes/basic/opensearch.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sphinx/themes/basic/opensearch.xml b/sphinx/themes/basic/opensearch.xml index a750b3041..bac08b4a2 100644 --- a/sphinx/themes/basic/opensearch.xml +++ b/sphinx/themes/basic/opensearch.xml @@ -6,5 +6,8 @@ {{ docstitle|e }} +{%- if favicon %} + {{ use_opensearch }}/{{ pathto('_static/' + favicon, 1) }} +{%- endif %} {% block extra %} {# Put e.g. an element here. #} {% endblock %} From afca037aa4c2c2d53ac6c9b6fc6e3ef1b827c2f4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 28 Nov 2019 22:29:56 +0900 Subject: [PATCH 27/28] Update CHANGES for PR #6548 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 183bccd43..0887943e5 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Features added * #6707: C++, support bit-fields. * #267: html: Eliminate prompt characters of doctest block from copyable text +* #6548: html: Use favicon for OpenSearch if available * #6729: html theme: agogo theme now supports ``rightsidebar`` option * #6780: Add PEP-561 Support * #6762: latex: Allow to load additonal LaTeX packages via ``extrapackages`` key From 82a6048f1205ee032327e1643d879ef322a2012f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 28 Nov 2019 23:31:08 +0900 Subject: [PATCH 28/28] Fix typo --- doc/usage/extensions/autodoc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/usage/extensions/autodoc.rst b/doc/usage/extensions/autodoc.rst index 74c0b609d..3bb9630bd 100644 --- a/doc/usage/extensions/autodoc.rst +++ b/doc/usage/extensions/autodoc.rst @@ -439,7 +439,7 @@ There are also config values that you can set: * ``'signature'`` -- Show typehints as its signature (default) * ``'none'`` -- Do not show typehints - .. versionadded: 2.1 + .. versionadded:: 2.1 .. confval:: autodoc_warningiserror