diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 93e256ebd80..4cdd748ebb7 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -176,7 +176,7 @@ def get_asset_paths(self) -> List[str]: def post_process_images(self, doctree: Node) -> None: """Pick the best candidate for all image URIs.""" images = ImageAdapter(self.env) - for node in doctree.traverse(nodes.image): + for node in doctree.findall(nodes.image): if '?' in node['candidates']: # don't rewrite nonlocal image URIs continue diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py index ab4eda4dde5..45368797848 100644 --- a/sphinx/builders/_epub_base.py +++ b/sphinx/builders/_epub_base.py @@ -277,7 +277,7 @@ def update_node_id(node: Element) -> None: new_ids.append(new_id) node['ids'] = new_ids - for reference in tree.traverse(nodes.reference): + for reference in tree.findall(nodes.reference): if 'refuri' in reference: m = self.refuri_re.match(reference['refuri']) if m: @@ -285,14 +285,14 @@ def update_node_id(node: Element) -> None: if 'refid' in reference: reference['refid'] = self.fix_fragment('', reference['refid']) - for target in tree.traverse(nodes.target): + for target in tree.findall(nodes.target): update_node_id(target) next_node: Node = target.next_node(ascend=True) if isinstance(next_node, nodes.Element): update_node_id(next_node) - for desc_signature in tree.traverse(addnodes.desc_signature): + for desc_signature in tree.findall(addnodes.desc_signature): update_node_id(desc_signature) def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None: @@ -323,14 +323,14 @@ def footnote_spot(tree: nodes.document) -> Tuple[Element, int]: # a) place them after the last existing footnote # b) place them after an (empty) Footnotes rubric # c) create an empty Footnotes rubric at the end of the document - fns = list(tree.traverse(nodes.footnote)) + fns = list(tree.findall(nodes.footnote)) if fns: fn = fns[-1] return fn.parent, fn.parent.index(fn) + 1 - for node in tree.traverse(nodes.rubric): + for node in tree.findall(nodes.rubric): if len(node) == 1 and node.astext() == FOOTNOTES_RUBRIC_NAME: return node.parent, node.parent.index(node) + 1 - doc = list(tree.traverse(nodes.document))[0] + doc = next(tree.findall(nodes.document)) rub = nodes.rubric() rub.append(nodes.Text(FOOTNOTES_RUBRIC_NAME)) doc.append(rub) @@ -339,10 +339,10 @@ def footnote_spot(tree: nodes.document) -> Tuple[Element, int]: if show_urls == 'no': return if show_urls == 'footnote': - doc = list(tree.traverse(nodes.document))[0] + doc = next(tree.findall(nodes.document)) fn_spot, fn_idx = footnote_spot(tree) nr = 1 - for node in list(tree.traverse(nodes.reference)): + for node in list(tree.findall(nodes.reference)): uri = node.get('refuri', '') if (uri.startswith('http:') or uri.startswith('https:') or uri.startswith('ftp:')) and uri not in node.astext(): diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 53660aa5a87..58d36cdab97 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -146,7 +146,7 @@ def compile_catalogs(self, catalogs: Set[CatalogInfo], message: str) -> None: def write_doc(self, docname: str, doctree: nodes.document) -> None: catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)] - for toctree in self.env.tocs[docname].traverse(addnodes.toctree): + for toctree in self.env.tocs[docname].findall(addnodes.toctree): for node, msg in extract_messages(toctree): node.uid = '' # type: ignore # Hack UUID model catalog.add(msg, node) diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py index 4e12a172076..ac1fbbaec9d 100644 --- a/sphinx/builders/html/__init__.py +++ b/sphinx/builders/html/__init__.py @@ -866,7 +866,7 @@ def post_process_images(self, doctree: Node) -> None: Builder.post_process_images(self, doctree) if self.config.html_scaled_image_link and self.html_scaled_image_link: - for node in doctree.traverse(nodes.image): + for node in doctree.findall(nodes.image): if not any((key in node) for key in ['scale', 'width', 'height']): # resizing options are not given. scaled image link is available # only for resized images. diff --git a/sphinx/builders/html/transforms.py b/sphinx/builders/html/transforms.py index 8c50ce0c4a0..ea1d69d12c3 100644 --- a/sphinx/builders/html/transforms.py +++ b/sphinx/builders/html/transforms.py @@ -48,7 +48,7 @@ class KeyboardTransform(SphinxPostTransform): def run(self, **kwargs: Any) -> None: matcher = NodeMatcher(nodes.literal, classes=["kbd"]) - for node in self.document.traverse(matcher): # type: nodes.literal + for node in self.document.findall(matcher): # type: nodes.literal parts = self.pattern.split(node[-1].astext()) if len(parts) == 1 or self.is_multiwords_key(parts): continue diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py index aa707bd5b2f..d7156b796b8 100644 --- a/sphinx/builders/latex/__init__.py +++ b/sphinx/builders/latex/__init__.py @@ -280,7 +280,7 @@ def write(self, *ignored: Any) -> None: encoding='utf-8', overwrite_if_changed=True) with progress_message(__("processing %s") % targetname): doctree = self.env.get_doctree(docname) - toctree = next(iter(doctree.traverse(addnodes.toctree)), None) + toctree = next(doctree.findall(addnodes.toctree), None) if toctree and toctree.get('maxdepth') > 0: tocdepth = toctree.get('maxdepth') else: @@ -310,7 +310,7 @@ def write(self, *ignored: Any) -> None: def get_contentsname(self, indexfile: str) -> str: tree = self.env.get_doctree(indexfile) contentsname = None - for toctree in tree.traverse(addnodes.toctree): + for toctree in tree.findall(addnodes.toctree): if 'caption' in toctree: contentsname = toctree['caption'] break @@ -338,7 +338,7 @@ def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[ new_sect += nodes.title('', '') new_tree += new_sect - for node in tree.traverse(addnodes.toctree): + for node in tree.findall(addnodes.toctree): new_sect += node tree = new_tree largetree = inline_all_toctrees(self, self.docnames, indexfile, tree, @@ -353,7 +353,7 @@ def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[ self.env.resolve_references(largetree, indexfile, self) # resolve :ref:s to distant tex files -- we can't add a cross-reference, # but append the document name - for pendingnode in largetree.traverse(addnodes.pending_xref): + for pendingnode in largetree.findall(addnodes.pending_xref): docname = pendingnode['refdocname'] sectname = pendingnode['refsectname'] newnodes: List[Node] = [nodes.emphasis(sectname, sectname)] diff --git a/sphinx/builders/latex/transforms.py b/sphinx/builders/latex/transforms.py index 343c36cea2b..b12882df68e 100644 --- a/sphinx/builders/latex/transforms.py +++ b/sphinx/builders/latex/transforms.py @@ -33,7 +33,7 @@ class FootnoteDocnameUpdater(SphinxTransform): def apply(self, **kwargs: Any) -> None: matcher = NodeMatcher(*self.TARGET_NODES) - for node in self.document.traverse(matcher): # type: Element + for node in self.document.findall(matcher): # type: Element node['docname'] = self.env.docname @@ -45,7 +45,7 @@ class SubstitutionDefinitionsRemover(SphinxPostTransform): formats = ('latex',) def run(self, **kwargs: Any) -> None: - for node in list(self.document.traverse(nodes.substitution_definition)): + for node in list(self.document.findall(nodes.substitution_definition)): node.parent.remove(node) @@ -81,7 +81,7 @@ def expand_show_urls(self) -> None: if show_urls is False or show_urls == 'no': return - for node in list(self.document.traverse(nodes.reference)): + for node in list(self.document.findall(nodes.reference)): uri = node.get('refuri', '') if uri.startswith(URI_SCHEMES): if uri.startswith('mailto:'): @@ -348,7 +348,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform): formats = ('latex',) def run(self, **kwargs: Any) -> None: - footnotes = list(self.document.traverse(nodes.footnote)) + footnotes = list(self.document.findall(nodes.footnote)) for node in footnotes: node.parent.remove(node) @@ -423,7 +423,7 @@ def depart_thead(self, node: nodes.thead) -> None: self.unrestrict(node) def depart_table(self, node: nodes.table) -> None: - tbody = list(node.traverse(nodes.tbody))[0] + tbody = next(node.findall(nodes.tbody)) for footnote in reversed(self.table_footnotes): fntext = footnotetext('', *footnote.children, ids=footnote['ids']) tbody.insert(0, fntext) @@ -501,7 +501,7 @@ class BibliographyTransform(SphinxPostTransform): def run(self, **kwargs: Any) -> None: citations = thebibliography() - for node in list(self.document.traverse(nodes.citation)): + for node in list(self.document.findall(nodes.citation)): node.parent.remove(node) citations += node @@ -521,7 +521,7 @@ class CitationReferenceTransform(SphinxPostTransform): def run(self, **kwargs: Any) -> None: domain = cast(CitationDomain, self.env.get_domain('citation')) matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref') - for node in self.document.traverse(matcher): # type: addnodes.pending_xref + for node in self.document.findall(matcher): # type: addnodes.pending_xref docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0)) if docname: citation_ref = nodes.citation_reference('', '', *node.children, @@ -540,7 +540,7 @@ class MathReferenceTransform(SphinxPostTransform): def run(self, **kwargs: Any) -> None: equations = self.env.get_domain('math').data['objects'] - for node in self.document.traverse(addnodes.pending_xref): + for node in self.document.findall(addnodes.pending_xref): if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'): docname, _ = equations.get(node['reftarget'], (None, None)) if docname: @@ -555,7 +555,7 @@ class LiteralBlockTransform(SphinxPostTransform): def run(self, **kwargs: Any) -> None: matcher = NodeMatcher(nodes.container, literal_block=True) - for node in self.document.traverse(matcher): # type: nodes.container + for node in self.document.findall(matcher): # type: nodes.container newnode = captioned_literal_block('', *node.children, **node.attributes) node.replace_self(newnode) @@ -566,7 +566,7 @@ class DocumentTargetTransform(SphinxPostTransform): formats = ('latex',) def run(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.start_of_file): + for node in self.document.findall(addnodes.start_of_file): section = node.next_node(nodes.section) if section: section['ids'].append(':doc') # special label for :doc: @@ -602,9 +602,9 @@ class IndexInSectionTitleTransform(SphinxPostTransform): formats = ('latex',) def run(self, **kwargs: Any) -> None: - for node in list(self.document.traverse(nodes.title)): + for node in list(self.document.findall(nodes.title)): if isinstance(node.parent, nodes.section): - for i, index in enumerate(list(node.traverse(addnodes.index))): + for i, index in enumerate(node.findall(addnodes.index)): # move the index node next to the section title node.remove(index) node.parent.insert(i + 1, index) diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index 1f9d601e413..61b6b45f954 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -650,7 +650,7 @@ def run(self, **kwargs: Any) -> None: hyperlinks = builder.hyperlinks # reference nodes - for refnode in self.document.traverse(nodes.reference): + for refnode in self.document.findall(nodes.reference): if 'refuri' not in refnode: continue uri = refnode['refuri'] @@ -664,7 +664,7 @@ def run(self, **kwargs: Any) -> None: hyperlinks[uri] = uri_info # image nodes - for imgnode in self.document.traverse(nodes.image): + for imgnode in self.document.findall(nodes.image): uri = imgnode['candidates'].get('?') if uri and '://' in uri: newuri = self.app.emit_firstresult('linkcheck-process-uri', uri) diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py index 88c2c9db57e..c942cfa8666 100644 --- a/sphinx/builders/manpage.py +++ b/sphinx/builders/manpage.py @@ -98,7 +98,7 @@ def write(self, *ignored: Any) -> None: logger.info('} ', nonl=True) self.env.resolve_references(largetree, docname, self) # remove pending_xref nodes - for pendingnode in largetree.traverse(addnodes.pending_xref): + for pendingnode in largetree.findall(addnodes.pending_xref): pendingnode.replace_self(pendingnode.children) docwriter.write(largetree, destination) diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py index 344e062b98a..09db8d2b933 100644 --- a/sphinx/builders/singlehtml.py +++ b/sphinx/builders/singlehtml.py @@ -54,7 +54,7 @@ def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str: def fix_refuris(self, tree: Node) -> None: # fix refuris with double anchor fname = self.config.root_doc + self.out_suffix - for refnode in tree.traverse(nodes.reference): + for refnode in tree.findall(nodes.reference): if 'refuri' not in refnode: continue refuri = refnode['refuri'] diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 4a2c58143f7..f07cd2516c8 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -138,7 +138,7 @@ def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[ new_sect += nodes.title('', '') new_tree += new_sect - for node in tree.traverse(addnodes.toctree): + for node in tree.findall(addnodes.toctree): new_sect += node tree = new_tree largetree = inline_all_toctrees(self, self.docnames, indexfile, tree, @@ -152,7 +152,7 @@ def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[ logger.info(__("resolving references...")) self.env.resolve_references(largetree, indexfile, self) # TODO: add support for external :ref:s - for pendingnode in largetree.traverse(addnodes.pending_xref): + for pendingnode in largetree.findall(addnodes.pending_xref): docname = pendingnode['refdocname'] sectname = pendingnode['refsectname'] newnodes: List[Node] = [nodes.emphasis(sectname, sectname)] diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py index 9dd3afb544e..fdef142596b 100644 --- a/sphinx/builders/xml.py +++ b/sphinx/builders/xml.py @@ -71,7 +71,7 @@ def write_doc(self, docname: str, doctree: Node) -> None: # work around multiple string % tuple issues in docutils; # replace tuples in attribute values with lists doctree = doctree.deepcopy() - for node in doctree.traverse(nodes.Element): + for node in doctree.findall(nodes.Element): for att, value in node.attributes.items(): if isinstance(value, tuple): node.attributes[att] = list(value) diff --git a/sphinx/directives/patches.py b/sphinx/directives/patches.py index 5308b283887..d4d498725c4 100644 --- a/sphinx/directives/patches.py +++ b/sphinx/directives/patches.py @@ -83,7 +83,7 @@ def run(self) -> List[Node]: # docutils' meta nodes aren't picklable because the class is nested meta.__class__ = addnodes.meta - return result + return result # type: ignore class RSTTable(tables.RSTTable): diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index 196937692be..6ed4f155994 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -3556,7 +3556,7 @@ def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool, return nodes def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(AliasNode): + for node in self.document.findall(AliasNode): node = cast(AliasNode, node) sig = node.sig parentKey = node.parentKey diff --git a/sphinx/domains/citation.py b/sphinx/domains/citation.py index ca3d6082ebd..f68d324bf63 100644 --- a/sphinx/domains/citation.py +++ b/sphinx/domains/citation.py @@ -112,7 +112,7 @@ class CitationDefinitionTransform(SphinxTransform): def apply(self, **kwargs: Any) -> None: domain = cast(CitationDomain, self.env.get_domain('citation')) - for node in self.document.traverse(nodes.citation): + for node in self.document.findall(nodes.citation): # register citation node to domain node['docname'] = self.env.docname domain.note_citation(node) @@ -131,7 +131,7 @@ class CitationReferenceTransform(SphinxTransform): def apply(self, **kwargs: Any) -> None: domain = cast(CitationDomain, self.env.get_domain('citation')) - for node in self.document.traverse(nodes.citation_reference): + for node in self.document.findall(nodes.citation_reference): target = node.astext() ref = pending_xref(target, refdomain='citation', reftype='ref', reftarget=target, refwarn=True, diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 8733a19cff1..c8625e81d76 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -7459,7 +7459,7 @@ def _render_symbol(self, s: Symbol, maxdepth: int, skipThis: bool, return nodes def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(AliasNode): + for node in self.document.findall(AliasNode): node = cast(AliasNode, node) sig = node.sig parentKey = node.parentKey diff --git a/sphinx/domains/index.py b/sphinx/domains/index.py index 975992b8397..7dbc1bb5aaf 100644 --- a/sphinx/domains/index.py +++ b/sphinx/domains/index.py @@ -48,7 +48,7 @@ def merge_domaindata(self, docnames: Iterable[str], otherdata: Dict) -> None: def process_doc(self, env: BuildEnvironment, docname: str, document: Node) -> None: """Process a document after it is read by the environment.""" entries = self.entries.setdefault(env.docname, []) - for node in list(document.traverse(addnodes.index)): + for node in list(document.findall(addnodes.index)): try: for entry in node['entries']: split_index_msg(entry[0], entry[1]) diff --git a/sphinx/domains/math.py b/sphinx/domains/math.py index ebc4da371e2..78b7784a79d 100644 --- a/sphinx/domains/math.py +++ b/sphinx/domains/math.py @@ -78,7 +78,7 @@ def process_doc(self, env: BuildEnvironment, docname: str, def math_node(node: Node) -> bool: return isinstance(node, (nodes.math, nodes.math_block)) - self.data['has_equations'][docname] = any(document.traverse(math_node)) + self.data['has_equations'][docname] = any(document.findall(math_node)) def clear_doc(self, docname: str) -> None: for equation_id, (doc, eqno) in list(self.equations.items()): diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index bd02f1c76dc..11a95e13b1e 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -776,7 +776,7 @@ def process_doc(self, env: "BuildEnvironment", docname: str, document: nodes.doc elif self.is_enumerable_node(node): sectname = self.get_numfig_title(node) else: - toctree = next(iter(node.traverse(addnodes.toctree)), None) + toctree = next(node.findall(addnodes.toctree), None) if toctree and toctree.get('caption'): sectname = toctree.get('caption') else: diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 0f7dbd8c706..9dde7b407d8 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -535,7 +535,7 @@ def get_and_resolve_doctree(self, docname: str, builder: "Builder", self.apply_post_transforms(doctree, docname) # now, resolve all toctree nodes - for toctreenode in doctree.traverse(addnodes.toctree): + for toctreenode in doctree.findall(addnodes.toctree): result = TocTree(self).resolve(docname, builder, toctreenode, prune=prune_toctrees, includehidden=includehidden) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 5a9e26d6d5f..962e731435a 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -161,7 +161,7 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str], process_only_nodes(toc, builder.tags) if title and toc.children and len(toc.children) == 1: child = toc.children[0] - for refnode in child.traverse(nodes.reference): + for refnode in child.findall(nodes.reference): if refnode['refuri'] == ref and \ not refnode['anchorname']: refnode.children = [nodes.Text(title)] @@ -193,13 +193,13 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str], for toplevel in children: # nodes with length 1 don't have any children anyway if len(toplevel) > 1: - subtrees = list(toplevel.traverse(addnodes.toctree)) + subtrees = list(toplevel.findall(addnodes.toctree)) if subtrees: toplevel[1][:] = subtrees # type: ignore else: toplevel.pop(1) # resolve all sub-toctrees - for subtocnode in list(toc.traverse(addnodes.toctree)): + for subtocnode in list(toc.findall(addnodes.toctree)): if not (subtocnode.get('hidden', False) and not includehidden): i = subtocnode.parent.index(subtocnode) + 1 @@ -257,7 +257,7 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str], # set the target paths in the toctrees (they are not known at TOC # generation time) - for refnode in newnode.traverse(nodes.reference): + for refnode in newnode.findall(nodes.reference): if not url_re.match(refnode['refuri']): refnode['refuri'] = builder.get_relative_uri( docname, refnode['refuri']) + refnode['anchorname'] @@ -308,7 +308,7 @@ def get_toc_for(self, docname: str, builder: "Builder") -> Node: # renders to nothing return nodes.paragraph() process_only_nodes(toc, builder.tags) - for node in toc.traverse(nodes.reference): + for node in toc.findall(nodes.reference): node['refuri'] = node['anchorname'] or '#' return toc @@ -324,7 +324,7 @@ def get_toctree_for(self, docname: str, builder: "Builder", collapse: bool, else: kwargs['maxdepth'] = int(kwargs['maxdepth']) kwargs['collapse'] = collapse - for toctreenode in doctree.traverse(addnodes.toctree): + for toctreenode in doctree.findall(addnodes.toctree): toctree = self.resolve(docname, builder, toctreenode, prune=True, **kwargs) if toctree: toctrees.append(toctree) diff --git a/sphinx/environment/collectors/asset.py b/sphinx/environment/collectors/asset.py index 44a1248ccc1..9530b3bd94d 100644 --- a/sphinx/environment/collectors/asset.py +++ b/sphinx/environment/collectors/asset.py @@ -43,7 +43,7 @@ def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: """Process and rewrite image URIs.""" docname = app.env.docname - for node in doctree.traverse(nodes.image): + for node in doctree.findall(nodes.image): # Map the mimetype to the corresponding image. The writer may # choose the best image from these candidates. The special key * is # set if there is only single candidate to be used by a writer. @@ -124,7 +124,7 @@ def merge_other(self, app: Sphinx, env: BuildEnvironment, def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: """Process downloadable file paths. """ - for node in doctree.traverse(addnodes.download_reference): + for node in doctree.findall(addnodes.download_reference): targetname = node['reftarget'] if '://' in targetname: node['refuri'] = targetname diff --git a/sphinx/environment/collectors/title.py b/sphinx/environment/collectors/title.py index f522231c838..8c285f3239c 100644 --- a/sphinx/environment/collectors/title.py +++ b/sphinx/environment/collectors/title.py @@ -43,7 +43,7 @@ def process_doc(self, app: Sphinx, doctree: nodes.document) -> None: longtitlenode = nodes.title() longtitlenode += nodes.Text(doctree['title']) # look for first section title and use that as the title - for node in doctree.traverse(nodes.section): + for node in doctree.findall(nodes.section): visitor = SphinxContentsFilter(doctree) node[0].walkabout(visitor) titlenode += visitor.get_entry_text() diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index 03270336585..250e16aa22d 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -196,7 +196,7 @@ def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None: for docname in env.numbered_toctrees: assigned.add(docname) doctree = env.get_doctree(docname) - for toctreenode in doctree.traverse(addnodes.toctree): + for toctreenode in doctree.findall(addnodes.toctree): depth = toctreenode.get('numbered', 0) if depth: # every numbered toctree gets new numbering diff --git a/sphinx/ext/autosectionlabel.py b/sphinx/ext/autosectionlabel.py index 0fe1857e2d0..e8efcb076c3 100644 --- a/sphinx/ext/autosectionlabel.py +++ b/sphinx/ext/autosectionlabel.py @@ -33,7 +33,7 @@ def get_node_depth(node: Node) -> int: def register_sections_as_label(app: Sphinx, document: Node) -> None: domain = cast(StandardDomain, app.env.get_domain('std')) - for node in document.traverse(nodes.section): + for node in document.findall(nodes.section): if (app.config.autosectionlabel_maxdepth and get_node_depth(node) >= app.config.autosectionlabel_maxdepth): continue diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index e3a04d3c76d..36dc230193e 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -587,7 +587,7 @@ def parse(doc: List[str], settings: Any) -> nodes.document: node = parse(doc, document.settings) if summary.endswith(WELL_KNOWN_ABBREVIATIONS): pass - elif not list(node.traverse(nodes.system_message)): + elif not any(node.findall(nodes.system_message)): # considered as that splitting by period does not break inline markups break diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index 990bf33efc4..490516d63f5 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -422,7 +422,7 @@ def condition(node: Node) -> bool: def condition(node: Node) -> bool: return isinstance(node, (nodes.literal_block, nodes.comment)) \ and 'testnodetype' in node - for node in doctree.traverse(condition): # type: Element + for node in doctree.findall(condition): # type: Element if self.skipped(node): continue diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py index 1ca428cc051..eb5c474d504 100644 --- a/sphinx/ext/extlinks.py +++ b/sphinx/ext/extlinks.py @@ -55,7 +55,7 @@ class ExternalLinksChecker(SphinxPostTransform): default_priority = 500 def run(self, **kwargs: Any) -> None: - for refnode in self.document.traverse(nodes.reference): + for refnode in self.document.findall(nodes.reference): self.check_uri(refnode) def check_uri(self, refnode: nodes.reference) -> None: diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py index f14300838a6..50a2b203f82 100644 --- a/sphinx/ext/ifconfig.py +++ b/sphinx/ext/ifconfig.py @@ -56,7 +56,7 @@ def process_ifconfig_nodes(app: Sphinx, doctree: nodes.document, docname: str) - ns = {confval.name: confval.value for confval in app.config} ns.update(app.config.__dict__.copy()) ns['builder'] = app.builder.name - for node in doctree.traverse(ifconfig): + for node in doctree.findall(ifconfig): try: res = eval(node['expr'], ns) except Exception as err: diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py index b9c165ca497..6ae8284084d 100644 --- a/sphinx/ext/linkcode.py +++ b/sphinx/ext/linkcode.py @@ -39,7 +39,7 @@ def doctree_read(app: Sphinx, doctree: Node) -> None: 'js': ['object', 'fullname'], } - for objnode in list(doctree.traverse(addnodes.desc)): + for objnode in list(doctree.findall(addnodes.desc)): domain = objnode.get('domain') uris: Set[str] = set() for signode in objnode: diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index dd743402235..3b8ba19247f 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -93,7 +93,7 @@ def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None: def process_doc(self, env: BuildEnvironment, docname: str, document: nodes.document) -> None: todos = self.todos.setdefault(docname, []) - for todo in document.traverse(todo_node): + for todo in document.findall(todo_node): env.app.emit('todo-defined', todo) todos.append(todo) @@ -131,7 +131,7 @@ def __init__(self, app: Sphinx, doctree: nodes.document, docname: str) -> None: def process(self, doctree: nodes.document, docname: str) -> None: todos: List[todo_node] = sum(self.domain.todos.values(), []) - for node in list(doctree.traverse(todolist)): + for node in list(doctree.findall(todolist)): if not self.config.todo_include_todos: node.parent.remove(node) continue @@ -184,7 +184,7 @@ def create_todo_reference(self, todo: todo_node, docname: str) -> nodes.paragrap def resolve_reference(self, todo: todo_node, docname: str) -> None: """Resolve references in the todo content.""" - for node in todo.traverse(addnodes.pending_xref): + for node in todo.findall(addnodes.pending_xref): if 'refdoc' in node: node['refdoc'] = docname diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index d7eb33fc608..54274ac04a2 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -108,7 +108,7 @@ def has_tag(modname: str, fullname: str, docname: str, refname: str) -> bool: return False - for objnode in list(doctree.traverse(addnodes.desc)): + for objnode in list(doctree.findall(addnodes.desc)): if objnode.get('domain') != 'py': continue names: Set[str] = set() @@ -184,14 +184,14 @@ def run(self, **kwargs: Any) -> None: self.remove_viewcode_anchors() def convert_viewcode_anchors(self) -> None: - for node in self.document.traverse(viewcode_anchor): + for node in self.document.findall(viewcode_anchor): anchor = nodes.inline('', _('[source]'), classes=['viewcode-link']) refnode = make_refnode(self.app.builder, node['refdoc'], node['reftarget'], node['refid'], anchor) node.replace_self(refnode) def remove_viewcode_anchors(self) -> None: - for node in list(self.document.traverse(viewcode_anchor)): + for node in list(self.document.findall(viewcode_anchor)): node.parent.remove(node) diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index e122a69b43f..f1359dfadc4 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -107,7 +107,7 @@ class DefaultSubstitutions(SphinxTransform): def apply(self, **kwargs: Any) -> None: # only handle those not otherwise defined in the document to_handle = default_substitutions - set(self.document.substitution_defs) - for ref in self.document.traverse(nodes.substitution_reference): + for ref in self.document.findall(nodes.substitution_reference): refname = ref['refname'] if refname in to_handle: text = self.config[refname] @@ -128,7 +128,7 @@ class MoveModuleTargets(SphinxTransform): default_priority = 210 def apply(self, **kwargs: Any) -> None: - for node in list(self.document.traverse(nodes.target)): + for node in list(self.document.findall(nodes.target)): if not node['ids']: continue if ('ismod' in node and @@ -147,12 +147,12 @@ class HandleCodeBlocks(SphinxTransform): def apply(self, **kwargs: Any) -> None: # move doctest blocks out of blockquotes - for node in self.document.traverse(nodes.block_quote): + for node in self.document.findall(nodes.block_quote): if all(isinstance(child, nodes.doctest_block) for child in node.children): node.replace_self(node.children) # combine successive doctest blocks - # for node in self.document.traverse(nodes.doctest_block): + # for node in self.document.findall(nodes.doctest_block): # if node not in node.parent.children: # continue # parindex = node.parent.index(node) @@ -172,7 +172,7 @@ class AutoNumbering(SphinxTransform): def apply(self, **kwargs: Any) -> None: domain: StandardDomain = self.env.get_domain('std') - for node in self.document.traverse(nodes.Element): + for node in self.document.findall(nodes.Element): if (domain.is_enumerable_node(node) and domain.get_numfig_title(node) is not None and node['ids'] == []): @@ -186,7 +186,7 @@ class SortIds(SphinxTransform): default_priority = 261 def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(nodes.section): + for node in self.document.findall(nodes.section): if len(node['ids']) > 1 and node['ids'][0].startswith('id'): node['ids'] = node['ids'][1:] + [node['ids'][0]] @@ -207,7 +207,7 @@ class ApplySourceWorkaround(SphinxTransform): default_priority = 10 def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(): # type: Node + for node in self.document.findall(): # type: Node if isinstance(node, (nodes.TextElement, nodes.image, nodes.topic)): apply_source_workaround(node) @@ -219,7 +219,7 @@ class AutoIndexUpgrader(SphinxTransform): default_priority = 210 def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.index): + for node in self.document.findall(addnodes.index): if 'entries' in node and any(len(entry) == 4 for entry in node['entries']): msg = __('4 column based index found. ' 'It might be a bug of extensions you use: %r') % node['entries'] @@ -244,7 +244,7 @@ def apply(self, **kwargs: Any) -> None: def is_translatable_node(node: Node) -> bool: return isinstance(node, tuple(target_nodes)) - for node in self.document.traverse(is_translatable_node): # type: Element + for node in self.document.findall(is_translatable_node): # type: Element node['translatable'] = True @@ -276,7 +276,7 @@ class DoctestTransform(SphinxTransform): default_priority = 500 def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(nodes.doctest_block): + for node in self.document.findall(nodes.doctest_block): node['classes'].append('doctest') @@ -293,7 +293,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: def apply(self, **kwargs: Any) -> None: matcher = NodeMatcher(nodes.table, nodes.figure) - for node in self.document.traverse(matcher): # type: Element + for node in self.document.findall(matcher): # type: Element node.setdefault('align', 'default') @@ -303,7 +303,7 @@ class FilterSystemMessages(SphinxTransform): def apply(self, **kwargs: Any) -> None: filterlevel = 2 if self.config.keep_warnings else 5 - for node in list(self.document.traverse(nodes.system_message)): + for node in list(self.document.findall(nodes.system_message)): if node['level'] < filterlevel: logger.debug('%s [filtered system message]', node.astext()) node.parent.remove(node) @@ -392,7 +392,7 @@ class ManpageLink(SphinxTransform): default_priority = 999 def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.manpage): + for node in self.document.findall(addnodes.manpage): manpage = ' '.join([str(x) for x in node.children if isinstance(x, nodes.Text)]) pattern = r'^(?P(?P.+)[\(\.](?P
[1-9]\w*)?\)?)$' # noqa diff --git a/sphinx/transforms/compact_bullet_list.py b/sphinx/transforms/compact_bullet_list.py index b43d0fb3e92..e39ac97d1c7 100644 --- a/sphinx/transforms/compact_bullet_list.py +++ b/sphinx/transforms/compact_bullet_list.py @@ -74,9 +74,9 @@ def check_refonly_list(node: Node) -> bool: else: return True - for node in self.document.traverse(nodes.bullet_list): + for node in self.document.findall(nodes.bullet_list): if check_refonly_list(node): - for item in node.traverse(nodes.list_item): + for item in node.findall(nodes.list_item): para = cast(nodes.paragraph, item[0]) ref = cast(nodes.reference, para[0]) compact_para = addnodes.compact_paragraph() diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py index 6e75286f869..08dcbe158cc 100644 --- a/sphinx/transforms/i18n.py +++ b/sphinx/transforms/i18n.py @@ -89,7 +89,7 @@ class PreserveTranslatableMessages(SphinxTransform): default_priority = 10 # this MUST be invoked before Locale transform def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.translatable): + for node in self.document.findall(addnodes.translatable): node.preserve_original_messages() @@ -199,7 +199,7 @@ def apply(self, **kwargs: Any) -> None: # replace target's refname to new target name matcher = NodeMatcher(nodes.target, refname=old_name) - for old_target in self.document.traverse(matcher): # type: nodes.target + for old_target in self.document.findall(matcher): # type: nodes.target old_target['refname'] = new_name processed = True @@ -301,8 +301,8 @@ def list_replace_or_append(lst: List[N], old: N, new: N) -> None: lst.append(new) is_autofootnote_ref = NodeMatcher(nodes.footnote_reference, auto=Any) - old_foot_refs: List[nodes.footnote_reference] = list(node.traverse(is_autofootnote_ref)) # NOQA - new_foot_refs: List[nodes.footnote_reference] = list(patch.traverse(is_autofootnote_ref)) # NOQA + old_foot_refs: List[nodes.footnote_reference] = list(node.findall(is_autofootnote_ref)) # NOQA + new_foot_refs: List[nodes.footnote_reference] = list(patch.findall(is_autofootnote_ref)) # NOQA if len(old_foot_refs) != len(new_foot_refs): old_foot_ref_rawsources = [ref.rawsource for ref in old_foot_refs] new_foot_ref_rawsources = [ref.rawsource for ref in new_foot_refs] @@ -344,8 +344,8 @@ def list_replace_or_append(lst: List[N], old: N, new: N) -> None: # * use translated refname for section refname. # * inline reference "`Python <...>`_" has no 'refname'. is_refnamed_ref = NodeMatcher(nodes.reference, refname=Any) - old_refs: List[nodes.reference] = list(node.traverse(is_refnamed_ref)) - new_refs: List[nodes.reference] = list(patch.traverse(is_refnamed_ref)) + old_refs: List[nodes.reference] = list(node.findall(is_refnamed_ref)) + new_refs: List[nodes.reference] = list(patch.findall(is_refnamed_ref)) if len(old_refs) != len(new_refs): old_ref_rawsources = [ref.rawsource for ref in old_refs] new_ref_rawsources = [ref.rawsource for ref in new_refs] @@ -371,8 +371,8 @@ def list_replace_or_append(lst: List[N], old: N, new: N) -> None: # refnamed footnote should use original 'ids'. is_refnamed_footnote_ref = NodeMatcher(nodes.footnote_reference, refname=Any) - old_foot_refs = list(node.traverse(is_refnamed_footnote_ref)) - new_foot_refs = list(patch.traverse(is_refnamed_footnote_ref)) + old_foot_refs = list(node.findall(is_refnamed_footnote_ref)) + new_foot_refs = list(patch.findall(is_refnamed_footnote_ref)) refname_ids_map: Dict[str, List[str]] = {} if len(old_foot_refs) != len(new_foot_refs): old_foot_ref_rawsources = [ref.rawsource for ref in old_foot_refs] @@ -390,8 +390,8 @@ def list_replace_or_append(lst: List[N], old: N, new: N) -> None: # citation should use original 'ids'. is_citation_ref = NodeMatcher(nodes.citation_reference, refname=Any) - old_cite_refs: List[nodes.citation_reference] = list(node.traverse(is_citation_ref)) # NOQA - new_cite_refs: List[nodes.citation_reference] = list(patch.traverse(is_citation_ref)) # NOQA + old_cite_refs: List[nodes.citation_reference] = list(node.findall(is_citation_ref)) + new_cite_refs: List[nodes.citation_reference] = list(patch.findall(is_citation_ref)) # NOQA refname_ids_map = {} if len(old_cite_refs) != len(new_cite_refs): old_cite_ref_rawsources = [ref.rawsource for ref in old_cite_refs] @@ -410,8 +410,8 @@ def list_replace_or_append(lst: List[N], old: N, new: N) -> None: # Original pending_xref['reftarget'] contain not-translated # target name, new pending_xref must use original one. # This code restricts to change ref-targets in the translation. - old_xrefs = list(node.traverse(addnodes.pending_xref)) - new_xrefs = list(patch.traverse(addnodes.pending_xref)) + old_xrefs = list(node.findall(addnodes.pending_xref)) + new_xrefs = list(patch.findall(addnodes.pending_xref)) xref_reftarget_map = {} if len(old_xrefs) != len(new_xrefs): old_xref_rawsources = [xref.rawsource for xref in old_xrefs] @@ -477,7 +477,7 @@ def get_ref_key(node: addnodes.pending_xref) -> Optional[Tuple[str, str, str]]: node['entries'] = new_entries # remove translated attribute that is used for avoiding double translation. - for translated in self.document.traverse(NodeMatcher(translated=Any)): # type: Element # NOQA + for translated in self.document.findall(NodeMatcher(translated=Any)): # type: Element # NOQA translated.delattr('translated') @@ -493,7 +493,7 @@ def apply(self, **kwargs: Any) -> None: return matcher = NodeMatcher(nodes.inline, translatable=Any) - for inline in list(self.document.traverse(matcher)): # type: nodes.inline + for inline in list(self.document.findall(matcher)): # type: nodes.inline inline.parent.remove(inline) inline.parent += inline.children diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py index 098f004c7fc..df2eeecbb6a 100644 --- a/sphinx/transforms/post_transforms/__init__.py +++ b/sphinx/transforms/post_transforms/__init__.py @@ -67,7 +67,7 @@ class ReferencesResolver(SphinxPostTransform): default_priority = 10 def run(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.pending_xref): + for node in self.document.findall(addnodes.pending_xref): content = self.find_pending_xref_condition(node, ("resolved", "*")) if content: contnode = cast(Element, content[0].deepcopy()) @@ -251,7 +251,7 @@ def has_visitor(translator: Type[nodes.NodeVisitor], node: Type[Element]) -> boo self.fallback(addnodes.desc_inline) def fallback(self, nodeType: Any) -> None: - for node in self.document.traverse(nodeType): + for node in self.document.findall(nodeType): newnode = nodes.inline() newnode.update_all_atts(node) newnode.extend(node) @@ -263,7 +263,7 @@ class PropagateDescDomain(SphinxPostTransform): default_priority = 200 def run(self, **kwargs: Any) -> None: - for node in self.document.traverse(addnodes.desc_signature): + for node in self.document.findall(addnodes.desc_signature): if node.parent.get('domain'): node['classes'].append(node.parent['domain']) diff --git a/sphinx/transforms/post_transforms/code.py b/sphinx/transforms/post_transforms/code.py index 5f31a434d4c..55bd56c2efd 100644 --- a/sphinx/transforms/post_transforms/code.py +++ b/sphinx/transforms/post_transforms/code.py @@ -42,7 +42,7 @@ def apply(self, **kwargs: Any) -> None: self.config.highlight_language) self.document.walkabout(visitor) - for node in list(self.document.traverse(addnodes.highlightlang)): + for node in list(self.document.findall(addnodes.highlightlang)): node.parent.remove(node) @@ -94,11 +94,11 @@ class TrimDoctestFlagsTransform(SphinxTransform): default_priority = HighlightLanguageTransform.default_priority + 1 def apply(self, **kwargs: Any) -> None: - for lbnode in self.document.traverse(nodes.literal_block): # type: nodes.literal_block + for lbnode in self.document.findall(nodes.literal_block): if self.is_pyconsole(lbnode): self.strip_doctest_flags(lbnode) - for dbnode in self.document.traverse(nodes.doctest_block): # type: nodes.doctest_block + for dbnode in self.document.findall(nodes.doctest_block): self.strip_doctest_flags(dbnode) def strip_doctest_flags(self, node: TextElement) -> None: diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py index d2929dca80f..8e2f9e2fadd 100644 --- a/sphinx/transforms/post_transforms/images.py +++ b/sphinx/transforms/post_transforms/images.py @@ -30,7 +30,7 @@ class BaseImageConverter(SphinxTransform): def apply(self, **kwargs: Any) -> None: - for node in self.document.traverse(nodes.image): + for node in self.document.findall(nodes.image): if self.match(node): self.handle(node) diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 456fa957644..c3a6ff9e2e9 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -500,6 +500,16 @@ def unknown_visit(self, node: Node) -> None: logger.warning(__('unknown node type: %r'), node, location=node) +# Node.findall() is a new interface to traverse a doctree since docutils-0.18. +# This applies a patch docutils-0.17 or older to be available Node.findall() +# method to use it from our codebase. +if __version_info__ < (0, 18): + def findall(self, *args, **kwargs): + return iter(self.traverse(*args, **kwargs)) + + Node.findall = findall # type: ignore + + # cache a vanilla instance of nodes.document # Used in new_document() function __document_cache__: Optional[nodes.document] = None diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py index b6542f1d36d..c16142a2cd1 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -38,7 +38,7 @@ class NodeMatcher: - """A helper class for Node.traverse(). + """A helper class for Node.findall(). It checks that the given node is an instance of the specified node-classes and has the specified node-attributes. @@ -47,7 +47,7 @@ class NodeMatcher: and ``reftype`` attributes:: matcher = NodeMatcher(nodes.reference, refdomain='std', reftype='citation') - doctree.traverse(matcher) + doctree.findall(matcher) # => [, , ...] A special value ``typing.Any`` matches any kind of node-attributes. For example, @@ -55,7 +55,7 @@ class NodeMatcher: from typing import Any matcher = NodeMatcher(nodes.reference, refdomain=Any) - doctree.traverse(matcher) + doctree.findall(matcher) # => [, , ...] """ @@ -147,7 +147,7 @@ def apply_source_workaround(node: Element) -> None: logger.debug('[i18n] PATCH: %r to have rawsource: %s', get_full_module_name(node), repr_domxml(node)) # strip classifier from rawsource of term - for classifier in reversed(list(node.parent.traverse(nodes.classifier))): + for classifier in reversed(list(node.parent.findall(nodes.classifier))): node.rawsource = re.sub(r'\s*:\s*%s' % re.escape(classifier.astext()), '', node.rawsource) if isinstance(node, nodes.topic) and node.source is None: @@ -259,7 +259,7 @@ def is_translatable(node: Node) -> bool: def extract_messages(doctree: Element) -> Iterable[Tuple[Element, str]]: """Extract translatable messages from a document tree.""" - for node in doctree.traverse(is_translatable): # type: Element + for node in doctree.findall(is_translatable): # type: Element if isinstance(node, addnodes.translatable): for msg in node.extract_original_messages(): yield node, msg @@ -323,7 +323,8 @@ def get_prev_node(node: Node) -> Optional[Node]: def traverse_translatable_index(doctree: Element) -> Iterable[Tuple[Element, List["IndexEntry"]]]: # NOQA """Traverse translatable index node from a document tree.""" - for node in doctree.traverse(NodeMatcher(addnodes.index, inline=False)): # type: addnodes.index # NOQA + matcher = NodeMatcher(addnodes.index, inline=False) + for node in doctree.findall(matcher): # type: addnodes.index if 'raw_entries' in node: entries = node['raw_entries'] else: @@ -353,9 +354,9 @@ def nested_parse_with_titles(state: Any, content: StringList, node: Node) -> str def clean_astext(node: Element) -> str: """Like node.astext(), but ignore images.""" node = node.deepcopy() - for img in node.traverse(nodes.image): + for img in node.findall(nodes.image): img['alt'] = '' - for raw in list(node.traverse(nodes.raw)): + for raw in list(node.findall(nodes.raw)): raw.parent.remove(raw) return node.astext() @@ -420,7 +421,7 @@ def inline_all_toctrees(builder: "Builder", docnameset: Set[str], docname: str, Record all docnames in *docnameset*, and output docnames with *colorfunc*. """ tree = cast(nodes.document, tree.deepcopy()) - for toctreenode in list(tree.traverse(addnodes.toctree)): + for toctreenode in list(tree.findall(addnodes.toctree)): newnodes = [] includefiles = map(str, toctreenode['includefiles']) for includefile in includefiles: @@ -438,7 +439,7 @@ def inline_all_toctrees(builder: "Builder", docnameset: Set[str], docname: str, else: sof = addnodes.start_of_file(docname=includefile) sof.children = subtree.children - for sectionnode in sof.traverse(nodes.section): + for sectionnode in sof.findall(nodes.section): if 'docname' not in sectionnode: sectionnode['docname'] = includefile newnodes.append(sof) @@ -615,7 +616,7 @@ def is_smartquotable(node: Node) -> bool: def process_only_nodes(document: Node, tags: "Tags") -> None: """Filter ``only`` nodes which do not match *tags*.""" - for node in document.traverse(addnodes.only): + for node in document.findall(addnodes.only): try: ret = tags.eval_condition(node['expr']) except Exception as err: diff --git a/sphinx/versioning.py b/sphinx/versioning.py index c007dd7b407..1a615101df9 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -42,7 +42,7 @@ def add_uids(doctree: Node, condition: Any) -> Iterator[Node]: :param condition: A callable which returns either ``True`` or ``False`` for a given node. """ - for node in doctree.traverse(condition): + for node in doctree.findall(condition): node.uid = uuid4().hex yield node @@ -57,8 +57,8 @@ def merge_doctrees(old: Node, new: Node, condition: Any) -> Iterator[Node]: :param condition: A callable which returns either ``True`` or ``False`` for a given node. """ - old_iter = old.traverse(condition) - new_iter = new.traverse(condition) + old_iter = old.findall(condition) + new_iter = new.findall(condition) old_nodes = [] new_nodes = [] ratios = {} diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 8cb4453ad79..ef19c803648 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -651,7 +651,7 @@ def visit_title(self, node: Element) -> None: raise nodes.SkipNode else: short = '' - if list(node.traverse(nodes.image)): + if any(node.findall(nodes.image)): short = ('[%s]' % self.escape(' '.join(clean_astext(node).split()))) try: @@ -1009,7 +1009,7 @@ def visit_entry(self, node: Element) -> None: context = (r'\par' + CR + r'\vskip-\baselineskip' r'\vbox{\hbox{\strut}}\end{varwidth}%' + CR + context) self.needs_linetrimming = 1 - if len(list(node.traverse(nodes.paragraph))) >= 2: + if len(list(node.findall(nodes.paragraph))) >= 2: self.table.has_oldproblematic = True if isinstance(node.parent.parent, nodes.thead) or (cell.col in self.table.stubs): if len(node) == 1 and isinstance(node[0], nodes.paragraph) and node.astext() == '': diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 4417274878c..0344d82e9fc 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -56,7 +56,7 @@ def __init__(self, document: nodes.document) -> None: def apply(self, **kwargs: Any) -> None: matcher = NodeMatcher(nodes.literal, nodes.emphasis, nodes.strong) - for node in list(self.document.traverse(matcher)): # type: TextElement + for node in list(self.document.findall(matcher)): # type: TextElement if any(matcher(subnode) for subnode in node): pos = node.parent.index(node) for subnode in reversed(list(node)): @@ -227,7 +227,7 @@ def depart_versionmodified(self, node: Element) -> None: # overwritten -- don't make whole of term bold if it includes strong node def visit_term(self, node: Element) -> None: - if list(node.traverse(nodes.strong)): + if any(node.findall(nodes.strong)): self.body.append('\n') else: super().visit_term(node) diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index 7551136ff69..351aef2f799 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -286,7 +286,7 @@ def add_node_name(name: str) -> str: self.indices = [(add_node_name(name), content) for name, content in self.indices] # each section is also a node - for section in self.document.traverse(nodes.section): + for section in self.document.findall(nodes.section): title = cast(nodes.TextElement, section.next_node(nodes.Titular)) name = title.astext() if title else '' section['node_name'] = add_node_name(name) @@ -295,7 +295,7 @@ def collect_node_menus(self) -> None: """Collect the menu entries for each "node" section.""" node_menus = self.node_menus targets: List[Element] = [self.document] - targets.extend(self.document.traverse(nodes.section)) + targets.extend(self.document.findall(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)] diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index 4027e0ec34b..2e1dd474a24 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -850,7 +850,7 @@ def depart_list_item(self, node: Element) -> None: self.end_state(first='%s. ' % self.list_counter[-1]) def visit_definition_list_item(self, node: Element) -> None: - self._classifier_count_in_li = len(list(node.traverse(nodes.classifier))) + self._classifier_count_in_li = len(list(node.findall(nodes.classifier))) def depart_definition_list_item(self, node: Element) -> None: pass diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index 9626e73cb40..d8244db6a09 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -553,7 +553,7 @@ def test_literalinclude_pydecorators(app, status, warning): def test_code_block_highlighted(app, status, warning): app.builder.build(['highlight']) doctree = app.env.get_doctree('highlight') - codeblocks = list(doctree.traverse(nodes.literal_block)) + codeblocks = list(doctree.findall(nodes.literal_block)) assert codeblocks[0]['language'] == 'default' assert codeblocks[1]['language'] == 'python2' diff --git a/tests/test_domain_js.py b/tests/test_domain_js.py index 42e2c972766..b109fe4d81e 100644 --- a/tests/test_domain_js.py +++ b/tests/test_domain_js.py @@ -42,7 +42,7 @@ def assert_refnode(node, mod_name, prefix, target, reftype=None, assert_node(node, **attributes) doctree = app.env.get_doctree('roles') - refnodes = list(doctree.traverse(addnodes.pending_xref)) + refnodes = list(doctree.findall(addnodes.pending_xref)) assert_refnode(refnodes[0], None, None, 'TopLevel', 'class') assert_refnode(refnodes[1], None, None, 'top_level', 'func') assert_refnode(refnodes[2], None, 'NestedParentA', 'child_1', 'func') @@ -60,7 +60,7 @@ def assert_refnode(node, mod_name, prefix, target, reftype=None, assert len(refnodes) == 13 doctree = app.env.get_doctree('module') - refnodes = list(doctree.traverse(addnodes.pending_xref)) + refnodes = list(doctree.findall(addnodes.pending_xref)) assert_refnode(refnodes[0], 'module_a.submodule', None, 'ModTopLevel', 'class') assert_refnode(refnodes[1], 'module_a.submodule', 'ModTopLevel', diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py index 18c1766aac5..14c2bd3e288 100644 --- a/tests/test_domain_std.py +++ b/tests/test_domain_std.py @@ -424,7 +424,7 @@ def test_productionlist2(app): " A: `:A` `A`\n" " B: `P1:B` `~P1:B`\n") doctree = restructuredtext.parse(app, text) - refnodes = list(doctree.traverse(pending_xref)) + refnodes = list(doctree.findall(pending_xref)) assert_node(refnodes[0], pending_xref, reftarget="A") assert_node(refnodes[1], pending_xref, reftarget="P2:A") assert_node(refnodes[2], pending_xref, reftarget="P1:B") diff --git a/tests/test_ext_doctest.py b/tests/test_ext_doctest.py index b79b2899cee..3a527acb2b7 100644 --- a/tests/test_ext_doctest.py +++ b/tests/test_ext_doctest.py @@ -36,7 +36,7 @@ def test_build(app, status, warning): def test_highlight_language_default(app, status, warning): app.build() doctree = app.env.get_doctree('doctest') - for node in doctree.traverse(nodes.literal_block): + for node in doctree.findall(nodes.literal_block): assert node['language'] in ('python3', 'pycon3', 'none') @@ -45,7 +45,7 @@ def test_highlight_language_default(app, status, warning): def test_highlight_language_python2(app, status, warning): app.build() doctree = app.env.get_doctree('doctest') - for node in doctree.traverse(nodes.literal_block): + for node in doctree.findall(nodes.literal_block): assert node['language'] in ('python', 'pycon', 'none')