jupyter / jupyter-sphinx

Sphinx extension for rendering of Jupyter interactive widgets.
https://jupyter-sphinx.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
187 stars 65 forks source link

Speed up building no execute and no output code blocks #199

Closed kwankyu closed 2 years ago

kwankyu commented 2 years ago

In our project, we are going to make a massive use of jupyer-sphinx for live documentation:

https://trac.sagemath.org/ticket/33320

In our case, all code blocks have :execute: false, :hide-code: and :hide-output: tags, and are supposed to run code via Thebe. But still building the live doc takes much more time than the static doc -- more than three times. This seems beyond reasonable. Is there a way to increase the building speed?

akhmerov commented 2 years ago

The extra overhead comes from spinning up jupyter kernels that populate virtual notebook metadata. That metadata is then used to determine how to launch thebe. I don't think there's a straightforward way to speed up launching kernels, and without launching the metadata wouldn't be available, so avoiding the empty kernel launch would also not be satisfactory.

My recommendation would be to define your own doctree directives that create the appropriate nodes right from the get go, but don't go through the execution transform.

kwankyu commented 2 years ago

Thanks for the comment. I didn't want to define our own directives and so ended up with this

class SageExecuteJupyterCells(SphinxTransform):
    """A cut-down ExecuteJupyterCells for building Sage documentation.

    All JupyterCellNodes for code blocks in the Sage documentation have
    `:hide-code:` and `:hide-output:` options. Hence no actual execution of
    Jupyter notebooks is necessary. So this class mimics ExecuteJupyterCells
    assuming empty inputs and outputs from Jupyter notebooks.
    """
    default_priority = 180

    def apply(self):
        doctree = self.document
        thebe_config = self.config.jupyter_sphinx_thebelab_config

        nodes = doctree.traverse(JupyterCellNode)

        if not nodes:
            return

        if thebe_config:
            # Add the button at the bottom if it is not present
            if not doctree.traverse(ThebeButtonNode):
                doctree.append(ThebeButtonNode())
            add_thebelab_library(doctree, self.env)

        for node in nodes:
            source = node.children[0]
            source.attributes["classes"].append("code_cell")
            node.attributes["cm_language"] = 'sage'
            node += CellOutputBundleNode([])
akhmerov commented 2 years ago

Neat, this is also an appropriate solution. I'm closing this as resolved.