You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.4 KiB
158 lines
4.4 KiB
2 years ago
|
import logging
|
||
|
import pathlib
|
||
|
import sys
|
||
|
from textwrap import dedent
|
||
|
|
||
|
import nbformat
|
||
|
from jupyter_core.application import JupyterApp
|
||
|
from traitlets import Bool, Integer, List, Unicode, default
|
||
|
from traitlets.config import catch_config_error
|
||
|
|
||
|
from nbclient import __version__
|
||
|
|
||
|
from .client import NotebookClient
|
||
|
|
||
|
nbclient_aliases = {
|
||
|
'timeout': 'NbClientApp.timeout',
|
||
|
'startup_timeout': 'NbClientApp.startup_timeout',
|
||
|
'kernel_name': 'NbClientApp.kernel_name',
|
||
|
}
|
||
|
|
||
|
nbclient_flags = {
|
||
|
'allow-errors': (
|
||
|
{
|
||
|
'NbClientApp': {
|
||
|
'allow_errors': True,
|
||
|
},
|
||
|
},
|
||
|
"Errors are ignored and execution is continued until the end of the notebook.",
|
||
|
),
|
||
|
}
|
||
|
|
||
|
|
||
|
class NbClientApp(JupyterApp):
|
||
|
"""
|
||
|
An application used to execute notebook files (``*.ipynb``)
|
||
|
"""
|
||
|
|
||
|
version = Unicode(__version__)
|
||
|
name = 'jupyter-execute'
|
||
|
aliases = nbclient_aliases
|
||
|
flags = nbclient_flags
|
||
|
|
||
|
description = "An application used to execute notebook files (*.ipynb)"
|
||
|
notebooks = List([], help="Path of notebooks to convert").tag(config=True)
|
||
|
timeout: int = Integer(
|
||
|
None,
|
||
|
allow_none=True,
|
||
|
help=dedent(
|
||
|
"""
|
||
|
The time to wait (in seconds) for output from executions.
|
||
|
If a cell execution takes longer, a TimeoutError is raised.
|
||
|
``-1`` will disable the timeout.
|
||
|
"""
|
||
|
),
|
||
|
).tag(config=True)
|
||
|
startup_timeout: int = Integer(
|
||
|
60,
|
||
|
help=dedent(
|
||
|
"""
|
||
|
The time to wait (in seconds) for the kernel to start.
|
||
|
If kernel startup takes longer, a RuntimeError is
|
||
|
raised.
|
||
|
"""
|
||
|
),
|
||
|
).tag(config=True)
|
||
|
allow_errors: bool = Bool(
|
||
|
False,
|
||
|
help=dedent(
|
||
|
"""
|
||
|
When a cell raises an error the default behavior is that
|
||
|
execution is stopped and a :py:class:`nbclient.exceptions.CellExecutionError`
|
||
|
is raised.
|
||
|
If this flag is provided, errors are ignored and execution
|
||
|
is continued until the end of the notebook.
|
||
|
"""
|
||
|
),
|
||
|
).tag(config=True)
|
||
|
skip_cells_with_tag: str = Unicode(
|
||
|
'skip-execution',
|
||
|
help=dedent(
|
||
|
"""
|
||
|
Name of the cell tag to use to denote a cell that should be skipped.
|
||
|
"""
|
||
|
),
|
||
|
).tag(config=True)
|
||
|
kernel_name: str = Unicode(
|
||
|
'',
|
||
|
help=dedent(
|
||
|
"""
|
||
|
Name of kernel to use to execute the cells.
|
||
|
If not set, use the kernel_spec embedded in the notebook.
|
||
|
"""
|
||
|
),
|
||
|
).tag(config=True)
|
||
|
|
||
|
@default('log_level')
|
||
|
def _log_level_default(self):
|
||
|
return logging.INFO
|
||
|
|
||
|
@catch_config_error
|
||
|
def initialize(self, argv=None):
|
||
|
super().initialize(argv)
|
||
|
|
||
|
# Get notebooks to run
|
||
|
self.notebooks = self.get_notebooks()
|
||
|
|
||
|
# If there are none, throw an error
|
||
|
if not self.notebooks:
|
||
|
print(f"{self.name}: error: expected path to notebook")
|
||
|
sys.exit(-1)
|
||
|
|
||
|
# Loop and run them one by one
|
||
|
[self.run_notebook(path) for path in self.notebooks]
|
||
|
|
||
|
def get_notebooks(self):
|
||
|
# If notebooks were provided from the command line, use those
|
||
|
if self.extra_args:
|
||
|
notebooks = self.extra_args
|
||
|
# If not, look to the class attribute
|
||
|
else:
|
||
|
notebooks = self.notebooks
|
||
|
|
||
|
# Return what we got.
|
||
|
return notebooks
|
||
|
|
||
|
def run_notebook(self, notebook_path):
|
||
|
# Log it
|
||
|
self.log.info(f"Executing {notebook_path}")
|
||
|
|
||
|
name = notebook_path.replace(".ipynb", "")
|
||
|
|
||
|
# Get its parent directory so we can add it to the $PATH
|
||
|
path = pathlib.Path(notebook_path).parent.absolute()
|
||
|
|
||
|
# Set the input file paths
|
||
|
input_path = f"{name}.ipynb"
|
||
|
|
||
|
# Open up the notebook we're going to run
|
||
|
with open(input_path) as f:
|
||
|
nb = nbformat.read(f, as_version=4)
|
||
|
|
||
|
# Configure nbclient to run the notebook
|
||
|
client = NotebookClient(
|
||
|
nb,
|
||
|
timeout=self.timeout,
|
||
|
startup_timeout=self.startup_timeout,
|
||
|
skip_cells_with_tag=self.skip_cells_with_tag,
|
||
|
allow_errors=self.allow_errors,
|
||
|
kernel_name=self.kernel_name,
|
||
|
resources={'metadata': {'path': path}},
|
||
|
)
|
||
|
|
||
|
# Run it
|
||
|
client.execute()
|
||
|
|
||
|
|
||
|
main = NbClientApp.launch_instance
|