Skip to content

Commit

Permalink
✨ NEW: Add nb_execution_raise_on_error config (#404)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjsewell authored Apr 21, 2022
1 parent edb0daf commit ba22f95
Show file tree
Hide file tree
Showing 14 changed files with 62 additions and 19 deletions.
8 changes: 8 additions & 0 deletions docs/use/execute.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ tags: [raises-exception]
print(thisvariabledoesntexist)
```
(execute/raise_on_error)=
## Error Reporting: Warning vs. Failure
When an error occurs in a context where `nb_execution_allow_errors=False`,
the default behaviour is for this to be reported as a warning.
This warning will simply be logged and not cause the build to fail unless `sphinx-build` is run with the [`-W` option](https://www.sphinx-doc.org/en/master/man/sphinx-build.html#cmdoption-sphinx-build-W).
If you would like unexpected execution errors to cause a build failure rather than a warning regardless of the `-W` option, you can achieve this by setting `nb_execution_raise_on_error=True` in your `conf.py`.
(execute/statistics)=
## Execution statistics
Expand Down
8 changes: 8 additions & 0 deletions myst_nb/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ def __post_init__(self):
"legacy_name": "execution_allow_errors",
},
)
execution_raise_on_error: bool = dc.field(
default=False,
metadata={
"validator": instance_of(bool),
"help": "Raise an exception on failed execution, "
"rather than emitting a warning",
},
)
execution_show_tb: bool = dc.field( # TODO implement
default=False,
metadata={
Expand Down
8 changes: 8 additions & 0 deletions myst_nb/core/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class ExecutionResult(TypedDict):
"""traceback if the notebook failed"""


class ExecutionError(Exception):
"""An exception for failed execution and `execution_raise_on_error` is true."""


def execute_notebook(
notebook: NotebookNode,
source: str,
Expand Down Expand Up @@ -111,6 +115,8 @@ def execute_notebook(
)

if result.err is not None:
if nb_config.execution_raise_on_error:
raise ExecutionError(str(source)) from result.err
msg = f"Executing notebook failed: {result.err.__class__.__name__}"
if nb_config.execution_show_tb:
msg += f"\n{result.exc_string}"
Expand Down Expand Up @@ -187,6 +193,8 @@ def execute_notebook(
# handle success / failure cases
# TODO do in try/except to be careful (in case of database write errors?
if result.err is not None:
if nb_config.execution_raise_on_error:
raise ExecutionError(str(source)) from result.err
msg = f"Executing notebook failed: {result.err.__class__.__name__}"
if nb_config.execution_show_tb:
msg += f"\n{result.exc_string}"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ testing = [
"coverage<5.0",
"beautifulsoup4",
"ipykernel~=5.5",
"ipython<8.1.0", # see https://github.com/ipython/ipython/issues/13554
"ipython!=8.1.0", # see https://github.com/ipython/ipython/issues/13554
"ipywidgets",
"jupytext~=1.11.2",
# TODO: 3.4.0 has some warnings that need to be fixed in the tests.
Expand Down
29 changes: 24 additions & 5 deletions tests/test_execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from IPython import version_info as ipy_version
import pytest

from myst_nb.core.execute import ExecutionError
from myst_nb.sphinx_ import NbMetadataCollector


Expand Down Expand Up @@ -153,6 +154,24 @@ def test_allow_errors_auto(sphinx_run, file_regression, check_nbs):
regress_nb_doc(file_regression, sphinx_run, check_nbs)


@pytest.mark.sphinx_params(
"basic_failing.ipynb",
conf={"nb_execution_raise_on_error": True, "nb_execution_mode": "force"},
)
def test_raise_on_error_force(sphinx_run):
with pytest.raises(ExecutionError, match="basic_failing.ipynb"):
sphinx_run.build()


@pytest.mark.sphinx_params(
"basic_failing.ipynb",
conf={"nb_execution_raise_on_error": True, "nb_execution_mode": "cache"},
)
def test_raise_on_error_cache(sphinx_run):
with pytest.raises(ExecutionError, match="basic_failing.ipynb"):
sphinx_run.build()


@pytest.mark.sphinx_params("basic_unrun.ipynb", conf={"nb_execution_mode": "force"})
def test_outputs_present(sphinx_run, file_regression, check_nbs):
sphinx_run.build()
Expand Down Expand Up @@ -222,13 +241,13 @@ def test_jupyter_cache_path(sphinx_run, file_regression, check_nbs):

# Testing relative paths within the notebook
@pytest.mark.sphinx_params("basic_relative.ipynb", conf={"nb_execution_mode": "cache"})
def test_relative_path_cache(sphinx_run, file_regression, check_nbs):
def test_relative_path_cache(sphinx_run):
sphinx_run.build()
assert "Execution Failed" not in sphinx_run.status(), sphinx_run.status()


@pytest.mark.sphinx_params("basic_relative.ipynb", conf={"nb_execution_mode": "force"})
def test_relative_path_force(sphinx_run, file_regression, check_nbs):
def test_relative_path_force(sphinx_run):
sphinx_run.build()
assert "Execution Failed" not in sphinx_run.status(), sphinx_run.status()

Expand All @@ -238,7 +257,7 @@ def test_relative_path_force(sphinx_run, file_regression, check_nbs):
"sleep_10.ipynb",
conf={"nb_execution_mode": "cache", "nb_execution_timeout": 1},
)
def test_execution_timeout(sphinx_run, file_regression, check_nbs):
def test_execution_timeout(sphinx_run):
"""execution should fail given the low timeout value"""
sphinx_run.build()
# print(sphinx_run.warnings())
Expand All @@ -249,7 +268,7 @@ def test_execution_timeout(sphinx_run, file_regression, check_nbs):
"sleep_10_metadata_timeout.ipynb",
conf={"nb_execution_mode": "cache", "nb_execution_timeout": 60},
)
def test_execution_metadata_timeout(sphinx_run, file_regression, check_nbs):
def test_execution_metadata_timeout(sphinx_run):
"""notebook timeout metadata has higher preference then execution_timeout config"""
sphinx_run.build()
# print(sphinx_run.warnings())
Expand All @@ -260,7 +279,7 @@ def test_execution_metadata_timeout(sphinx_run, file_regression, check_nbs):
"nb_exec_table.md",
conf={"nb_execution_mode": "auto"},
)
def test_nb_exec_table(sphinx_run, file_regression, check_nbs):
def test_nb_exec_table(sphinx_run, file_regression):
"""Test that the table gets output into the HTML,
including a row for the executed notebook.
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_execute/test_allow_errors_auto.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"\u001b[0;31mException\u001b[0m: oopsie!"
]
}
Expand All @@ -47,7 +47,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
"version": "3.8.13"
},
"test_name": "notebook1"
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_execute/test_allow_errors_auto.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<literal_block classes="output traceback" language="ipythontb" xml:space="preserve">
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Input In [1], in <module>
Input In [1], in <cell line: 1>()
----> 1 raise Exception('oopsie!')

Exception: oopsie!
4 changes: 2 additions & 2 deletions tests/test_execute/test_allow_errors_cache.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"\u001b[0;31mException\u001b[0m: oopsie!"
]
}
Expand All @@ -47,7 +47,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
"version": "3.8.13"
},
"test_name": "notebook1"
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_execute/test_allow_errors_cache.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<literal_block classes="output traceback" language="ipythontb" xml:space="preserve">
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Input In [1], in <module>
Input In [1], in <cell line: 1>()
----> 1 raise Exception('oopsie!')

Exception: oopsie!
4 changes: 2 additions & 2 deletions tests/test_execute/test_basic_failing_auto.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"\u001b[0;31mException\u001b[0m: oopsie!"
]
}
Expand All @@ -47,7 +47,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
"version": "3.8.13"
},
"test_name": "notebook1"
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_execute/test_basic_failing_auto.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<literal_block classes="output traceback" language="ipythontb" xml:space="preserve">
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Input In [1], in <module>
Input In [1], in <cell line: 1>()
----> 1 raise Exception('oopsie!')

Exception: oopsie!
4 changes: 2 additions & 2 deletions tests/test_execute/test_basic_failing_cache.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"Input \u001b[0;32mIn [1]\u001b[0m, in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124moopsie!\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
"\u001b[0;31mException\u001b[0m: oopsie!"
]
}
Expand All @@ -47,7 +47,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.12"
"version": "3.8.13"
},
"test_name": "notebook1"
},
Expand Down
2 changes: 1 addition & 1 deletion tests/test_execute/test_basic_failing_cache.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<literal_block classes="output traceback" language="ipythontb" xml:space="preserve">
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
Input In [1], in <module>
Input In [1], in <cell line: 1>()
----> 1 raise Exception('oopsie!')

Exception: oopsie!
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# then then deleting compiled files has been found to fix it: `find . -name \*.pyc -delete`

[tox]
envlist = py37-sphinx4
envlist = py38-sphinx4

[testenv]
usedevelop = true
Expand Down

0 comments on commit ba22f95

Please sign in to comment.