def assign_section_numbers(self, env: BuildEnvironment) -> List[str]: """Assign a section number to each heading under a numbered toctree.""" # a list of all docnames whose section numbers changed rewrite_needed = [] assigned: Set[str] = set() old_secnumbers = env.toc_secnumbers env.toc_secnumbers = {} def _walk_toc(node: Element, secnums: Dict, depth: int, titlenode: nodes.title = None) -> None: # NOQA # titlenode is the title of the document, it will get assigned a # secnumber too, so that it shows up in next/prev/parent rellinks for subnode in node.children: if isinstance(subnode, nodes.bullet_list): numstack.append(0) _walk_toc(subnode, secnums, depth - 1, titlenode) numstack.pop() titlenode = None elif isinstance(subnode, nodes.list_item): _walk_toc(subnode, secnums, depth, titlenode) titlenode = None elif isinstance(subnode, addnodes.only): # at this stage we don't know yet which sections are going # to be included; just include all of them, even if it leads # to gaps in the numbering _walk_toc(subnode, secnums, depth, titlenode) titlenode = None elif isinstance(subnode, addnodes.compact_paragraph): numstack[-1] += 1 reference = cast(nodes.reference, subnode[0]) if depth > 0: number = list(numstack) secnums[reference['anchorname']] = tuple(numstack) else: number = None secnums[reference['anchorname']] = None reference['secnumber'] = number if titlenode: titlenode['secnumber'] = number titlenode = None elif isinstance(subnode, addnodes.toctree): _walk_toctree(subnode, depth) def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None: if depth == 0: return for (_title, ref) in toctreenode['entries']: if url_re.match(ref) or ref == 'self': # don't mess with those continue elif ref in assigned: logger.warning(__('%s is already assigned section numbers ' '(nested numbered toctree?)'), ref, location=toctreenode, type='toc', subtype='secnum') elif ref in env.tocs: secnums: Dict[str, Tuple[int, ...]] = {} env.toc_secnumbers[ref] = secnums assigned.add(ref) _walk_toc(env.tocs[ref], secnums, depth, env.titles.get(ref)) if secnums != old_secnumbers.get(ref): rewrite_needed.append(ref) for docname in env.numbered_toctrees: assigned.add(docname) doctree = env.get_doctree(docname) for toctreenode in doctree.findall(addnodes.toctree): depth = toctreenode.get('numbered', 0) if depth: # every numbered toctree gets new numbering numstack = [0] _walk_toctree(toctreenode, depth) return rewrite_needed
def assign_section_numbers(self, env: BuildEnvironment) -> List[str]: """Assign a section number to each heading under a numbered toctree.""" # a list of all docnames whose section numbers changed rewrite_needed = [] old_secnumbers = env.toc_secnumbers env.toc_secnumbers = {} self.last_chapter_number = 0 assigned, toctree_nodes = get_toctree_nodes(env) def _walk_toc(node: Element, secnums: Dict, depth: int, titlenode: nodes.title = None) -> None: # titlenode is the title of the document, it will get assigned a # secnumber too, so that it shows up in next/prev/parent rellinks for subnode in node.children: if isinstance(subnode, nodes.bullet_list): numstack.append(0) _walk_toc(subnode, secnums, depth - 1, titlenode) numstack.pop() titlenode = None elif isinstance(subnode, nodes.list_item): _walk_toc(subnode, secnums, depth, titlenode) titlenode = None elif isinstance(subnode, addnodes.only): # at this stage we don't know yet which sections are going # to be included; just include all of them, even if it leads # to gaps in the numbering _walk_toc(subnode, secnums, depth, titlenode) titlenode = None elif isinstance(subnode, addnodes.compact_paragraph): numstack[-1] += 1 reference = cast(nodes.reference, subnode[0]) # if a new chapter is encountered increment the chapter number if len(numstack) == 1: self.last_chapter_number += 1 if depth > 0: number = list(numstack) secnums[reference["anchorname"]] = tuple(numstack) else: number = None secnums[reference["anchorname"]] = None reference["secnumber"] = number if titlenode: titlenode["secnumber"] = number titlenode = None elif isinstance(subnode, addnodes.toctree): _walk_toctree(subnode, depth) def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None: if depth == 0: return for _, ref in toctreenode["entries"]: if url_re.match(ref) or ref == "self": # don't mess with those continue elif ref in assigned: logger.warning( __("%s is already assigned section numbers (nested numbered toctree?)" ), ref, location=toctreenode, type="toc", subtype="secnum", ) elif ref in env.tocs: secnums = {} # type: Dict[str, Tuple[int, ...]] env.toc_secnumbers[ref] = secnums assigned.add(ref) _walk_toc(env.tocs[ref], secnums, depth, env.titles.get(ref)) if secnums != old_secnumbers.get(ref): rewrite_needed.append(ref) for toctreenode in toctree_nodes: depth = toctreenode.get("numbered", 0) if depth: # every numbered toctree continues the numbering numstack = [self.last_chapter_number] _walk_toctree(toctreenode, depth) return rewrite_needed