From 8f8b0ac9315fee07280d5ba03bbbca6264ebd14d Mon Sep 17 00:00:00 2001 From: Arnaud Desmier Date: Thu, 14 Nov 2024 11:18:31 +0100 Subject: [PATCH] Closes #13022: fix _toctree_copy with multi level 'only' nodes. When copying toc tree, 'only' nodes should not be copied, but previous implementation always considered 'only' node children as duplicable nodes which is wrong when 'only' nodes is parent of other 'only' nodes. --- sphinx/environment/adapters/toctree.py | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 3079c7dc543..ce80ca402a1 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -465,15 +465,13 @@ def _toctree_add_classes(node: Element, depth: int, docname: str) -> None: ET = TypeVar('ET', bound=Element) -def _toctree_copy( - node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags -) -> ET: +def _toctree_copy_children( + copy: ET, node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags +) -> None: """Utility: Cut and deep-copy a TOC at a specified depth.""" keep_bullet_list_sub_nodes = depth <= 1 or ( (depth <= maxdepth or maxdepth <= 0) and (not collapse or 'iscurrent' in node) ) - - copy = node.copy() for subnode in node.children: if isinstance(subnode, addnodes.compact_paragraph | nodes.list_item): # for

and

  • , just recurse @@ -489,18 +487,11 @@ def _toctree_copy( # copy sub toctree nodes for later processing copy.append(subnode.copy()) elif isinstance(subnode, addnodes.only): - # only keep children if the only node matches the tags + # Only keep its children if the 'only' node matches the tags. When + # matching, call recursively the current function without + # incrementing the depth as 'only' nodes are not toctree nodes. if _only_node_keep_children(subnode, tags): - for child in subnode.children: - copy.append( - _toctree_copy( - child, - depth, - maxdepth, - collapse, - tags, # type: ignore[type-var] - ) - ) + _toctree_copy_children(copy, subnode, depth, maxdepth, collapse, tags) elif isinstance(subnode, nodes.reference | nodes.title): # deep copy references and captions sub_node_copy = subnode.copy() @@ -511,6 +502,15 @@ def _toctree_copy( else: msg = f'Unexpected node type {subnode.__class__.__name__!r}!' raise ValueError(msg) + + return copy + + +def _toctree_copy( + node: ET, depth: int, maxdepth: int, collapse: bool, tags: Tags +) -> ET: + copy = node.copy() + _toctree_copy_children(copy, node, depth, maxdepth, collapse, tags) return copy