Exemple #1
0
    def visit_transition(self, node):

        if isinstance(node.parent, addnodes.only):
            process_only_nodes(
                node.parent.parent,
                tags=self.document.settings.env.app.builder.tags,
            )
Exemple #2
0
 def run(self, **kwargs):
     # type: (Any) -> None
     # A comment on the comment() nodes being inserted: replacing by [] would
     # result in a "Losing ids" exception if there is a target node before
     # the only node, so we make sure docutils can transfer the id to
     # something, even if it's just a comment and will lose the id anyway...
     process_only_nodes(self.document, self.app.builder.tags)
Exemple #3
0
 def apply(self, **kwargs):
     # type: (Any) -> None
     # A comment on the comment() nodes being inserted: replacing by [] would
     # result in a "Losing ids" exception if there is a target node before
     # the only node, so we make sure docutils can transfer the id to
     # something, even if it's just a comment and will lose the id anyway...
     process_only_nodes(self.document, self.app.builder.tags)
Exemple #4
0
 def get_toc_for(self, docname: str, builder: "Builder") -> Node:
     """Return a TOC nodetree -- for use on the same page only!"""
     tocdepth = self.env.metadata[docname].get('tocdepth', 0)
     try:
         toc = self.env.tocs[docname].deepcopy()
         self._toctree_prune(toc, 2, tocdepth)
     except KeyError:
         # the document does not exist anymore: return a dummy node that
         # renders to nothing
         return nodes.paragraph()
     process_only_nodes(toc, builder.tags)
     for node in toc.traverse(nodes.reference):
         node['refuri'] = node['anchorname'] or '#'
     return toc
Exemple #5
0
 def get_toc_for(self, docname, builder):
     """Return a TOC nodetree -- for use on the same page only!"""
     tocdepth = self.env.metadata[docname].get('tocdepth', 0)
     try:
         toc = self.tocs[docname].deepcopy()
         self._toctree_prune(toc, 2, tocdepth)
     except KeyError:
         # the document does not exist anymore: return a dummy node that
         # renders to nothing
         return nodes.paragraph()
     process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
     for node in toc.traverse(nodes.reference):
         node['refuri'] = node['anchorname'] or '#'
     return toc
Exemple #6
0
    def resolve_references(self, doctree, fromdocname, builder):
        # type: (nodes.Node, unicode, Builder) -> None
        for node in doctree.traverse(addnodes.pending_xref):
            contnode = node[0].deepcopy()
            newnode = None

            typ = node['reftype']
            target = node['reftarget']
            refdoc = node.get('refdoc', fromdocname)
            domain = None

            try:
                if 'refdomain' in node and node['refdomain']:
                    # let the domain try to resolve the reference
                    try:
                        domain = self.domains[node['refdomain']]
                    except KeyError:
                        raise NoUri
                    newnode = domain.resolve_xref(self, refdoc, builder, typ,
                                                  target, node, contnode)
                # really hardwired reference types
                elif typ == 'any':
                    newnode = self._resolve_any_reference(
                        builder, refdoc, node, contnode)
                elif typ == 'doc':
                    newnode = self._resolve_doc_reference(
                        builder, refdoc, node, contnode)
                # no new node found? try the missing-reference event
                if newnode is None:
                    newnode = builder.app.emit_firstresult(
                        'missing-reference', self, node, contnode)
                    # still not found? warn if node wishes to be warned about or
                    # we are in nit-picky mode
                    if newnode is None:
                        self._warn_missing_reference(refdoc, typ, target, node,
                                                     domain)
            except NoUri:
                newnode = contnode
            node.replace_self(newnode or contnode)

        # remove only-nodes that do not belong to our builder
        process_only_nodes(doctree, builder.tags)

        # allow custom references to be resolved
        builder.app.emit('doctree-resolved', doctree, fromdocname)
def get_local_toc_for(builder, docname, maxdepth=-1):
    """Return a TOC nodetree -- for use on the same page only!"""
    env = builder.env

    if maxdepth < 0:
        maxdepth = env.metadata[docname].get('tocdepth', 0)

    toctree = env.toctree
    try:
        toc = toctree.tocs[docname].deepcopy()
        toctree._toctree_prune(toc, 2, maxdepth)
    except KeyError:
        # the document does not exist anymore: return a dummy node that
        # renders to nothing
        return nodes.paragraph()
    sphinx_nodes.process_only_nodes(toc, builder.tags, warn_node=env.warn_node)
    for node in toc.traverse(nodes.reference):
        node['refuri'] = node['anchorname'] or '#'
    return toc
