Skip to content
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

Improve typing by ignoring less #1001

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
115 changes: 57 additions & 58 deletions jupyter_client/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from .asynchronous import AsyncKernelClient
from .blocking import BlockingKernelClient
from .client import KernelClient
from .clientabc import KernelClientABC
from .connect import ConnectionFileMixin
from .managerabc import KernelManagerABC
from .provisioning import KernelProvisionerBase
Expand All @@ -58,6 +59,7 @@ class _ShutdownStatus(Enum):


F = t.TypeVar("F", bound=t.Callable[..., t.Any])
KernelClientBound = t.TypeVar("KernelClientBound", bound=KernelClientABC)


def _get_future() -> t.Union[Future, CFuture]:
Expand Down Expand Up @@ -98,7 +100,7 @@ async def wrapper(self: t.Any, *args: t.Any, **kwargs: t.Any) -> t.Any:
return t.cast(F, wrapper)


class KernelManager(ConnectionFileMixin):
class _KernelManagerBase(ConnectionFileMixin, t.Generic[KernelClientBound]):
"""Manages a single kernel in a subprocess on this host.

This version starts kernels with Popen.
Expand Down Expand Up @@ -126,18 +128,15 @@ def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
_created_context: Bool = Bool(False)

# The PyZMQ Context to use for communication with the kernel.
context: Instance = Instance(zmq.Context)
context: Instance

@default("context")
def _context_default(self) -> zmq.Context:
self._created_context = True
return zmq.Context()
raise NotImplementedError

# the class to create with our `client` method
client_class: DottedObjectName = DottedObjectName(
"jupyter_client.blocking.BlockingKernelClient"
)
client_factory: Type = Type(klass=KernelClient)
client_class: DottedObjectName
client_factory: Type

@default("client_factory")
def _client_factory_default(self) -> Type:
Expand Down Expand Up @@ -260,7 +259,7 @@ def remove_restart_callback(self, callback: t.Callable, event: str = "restart")
# create a Client connected to our Kernel
# --------------------------------------------------------------------------

def client(self, **kwargs: t.Any) -> BlockingKernelClient:
def client(self, **kwargs: t.Any) -> KernelClientBound:
"""Create a client configured to connect to our kernel"""
kw: dict = {}
kw.update(self.get_connection_info(session=True))
Expand Down Expand Up @@ -357,8 +356,6 @@ async def _async_launch_kernel(self, kernel_cmd: t.List[str], **kw: t.Any) -> No
# and write the connection file, if not already done.
self._reconcile_connection_info(connection_info)

_launch_kernel = run_sync(_async_launch_kernel)

# Control socket used for polite kernel shutdown

def _connect_control_socket(self) -> None:
Expand Down Expand Up @@ -401,8 +398,6 @@ async def _async_pre_start_kernel(
kernel_cmd = kw.pop("cmd")
return kernel_cmd, kw

pre_start_kernel = run_sync(_async_pre_start_kernel)

async def _async_post_start_kernel(self, **kw: t.Any) -> None:
"""Performs any post startup tasks relative to the kernel.

Expand All @@ -416,8 +411,6 @@ async def _async_post_start_kernel(self, **kw: t.Any) -> None:
assert self.provisioner is not None
await self.provisioner.post_launch(**kw)

post_start_kernel = run_sync(_async_post_start_kernel)

@in_pending_state
async def _async_start_kernel(self, **kw: t.Any) -> None:
"""Starts a kernel on this host in a separate process.
Expand All @@ -439,8 +432,6 @@ async def _async_start_kernel(self, **kw: t.Any) -> None:
await self._async_launch_kernel(kernel_cmd, **kw)
await self._async_post_start_kernel(**kw)

start_kernel = run_sync(_async_start_kernel)

async def _async_request_shutdown(self, restart: bool = False) -> None:
"""Send a shutdown request via control channel"""
content = {"restart": restart}
Expand All @@ -452,8 +443,6 @@ async def _async_request_shutdown(self, restart: bool = False) -> None:
await self.provisioner.shutdown_requested(restart=restart)
self._shutdown_status = _ShutdownStatus.ShutdownRequest

request_shutdown = run_sync(_async_request_shutdown)

async def _async_finish_shutdown(
self,
waittime: t.Optional[float] = None,
Expand Down Expand Up @@ -493,8 +482,6 @@ async def _async_finish_shutdown(
assert self.provisioner is not None
await self.provisioner.wait()

finish_shutdown = run_sync(_async_finish_shutdown)

async def _async_cleanup_resources(self, restart: bool = False) -> None:
"""Clean up resources when the kernel is shut down"""
if not restart:
Expand All @@ -510,8 +497,6 @@ async def _async_cleanup_resources(self, restart: bool = False) -> None:
if self.provisioner:
await self.provisioner.cleanup(restart=restart)

cleanup_resources = run_sync(_async_cleanup_resources)

@in_pending_state
async def _async_shutdown_kernel(self, now: bool = False, restart: bool = False) -> None:
"""Attempts to stop the kernel process cleanly.
Expand Down Expand Up @@ -552,8 +537,6 @@ async def _async_shutdown_kernel(self, now: bool = False, restart: bool = False)

