Example #1
0
def run_nb_test(nb_filename, output_fname):
    """test run"""
    print(f'(1) Run notebook: {nb_filename}')
    ye_notebook = nbformat.read(nb_filename, as_version=4)

    client = NotebookClient(ye_notebook,
                            timeout=600,
                            kernel_name='python3',
                            resources={'metadata': {
                                'path': '.'
                            }})

    client.execute()

    if not os.path.isdir('test_output'):
        os.makedirs('test_output')

    output_file = f'test_output/{output_fname}'
    nbformat.write(ye_notebook, output_file)
    print(f'(2) file written: {output_file}')

    ye_notebook2 = nbformat.read(output_file, as_version=4)
    # 2. Instantiate the exporter. We use the `classic` template for now; we'll get into more details
    # later about how to customize the exporter further.
    html_exporter = HTMLExporter()
    html_exporter.template_name = 'classic'

    # 3. Process the notebook we loaded earlier
    (body, resources) = html_exporter.from_notebook_node(ye_notebook)

    html_filename = f'{output_file}.html'
    open(html_filename, 'w').write(body)
    print(f'file written: {html_filename}')
Example #2
0
def run_notebook(nb_path, tmp_path, env=None, kernel=None, allow_errors=False):
    """Execute a Jupyter notebook via :mod:`nbclient` and collect output.

    Parameters
    ----------
    nb_path : path-like
        The notebook file to execute.
    tmp_path : path-like
        A directory in which to create temporary output.
    env : dict-like, optional
        Execution environment for ``nbconvert``.
        If not supplied, :obj:`os.environ` is used.
    kernel : str, optional
        Jupyter kernel to use. Default: 'python2' or 'python3', matching the
        current Python version.
    allow_errors : bool, optional
        Whether to pass the ``--allow-errors`` option to ``nbconvert``. If
        :obj:`True`, the execution always succeeds, and cell output contains
        exception information.

    Returns
    -------
    nb : :class:`nbformat.NotebookNode`
        Parsed and executed notebook.
    errors : list
        Any execution errors.
    """
    import nbformat
    from nbclient import NotebookClient

    # Workaround for https://github.com/jupyter/nbclient/issues/85
    if (sys.version_info[0] == 3 and sys.version_info[1] >= 8
            and sys.platform.startswith("win")):
        import asyncio
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

    # Read the notebook
    with open(nb_path, encoding="utf-8") as f:
        nb = nbformat.read(f, as_version=4)

    # Create a client and use it to execute the notebook
    client = NotebookClient(nb,
                            timeout=60,
                            kernel_name=kernel
                            or f"python{sys.version_info[0]}",
                            allow_errors=allow_errors,
                            resources=dict(metadata=dict(path=tmp_path)))

    # Execute the notebook.
    # `env` is passed from nbclient to jupyter_client.launcher.launch_kernel()
    client.execute(env=env or os.environ.copy())

    # Retrieve error information from cells
    errors = [
        output for cell in nb.cells if "outputs" in cell
        for output in cell["outputs"] if output.output_type == "error"
    ]

    return nb, errors
Example #3
0
def test_notebook_3d_backend(renderer_notebook, brain_gc):
    """Test executing a notebook that should not fail."""
    import nbformat
    from nbclient import NotebookClient

    notebook_filename = os.path.join(PATH, "test.ipynb")
    with open(notebook_filename) as f:
        nb = nbformat.read(f, as_version=4)
    client = NotebookClient(nb)
    client.execute()
Example #4
0
def main(notebook_paths):
    """
    Executes Jupyter Notebooks from the command line.

    Expects one or more file paths input as arguments.

    Errors are raised and printed to the console.

    Example:

        $ python run.py ./src/notebooks.ipynb
    """
    for path_string in notebook_paths:
        click.echo(f"🐍🗒️  {path_string}")

        # Get the file name
        name = path_string.replace(".ipynb", "")

        # Get its parent directory so we can add it to the $PATH
        path = pathlib.Path(path_string).parent.absolute()

        # Set the intput and output file paths
        input_path = f"{name}.ipynb"
        output_path = f"{name}-output.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(
            # What we want it to run
            nb,
            timeout=600,
            kernel_name='python3',
            # We want to allow errors so it doesn't fail silently
            allow_errors=False,
            force_raise_errors=True,
            # Here's where the path gets set
            resources={'metadata': {
                'path': path
            }})
        try:
            # Run it
            client.execute()
        except CellExecutionError:
            # If there's an error, print it to the terminal.
            msg = f"Error executing {input_path}.\n See {output_path} for the traceback."
            click.echo(msg)
            # And then raise it too
            raise
        finally:
            # Once all that's done, write out the output notebook to the filesystem
            with open(output_path, mode='w', encoding='utf-8') as f:
                nbformat.write(nb, f)
Example #5
0
def _execute_notebook(path):
    """
    Private method to execute the provided notebook and handle errors.
    """
    with open(path) as f:
        nb = nbformat.read(f, as_version=4)
    client = NotebookClient(nb,
                            timeout=600,
                            kernel_name='python3',
                            resources={'metadata': {
                                'path': 'notebooks/'
                            }})
    try:
        client.execute()
    except CellExecutionError:
        out = None
        msg = f'Error executing the notebook "{path}".\n\n'
        msg += f'See notebook "{path}" for the traceback.'
        print(msg)
        raise
    finally:
        with open(path, mode='w', encoding='utf-8') as f:
            nbformat.write(nb, f)
]

