Skip to content

Commit 29646f3

Browse files
feat: allow showing of stacktraces in server extension mode
Closes #751 This is a followup of #630
1 parent 6bcc277 commit 29646f3

File tree

8 files changed

+72
-17
lines changed

8 files changed

+72
-17
lines changed

tests/app/show_traceback_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(params=[True, False])
5+
def show_tracebacks(request):
6+
return request.param
7+
8+
9+
@pytest.fixture
10+
def voila_args(notebook_directory, voila_args_extra, show_tracebacks):
11+
return ['--VoilaTest.root_dir=%r' % notebook_directory, f'--VoilaConfiguration.show_tracebacks={show_tracebacks}'] + voila_args_extra
12+
13+
14+
async def test_syntax_error(http_server_client, syntax_error_notebook_url, show_tracebacks):
15+
response = await http_server_client.fetch(syntax_error_notebook_url)
16+
assert response.code == 200
17+
output = response.body.decode('utf-8')
18+
if show_tracebacks:
19+
assert 'this is a syntax error' in output, 'should show the "code"'
20+
assert 'SyntaxError' in output and 'invalid syntax' in output, "should show the error"
21+
else:
22+
assert 'There was an error when executing cell' in output
23+
assert 'This should not be executed' not in output

tests/app/syntax_error_test.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import pytest
22

33

4-
@pytest.fixture
5-
def syntax_error_notebook(base_url):
6-
return base_url + "voila/render/syntax_error.ipynb"
7-
8-
94
@pytest.fixture
105
def voila_args(notebook_directory, voila_args_extra):
116
return ['--VoilaTest.root_dir=%r' % notebook_directory] + voila_args_extra
127

138

14-
async def test_syntax_error(capsys, http_server_client, syntax_error_notebook):
15-
response = await http_server_client.fetch(syntax_error_notebook)
9+
async def test_syntax_error(capsys, http_server_client, syntax_error_notebook_url):
10+
response = await http_server_client.fetch(syntax_error_notebook_url)
1611
assert response.code == 200
1712
output = response.body.decode('utf-8')
1813
assert 'There was an error when executing cell' in output

tests/conftest.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ def print_notebook_url(base_url):
1717
return base_url + "voila/render/print.ipynb"
1818

1919

20+
@pytest.fixture
21+
def syntax_error_notebook_url(base_url):
22+
return base_url + "voila/render/syntax_error.ipynb"
23+
24+
2025
@pytest.fixture
2126
def voila_notebook(notebook_directory):
2227
return os.path.join(notebook_directory, 'print.ipynb')
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
3+
4+
@pytest.fixture(params=[True, False])
5+
def show_tracebacks(request):
6+
return request.param
7+
8+
9+
@pytest.fixture
10+
def jupyter_server_args_extra(show_tracebacks):
11+
return [f'--VoilaConfiguration.show_tracebacks={show_tracebacks}']
12+
13+
14+
async def test_syntax_error(http_server_client, syntax_error_notebook_url, show_tracebacks):
15+
response = await http_server_client.fetch(syntax_error_notebook_url)
16+
assert response.code == 200
17+
output = response.body.decode('utf-8')
18+
if show_tracebacks:
19+
assert 'this is a syntax error' in output, 'should show the "code"'
20+
assert 'SyntaxError' in output and 'invalid syntax' in output, "should show the error"
21+
else:
22+
assert 'There was an error when executing cell' in output
23+
assert 'This should not be executed' not in output

voila/app.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ class Voila(Application):
7575

7676
flags = {
7777
'debug': (
78-
{'Voila': {'log_level': logging.DEBUG, 'show_tracebacks': True}},
78+
{
79+
'Voila': {'log_level': logging.DEBUG},
80+
'VoilaConfiguration': {'show_tracebacks': True},
81+
},
7982
_("Set the log level to logging.DEBUG, and show exception tracebacks in output.")
8083
),
8184
'no-browser': ({'Voila': {'open_browser': False}}, _('Don\'t open the notebook in a browser after startup.'))
@@ -125,7 +128,8 @@ class Voila(Application):
125128
'theme': 'VoilaConfiguration.theme',
126129
'base_url': 'Voila.base_url',
127130
'server_url': 'Voila.server_url',
128-
'enable_nbextensions': 'VoilaConfiguration.enable_nbextensions'
131+
'enable_nbextensions': 'VoilaConfiguration.enable_nbextensions',
132+
'show_tracebacks': 'VoilaConfiguration.show_tracebacks',
129133
}
130134
classes = [
131135
VoilaConfiguration,
@@ -187,10 +191,6 @@ class Voila(Application):
187191
)
188192
)
189193

190-
show_tracebacks = Bool(False, config=True, help=_(
191-
'Whether to send tracebacks to clients on exceptions.'
192-
))
193-
194194
port_retries = Integer(50, config=True,
195195
help=_("The number of additional ports to try if the specified port is not available.")
196196
)

voila/configuration.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,7 @@ class VoilaConfiguration(traitlets.config.Configurable):
8181
When a cell takes a long time to execute, the http connection can timeout (possibly because of a proxy).
8282
Voila sends a 'heartbeat' message after the timeout is passed to keep the http connection alive.
8383
""").tag(config=True)
84+
85+
show_tracebacks = Bool(False, config=True, help=(
86+
'Whether to send tracebacks to clients on exceptions.'
87+
))

voila/execute.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from nbclient.exceptions import CellExecutionError
1212
from nbclient import NotebookClient
1313

14-
from traitlets import Unicode
14+
from traitlets import Bool, Unicode
1515

1616

1717
def strip_code_cell_warnings(cell):
@@ -32,7 +32,7 @@ def strip_code_cell_warnings(cell):
3232
class VoilaExecutor(NotebookClient):
3333
"""Execute, but respect the output widget behaviour"""
3434
cell_error_instruction = Unicode(
35-
'Please run Voilà with --debug to see the error message.',
35+
'Please run Voilà with --show_tracebacks=True or --debug to see the error message, or configure VoilaConfigurion.show_tracebacks.',
3636
config=True,
3737
help=(
3838
'instruction given to user to debug cell errors'
@@ -47,6 +47,10 @@ class VoilaExecutor(NotebookClient):
4747
)
4848
)
4949

50+
show_tracebacks = Bool(False, config=True, help=(
51+
'Whether to send tracebacks to clients on exceptions.'
52+
))
53+
5054
def execute(self, nb, resources, km=None):
5155
try:
5256
result = super(VoilaExecutor, self).execute()
@@ -77,7 +81,7 @@ async def execute_cell(self, cell, resources, cell_index, store_history=True):
7781

7882
def should_strip_error(self):
7983
"""Return True if errors should be stripped from the Notebook, False otherwise, depending on the current config."""
80-
return 'Voila' not in self.config or not self.config['Voila'].get('show_tracebacks', False)
84+
return not self.show_tracebacks
8185

8286
def strip_notebook_errors(self, nb):
8387
"""Strip error messages and traceback from a Notebook."""

voila/handler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ async def _jinja_kernel_start(self, nb):
170170
))
171171
km = self.kernel_manager.get_kernel(kernel_id)
172172

173-
self.executor = VoilaExecutor(nb, km=km, config=self.traitlet_config)
173+
self.executor = VoilaExecutor(nb, km=km, config=self.traitlet_config,
174+
show_tracebacks=self.voila_configuration.show_tracebacks)
174175

175176
###
176177
# start kernel client

0 commit comments

Comments
 (0)