Skip to content

Commit

Permalink
Merge pull request voila-dashboards#544 from davidbrochart/show_timeout
Browse files Browse the repository at this point in the history
Show timeout error in cell output
  • Loading branch information
maartenbreddels authored Mar 23, 2020
2 parents 33ab5f3 + 3103385 commit 112163d
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 16 deletions.
10 changes: 4 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ jobs:
- name: Add conda to $PATH
run: echo ::add-path::$CONDA/condabin

- name: Update conda on Mac
- name: Fix permissions on Mac
if: matrix.os == 'macos-latest'
run: |
# sudo required?
sudo conda update -y -n base conda setuptools
- name: Update conda on Linux
if: matrix.os == 'ubuntu-latest'
sudo chmod -R a+rw /usr/local/miniconda
- name: Update conda
run: |
conda update -y -n base conda setuptools
Expand Down
20 changes: 20 additions & 0 deletions tests/app/timeout_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import pytest

import os


@pytest.fixture
def voila_notebook(notebook_directory):
return os.path.join(notebook_directory, 'sleep.ipynb')


@pytest.fixture
def voila_args_extra():
return ['--VoilaExecutePreprocessor.timeout=1', '--KernelManager.shutdown_wait_time=0.1']


@pytest.mark.gen_test
def test_timeout(http_client, base_url):
response = yield http_client.fetch(base_url)
html_text = response.body.decode('utf-8')
assert 'Cell execution timed out' in html_text
35 changes: 35 additions & 0 deletions tests/notebooks/sleep.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"time.sleep(10)"
]
}
],
"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.8.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
34 changes: 25 additions & 9 deletions voila/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
#############################################################################
import collections
import logging
try:
from time import monotonic # Py 3
except ImportError:
from time import time as monotonic # Py 2
from time import monotonic

from nbconvert.preprocessors import ClearOutputPreprocessor
from nbconvert.preprocessors.execute import CellExecutionError, ExecutePreprocessor
Expand All @@ -21,11 +18,6 @@
from traitlets import Unicode
from ipykernel.jsonutil import json_clean

try:
TimeoutError # Py 3
except NameError:
TimeoutError = RuntimeError # Py 2


def strip_code_cell_warnings(cell):
"""Strip any warning outputs and traceback from a code cell."""
Expand Down Expand Up @@ -131,6 +123,14 @@ class VoilaExecutePreprocessor(ExecutePreprocessor):
)
)

cell_timeout_instruction = Unicode(
'Please run Voila with --VoilaExecutePreprocessor.interrupt_on_timeout=True to continue executing the rest of the notebook.',
config=True,
help=(
'instruction given to user to continue execution on timeout'
)
)

def __init__(self, **kwargs):
super(VoilaExecutePreprocessor, self).__init__(**kwargs)
self.output_hook_stack = collections.defaultdict(list) # maps to list of hooks, where the last is used
Expand All @@ -154,6 +154,10 @@ def preprocess_cell(self, cell, resources, cell_index, store_history=True):
# TODO: pass store_history as a 5th argument when we can require nbconver >=5.6.1
# result = super(VoilaExecutePreprocessor, self).preprocess_cell(cell, resources, cell_index, store_history)
result = super(VoilaExecutePreprocessor, self).preprocess_cell(cell, resources, cell_index)
except TimeoutError as e:
self.log.error(e)
self.show_code_cell_timeout(cell)
raise e
except CellExecutionError as e:
self.log.error(e)
result = (cell, resources)
Expand Down Expand Up @@ -321,6 +325,18 @@ def run_cell(self, cell, cell_index=0, store_history=False):

return execute_reply, cell.outputs

def show_code_cell_timeout(self, cell):
"""Show a timeout error output in a code cell."""

timeout_message = 'Cell execution timed out, aborting notebook execution. {}'.format(self.cell_timeout_instruction)

output = {'output_type': 'error',
'ename': 'TimeoutError',
'evalue': 'Timeout error',
'traceback': [timeout_message]}

cell['outputs'] = [output]


def executenb(nb, cwd=None, km=None, **kwargs):
resources = {}
Expand Down
9 changes: 8 additions & 1 deletion voila/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,16 @@ def _jinja_cell_generator(self, nb, kernel_id):
nb, resources = ClearOutputPreprocessor().preprocess(nb, {'metadata': {'path': self.cwd}})
ep = VoilaExecutePreprocessor(config=self.traitlet_config)

stop_execution = False
with ep.setup_preprocessor(nb, resources, km=km):
for cell_idx, cell in enumerate(nb.cells):
res = ep.preprocess_cell(cell, resources, cell_idx, store_history=False)
if stop_execution:
break
try:
res = ep.preprocess_cell(cell, resources, cell_idx, store_history=False)
except TimeoutError:
res = (cell, resources)
stop_execution = True

yield res[0]

Expand Down

0 comments on commit 112163d

Please sign in to comment.