{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Execute notebooks\n", "\n", "This notebook executes all phconvert notebooks to automate testing.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import os\n", "from pathlib import Path\n", "\n", "import nbformat\n", "from nbconvert.preprocessors import ExecutePreprocessor\n", "from IPython.display import display, FileLink\n", "\n", "\n", "def run_notebook(in_filepath, run_path=None, out_dir=None, out_suffix=''):\n", " \"\"\"Runs the notebook `notebook_name` (file name with no extension).\n", "\n", " This function executes notebook with name `notebook_name` (no extension)\n", " and saves the fully executed notebook in a new file appending \"-out\"\n", " to the original file name.\n", "\n", " It also displays links to the original and executed notebooks.\n", " \"\"\"\n", " if not in_filepath.is_file():\n", " raise IOError('File \"%s\" not found.' % in_filepath)\n", " in_filepath = in_filepath.resolve()\n", " \n", " if run_path is None:\n", " run_path = str(in_filepath.parent)\n", " \n", " if out_dir is None:\n", " out_dir = in_filepath.parent\n", " else:\n", " out_dir = Path(out_dir).resolve()\n", " \n", " out_filepath = Path(out_dir, \"%s%s.ipynb\" % (in_filepath.stem, out_suffix))\n", " \n", " nb = nbformat.read(in_filepath.open(), as_version=4)\n", " ep = ExecutePreprocessor(timeout = 3600)\n", "\n", " try:\n", " out = ep.preprocess(nb, {'metadata': {'path': run_path}})\n", " except Exception:\n", " msg = 'Error executing the notebook \"%s\".\\n\\n' % in_filepath\n", " msg += 'See notebook \"%s\" for the traceback.' % out_filepath\n", " print(msg)\n", " raise\n", " finally:\n", " nbformat.write(nb, out_filepath.open(mode='wt'))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "## Monkey patch needed until nbconvert > 4.0.0 is released\n", "## https://github.com/jupyter/nbconvert/releases\n", "\n", "from nbformat.v4 import output_from_msg\n", "from nbconvert.preprocessors.execute import CellExecutionError\n", "from textwrap import dedent\n", "\n", "def preprocess_cell(self, cell, resources, cell_index):\n", " \"\"\"\n", " Apply a transformation on each code cell. See base.py for details.\n", " \"\"\"\n", " if cell.cell_type != 'code':\n", " return cell, resources\n", "\n", " outputs = self.run_cell(cell)\n", " cell.outputs = outputs\n", "\n", " if not self.allow_errors:\n", " for out in outputs:\n", " if out.output_type == 'error':\n", " pattern = \"\"\"\\\n", " An error occurred while executing the following cell:\n", " ------------------\n", " {cell.source}\n", " ------------------\n", "\n", " {out.ename}: {out.evalue}\n", " \"\"\"\n", " msg = dedent(pattern).format(out=out, cell=cell)\n", " raise CellExecutionError(msg) \n", " return cell, resources\n", "\n", "def run_cell(self, cell):\n", " msg_id = self.kc.execute(cell.source)\n", " self.log.debug(\"Executing cell:\\n%s\", cell.source)\n", " # wait for finish, with timeout\n", " while True:\n", " try:\n", " msg = self.kc.shell_channel.get_msg(timeout=self.timeout)\n", " except Empty:\n", " self.log.error(\"\"\"Timeout waiting for execute reply (%is).\n", " If your cell should take longer than this, you can increase the timeout with:\n", "\n", " c.ExecutePreprocessor.timeout = SECONDS\n", "\n", " in jupyter_nbconvert_config.py\n", " \"\"\" % self.timeout)\n", " if self.interrupt_on_timeout:\n", " self.log.error(\"Interrupting kernel\")\n", " self.km.interrupt_kernel()\n", " break\n", " else:\n", " try:\n", " exception = TimeoutError\n", " except NameError:\n", " exception = RuntimeError\n", " raise exception(\"Cell execution timed out, see log\"\n", " \" for details.\")\n", "\n", " if msg['parent_header'].get('msg_id') == msg_id:\n", " break\n", " else:\n", " # not our reply\n", " continue\n", "\n", " outs = []\n", "\n", " while True:\n", " try:\n", " msg = self.kc.iopub_channel.get_msg(timeout=self.timeout)\n", " except Empty:\n", " self.log.warn(\"Timeout waiting for IOPub output\")\n", " break\n", " if msg['parent_header'].get('msg_id') != msg_id:\n", " # not an output from our execution\n", " continue\n", "\n", " msg_type = msg['msg_type']\n", " self.log.debug(\"output: %s\", msg_type)\n", " content = msg['content']\n", "\n", " # set the prompt number for the input and the output\n", " if 'execution_count' in content:\n", " cell['execution_count'] = content['execution_count']\n", "\n", " if msg_type == 'status':\n", " if content['execution_state'] == 'idle':\n", " break\n", " else:\n", " continue\n", " elif msg_type == 'execute_input':\n", " continue\n", " elif msg_type == 'clear_output':\n", " outs = []\n", " continue\n", " elif msg_type.startswith('comm'):\n", " continue\n", "\n", " try:\n", " out = output_from_msg(msg)\n", " except ValueError:\n", " self.log.error(\"unhandled iopub msg: \" + msg_type)\n", " else:\n", " outs.append(out)\n", "\n", " return outs\n", "\n", "ExecutePreprocessor.preprocess_cell = preprocess_cell\n", "ExecutePreprocessor.run_cell = run_cell" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%pwd" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pathlist = list(f for f in Path('../notebooks').glob('*.ipynb') if not f.name.startswith('_'))\n", "pathlist" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "for nbpath in pathlist:\n", " print(nbpath.stem)\n", " run_notebook(nbpath, out_dir=Path(nbpath.parent, 'out'))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.3" } }, "nbformat": 4, "nbformat_minor": 0 }