1

I am trying to write a Sphinx extension and I noticed that the nodes instances parsed during the environnement collector are not the same instances later when the doctree is resolved. I really don't understand why.

I would like to set new properties to my instance, but I loose it later in the process.

In the following example, the id of the node in A and Z are different:

from docutils import nodes

from sphinx import addnodes
from sphinx.util.docutils import SphinxDirective
from sphinx.environment.adapters.toctree import TocTree
from sphinx.environment.collectors import EnvironmentCollector

class dummy(nodes.Element):
    pass

class DummyDirective(SphinxDirective):
    has_content = True

    def run(self):
        return [dummy()]

def process_dummy_nodes(app, doctree, fromdocname):
    for node in doctree.traverse(dummy):
        # cannot get `node.property` because node was rewritten somewhere...
        print('Z. dummy id: ', id(node))


class DummyCollector(EnvironmentCollector):
    def clear_doc(self, app, env, docname):
        pass

    def process_doc(self, app, doctree):
        pass

    def get_updated_docs(self, app, env):

        def traverse_all(env, docname):
            doctree = env.get_doctree(docname)

            for toc in doctree.traverse(addnodes.toctree):
                for _, subdocname in toc['entries']:
                    traverse_all(env, subdocname)

            for node in doctree.traverse(dummy):
                self.process_dummy(env, node, docname)

        traverse_all(env, env.config.master_doc)

        return []

    def process_dummy(self, env, node, docname):
        node.property = 42
        print('A. dummy id: ', id(node))

def setup(app):
    app.add_enumerable_node(dummy, 'dummy', html=(lambda x, y: 0, lambda x, y: 0))
    app.add_directive('dummy', DummyDirective)
    app.connect('doctree-resolved', process_dummy_nodes)
    app.add_env_collector(DummyCollector)

    return {
        'version': '0.1',
        'parallel_read_safe': True,
        'parallel_write_safe': True,
    }ยจ

The output for one dummy node would be something like the following. You notice that the id of the same dummy node is different and obviously the property I have set earlier is gone.

$ make clean html
Removing everything under 'build'...
Running Sphinx v2.2.0
making output directory... done
building [mo]: targets for 0 po files that are out of date
building [html]: targets for 4 source files that are out of date
updating environment: 4 added, 0 changed, 0 removed
reading sources... [100%] index
looking for now-outdated files... 

A. dummy id:  140140465053368

pickling environment... done
checking consistency... done
preparing documents... done

Z. dummy id:  140140464440600

generating indices...  genindexdone
writing additional pages...  searchdone
copying static files... ... done
copying extra files... done
dumping search index in English (code: en)... done
dumping object inventory... done
build succeeded.

The HTML pages are in build/html.

I suppose it is because the nodes are written on the disk between the two processes, but custom properties are therefore not preserved during the process.

Is there a way to keep them?

nowox
  • 25,978
  • 39
  • 143
  • 293

0 Answers0