Skip to content

Commit

Permalink
Update Execute preprocessor traits
Browse files Browse the repository at this point in the history
Update the traits on the Execute preprocessor based on the discussion in
#1690, including adding a
version pin of ipython >= 8.10.0

Also, reorder traits to match the upstream parent, NotebookClient.
  • Loading branch information
shreve authored and brichet committed Mar 23, 2023
1 parent 4d14ce6 commit 0a7c117
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 46 deletions.
57 changes: 12 additions & 45 deletions nbgrader/preprocessors/execute.py
Expand Up @@ -14,57 +14,31 @@ class UnresponsiveKernelError(Exception):

class Execute(NbGraderPreprocessor, ExecutePreprocessor):

timeout = Integer(
30,
help=ExecutePreprocessor.timeout.help,
allow_none=True,
).tag(config=True)

interrupt_on_timeout = Bool(
True,
help=dedent(
"""
If execution of a cell times out, interrupt the kernel and
continue executing other cells rather than throwing an error and
stopping.
"""
)
help=ExecutePreprocessor.interrupt_on_timeout.help
).tag(config=True)

allow_errors = Bool(
True,
help=dedent(
"""
If ``False``, when a cell raises an error the
execution is stopped and a ``CellExecutionError``
is raised, except if the error name is in
``allow_error_names``.
If ``True`` (default), execution errors are ignored and the execution
is continued until the end of the notebook. Output from
exceptions is included in the cell output in both cases.
When a cell execution results in an error, continue executing the rest of
the notebook. If False, the thrown nbclient exception would break aspects of
output rendering.
"""
),
).tag(config=True)
)

raise_on_iopub_timeout = Bool(
True,
help=dedent(
"""
If ``False``, then the kernel will continue waiting for
iopub messages until it receives a kernel idle message, or until a
timeout occurs, at which point the currently executing cell will be
skipped. If ``True`` (default), then an error will be raised after the first
timeout. This option generally does not need to be used, but may be
useful in contexts where there is the possibility of executing
notebooks with memory-consuming infinite loops.
"""
),
).tag(config=True)

timeout = Integer(
30,
help=dedent(
"""
The time to wait (in seconds) for output from executions.
If a cell execution takes longer, a TimeoutError is raised.
``None`` or ``-1`` will disable the timeout. If ``timeout_func`` is set,
it overrides ``timeout``.
"""
)
help=ExecutePreprocessor.raise_on_iopub_timeout.help
).tag(config=True)

error_on_timeout = {
Expand All @@ -89,13 +63,6 @@ class Execute(NbGraderPreprocessor, ExecutePreprocessor):
""")
).tag(config=True)

@validate('timeout')
def _validate_timeout(self, proposal):
value = int(proposal['value'])
if value <= 0:
raise TraitError("the timeout should be a positive value")
return value

def on_cell_executed(self, **kwargs):
cell = kwargs['cell']
reply = kwargs['execute_reply']
Expand Down
7 changes: 6 additions & 1 deletion nbgrader/tests/apps/test_nbgrader_autograde.py
Expand Up @@ -105,6 +105,11 @@ def test_showtraceback_exploit(self, db, course_dir):
self._copy_file(join("files", "submitted-unchanged.ipynb"), join(course_dir, "source", "ps1", "p1.ipynb"))
run_nbgrader(["generate_assignment", "ps1", "--db", db])

# This exploit previously caused cell executions that would indefinitely hang.
# See: https://github.com/ipython/ipython/commit/fd34cf5
with open("nbgrader_config.py", "a") as fh:
fh.write("""c.Execute.timeout = None""")

self._copy_file(join("files", "submitted-unchanged.ipynb"), join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"))
self._copy_file(join("files", "submitted-changed.ipynb"), join(course_dir, "submitted", "bar", "ps1", "p1.ipynb"))
self._copy_file(join("files", "submitted-cheat-attempt.ipynb"), join(course_dir, "submitted", "spam", "ps1", "p1.ipynb"))
Expand Down Expand Up @@ -995,7 +1000,7 @@ def test_infinite_loop(self, db, course_dir):
run_nbgrader(["db", "student", "add", "foo", "--db", db])
run_nbgrader(["db", "student", "add", "bar", "--db", db])
with open("nbgrader_config.py", "a") as fh:
fh.write("""c.ExecutePreprocessor.timeout = 1""")
fh.write("""c.Execute.timeout = 1""")

self._copy_file(join("files", "infinite-loop.ipynb"), join(course_dir, "source", "ps1", "p1.ipynb"))
run_nbgrader(["generate_assignment", "ps1", "--db", db])
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Expand Up @@ -32,6 +32,7 @@ classifiers = [
]
dependencies = [
"alembic>=1.7",
"ipython>=8.10.0",
"ipywidgets>=7.6",
"Jinja2>=3",
"jsonschema>=3",
Expand Down

0 comments on commit 0a7c117

Please sign in to comment.