Exemple #8
0
    def resolve_references(self, doctree, fromdocname, builder):
        for node in doctree.traverse(addnodes.pending_xref):
            contnode = node[0].deepcopy()
            newnode = None

            typ = node['reftype']
            target = node['reftarget']
            refdoc = node.get('refdoc', fromdocname)
            domain = None

            try:
                if 'refdomain' in node and node['refdomain']:
                    # let the domain try to resolve the reference
                    try:
                        domain = self.domains[node['refdomain']]
                    except KeyError:
                        raise NoUri
                    newnode = domain.resolve_xref(self, refdoc, builder,
                                                  typ, target, node, contnode)
                # really hardwired reference types
                elif typ == 'any':
                    newnode = self._resolve_any_reference(builder, refdoc, node, contnode)
                elif typ == 'doc':
                    newnode = self._resolve_doc_reference(builder, refdoc, node, contnode)
                # no new node found? try the missing-reference event
                if newnode is None:
                    newnode = builder.app.emit_firstresult(
                        'missing-reference', self, node, contnode)
                    # still not found? warn if node wishes to be warned about or
                    # we are in nit-picky mode
                    if newnode is None:
                        self._warn_missing_reference(refdoc, typ, target, node, domain)
            except NoUri:
                newnode = contnode
            node.replace_self(newnode or contnode)

        # remove only-nodes that do not belong to our builder
        process_only_nodes(doctree, builder.tags, warn_node=self.warn_node)

        # allow custom references to be resolved
        builder.app.emit('doctree-resolved', doctree, fromdocname)
Exemple #9
0
def test_sectioning(app, status, warning):
    def getsects(section):
        if not isinstance(section, nodes.section):
            return [getsects(n) for n in section.children]
        title = section.next_node(nodes.title).astext().strip()
        subsects = []
        children = section.children[:]
        while children:
            node = children.pop(0)
            if isinstance(node, nodes.section):
                subsects.append(node)
                continue
            children = list(node.children) + children
        return [title, [getsects(subsect) for subsect in subsects]]

    def testsects(prefix, sects, indent=0):
        title = sects[0]
        parent_num = title.split()[0]
        assert prefix == parent_num, \
            'Section out of place: %r' % title
        for i, subsect in enumerate(sects[1]):
            num = subsect[0].split()[0]
            assert re.match('[0-9]+[.0-9]*[.]', num), \
                'Unnumbered section: %r' % subsect[0]
            testsects(prefix + str(i + 1) + '.', subsect, indent + 4)

    app.builder.build(['only'])
    doctree = app.env.get_doctree('only')
    process_only_nodes(doctree, app.builder.tags)

    parts = [
        getsects(n) for n in
        [_n for _n in doctree.children if isinstance(_n, nodes.section)]
    ]
    for i, s in enumerate(parts):
        testsects(str(i + 1) + '.', s, 4)
    assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \
        '\n'.join([p[0] for p in parts])
def test_sectioning(app, status, warning):

    def getsects(section):
        if not isinstance(section, nodes.section):
            return [getsects(n) for n in section.children]
        title = section.next_node(nodes.title).astext().strip()
        subsects = []
        children = section.children[:]
        while children:
            node = children.pop(0)
            if isinstance(node, nodes.section):
                subsects.append(node)
                continue
            children = list(node.children) + children
        return [title, [getsects(subsect) for subsect in subsects]]

    def testsects(prefix, sects, indent=0):
        title = sects[0]
        parent_num = title.split()[0]
        assert prefix == parent_num, \
            'Section out of place: %r' % title
        for i, subsect in enumerate(sects[1]):
            num = subsect[0].split()[0]
            assert re.match('[0-9]+[.0-9]*[.]', num), \
                'Unnumbered section: %r' % subsect[0]
            testsects(prefix + str(i+1) + '.', subsect, indent+4)

    app.builder.build(['only'])
    doctree = app.env.get_doctree('only')
    process_only_nodes(doctree, app.builder.tags)

    parts = [getsects(n)
             for n in [_n for _n in doctree.children if isinstance(_n, nodes.section)]]
    for i, s in enumerate(parts):
        testsects(str(i+1) + '.', s, 4)
    assert len(parts) == 4, 'Expected 4 document level headings, got:\n%s' % \
        '\n'.join([p[0] for p in parts])
