diff options
Diffstat (limited to 'sphinx/writers/texinfo.py')
| -rw-r--r-- | sphinx/writers/texinfo.py | 600 |
1 files changed, 307 insertions, 293 deletions
diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index d7490a652..4ea518eec 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ sphinx.writers.texinfo ~~~~~~~~~~~~~~~~~~~~~~ @@ -11,16 +10,18 @@ import re import textwrap +import warnings from os import path +from typing import Iterable, cast from docutils import nodes, writers -from six import itervalues -from six.moves import range from sphinx import addnodes, __display_version__ +from sphinx.deprecation import RemovedInSphinx30Warning from sphinx.errors import ExtensionError from sphinx.locale import admonitionlabels, _, __ from sphinx.util import logging +from sphinx.util.docutils import SphinxTranslator from sphinx.util.i18n import format_date from sphinx.writers.latex import collected_footnote @@ -28,6 +29,7 @@ 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 logger = logging.getLogger(__name__) @@ -88,19 +90,20 @@ TEMPLATE = """\ def find_subsections(section): - # type: (nodes.Node) -> List[nodes.Node] + # type: (nodes.Element) -> List[nodes.section] """Return a list of subsections for the given ``section``.""" result = [] - for child in section.children: + for child in section: if isinstance(child, nodes.section): result.append(child) continue - result.extend(find_subsections(child)) + elif isinstance(child, nodes.Element): + result.extend(find_subsections(child)) return result def smart_capwords(s, sep=None): - # type: (unicode, unicode) -> unicode + # type: (str, str) -> str """Like string.capwords() but does not capitalize words that already contain a capital letter.""" words = s.split(sep) @@ -120,30 +123,32 @@ class TexinfoWriter(writers.Writer): ('Dir entry', ['--texinfo-dir-entry'], {'default': ''}), ('Description', ['--texinfo-dir-description'], {'default': ''}), ('Category', ['--texinfo-dir-category'], {'default': - 'Miscellaneous'}))) # type: Tuple[unicode, Any, Tuple[Tuple[unicode, List[unicode], Dict[unicode, unicode]], ...]] # NOQA + 'Miscellaneous'}))) # type: Tuple[str, Any, Tuple[Tuple[str, List[str], Dict[str, str]], ...]] # NOQA settings_defaults = {} # type: Dict - output = None # type: unicode + output = None # type: str visitor_attributes = ('output', 'fragment') def __init__(self, builder): # type: (TexinfoBuilder) -> None - writers.Writer.__init__(self) + super().__init__() self.builder = builder def translate(self): # type: () -> None - self.visitor = visitor = self.builder.create_translator(self.document, self.builder) + visitor = self.builder.create_translator(self.document, self.builder) + self.visitor = cast(TexinfoTranslator, visitor) self.document.walkabout(visitor) - visitor.finish() + self.visitor.finish() for attr in self.visitor_attributes: - setattr(self, attr, getattr(visitor, attr)) + setattr(self, attr, getattr(self.visitor, attr)) -class TexinfoTranslator(nodes.NodeVisitor): +class TexinfoTranslator(SphinxTranslator): + builder = None # type: TexinfoBuilder ignore_missing_images = False default_elements = { @@ -162,24 +167,23 @@ class TexinfoTranslator(nodes.NodeVisitor): } def __init__(self, document, builder): - # type: (nodes.Node, TexinfoBuilder) -> None - nodes.NodeVisitor.__init__(self, document) - self.builder = builder + # type: (nodes.document, TexinfoBuilder) -> None + super().__init__(document, builder) self.init_settings() - self.written_ids = set() # type: Set[unicode] + self.written_ids = set() # type: Set[str] # node names and anchors in output # node names and anchors that should be in output - self.referenced_ids = set() # type: Set[unicode] - self.indices = [] # type: List[Tuple[unicode, unicode]] + self.referenced_ids = set() # type: Set[str] + self.indices = [] # type: List[Tuple[str, str]] # (node name, content) - self.short_ids = {} # type: Dict[unicode, unicode] + self.short_ids = {} # type: Dict[str, str] # anchors --> short ids - self.node_names = {} # type: Dict[unicode, unicode] + self.node_names = {} # type: Dict[str, str] # node name --> node's name to display - self.node_menus = {} # type: Dict[unicode, List[unicode]] + self.node_menus = {} # type: Dict[str, List[str]] # node name --> node's menu entries - self.rellinks = {} # type: Dict[unicode, List[unicode]] + self.rellinks = {} # type: Dict[str, List[str]] # node name --> (next, previous, up) self.collect_indices() @@ -187,18 +191,18 @@ class TexinfoTranslator(nodes.NodeVisitor): self.collect_node_menus() self.collect_rellinks() - self.body = [] # type: List[unicode] - self.context = [] # type: List[unicode] + self.body = [] # type: List[str] + self.context = [] # type: List[str] self.previous_section = None # type: nodes.section self.section_level = 0 self.seen_title = False - self.next_section_ids = set() # type: Set[unicode] + self.next_section_ids = set() # type: Set[str] self.escape_newlines = 0 self.escape_hyphens = 0 - self.curfilestack = [] # type: List[unicode] - self.footnotestack = [] # type: List[Dict[unicode, List[Union[collected_footnote, bool]]]] # NOQA + self.curfilestack = [] # type: List[str] + self.footnotestack = [] # type: List[Dict[str, List[Union[collected_footnote, bool]]]] # NOQA self.in_footnote = 0 - self.handled_abbrs = set() # type: Set[unicode] + self.handled_abbrs = set() # type: Set[str] self.colwidths = None # type: List[int] def finish(self): @@ -225,14 +229,13 @@ class TexinfoTranslator(nodes.NodeVisitor): def init_settings(self): # type: () -> None - settings = self.settings = self.document.settings elements = self.elements = self.default_elements.copy() elements.update({ # if empty, the title is set to the first section title - 'title': settings.title, - 'author': settings.author, + 'title': self.settings.title, + 'author': self.settings.author, # if empty, use basename of input file - 'filename': settings.texinfo_filename, + 'filename': self.settings.texinfo_filename, 'release': self.escape(self.builder.config.release), 'project': self.escape(self.builder.config.project), 'copyright': self.escape(self.builder.config.copyright), @@ -241,11 +244,10 @@ class TexinfoTranslator(nodes.NodeVisitor): language=self.builder.config.language)) }) # title - title = None # type: unicode - title = elements['title'] # type: ignore + title = self.settings.title # type: str if not title: - title = self.document.next_node(nodes.title) - title = (title and title.astext()) or '<untitled>' # type: ignore + title_node = self.document.next_node(nodes.title) + title = (title and title_node.astext()) or '<untitled>' elements['title'] = self.escape_id(title) or '<untitled>' # filename if not elements['filename']: @@ -254,19 +256,19 @@ class TexinfoTranslator(nodes.NodeVisitor): elements['filename'] = elements['filename'][:-4] # type: ignore elements['filename'] += '.info' # type: ignore # direntry - if settings.texinfo_dir_entry: + if self.settings.texinfo_dir_entry: entry = self.format_menu_entry( - self.escape_menu(settings.texinfo_dir_entry), + self.escape_menu(self.settings.texinfo_dir_entry), '(%s)' % elements['filename'], - self.escape_arg(settings.texinfo_dir_description)) + self.escape_arg(self.settings.texinfo_dir_description)) elements['direntry'] = ('@dircategory %s\n' '@direntry\n' '%s' '@end direntry\n') % ( - self.escape_id(settings.texinfo_dir_category), entry) + self.escape_id(self.settings.texinfo_dir_category), entry) elements['copying'] = COPYING % elements # allow the user to override them all - elements.update(settings.texinfo_elements) + elements.update(self.settings.texinfo_elements) def collect_node_names(self): # type: () -> None @@ -275,7 +277,7 @@ class TexinfoTranslator(nodes.NodeVisitor): Assigns the attribute ``node_name`` to each section.""" def add_node_name(name): - # type: (unicode) -> unicode + # type: (str) -> str node_id = self.escape_id(name) nth, suffix = 1, '' while node_id + suffix in self.written_ids or \ @@ -296,7 +298,7 @@ class TexinfoTranslator(nodes.NodeVisitor): for name, content in self.indices] # each section is also a node for section in self.document.traverse(nodes.section): - title = section.next_node(nodes.Titular) + title = cast(nodes.TextElement, section.next_node(nodes.Titular)) name = (title and title.astext()) or '<untitled>' section['node_name'] = add_node_name(name) @@ -304,8 +306,9 @@ class TexinfoTranslator(nodes.NodeVisitor): # type: () -> None """Collect the menu entries for each "node" section.""" node_menus = self.node_menus - for node in ([self.document] + - self.document.traverse(nodes.section)): + targets = [self.document] # type: List[nodes.Element] + targets.extend(self.document.traverse(nodes.section)) + for node in targets: assert 'node_name' in node and node['node_name'] entries = [s['node_name'] for s in find_subsections(node)] node_menus[node['node_name']] = entries @@ -360,7 +363,7 @@ class TexinfoTranslator(nodes.NodeVisitor): # characters. def escape(self, s): - # type: (unicode) -> unicode + # type: (str) -> str """Return a string with Texinfo command characters escaped.""" s = s.replace('@', '@@') s = s.replace('{', '@{') @@ -371,7 +374,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return s def escape_arg(self, s): - # type: (unicode) -> unicode + # type: (str) -> str """Return an escaped string suitable for use as an argument to a Texinfo command.""" s = self.escape(s) @@ -382,7 +385,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return s def escape_id(self, s): - # type: (unicode) -> unicode + # type: (str) -> str """Return an escaped string suitable for node names and anchors.""" bad_chars = ',:.()' for bc in bad_chars: @@ -391,7 +394,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return self.escape(s) def escape_menu(self, s): - # type: (unicode) -> unicode + # type: (str) -> str """Return an escaped string suitable for menu entries.""" s = self.escape_arg(s) s = s.replace(':', ';') @@ -405,7 +408,7 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('\n') def format_menu_entry(self, name, node_name, desc): - # type: (unicode, unicode, unicode) -> unicode + # type: (str, str, str) -> str if name == node_name: s = '* %s:: ' % (name,) else: @@ -416,7 +419,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return s + wdesc.strip() + '\n' def add_menu_entries(self, entries, reg=re.compile(r'\s+---?\s+')): - # type: (List[unicode], Pattern) -> None + # type: (List[str], Pattern) -> None for entry in entries: name = self.node_names[entry] # special formatting for entries that are divided by an em-dash @@ -434,7 +437,7 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append(self.format_menu_entry(name, entry, desc)) def add_menu(self, node_name): - # type: (unicode) -> None + # type: (str) -> None entries = self.node_menus[node_name] if not entries: return @@ -447,7 +450,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return def _add_detailed_menu(name): - # type: (unicode) -> None + # type: (str) -> None entries = self.node_menus[name] if not entries: return @@ -464,7 +467,7 @@ class TexinfoTranslator(nodes.NodeVisitor): '@end menu\n') def tex_image_length(self, width_str): - # type: (unicode) -> unicode + # type: (str) -> str match = re.match(r'(\d*\.?\d*)\s*(\S*)', width_str) if not match: # fallback @@ -482,15 +485,15 @@ class TexinfoTranslator(nodes.NodeVisitor): def collect_indices(self): # type: () -> None def generate(content, collapsed): - # type: (List[Tuple[unicode, List[List[Union[unicode, int]]]]], bool) -> unicode - ret = ['\n@menu\n'] # type: List[unicode] + # type: (List[Tuple[str, List[IndexEntry]]], bool) -> str + ret = ['\n@menu\n'] for letter, entries in content: for entry in entries: if not entry[3]: continue - name = self.escape_menu(entry[0]) # type: ignore + name = self.escape_menu(entry[0]) sid = self.get_short_id('%s:%s' % (entry[2], entry[3])) - desc = self.escape_arg(entry[6]) # type: ignore + desc = self.escape_arg(entry[6]) me = self.format_menu_entry(name, sid, desc) ret.append(me) ret.append('@end menu\n') @@ -498,7 +501,7 @@ class TexinfoTranslator(nodes.NodeVisitor): indices_config = self.builder.config.texinfo_domain_indices if indices_config: - for domain in itervalues(self.builder.env.domains): + for domain in self.builder.env.domains.values(): for indexcls in domain.indices: indexname = '%s-%s' % (domain.name, indexcls.name) if isinstance(indices_config, list): @@ -520,27 +523,28 @@ class TexinfoTranslator(nodes.NodeVisitor): # TODO: move this to sphinx.util def collect_footnotes(self, node): - # type: (nodes.Node) -> Dict[unicode, List[Union[collected_footnote, bool]]] + # type: (nodes.Element) -> Dict[str, List[Union[collected_footnote, bool]]] def footnotes_under(n): - # type: (nodes.Node) -> Iterator[nodes.footnote] + # type: (nodes.Element) -> Iterator[nodes.footnote] if isinstance(n, nodes.footnote): yield n else: for c in n.children: if isinstance(c, addnodes.start_of_file): continue - for k in footnotes_under(c): - yield k - fnotes = {} # type: Dict[unicode, List[Union[collected_footnote, bool]]] + elif isinstance(c, nodes.Element): + yield from footnotes_under(c) + fnotes = {} # type: Dict[str, List[Union[collected_footnote, bool]]] for fn in footnotes_under(node): - num = fn.children[0].astext().strip() - fnotes[num] = [collected_footnote(*fn.children), False] + label = cast(nodes.label, fn[0]) + num = label.astext().strip() + fnotes[num] = [collected_footnote('', *fn.children), False] return fnotes # -- xref handling def get_short_id(self, id): - # type: (unicode) -> unicode + # type: (str) -> str """Return a shorter 'id' associated with ``id``.""" # Shorter ids improve paragraph filling in places # that the id is hidden by Emacs. @@ -552,7 +556,7 @@ class TexinfoTranslator(nodes.NodeVisitor): return sid def add_anchor(self, id, node): - # type: (unicode, nodes.Node) -> None + # type: (str, nodes.Node) -> None if id.startswith('index-'): return id = self.curfilestack[-1] + ':' + id @@ -564,7 +568,7 @@ class TexinfoTranslator(nodes.NodeVisitor): self.written_ids.add(id) def add_xref(self, id, name, node): - # type: (unicode, unicode, nodes.Node) -> None + # type: (str, str, nodes.Node) -> None name = self.escape_menu(name) sid = self.get_short_id(id) self.body.append('@ref{%s,,%s}' % (sid, name)) @@ -574,19 +578,19 @@ class TexinfoTranslator(nodes.NodeVisitor): # -- Visiting def visit_document(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.footnotestack.pop() self.curfilestack.pop() def visit_Text(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Text) -> None s = self.escape(node.astext()) if self.escape_newlines: s = s.replace('\n', ' ') @@ -596,11 +600,11 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append(s) def depart_Text(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Text) -> None pass def visit_section(self, node): - # type: (nodes.section) -> None + # type: (nodes.Element) -> None self.next_section_ids.update(node.get('ids', [])) if not self.seen_title: return @@ -616,11 +620,11 @@ class TexinfoTranslator(nodes.NodeVisitor): self.add_anchor(id, node) self.next_section_ids.clear() - self.previous_section = node + self.previous_section = cast(nodes.section, node) self.section_level += 1 def depart_section(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.section_level -= 1 headings = ( @@ -629,16 +633,16 @@ class TexinfoTranslator(nodes.NodeVisitor): '@section', '@subsection', '@subsubsection', - ) # type: Tuple[unicode, ...] + ) rubrics = ( '@heading', '@subheading', '@subsubheading', - ) # type: Tuple[unicode, ...] + ) def visit_title(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None if not self.seen_title: self.seen_title = True raise nodes.SkipNode @@ -660,13 +664,12 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('\n%s ' % heading) def depart_title(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n') def visit_rubric(self, node): - # type: (nodes.Node) -> None - if len(node.children) == 1 and node.children[0].astext() in \ - ('Footnotes', _('Footnotes')): + # type: (nodes.Element) -> None + if len(node) == 1 and node.astext() in ('Footnotes', _('Footnotes')): raise nodes.SkipNode try: rubric = self.rubrics[self.section_level] @@ -676,22 +679,22 @@ class TexinfoTranslator(nodes.NodeVisitor): self.escape_newlines += 1 def depart_rubric(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.escape_newlines -= 1 self.body.append('\n\n') def visit_subtitle(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n@noindent\n') def depart_subtitle(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n') # -- References def visit_target(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None # postpone the labels until after the sectioning command parindex = node.parent.index(node) try: @@ -716,11 +719,11 @@ class TexinfoTranslator(nodes.NodeVisitor): self.add_anchor(id, node) def depart_target(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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)): @@ -784,17 +787,17 @@ class TexinfoTranslator(nodes.NodeVisitor): raise nodes.SkipNode def depart_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_number_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None text = nodes.Text(node.get('title', '#')) self.visit_Text(text) raise nodes.SkipNode def visit_title_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None text = node.astext() self.body.append('@cite{%s}' % self.escape_arg(text)) raise nodes.SkipNode @@ -802,28 +805,28 @@ class TexinfoTranslator(nodes.NodeVisitor): # -- Blocks def visit_paragraph(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def depart_paragraph(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def visit_block_quote(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@quotation\n') def depart_block_quote(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end quotation\n') def visit_literal_block(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@example\n') def depart_literal_block(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end example\n') @@ -831,86 +834,86 @@ class TexinfoTranslator(nodes.NodeVisitor): depart_doctest_block = depart_literal_block def visit_line_block(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.escape_newlines += 1 def depart_line(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@w{ }\n') self.escape_newlines -= 1 # -- Inline def visit_strong(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@strong{') def depart_strong(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_emphasis(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@emph{') def depart_emphasis(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_literal(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@code{') def depart_literal(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_superscript(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@w{^') def depart_superscript(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_subscript(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@w{[') def depart_subscript(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(']}') # -- Footnotes def visit_footnote(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_collected_footnote(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.in_footnote += 1 self.body.append('@footnote{') def depart_collected_footnote(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') self.in_footnote -= 1 def visit_footnote_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None num = node.astext().strip() try: footnode, used = self.footnotestack[-1][num] @@ -921,38 +924,38 @@ class TexinfoTranslator(nodes.NodeVisitor): raise nodes.SkipChildren def visit_citation(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.escape_newlines -= 1 def visit_citation_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@w{[') def depart_citation_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(']}') # -- Lists def visit_bullet_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None bullet = node.get('bullet', '*') self.body.append('\n\n@itemize %s\n' % bullet) def depart_bullet_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end itemize\n') def visit_enumerated_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None # doesn't support Roman numerals enum = node.get('enumtype', 'arabic') starters = {'arabic': '', @@ -962,100 +965,100 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('\n\n@enumerate %s\n' % start) def depart_enumerated_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end enumerate\n') def visit_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@item ') def depart_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass # -- Option List def visit_option_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n@table @option\n') def depart_option_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end table\n') def visit_option_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_option_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_option_group(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.at_item_x = '@item' def depart_option_group(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_option(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.escape_hyphens -= 1 def visit_option_string(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_option_string(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_option_argument(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(node.get('delimiter', ' ')) def depart_option_argument(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_description(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def depart_description(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass # -- Definitions def visit_definition_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n@table @asis\n') def depart_definition_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end table\n') def visit_definition_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.at_item_x = '@item' def depart_definition_list_item(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_term(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None for id in node.get('ids'): self.add_anchor(id, node) # anchors and indexes need to go in front @@ -1067,45 +1070,45 @@ class TexinfoTranslator(nodes.NodeVisitor): self.at_item_x = '@itemx' def depart_term(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_classifier(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(' : ') def depart_classifier(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_definition(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def depart_definition(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass # -- Tables def visit_table(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.entry_sep = '@item' def depart_table(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@end multitable\n\n') def visit_tabular_col_spec(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_tabular_col_spec(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_colspec(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.colwidths.append(node['colwidth']) if len(self.colwidths) != self.n_cols: return @@ -1114,209 +1117,208 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('{%s} ' % ('x' * (n + 2))) def depart_colspec(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_tgroup(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.colwidths = [] self.n_cols = node['cols'] def depart_tgroup(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_thead(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.entry_sep = '@headitem' def depart_thead(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_tbody(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_tbody(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_row(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_row(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.entry_sep = '@item' def visit_entry(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n%s\n' % self.entry_sep) self.entry_sep = '@tab' def depart_entry(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None pass def depart_field_list(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_field(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def depart_field(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def visit_field_name(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@*') def depart_field_name(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(': ') def visit_field_body(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_field_body(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass # -- Admonitions def visit_admonition(self, node, name=''): - # type: (nodes.Node, unicode) -> None + # type: (nodes.Element, str) -> None if not name: - name = self.escape(node[0].astext()) - self.body.append(u'\n@cartouche\n@quotation %s ' % 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 + label = admonitionlabels[node.tagname] + self.body.append('\n@cartouche\n@quotation %s ' % label) def depart_admonition(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.ensure_eol() self.body.append('@end quotation\n' '@end cartouche\n') - def _make_visit_admonition(name): - # type: (unicode) -> Callable[[TexinfoTranslator, nodes.Node], None] - def visit(self, node): - # type: (nodes.Node) -> None - self.visit_admonition(node, admonitionlabels[name]) - return visit - - visit_attention = _make_visit_admonition('attention') + visit_attention = _visit_named_admonition depart_attention = depart_admonition - visit_caution = _make_visit_admonition('caution') + visit_caution = _visit_named_admonition depart_caution = depart_admonition - visit_danger = _make_visit_admonition('danger') + visit_danger = _visit_named_admonition depart_danger = depart_admonition - visit_error = _make_visit_admonition('error') + visit_error = _visit_named_admonition depart_error = depart_admonition - visit_hint = _make_visit_admonition('hint') + visit_hint = _visit_named_admonition depart_hint = depart_admonition - visit_important = _make_visit_admonition('important') + visit_important = _visit_named_admonition depart_important = depart_admonition - visit_note = _make_visit_admonition('note') + visit_note = _visit_named_admonition depart_note = depart_admonition - visit_tip = _make_visit_admonition('tip') + visit_tip = _visit_named_admonition depart_tip = depart_admonition - visit_warning = _make_visit_admonition('warning') + visit_warning = _visit_named_admonition depart_warning = depart_admonition # -- Misc def visit_docinfo(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_generated(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_header(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_footer(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_container(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None if node.get('literal_block'): self.body.append('\n\n@float LiteralBlock\n') def depart_container(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None if node.get('literal_block'): self.body.append('\n@end float\n\n') def visit_decoration(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_decoration(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_topic(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None # ignore TOC's since we have to have a "menu" anyway if 'contents' in node.get('classes', []): raise nodes.SkipNode - title = node[0] + title = cast(nodes.title, node[0]) self.visit_rubric(title) self.body.append('%s\n' % self.escape(title.astext())) def depart_topic(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_transition(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n%s\n\n' % ('_' * 66)) def depart_transition(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_attribution(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n@center --- ') def depart_attribution(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n') def visit_raw(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n\n@float Figure\n') def depart_figure(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@end float\n\n') def visit_caption(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None if (isinstance(node.parent, nodes.figure) or (isinstance(node.parent, nodes.container) and node.parent.get('literal_block'))): @@ -1326,14 +1328,14 @@ class TexinfoTranslator(nodes.NodeVisitor): location=(self.curfilestack[-1], node.line)) def depart_caption(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None if node['uri'] in self.builder.images: uri = self.builder.images[node['uri']] else: @@ -1354,65 +1356,65 @@ class TexinfoTranslator(nodes.NodeVisitor): (name, width, height, alt, ext[1:])) def depart_image(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_compound(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_compound(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_sidebar(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.visit_topic(node) def depart_sidebar(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.depart_topic(node) def visit_label(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@w{(') def depart_label(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(')} ') def visit_legend(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_legend(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_system_message(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n@verbatim\n' '<SYSTEM MESSAGE: %s>\n' '@end verbatim\n' % node.astext()) raise nodes.SkipNode def visit_comment(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.body.append('>>') def depart_problematic(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('<<') def unimplemented_visit(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None logger.warning(__("unimplemented node type: %r"), node, location=(self.curfilestack[-1], node.line)) @@ -1428,13 +1430,14 @@ class TexinfoTranslator(nodes.NodeVisitor): # -- Sphinx specific def visit_productionlist(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.visit_literal_block(None) names = [] - for production in node: + productionlist = cast(Iterable[addnodes.production], node) + for production in productionlist: names.append(production['tokenname']) maxlen = max(len(name) for name in names) - for production in node: + for production in productionlist: if production['tokenname']: for id in production.get('ids'): self.add_anchor(id, production) @@ -1447,31 +1450,31 @@ class TexinfoTranslator(nodes.NodeVisitor): raise nodes.SkipNode def visit_production(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_production(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_literal_emphasis(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@code{') def depart_literal_emphasis(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_literal_strong(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@code{') def depart_literal_strong(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('}') def visit_index(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None # terminate the line but don't prevent paragraph breaks if isinstance(node.parent, nodes.paragraph): self.ensure_eol() @@ -1483,75 +1486,76 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('@geindex %s\n' % text) def visit_versionmodified(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def depart_versionmodified(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def visit_start_of_file(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None + # type: (nodes.Element) -> None self.curfilestack.pop() self.footnotestack.pop() def visit_centered(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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.Node) -> None - self.body.append(u'\n\n@subsubheading %s\n\n' % + # type: (nodes.Element) -> None + self.body.append('\n\n@subsubheading %s\n\n' % admonitionlabels['seealso']) def depart_seealso(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('\n') def visit_meta(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None raise nodes.SkipNode def visit_glossary(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_glossary(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_acks(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None + bullet_list = cast(nodes.bullet_list, node[0]) + list_items = cast(Iterable[nodes.list_item], bullet_list) self.body.append('\n\n') - self.body.append(', '.join(n.astext() - for n in node.children[0].children) + '.') + self.body.append(', '.join(n.astext() for n in list_items) + '.') self.body.append('\n\n') raise nodes.SkipNode # -- Desc def visit_desc(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.desc = node self.at_deffnx = '@deffn' def depart_desc(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.desc = None self.ensure_eol() self.body.append('@end deffn\n') def visit_desc_signature(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.escape_hyphens += 1 objtype = node.parent['objtype'] if objtype != 'describe': @@ -1572,74 +1576,74 @@ class TexinfoTranslator(nodes.NodeVisitor): self.desc_type_name = name def depart_desc_signature(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append("\n") self.escape_hyphens -= 1 self.desc_type_name = None def visit_desc_name(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_desc_name(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_desc_addname(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_desc_addname(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_desc_type(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_desc_type(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_desc_returns(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(' -> ') def depart_desc_returns(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_desc_parameterlist(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(' (') self.first_param = 1 def depart_desc_parameterlist(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(')') def visit_desc_parameter(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None if not self.first_param: self.body.append(', ') else: self.first_param = 0 text = self.escape(node.astext()) # replace no-break spaces with normal ones - text = text.replace(u' ', '@w{ }') + text = text.replace(' ', '@w{ }') self.body.append(text) raise nodes.SkipNode def visit_desc_optional(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('[') def depart_desc_optional(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(']') def visit_desc_annotation(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None # Try to avoid duplicating info already displayed by the deffn category. # e.g. # @deffn {Class} Foo @@ -1652,27 +1656,27 @@ class TexinfoTranslator(nodes.NodeVisitor): raise nodes.SkipNode def depart_desc_annotation(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_desc_content(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_desc_content(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_inline(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_inline(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_abbreviation(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None abbr = node.astext() self.body.append('@abbr{') if node.hasattr('explanation') and abbr not in self.handled_abbrs: @@ -1682,58 +1686,68 @@ class TexinfoTranslator(nodes.NodeVisitor): self.context.append('}') def depart_abbreviation(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append(self.context.pop()) def visit_manpage(self, node): - # type: (nodes.Node) -> Any + # type: (nodes.Element) -> None return self.visit_literal_emphasis(node) def depart_manpage(self, node): - # type: (nodes.Node) -> Any + # type: (nodes.Element) -> None return self.depart_literal_emphasis(node) def visit_download_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_download_reference(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_hlist(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.visit_bullet_list(node) def depart_hlist(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.depart_bullet_list(node) def visit_hlistcol(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_hlistcol(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_pending_xref(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def depart_pending_xref(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None pass def visit_math(self, node): - # type: (nodes.Node) -> None + # type: (nodes.Element) -> None self.body.append('@math{' + self.escape_arg(node.astext()) + '}') raise nodes.SkipNode def visit_math_block(self, node): - # type: (nodes.Node) -> None + # type: (nodes.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] + warnings.warn('TexinfoTranslator._make_visit_admonition() is deprecated.', + RemovedInSphinx30Warning) + + def visit(self, node): + # type: (nodes.Element) -> None + self.visit_admonition(node, admonitionlabels[name]) + return visit |
