Skip to content

Commit 369a2c0

Browse files
committed
Use nbconvert's preprocessor infrastructure to execute the notebook.
This allows the cell removal plugins to remove cells before execution, for example. There is a problem using this nbsphinx with ipywidets - it complains about missing files in the html-collect-pages step.
1 parent f963a2a commit 369a2c0

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

src/nbsphinx.py

+24-14
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,13 @@
749749
"""
750750

751751

752+
class Writer(nbconvert.preprocessors.Preprocessor):
753+
def preprocess(self, nb, resources):
754+
if 'nbsphinx_save_notebook' in resources:
755+
# Save *executed* notebook *before* the Exporter can change it:
756+
nbformat.write(nb, resources['nbsphinx_save_notebook'])
757+
return nb, resources
758+
752759
class Exporter(nbconvert.RSTExporter):
753760
"""Convert Jupyter notebooks to reStructuredText.
754761
@@ -760,8 +767,6 @@ class Exporter(nbconvert.RSTExporter):
760767
761768
"""
762769

763-
# TODO: define default preprocessors to include our one to write out notebook just after execution
764-
765770
def __init__(self, execute='auto', kernel_name='', execute_arguments=[],
766771
allow_errors=False, timeout=None, codecell_lexer='none',
767772
nbconvert_config=None):
@@ -804,7 +809,6 @@ def replace_attachments(text):
804809
# Work around https://github.com/jupyter/nbconvert/issues/720:
805810
'RegexRemovePreprocessor': {'enabled': False},
806811
}
807-
808812
super(Exporter, self).__init__(
809813
template_file='nbsphinx-rst.tpl', extra_loaders=[loader],
810814
config=traitlets.config.Config(nbconvert_config),
@@ -848,23 +852,29 @@ def from_notebook_node(self, nb, resources=None, **kw):
848852
not any(c.get('outputs') or c.get('execution_count')
849853
for c in nb.cells if c.cell_type == 'code')
850854
)
855+
preprocessors = []
851856
if auto_execute or execute == 'always':
852857
allow_errors = nbsphinx_metadata.get(
853858
'allow_errors', self._allow_errors)
854859
timeout = nbsphinx_metadata.get('timeout', self._timeout)
855-
# TODO: Here, just add the execute preprocessor to the exporter list of preprocessors
856-
# rather than executing directly. We can still pass appropriate config values in
857-
# and that way the tag remove preprocessor is run *before* execution rather than after.
858-
pp = nbconvert.preprocessors.ExecutePreprocessor(
860+
preprocessors.append(nbconvert.preprocessors.ExecutePreprocessor(
859861
kernel_name=self._kernel_name,
860862
extra_arguments=self._execute_arguments,
861-
allow_errors=allow_errors, timeout=timeout)
862-
nb, resources = pp.preprocess(nb, resources)
863-
864-
if 'nbsphinx_save_notebook' in resources:
865-
# TODO: maybe we write our *own* preprocessor to hook into this stage, right after the execute preprocessor, to save the notebook
866-
# Save *executed* notebook *before* the Exporter can change it:
867-
nbformat.write(nb, resources['nbsphinx_save_notebook'])
863+
allow_errors=allow_errors, timeout=timeout))
864+
# pp = nbconvert.preprocessors.ExecutePreprocessor(
865+
# kernel_name=self._kernel_name,
866+
# extra_arguments=self._execute_arguments,
867+
# allow_errors=allow_errors, timeout=timeout)
868+
# nb, resources = pp.preprocess(nb, resources)
869+
870+
# if 'nbsphinx_save_notebook' in resources:
871+
# # Save *executed* notebook *before* the Exporter can change it:
872+
# nbformat.write(nb, resources['nbsphinx_save_notebook'])
873+
874+
preprocessors.append(Writer())
875+
# Find the existing execute preprocessor and replace it
876+
i = next((i for i,p in enumerate(self._preprocessors) if isinstance(p, nbconvert.preprocessors.ExecutePreprocessor)), len(self._preprocessors))
877+
self._preprocessors[i:i+1] = preprocessors
868878

869879
# Call into RSTExporter
870880
rststr, resources = super(Exporter, self).from_notebook_node(

0 commit comments

Comments
 (0)