if os.environ.get("PR", "") != "":
    notebooks = [
        nb for nb in notebooks if not any(avoid in nb for avoid in run_on_master_only)
    ]

os.chdir("workshop")
for notebook in notebooks:
    print(f"Loading {notebook}")
    nb = nbformat.read(notebook, as_version=4)

    for cell in nb.cells:
        if cell.get("cell_type", "") == "code" and "no-execute" in cell.get(
            "metadata", {}
        ).get("tags", []):
            cell["cell_type"] = "markdown"

    client = NotebookClient(
        nb,
        timeout=600,
        resources={"metadata": {"path": os.path.dirname(notebook)}},
    )
    try:
        client.execute()
        nbformat.write(nb, notebook)
    except CellExecutionError:
        msg = 'Error executing the notebook "%s".\n\n' % notebook
        print(msg)
        raise
Example #7
0
def compile_tutorial(tutorial_name, force_recompile=False):
    print('- Compiling tutorial ' + tutorial_name + '...')

    notebook_path = 'tutorial_notebooks/' + tutorial_name + '/' + tutorial_name + '.ipynb'
    export_path = 'tutorials/' + tutorial_name + '/' + tutorial_name
    thumb_dest = os.path.dirname(export_path) + '/thumb.png'

    if not os.path.exists(os.path.dirname(export_path)):
        os.makedirs(os.path.dirname(export_path))

    # Read in notebook
    notebook = nbformat.read(notebook_path, 4)

    # Scrape title, description and thumbnail
    first_cell = notebook.cells[0]

    title = first_cell.source.splitlines()[0]
    if '#' in title:
        title = title.replace('#', '').strip()

    description = ''
    for line in first_cell.source.splitlines()[1:]:
        if line.strip():
            description = line.strip()
            break

    if not description:
        print('  Description could not be found in the notebook.')

    if 'thumbnail_figure_index' in notebook.metadata:
        thumbnail_figure_index = notebook.metadata['thumbnail_figure_index']
    else:
        thumbnail_figure_index = -1

    if 'level' in notebook.metadata:
        level = notebook.metadata['level'].capitalize()
    elif 'difficulty' in notebook.metadata:
        level = notebook.metadata['difficulty'].capitalize()
    else:
        level = 'Unknown'

    # Check if the tutorial was already compiled.
    if os.path.exists(export_path + '.rst'):
        if os.path.getmtime(export_path +
                            '.rst') > os.path.getmtime(notebook_path):
            if force_recompile:
                print('  Already compiled. Recompiling anyway...')
            else:
                print('  Already compiled. Skipping...')
                return title, level, description, thumb_dest.split('/', 1)[-1]

    # Execute notebook if not already executed
    already_executed = any(
        c.get('outputs') or c.get('execution_count') for c in notebook.cells
        if c.cell_type == 'code')

    resources = {'metadata': {'path': os.path.dirname(notebook_path)}}

    if not already_executed:
        start = time.time()

        additional_cell_1 = {
            "cell_type":
            "code",
            "execution_count":
            None,
            "metadata": {},
            "outputs": [],
            "source":
            r"%matplotlib inline" + '\n' +
            r"%config InlineBackend.print_figure_kwargs = {'bbox_inches': None, 'figsize': (8, 6)}"
        }

        additional_cell_2 = {
            "cell_type":
            "code",
            "execution_count":
            None,
            "metadata": {},
            "outputs": [],
            "source":
            "import matplotlib as mpl\nmpl.rcParams['figure.figsize'] = (8, 6)\nmpl.rcParams['figure.dpi'] = 150\nmpl.rcParams['savefig.dpi'] = 150"
        }

        notebook.cells.insert(1, nbformat.from_dict(additional_cell_1))
        notebook.cells.insert(2, nbformat.from_dict(additional_cell_2))

        client = NotebookClient(nb=notebook,
                                resources=resources,
                                timeout=600,
                                kernel_name='python3')

        try:
            client.execute()
        except CellExecutionError as err:
            print('  Error while processing notebook:')
            print('  ', err)

        notebook.cells.pop(2)
        notebook.cells.pop(1)

        end = time.time()
        print('  Compilation took %d seconds.' % (end - start))
    else:
        print('  Notebook was already executed.')

    exporter = RSTExporter()
    output, resources = exporter.from_notebook_node(notebook, resources)

    writer = FilesWriter(build_directory=os.path.dirname(export_path))
    writer.write(output,
                 resources,
                 notebook_name=os.path.basename(export_path))

    pictures = sorted(resources['outputs'], key=output.find)

    try:
        thumbnail_source = pictures[thumbnail_figure_index]

        # Read in thumbnail source image
        img = Image.open(os.path.dirname(export_path) + '/' + thumbnail_source)

        # Trim whitespace
        bg = Image.new(img.mode, img.size, img.getpixel((0, 0)))
        diff = ImageChops.difference(img, bg)
        diff = ImageChops.add(diff, diff)
        bbox = diff.getbbox()
        if bbox:
            img = img.crop(bbox)

        # Resize image to have a width of 400px
        img.thumbnail([400, 1000])

        # Save thumbnail
        img.save(thumb_dest)
    except:
        shutil.copyfile('_static/no_thumb.png', thumb_dest)

    print('  Done!')

    return title, level, description, thumb_dest.split('/', 1)[-1]