Exemple #11
0
 def _entries_from_toctree(toctreenode,
                           parents,
                           separate=False,
                           subtree=False):
     """Return TOC entries for a toctree node."""
     refs = [(e[0], e[1]) for e in toctreenode['entries']]
     entries = []
     for (title, ref) in refs:
         try:
             refdoc = None
             if url_re.match(ref):
                 if title is None:
                     title = ref
                 reference = nodes.reference('',
                                             '',
                                             internal=False,
                                             refuri=ref,
                                             anchorname='',
                                             *[nodes.Text(title)])
                 para = addnodes.compact_paragraph('', '', reference)
                 item = nodes.list_item('', para)
                 toc = nodes.bullet_list('', item)
             elif ref == 'self':
                 # 'self' refers to the document from which this
                 # toctree originates
                 ref = toctreenode['parent']
                 if not title:
                     title = clean_astext(self.env.titles[ref])
                 reference = nodes.reference('',
                                             '',
                                             internal=True,
                                             refuri=ref,
                                             anchorname='',
                                             *[nodes.Text(title)])
                 para = addnodes.compact_paragraph('', '', reference)
                 item = nodes.list_item('', para)
                 # don't show subitems
                 toc = nodes.bullet_list('', item)
             else:
                 if ref in parents:
                     logger.warning(
                         'circular toctree references '
                         'detected, ignoring: %s <- %s',
                         ref,
                         ' <- '.join(parents),
                         location=ref)
                     continue
                 refdoc = ref
                 toc = self.tocs[ref].deepcopy()
                 maxdepth = self.env.metadata[ref].get('tocdepth', 0)
                 if ref not in toctree_ancestors or (prune
                                                     and maxdepth > 0):
                     self._toctree_prune(toc, 2, maxdepth, collapse)
                 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):
                         if refnode['refuri'] == ref and \
                            not refnode['anchorname']:
                             refnode.children = [nodes.Text(title)]
             if not toc.children:
                 # empty toc means: no titles will show up in the toctree
                 logger.warning(
                     'toctree contains reference to document %r that '
                     'doesn\'t have a title: no link will be generated',
                     ref,
                     location=toctreenode)
         except KeyError:
             # this is raised if the included file does not exist
             logger.warning(
                 'toctree contains reference to nonexisting document %r',
                 ref,
                 location=toctreenode)
         else:
             # if titles_only is given, only keep the main title and
             # sub-toctrees
             if titles_only:
                 # delete everything but the toplevel title(s)
                 # and toctrees
                 for toplevel in toc:
                     # nodes with length 1 don't have any children anyway
                     if len(toplevel) > 1:
                         subtrees = toplevel.traverse(addnodes.toctree)
                         if subtrees:
                             toplevel[1][:] = subtrees
                         else:
                             toplevel.pop(1)
             # resolve all sub-toctrees
             for subtocnode in toc.traverse(addnodes.toctree):
                 if not (subtocnode.get('hidden', False)
                         and not includehidden):
                     i = subtocnode.parent.index(subtocnode) + 1
                     for item in _entries_from_toctree(
                             subtocnode, [refdoc] + parents,
                             subtree=True):
                         subtocnode.parent.insert(i, item)
                         i += 1
                     subtocnode.parent.remove(subtocnode)
             if separate:
                 entries.append(toc)
             else:
                 entries.extend(toc.children)
     if not subtree and not separate:
         ret = nodes.bullet_list()
         ret += entries
         return [ret]
     return entries
