Skip to content

Support external kernels #1305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 42 additions & 6 deletions jupyter_server/serverapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import urllib
import warnings
from base64 import encodebytes
from pathlib import Path

import jupyter_client
from jupyter_client.kernelspec import KernelSpecManager
from jupyter_client.manager import KernelManager
from jupyter_client.session import Session
Expand Down Expand Up @@ -1638,6 +1640,26 @@ def _update_notebook_dir(self, change):
self.log.warning(_i18n("notebook_dir is deprecated, use root_dir"))
self.root_dir = change["new"]

external_connection_dir = Unicode(
None,
allow_none=True,
config=True,
help=_i18n(
"The directory to look at for external kernel connection files, if allow_external_kernels is True. "
"Defaults to Jupyter runtime_dir/external_kernels. "
"Make sure that this directory is not filled with left-over connection files, "
"that could result in unnecessary kernel manager creations."
),
)

allow_external_kernels = Bool(
False,
config=True,
help=_i18n(
"Whether or not to allow external kernels, whose connection files are placed in external_connection_dir."
),
)

root_dir = Unicode(config=True, help=_i18n("The directory to use for notebooks and kernels."))
_root_dir_set = False

Expand Down Expand Up @@ -1873,12 +1895,26 @@ def init_configurables(self):
self.kernel_spec_manager = self.kernel_spec_manager_class(
parent=self,
)
self.kernel_manager = self.kernel_manager_class(
parent=self,
log=self.log,
connection_dir=self.runtime_dir,
kernel_spec_manager=self.kernel_spec_manager,
)

kwargs = {
"parent": self,
"log": self.log,
"connection_dir": self.runtime_dir,
"kernel_spec_manager": self.kernel_spec_manager,
}
if jupyter_client.version_info > (8, 3, 0):
if self.allow_external_kernels:
external_connection_dir = self.external_connection_dir
if external_connection_dir is None:
external_connection_dir = str(Path(self.runtime_dir) / "external_kernels")
kwargs["external_connection_dir"] = external_connection_dir
elif self.allow_external_kernels:
self.log.warning(
"Although allow_external_kernels=True, external kernels are not supported "
"because jupyter-client's version does not allow them (should be >8.3.0)."
)

self.kernel_manager = self.kernel_manager_class(**kwargs)
self.contents_manager = self.contents_manager_class(
parent=self,
log=self.log,
Expand Down
5 changes: 4 additions & 1 deletion jupyter_server/services/kernels/connection/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ def disconnect(self):
)

# start buffering instead of closing if this was the last connection
if self.multi_kernel_manager._kernel_connections[self.kernel_id] == 0:
if (
self.kernel_id in self.multi_kernel_manager._kernel_connections
and self.multi_kernel_manager._kernel_connections[self.kernel_id] == 0
):
self.multi_kernel_manager.start_buffering(
self.kernel_id, self.session_key, self.channels
)
Expand Down