await self._async_cleanup_resources(restart=restart)

shutdown_kernel = run_sync(_async_shutdown_kernel)

async def _async_restart_kernel(
self, now: bool = False, newports: bool = False, **kw: t.Any
) -> None:
Expand Down Expand Up @@ -595,8 +578,6 @@ async def _async_restart_kernel(
self._launch_args.update(kw)
await self._async_start_kernel(**self._launch_args)

restart_kernel = run_sync(_async_restart_kernel)

@property
def owns_kernel(self) -> bool:
return self._owns_kernel
Expand All @@ -612,8 +593,6 @@ async def _async_send_kernel_sigterm(self, restart: bool = False) -> None:
assert self.provisioner is not None
await self.provisioner.terminate(restart=restart)

_send_kernel_sigterm = run_sync(_async_send_kernel_sigterm)

async def _async_kill_kernel(self, restart: bool = False) -> None:
"""Kill the running kernel.

Expand All @@ -635,8 +614,6 @@ async def _async_kill_kernel(self, restart: bool = False) -> None:
if self.has_kernel:
await self.provisioner.wait()

_kill_kernel = run_sync(_async_kill_kernel)

async def _async_interrupt_kernel(self) -> None:
"""Interrupts the kernel by sending it a signal.

Expand Down Expand Up @@ -668,8 +645,6 @@ async def _async_interrupt_kernel(self) -> None:
msg = "Cannot interrupt kernel. No kernel is running!"
raise RuntimeError(msg)

interrupt_kernel = run_sync(_async_interrupt_kernel)

async def _async_signal_kernel(self, signum: int) -> None:
"""Sends a signal to the process group of the kernel (this
usually includes the kernel and any subprocesses spawned by
Expand All @@ -685,8 +660,6 @@ async def _async_signal_kernel(self, signum: int) -> None:
msg = "Cannot signal kernel. No kernel is running!"
raise RuntimeError(msg)

signal_kernel = run_sync(_async_signal_kernel)

async def _async_is_alive(self) -> bool:
"""Is the kernel process still running?"""
if not self.owns_kernel:
Expand All @@ -699,8 +672,6 @@ async def _async_is_alive(self) -> bool:
return True
return False

is_alive = run_sync(_async_is_alive)

async def _async_wait(self, pollinterval: float = 0.1) -> None:
# Use busy loop at 100ms intervals, polling until the process is
# not alive. If we find the process is no longer alive, complete
Expand All @@ -710,7 +681,40 @@ async def _async_wait(self, pollinterval: float = 0.1) -> None:
await asyncio.sleep(pollinterval)


class AsyncKernelManager(KernelManager):
class KernelManager(_KernelManagerBase[BlockingKernelClient]):
"""A blocking kernel manager."""

# the class to create with our `client` method
client_class: DottedObjectName = DottedObjectName(
"jupyter_client.blocking.BlockingKernelClient"
)
client_factory: Type = Type(klass=BlockingKernelClient)

# The PyZMQ Context to use for communication with the kernel.
context: Instance = Instance(zmq.Context)

@default("context")
def _context_default(self) -> zmq.Context:
self._created_context = True
return zmq.Context()

_launch_kernel = run_sync(_KernelManagerBase._async_launch_kernel)
start_kernel = run_sync(_KernelManagerBase._async_start_kernel)
pre_start_kernel = run_sync(_KernelManagerBase._async_pre_start_kernel)
post_start_kernel = run_sync(_KernelManagerBase._async_post_start_kernel)
request_shutdown = run_sync(_KernelManagerBase._async_request_shutdown)
finish_shutdown = run_sync(_KernelManagerBase._async_finish_shutdown)
cleanup_resources = run_sync(_KernelManagerBase._async_cleanup_resources)
shutdown_kernel = run_sync(_KernelManagerBase._async_shutdown_kernel)
restart_kernel = run_sync(_KernelManagerBase._async_restart_kernel)
_send_kernel_sigterm = run_sync(_KernelManagerBase._async_send_kernel_sigterm)
_kill_kernel = run_sync(_KernelManagerBase._async_kill_kernel)
interrupt_kernel = run_sync(_KernelManagerBase._async_interrupt_kernel)
signal_kernel = run_sync(_KernelManagerBase._async_signal_kernel)
is_alive = run_sync(_KernelManagerBase._async_is_alive)


class AsyncKernelManager(_KernelManagerBase[AsyncKernelClient]):
"""An async kernel manager."""

# the class to create with our `client` method
Expand All @@ -727,29 +731,24 @@ def _context_default(self) -> zmq.asyncio.Context:
self._created_context = True
return zmq.asyncio.Context()

def client( # type:ignore[override]
self, **kwargs: t.Any
) -> AsyncKernelClient:
"""Get a client for the manager."""
return super().client(**kwargs) # type:ignore[return-value]

_launch_kernel = KernelManager._async_launch_kernel # type:ignore[assignment]
start_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_start_kernel # type:ignore[assignment]
pre_start_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_pre_start_kernel # type:ignore[assignment]
post_start_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_post_start_kernel # type:ignore[assignment]
request_shutdown: t.Callable[..., t.Awaitable] = KernelManager._async_request_shutdown # type:ignore[assignment]
finish_shutdown: t.Callable[..., t.Awaitable] = KernelManager._async_finish_shutdown # type:ignore[assignment]
cleanup_resources: t.Callable[..., t.Awaitable] = KernelManager._async_cleanup_resources # type:ignore[assignment]
shutdown_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_shutdown_kernel # type:ignore[assignment]
restart_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_restart_kernel # type:ignore[assignment]
_send_kernel_sigterm = KernelManager._async_send_kernel_sigterm # type:ignore[assignment]
_kill_kernel = KernelManager._async_kill_kernel # type:ignore[assignment]
interrupt_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_interrupt_kernel # type:ignore[assignment]
signal_kernel: t.Callable[..., t.Awaitable] = KernelManager._async_signal_kernel # type:ignore[assignment]
is_alive: t.Callable[..., t.Awaitable] = KernelManager._async_is_alive # type:ignore[assignment]
_launch_kernel = _KernelManagerBase._async_launch_kernel
start_kernel = _KernelManagerBase._async_start_kernel
pre_start_kernel = _KernelManagerBase._async_pre_start_kernel
post_start_kernel = _KernelManagerBase._async_post_start_kernel
request_shutdown = _KernelManagerBase._async_request_shutdown
finish_shutdown = _KernelManagerBase._async_finish_shutdown
cleanup_resources = _KernelManagerBase._async_cleanup_resources
shutdown_kernel = _KernelManagerBase._async_shutdown_kernel
restart_kernel = _KernelManagerBase._async_restart_kernel
_send_kernel_sigterm = _KernelManagerBase._async_send_kernel_sigterm
_kill_kernel = _KernelManagerBase._async_kill_kernel
interrupt_kernel = _KernelManagerBase._async_interrupt_kernel
signal_kernel = _KernelManagerBase._async_signal_kernel
is_alive = _KernelManagerBase._async_is_alive


KernelManagerABC.register(KernelManager)
KernelManagerABC.register(AsyncKernelManager)


def start_new_kernel(
Expand Down
31 changes: 15 additions & 16 deletions jupyter_client/multikernelmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def wrapped(
return wrapped


class MultiKernelManager(LoggingConfigurable):
class _MultiKernelManagerBase(LoggingConfigurable):
"""A class for managing multiple kernels."""

default_kernel_name = Unicode(
Expand Down Expand Up @@ -226,7 +226,7 @@ def update_env(self, *, kernel_id: str, env: t.Dict[str, str]) -> None:
self._kernels[kernel_id].update_env(env=env)

async def _add_kernel_when_ready(
self, kernel_id: str, km: KernelManager, kernel_awaitable: t.Awaitable
self, kernel_id: str, km: KernelManager, kernel_awaitable: t.Awaitable[t.Any]
) -> None:
try:
await kernel_awaitable
Expand All @@ -236,7 +236,7 @@ async def _add_kernel_when_ready(
self.log.exception(e)

async def _remove_kernel_when_ready(
self, kernel_id: str, kernel_awaitable: t.Awaitable
self, kernel_id: str, kernel_awaitable: t.Awaitable[t.Any]
) -> None:
try:
await kernel_awaitable
Expand Down Expand Up @@ -284,8 +284,6 @@ async def _async_start_kernel(self, *, kernel_name: str | None = None, **kwargs:

return kernel_id

start_kernel = run_sync(_async_start_kernel)

async def _async_shutdown_kernel(
self,
kernel_id: str,
Expand Down Expand Up @@ -331,8 +329,6 @@ async def _async_shutdown_kernel(
if km.ready.exception():
raise km.ready.exception() # type: ignore[misc]

shutdown_kernel = run_sync(_async_shutdown_kernel)

@kernel_method
def request_shutdown(self, kernel_id: str, restart: bool | None = False) -> None:
"""Ask a kernel to shut down by its kernel uuid"""
Expand Down Expand Up @@ -379,8 +375,6 @@ async def _async_shutdown_all(self, now: bool = False) -> None:
# Will have been logged in _add_kernel_when_ready
pass

shutdown_all = run_sync(_async_shutdown_all)

def interrupt_kernel(self, kernel_id: str) -> None:
"""Interrupt (SIGINT) the kernel by its uuid.

Expand Down Expand Up @@ -435,8 +429,6 @@ async def _async_restart_kernel(self, kernel_id: str, now: bool = False) -> None
await ensure_async(kernel.restart_kernel(now=now))
self.log.info("Kernel restarted: %s", kernel_id)

restart_kernel = run_sync(_async_restart_kernel)

@kernel_method
def is_alive(self, kernel_id: str) -> bool: # type:ignore[empty-body]
"""Is the kernel alive.
Expand Down Expand Up @@ -596,7 +588,14 @@ def new_kernel_id(self, **kwargs: t.Any) -> str:
return str(uuid.uuid4())


class AsyncMultiKernelManager(MultiKernelManager):
class MultiKernelManager(_MultiKernelManagerBase):
start_kernel = run_sync(_MultiKernelManagerBase._async_start_kernel)
restart_kernel = run_sync(_MultiKernelManagerBase._async_restart_kernel)
shutdown_kernel = run_sync(_MultiKernelManagerBase._async_shutdown_kernel)
shutdown_all = run_sync(_MultiKernelManagerBase._async_shutdown_all)


class AsyncMultiKernelManager(_MultiKernelManagerBase):
kernel_manager_class = DottedObjectName(
"jupyter_client.ioloop.AsyncIOLoopKernelManager",
config=True,
Expand All @@ -618,7 +617,7 @@ def _context_default(self) -> zmq.asyncio.Context:
self._created_context = True
return zmq.asyncio.Context()

start_kernel: t.Callable[..., t.Awaitable] = MultiKernelManager._async_start_kernel # type:ignore[assignment]
restart_kernel: t.Callable[..., t.Awaitable] = MultiKernelManager._async_restart_kernel # type:ignore[assignment]
shutdown_kernel: t.Callable[..., t.Awaitable] = MultiKernelManager._async_shutdown_kernel # type:ignore[assignment]
shutdown_all: t.Callable[..., t.Awaitable] = MultiKernelManager._async_shutdown_all # type:ignore[assignment]
start_kernel = _MultiKernelManagerBase._async_start_kernel
restart_kernel = _MultiKernelManagerBase._async_restart_kernel
shutdown_kernel = _MultiKernelManagerBase._async_shutdown_kernel
shutdown_all = _MultiKernelManagerBase._async_shutdown_all
2 changes: 1 addition & 1 deletion jupyter_client/restarter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
class KernelRestarter(LoggingConfigurable):
"""Monitor and autorestart a kernel."""

kernel_manager = Instance("jupyter_client.KernelManager")
kernel_manager = Instance("jupyter_client.managerabc.KernelManagerABC")

debug = Bool(
False,
Expand Down
2 changes: 1 addition & 1 deletion jupyter_client/ssh/tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
except ImportError:
paramiko = None # type:ignore[assignment]

class SSHException(Exception): # type:ignore[no-redef] # noqa
class SSHException(Exception): # type:ignore[no-redef] # noqa: N818
pass

else:
Expand Down
2 changes: 1 addition & 1 deletion tests/problemkernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ProblemTestKernel(Kernel):


class ProblemTestApp(IPKernelApp):
kernel_class = ProblemTestKernel # type:ignore[assignment]
kernel_class = ProblemTestKernel

def init_io(self):
# Overridden to disable stdout/stderr capture
Expand Down
2 changes: 1 addition & 1 deletion tests/signalkernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def do_execute(


class SignalTestApp(IPKernelApp):
kernel_class = SignalTestKernel # type:ignore[assignment]
kernel_class = SignalTestKernel

def init_io(self):
# Overridden to disable stdout/stderr capture
Expand Down
Loading