Exemple #12
0
 def _entries_from_toctree(toctreenode, parents,
                           separate=False, subtree=False):
     """Return TOC entries for a toctree node."""
     refs = [(e[0], e[1]) for e in toctreenode['entries']]
     entries = []
     for (title, ref) in refs:
         try:
             refdoc = None
             if url_re.match(ref):
                 if title is None:
                     title = ref
                 reference = nodes.reference('', '', internal=False,
                                             refuri=ref, anchorname='',
                                             *[nodes.Text(title)])
                 para = addnodes.compact_paragraph('', '', reference)
                 item = nodes.list_item('', para)
                 toc = nodes.bullet_list('', item)
             elif ref == 'self':
                 # 'self' refers to the document from which this
                 # toctree originates
                 ref = toctreenode['parent']
                 if not title:
                     title = clean_astext(self.titles[ref])
                 reference = nodes.reference('', '', internal=True,
                                             refuri=ref,
                                             anchorname='',
                                             *[nodes.Text(title)])
                 para = addnodes.compact_paragraph('', '', reference)
                 item = nodes.list_item('', para)
                 # don't show subitems
                 toc = nodes.bullet_list('', item)
             else:
                 if ref in parents:
                     self.env.warn(ref, 'circular toctree references '
                                   'detected, ignoring: %s <- %s' %
                                   (ref, ' <- '.join(parents)))
                     continue
                 refdoc = ref
                 toc = self.tocs[ref].deepcopy()
                 maxdepth = self.env.metadata[ref].get('tocdepth', 0)
                 if ref not in toctree_ancestors or (prune and maxdepth > 0):
                     self._toctree_prune(toc, 2, maxdepth, collapse)
                 process_only_nodes(toc, builder.tags, warn_node=self.env.warn_node)
                 if title and toc.children and len(toc.children) == 1:
                     child = toc.children[0]
                     for refnode in child.traverse(nodes.reference):
                         if refnode['refuri'] == ref and \
                            not refnode['anchorname']:
                             refnode.children = [nodes.Text(title)]
             if not toc.children:
                 # empty toc means: no titles will show up in the toctree
                 self.env.warn_node(
                     'toctree contains reference to document %r that '
                     'doesn\'t have a title: no link will be generated'
                     % ref, toctreenode)
         except KeyError:
             # this is raised if the included file does not exist
             self.env.warn_node(
                 'toctree contains reference to nonexisting document %r'
                 % ref, toctreenode)
         else:
             # if titles_only is given, only keep the main title and
             # sub-toctrees
             if titles_only:
                 # delete everything but the toplevel title(s)
                 # and toctrees
                 for toplevel in toc:
                     # nodes with length 1 don't have any children anyway
                     if len(toplevel) > 1:
                         subtrees = toplevel.traverse(addnodes.toctree)
                         if subtrees:
                             toplevel[1][:] = subtrees
                         else:
                             toplevel.pop(1)
             # resolve all sub-toctrees
             for subtocnode in toc.traverse(addnodes.toctree):
                 if not (subtocnode.get('hidden', False) and
                         not includehidden):
                     i = subtocnode.parent.index(subtocnode) + 1
                     for item in _entries_from_toctree(
                             subtocnode, [refdoc] + parents,
                             subtree=True):
                         subtocnode.parent.insert(i, item)
                         i += 1
                     subtocnode.parent.remove(subtocnode)
             if separate:
                 entries.append(toc)
             else:
                 entries.extend(toc.children)
     if not subtree and not separate:
         ret = nodes.bullet_list()
         ret += entries
         return [ret]
     return entries
Exemple #13
0
    def write(self, *ignored: Any) -> None:
        assert self.env is not None

        docwriter = LaTeXWriter(self)
        docsettings: Any = OptionParser(
            defaults=self.env.settings,
            components=(docwriter, ),
            read_config_files=True,
        ).get_default_values()

        if sphinx.version_info <= (4, 0):
            # 3rd party
            from sphinx.builders.latex import patch_settings  # type: ignore
            patch_settings(docsettings)

        self.init_document_data()
        self.write_stylesheet()

        for entry in self.document_data:
            docname, targetname, title, author, themename = entry[:5]
            theme = self.themes.get(themename)
            toctree_only = False
            if len(entry) > 5:
                toctree_only = entry[5]
            destination = SphinxFileOutput(destination_path=os.path.join(
                self.outdir, targetname),
                                           encoding="utf-8",
                                           overwrite_if_changed=True)
            with progress_message(__("processing %s") % targetname):
                doctree = self.env.get_doctree(docname)
                process_only_nodes(doctree, self.tags)
                toctree = next(iter(doctree.traverse(addnodes.toctree)), None)
                if toctree and toctree.get("maxdepth") > 0:
                    tocdepth = toctree.get("maxdepth")
                else:
                    tocdepth = None

                doctree = self.assemble_doctree(
                    docname,
                    toctree_only,
                    appendices=(self.config.latex_appendices
                                if theme.name != "howto" else []))
                doctree["docclass"] = theme.docclass
                doctree["contentsname"] = self.get_contentsname(docname)
                doctree["tocdepth"] = tocdepth
                self.post_process_images(doctree)
                self.update_doc_context(title, author, theme)

                if hasattr(self, "update_context"):  # pragma: no cover
                    # Only present in newer Sphinx versions
                    self.update_context()

            with progress_message(__("writing")):
                docsettings._author = author
                docsettings._title = title
                docsettings._contentsname = doctree["contentsname"]
                docsettings._docname = docname
                docsettings._docclass = theme.name

                doctree.settings = docsettings
                docwriter.theme = theme
                docwriter.write(doctree, destination)