first comit

This commit is contained in:
2024-02-23 10:30:02 +00:00
commit ddeb07d0ba
12482 changed files with 1857507 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
from .manager import AsyncIOLoopKernelManager # noqa
from .manager import IOLoopKernelManager # noqa
from .restarter import AsyncIOLoopKernelRestarter # noqa
from .restarter import IOLoopKernelRestarter # noqa

View File

@@ -0,0 +1,116 @@
"""A kernel manager with a tornado IOLoop"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import typing as t
import zmq
from tornado import ioloop
from traitlets import Instance, Type
from zmq.eventloop.zmqstream import ZMQStream
from ..manager import AsyncKernelManager, KernelManager
from .restarter import AsyncIOLoopKernelRestarter, IOLoopKernelRestarter
def as_zmqstream(f: t.Any) -> t.Callable:
"""Convert a socket to a zmq stream."""
def wrapped(self: t.Any, *args: t.Any, **kwargs: t.Any) -> t.Any:
save_socket_class = None
# zmqstreams only support sync sockets
if self.context._socket_class is not zmq.Socket:
save_socket_class = self.context._socket_class
self.context._socket_class = zmq.Socket
try:
socket = f(self, *args, **kwargs)
finally:
if save_socket_class:
# restore default socket class
self.context._socket_class = save_socket_class
return ZMQStream(socket, self.loop)
return wrapped
class IOLoopKernelManager(KernelManager):
"""An io loop kernel manager."""
loop = Instance("tornado.ioloop.IOLoop")
def _loop_default(self) -> ioloop.IOLoop:
return ioloop.IOLoop.current()
restarter_class = Type(
default_value=IOLoopKernelRestarter,
klass=IOLoopKernelRestarter,
help=(
"Type of KernelRestarter to use. "
"Must be a subclass of IOLoopKernelRestarter.\n"
"Override this to customize how kernel restarts are managed."
),
config=True,
)
_restarter: t.Any = Instance("jupyter_client.ioloop.IOLoopKernelRestarter", allow_none=True)
def start_restarter(self) -> None:
"""Start the restarter."""
if self.autorestart and self.has_kernel:
if self._restarter is None:
self._restarter = self.restarter_class(
kernel_manager=self, loop=self.loop, parent=self, log=self.log
)
self._restarter.start()
def stop_restarter(self) -> None:
"""Stop the restarter."""
if self.autorestart and self._restarter is not None:
self._restarter.stop()
connect_shell = as_zmqstream(KernelManager.connect_shell)
connect_control = as_zmqstream(KernelManager.connect_control)
connect_iopub = as_zmqstream(KernelManager.connect_iopub)
connect_stdin = as_zmqstream(KernelManager.connect_stdin)
connect_hb = as_zmqstream(KernelManager.connect_hb)
class AsyncIOLoopKernelManager(AsyncKernelManager):
"""An async ioloop kernel manager."""
loop = Instance("tornado.ioloop.IOLoop")
def _loop_default(self) -> ioloop.IOLoop:
return ioloop.IOLoop.current()
restarter_class = Type(
default_value=AsyncIOLoopKernelRestarter,
klass=AsyncIOLoopKernelRestarter,
help=(
"Type of KernelRestarter to use. "
"Must be a subclass of AsyncIOLoopKernelManager.\n"
"Override this to customize how kernel restarts are managed."
),
config=True,
)
_restarter: t.Any = Instance(
"jupyter_client.ioloop.AsyncIOLoopKernelRestarter", allow_none=True
)
def start_restarter(self) -> None:
"""Start the restarter."""
if self.autorestart and self.has_kernel:
if self._restarter is None:
self._restarter = self.restarter_class(
kernel_manager=self, loop=self.loop, parent=self, log=self.log
)
self._restarter.start()
def stop_restarter(self) -> None:
"""Stop the restarter."""
if self.autorestart and self._restarter is not None:
self._restarter.stop()
connect_shell = as_zmqstream(AsyncKernelManager.connect_shell)
connect_control = as_zmqstream(AsyncKernelManager.connect_control)
connect_iopub = as_zmqstream(AsyncKernelManager.connect_iopub)
connect_stdin = as_zmqstream(AsyncKernelManager.connect_stdin)
connect_hb = as_zmqstream(AsyncKernelManager.connect_hb)

View File

@@ -0,0 +1,102 @@
"""A basic in process kernel monitor with autorestarting.
This watches a kernel's state using KernelManager.is_alive and auto
restarts the kernel if it dies.
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import time
import warnings
from typing import Any
from traitlets import Instance
from ..restarter import KernelRestarter
class IOLoopKernelRestarter(KernelRestarter):
"""Monitor and autorestart a kernel."""
loop = Instance("tornado.ioloop.IOLoop")
def _loop_default(self) -> Any:
warnings.warn(
"IOLoopKernelRestarter.loop is deprecated in jupyter-client 5.2",
DeprecationWarning,
stacklevel=4,
)
from tornado import ioloop
return ioloop.IOLoop.current()
_pcallback = None
def start(self) -> None:
"""Start the polling of the kernel."""
if self._pcallback is None:
from tornado.ioloop import PeriodicCallback
self._pcallback = PeriodicCallback(
self.poll,
1000 * self.time_to_dead,
)
self._pcallback.start()
def stop(self) -> None:
"""Stop the kernel polling."""
if self._pcallback is not None:
self._pcallback.stop()
self._pcallback = None
class AsyncIOLoopKernelRestarter(IOLoopKernelRestarter):
"""An async io loop kernel restarter."""
async def poll(self) -> None: # type:ignore[override]
"""Poll the kernel."""
if self.debug:
self.log.debug("Polling kernel...")
is_alive = await self.kernel_manager.is_alive()
now = time.time()
if not is_alive:
self._last_dead = now
if self._restarting:
self._restart_count += 1
else:
self._restart_count = 1
if self._restart_count > self.restart_limit:
self.log.warning("AsyncIOLoopKernelRestarter: restart failed")
self._fire_callbacks("dead")
self._restarting = False
self._restart_count = 0
self.stop()
else:
newports = self.random_ports_until_alive and self._initial_startup
self.log.info(
"AsyncIOLoopKernelRestarter: restarting kernel (%i/%i), %s random ports",
self._restart_count,
self.restart_limit,
"new" if newports else "keep",
)
self._fire_callbacks("restart")
await self.kernel_manager.restart_kernel(now=True, newports=newports)
self._restarting = True
else:
# Since `is_alive` only tests that the kernel process is alive, it does not
# indicate that the kernel has successfully completed startup. To solve this
# correctly, we would need to wait for a kernel info reply, but it is not
# necessarily appropriate to start a kernel client + channels in the
# restarter. Therefore, we use "has been alive continuously for X time" as a
# heuristic for a stable start up.
# See https://github.com/jupyter/jupyter_client/pull/717 for details.
stable_start_time = self.stable_start_time
if self.kernel_manager.provisioner:
stable_start_time = self.kernel_manager.provisioner.get_stable_start_time(
recommended=stable_start_time
)
if self._initial_startup and now - self._last_dead >= stable_start_time:
self._initial_startup = False
if self._restarting and now - self._last_dead >= stable_start_time:
self.log.debug("AsyncIOLoopKernelRestarter: restart apparently succeeded")
self._restarting = False