Skip to content

Commit

Permalink
Support MultiKernelManager (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart authored May 14, 2020
1 parent 0418c04 commit 67c2f28
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 4 deletions.
24 changes: 20 additions & 4 deletions nbclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,25 +363,41 @@ async def async_start_new_kernel_client(self, **kwargs):
-------
kc : KernelClient
Kernel client as created by the kernel manager `km`.
kernel_id : string-ized version 4 uuid
The id of the started kernel.
"""
resource_path = self.resources.get('metadata', {}).get('path') or None
if resource_path and 'cwd' not in kwargs:
kwargs["cwd"] = resource_path

if self.km.ipykernel and self.ipython_hist_file:
# if self.km is a MultiKernelManager, it doesn't have an ipykernel attribute
# so no extra_arguments can be passed
if hasattr(self.km, 'ipykernel') and self.km.ipykernel and self.ipython_hist_file:
self.extra_arguments += ['--HistoryManager.hist_file={}'.format(self.ipython_hist_file)]

await ensure_async(self.km.start_kernel(extra_arguments=self.extra_arguments, **kwargs))
kernel_id = await ensure_async(self.km.start_kernel(extra_arguments=self.extra_arguments,
**kwargs))

self.kc = self.km.client()
# if self.km is not a KernelManager, it's probably a MultiKernelManager
try:
self.km.client
km = self.km
except AttributeError:
try:
km = self.km.get_kernel(kernel_id)
except AttributeError:
raise AttributeError('self.km={} has no client() or get_kernel() method, '
'what is this?'.format(self.km))

self.kc = km.client()
await ensure_async(self.kc.start_channels())
try:
await ensure_async(self.kc.wait_for_ready(timeout=self.startup_timeout))
except RuntimeError:
await self._async_cleanup_kernel()
raise
self.kc.allow_stdin = False
return self.kc
return self.kc, kernel_id

start_new_kernel_client = run_sync(async_start_new_kernel_client)

Expand Down
38 changes: 38 additions & 0 deletions nbclient/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import IPython
from traitlets import TraitError
from nbformat import NotebookNode
from jupyter_client import KernelManager, MultiKernelManager
from jupyter_client.kernelspec import KernelSpecManager
from nbconvert.filters import strip_ansi
from testpath import modified_env
Expand Down Expand Up @@ -400,6 +401,43 @@ def test_synchronous_setup_kernel():
assert executor.kc is None


def test_startnewkernel_with_kernelmanager():
nb = nbformat.v4.new_notebook()
km = KernelManager()
executor = NotebookClient(nb, km=km)
kc, kernel_id = executor.start_new_kernel_client()
# no kernel_id for a single kernel manager
assert kernel_id is None
# prove it initalized client
assert kc is not None
# since we are not using the setup_kernel context manager,
# cleanup has to be done manually
kc.shutdown()
km.cleanup()
kc.stop_channels()


def test_startnewkernel_with_multikernelmanager():
nb = nbformat.v4.new_notebook()
km = MultiKernelManager()
executor = NotebookClient(nb, km=km)
kc, kernel_id = executor.start_new_kernel_client()
# a multi kernel manager always gives back an id to the started kernel
assert kernel_id is not None
# prove it initalized client
assert kc is not None
# since we are not using the setup_kernel context manager,
# cleanup has to be done manually
kc.shutdown()
km.cleanup(kernel_id)
km.remove_kernel(kernel_id)
# check that the kernel doesn't exist anymore
with pytest.raises(KeyError) as e_info:
km.get_kernel(kernel_id)
assert str(e_info.value) == "'Kernel with id not found: {}'".format(kernel_id)
kc.stop_channels()


class TestExecute(NBClientTestsBase):
"""Contains test functions for execute.py"""

Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
codecov
coverage
ipython
ipykernel
ipywidgets
pytest>=4.1
pytest-cov>=2.6.1
Expand Down

0 comments on commit 67c2f28

Please sign in to comment.