Skip to content

Commit

Permalink
Allow interrupt during restart of pending kernels (#898)
Browse files Browse the repository at this point in the history
  • Loading branch information
blink1073 authored Dec 13, 2022
1 parent 4dbac9e commit b51a3b5
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 8 deletions.
8 changes: 4 additions & 4 deletions jupyter_client/consoleapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
# Aliases and Flags
# -----------------------------------------------------------------------------

flags = {}
flags: dict = {}
flags.update(base_flags)
# the flags that are specific to the frontend
# these must be scrubbed before being passed to the kernel,
# or it will raise an error on unrecognized flags
app_flags = {
app_flags: dict = {
"existing": (
{"JupyterConsoleApp": {"existing": "kernel*.json"}},
"Connect to an existing kernel. If no argument specified, guess most recent",
Expand All @@ -61,11 +61,11 @@
)
flags.update(app_flags)

aliases = {}
aliases: dict = {}
aliases.update(base_aliases)

# also scrub aliases from the frontend
app_aliases = {
app_aliases: dict = {
"ip": "JupyterConsoleApp.ip",
"transport": "JupyterConsoleApp.transport",
"hb": "JupyterConsoleApp.hb_port",
Expand Down
4 changes: 2 additions & 2 deletions jupyter_client/kernelspecapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,8 @@ class KernelSpecApp(Application):
}
)

aliases: t.Dict[str, object] = {}
flags: t.Dict[str, object] = {}
aliases: t.Dict[str, object] = {} # type:ignore[assignment]
flags: t.Dict[str, object] = {} # type:ignore[assignment]

def start(self):
if self.subapp is None:
Expand Down
12 changes: 12 additions & 0 deletions jupyter_client/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,18 @@ async def _async_interrupt_kernel(self) -> None:
Unlike ``signal_kernel``, this operation is well supported on all
platforms.
"""
if not self.has_kernel:
if self._ready is not None:
if isinstance(self._ready, CFuture):
ready = asyncio.ensure_future(self._ready) # type:ignore
else:
ready = self._ready
# Wait for a shutdown if one is in progress.
if self.shutting_down:
await ready
# Wait for a startup.
await ready

if self.has_kernel:
assert self.kernel_spec is not None
interrupt_mode = self.kernel_spec.interrupt_mode
Expand Down
6 changes: 4 additions & 2 deletions tests/test_multikernelmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,10 +311,12 @@ async def _run_lifecycle(km, test_kid=None):
assert kid in km
assert kid in km.list_kernel_ids()
assert len(km) == 1, f"{len(km)} != {1}"
await km.restart_kernel(kid, now=True)
# Ensure we can interrupt during a restart.
fut = km.restart_kernel(kid, now=True)
await km.interrupt_kernel(kid)
assert await km.is_alive(kid)
await fut
assert kid in km.list_kernel_ids()
await km.interrupt_kernel(kid)
k = km.get_kernel(kid)
assert isinstance(k, AsyncKernelManager)
await km.shutdown_kernel(kid, now=True)
Expand Down

0 comments on commit b51a3b5

Please sign in to comment.