marbu
marbu

Reputation: 2031

How to fix sphinx extension when two sphinx builders generates different doctrees?

In my pylatest sphinx extension, I define custom rst directive test_action and custom sphinx builder xmlexport so that when I build a sphinx project with default sphinx html builder (via make html), the test_action directives are transformed into single html table, while with xmlexport builder, the directives are just wrapped in div html tags without any additional processing.

To achieve this, the test_action directives generates custom doctree nodes which are either directly translated into html (extending html translator) when xmlexport builder is used, or with html builder the custom nodes are transformed into html table via custom rst transformation class.

I achieve this by checking which builder is used and adding transform classes accordingly:

def pylatest_transform_handler(app):
    if isinstance(app.builder, builders.XmlExportBuilder):
        ...
    else:
        # pylatest transforms for human readable html output,
        # translates pylatest nodes into nice sections or tables
        app.add_transform(transforms.TestActionsTableTransform)

In a function which handles builder-inited event in my sphinx extension:

def setup(app):
    ...
    # pylatest transforms are added based on app.builder value
    app.connect('builder-inited', pylatest_transform_handler)

This hack works, but it has one problem: when html builder is used, doctree cached in _build/doctree/ is diferent compared to one cached after xmlexport builder run. This means that when I run make html after I executed make xmlexport, the build fails because sphinx uses wrong doctree.

So the question I have is: How do I make sure that sphinx doctree cache is regenerated when different builders are used after each other, but kept when the same builder is used again?

Upvotes: 1

Views: 747

Answers (1)

marbu
marbu

Reputation: 2031

The problem here is that I'm using event builder-inited, which is not a good fit for this particular usage.

This causes the transformation to be performed during initialization phase of sphinx build and because doctree builds are saved after consistency checks phase, which follows the initialization one, the effects of the transformation are stored in doctree build files.

When I switched from add_transform to add_post_transform hooked on doctree-resolved event instead, it started to work as I need: the doctree saved into the files is the same (as the files are not affected by the transformation) and the transformations happens later during writing phase.

Upvotes: 2

Related Questions