Skip to content

Commit e0e0bf6

Browse files
committed
Merge branch 'main' into zmq_anyio
2 parents a6de84e + f9cfd11 commit e0e0bf6

22 files changed

+191
-178
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -214,22 +214,3 @@ jobs:
214214
- uses: actions/checkout@v4
215215
- uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1
216216
- uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1
217-
218-
tests_check: # This job does nothing and is only used for the branch protection
219-
if: always()
220-
needs:
221-
- coverage
222-
- test_docs
223-
- test_without_debugpy
224-
- test_miniumum_versions
225-
- test_lint
226-
- test_prereleases
227-
- check_release
228-
- link_check
229-
- test_sdist
230-
runs-on: ubuntu-latest
231-
steps:
232-
- name: Decide whether the needed jobs succeeded or failed
233-
uses: re-actors/alls-green@release/v1
234-
with:
235-
jobs: ${{ toJSON(needs) }}

.github/workflows/downstream.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ jobs:
132132
- name: Install System Packages
133133
run: |
134134
sudo apt-get update
135-
sudo apt-get install -y --no-install-recommends libegl1-mesa
135+
sudo apt-get install -y --no-install-recommends libgl1 libglx-mesa0
136136
- name: Install spyder-kernels dependencies
137137
shell: bash -l {0}
138138
run: |

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@ repos:
4040
types_or: [yaml, html, json]
4141

4242
- repo: https://github.com/pre-commit/mirrors-mypy
43-
rev: "v1.8.0"
43+
rev: "v1.15.0"
4444
hooks:
4545
- id: mypy
4646
files: ipykernel
47-
stages: [manual]
4847
args: ["--install-types", "--non-interactive"]
4948
additional_dependencies:
5049
[
5150
"traitlets>=5.13",
5251
"ipython>=8.16.1",
5352
"jupyter_client>=8.5",
5453
"appnope",
54+
"types-psutil",
5555
]
5656

5757
- repo: https://github.com/adamchainz/blacken-docs

ipykernel/datapub.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from jupyter_client.session import Session, extract_header
2121

2222
warnings.warn(
23-
"ipykernel.datapub is deprecated. It has moved to ipyparallel.datapub",
23+
"ipykernel.datapub is deprecated since ipykernel 4.3.0 (2016). It has moved to ipyparallel.datapub",
2424
DeprecationWarning,
2525
stacklevel=2,
2626
)
@@ -73,7 +73,7 @@ def publish_data(data):
7373
The data to be published. Think of it as a namespace.
7474
"""
7575
warnings.warn(
76-
"ipykernel.datapub is deprecated. It has moved to ipyparallel.datapub",
76+
"ipykernel.datapub is deprecated since ipykernel 4.3.0 (2016). It has moved to ipyparallel.datapub",
7777
DeprecationWarning,
7878
stacklevel=2,
7979
)

ipykernel/embed.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ def embed_kernel(module=None, local_ns=None, **kwargs):
4848
if module is None:
4949
module = caller_module
5050
if local_ns is None:
51-
local_ns = caller_locals
51+
local_ns = dict(**caller_locals)
5252

5353
app.kernel.user_module = module
54+
assert isinstance(local_ns, dict)
5455
app.kernel.user_ns = local_ns
5556
app.shell.set_completer_frame() # type:ignore[union-attr]
5657
app.start()

ipykernel/inprocess/blocking.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def call_handlers(self, msg):
6969
_raw_input = self.client.kernel._sys_raw_input
7070
prompt = msg["content"]["prompt"]
7171
print(prompt, end="", file=sys.__stdout__)
72+
assert sys.__stdout__ is not None
7273
sys.__stdout__.flush()
7374
self.client.input(_raw_input())
7475

ipykernel/inprocess/client.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
# Imports
1212
# -----------------------------------------------------------------------------
1313

14+
15+
from typing import Any
16+
1417
from jupyter_client.client import KernelClient
1518
from jupyter_client.clientabc import KernelClientABC
1619

@@ -54,9 +57,9 @@ def _default_blocking_class(self):
5457

5558
return BlockingInProcessKernelClient
5659

57-
def get_connection_info(self):
60+
def get_connection_info(self, session: bool = False):
5861
"""Get the connection info for the client."""
59-
d = super().get_connection_info()
62+
d = super().get_connection_info(session=session)
6063
d["kernel"] = self.kernel # type:ignore[assignment]
6164
return d
6265

@@ -99,9 +102,18 @@ def hb_channel(self):
99102
# Methods for sending specific messages
100103
# -------------------------------------
101104

102-
async def execute(
103-
self, code, silent=False, store_history=True, user_expressions=None, allow_stdin=None
104-
):
105+
# Feb 2025: superclass in jupyter-Client is sync,
106+
# it should likely be made all consistent and push
107+
# jupyter_client async as well
108+
async def execute( # type:ignore [override]
109+
self,
110+
code: str,
111+
silent: bool = False,
112+
store_history: bool = True,
113+
user_expressions: dict[str, Any] | None = None,
114+
allow_stdin: bool | None = None,
115+
stop_on_error: bool = True,
116+
) -> str:
105117
"""Execute code on the client."""
106118
if allow_stdin is None:
107119
allow_stdin = self.allow_stdin
@@ -114,7 +126,9 @@ async def execute(
114126
)
115127
msg = self.session.msg("execute_request", content)
116128
await self._dispatch_to_kernel(msg)
117-
return msg["header"]["msg_id"]
129+
res = msg["header"]["msg_id"]
130+
assert isinstance(res, str)
131+
return res
118132

119133
async def complete(self, code, cursor_pos=None):
120134
"""Get code completion."""

ipykernel/inprocess/session.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
1+
from typing import Any
2+
13
from jupyter_client.session import Session as _Session
24

35

46
class Session(_Session):
5-
async def recv(self, socket, copy=True):
7+
# superclass is not async.
8+
async def recv( # type: ignore[override]
9+
self, socket, mode: int = 0, content: bool = True, copy=True
10+
) -> Any:
11+
"""
12+
mode, content, copy have no effect, but are present for superclass compatibility
13+
14+
"""
615
return await socket.arecv_multipart().wait()
716

817
def send(

ipykernel/ipkernel.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@
1818
from IPython.core import release
1919
from IPython.utils.tokenutil import line_at_cursor, token_at_cursor
2020
from jupyter_client.session import extract_header
21-
from traitlets import Any, Bool, HasTraits, Instance, List, Type, default, observe, observe_compat
21+
from traitlets import (
22+
Any,
23+
Bool,
24+
Dict,
25+
HasTraits,
26+
Instance,
27+
List,
28+
Type,
29+
default,
30+
observe,
31+
observe_compat,
32+
)
2233

2334
from .comm.comm import BaseComm
2435
from .comm.manager import CommManager
@@ -92,7 +103,7 @@ def _user_module_changed(self, change):
92103
if self.shell is not None:
93104
self.shell.user_module = change["new"]
94105

95-
user_ns = Instance("collections.abc.Mapping", allow_none=True)
106+
user_ns = Dict(allow_none=True)
96107

97108
@default("user_ns")
98109
def _default_user_ns(self):

ipykernel/kernelapp.py

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,12 @@ def init_sockets(self):
339339
self.shell_socket = zmq_anyio.Socket(context.socket(zmq.ROUTER))
340340
self.shell_socket.linger = 1000
341341
self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
342-
self.log.debug("shell ROUTER Channel on port: %i" % self.shell_port)
342+
self.log.debug("shell ROUTER Channel on port: %i", self.shell_port)
343343

344344
self.stdin_socket = context.socket(zmq.ROUTER)
345345
self.stdin_socket.linger = 1000
346346
self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
347-
self.log.debug("stdin ROUTER Channel on port: %i" % self.stdin_port)
347+
self.log.debug("stdin ROUTER Channel on port: %i", self.stdin_port)
348348

349349
if hasattr(zmq, "ROUTER_HANDOVER"):
350350
# set router-handover to workaround zeromq reconnect problems
@@ -360,7 +360,7 @@ def init_control(self, context):
360360
self.control_socket = zmq_anyio.Socket(context.socket(zmq.ROUTER))
361361
self.control_socket.linger = 1000
362362
self.control_port = self._bind_socket(self.control_socket, self.control_port)
363-
self.log.debug("control ROUTER Channel on port: %i" % self.control_port)
363+
self.log.debug("control ROUTER Channel on port: %i", self.control_port)
364364

365365
self.debugpy_socket = zmq_anyio.Socket(context.socket(zmq.STREAM))
366366
self.debugpy_socket.linger = 1000
@@ -385,7 +385,7 @@ def init_iopub(self, context):
385385
self.iopub_socket = zmq_anyio.Socket(context.socket(zmq.PUB))
386386
self.iopub_socket.linger = 1000
387387
self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
388-
self.log.debug("iopub PUB Channel on port: %i" % self.iopub_port)
388+
self.log.debug("iopub PUB Channel on port: %i", self.iopub_port)
389389
self.configure_tornado_logger()
390390
self.iopub_thread = IOPubThread(self.iopub_socket, pipe=True)
391391
self.iopub_thread.start()
@@ -399,7 +399,7 @@ def init_heartbeat(self):
399399
hb_ctx = zmq.Context()
400400
self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
401401
self.hb_port = self.heartbeat.port
402-
self.log.debug("Heartbeat REP Channel on port: %i" % self.hb_port)
402+
self.log.debug("Heartbeat REP Channel on port: %i", self.hb_port)
403403
self.heartbeat.start()
404404

405405
def close(self):
@@ -515,7 +515,7 @@ def init_io(self):
515515
isinstance(handler, StreamHandler)
516516
and (buffer := getattr(handler.stream, "buffer", None))
517517
and (fileno := getattr(buffer, "fileno", None))
518-
and fileno() == sys.stderr._original_stdstream_fd # type:ignore[attr-defined]
518+
and fileno() == sys.stderr._original_stdstream_fd
519519
):
520520
self.log.debug("Seeing logger to stderr, rerouting to raw filedescriptor.")
521521
io_wrapper = TextIOWrapper(
@@ -697,7 +697,7 @@ def init_pdb(self):
697697
pdb.set_trace = debugger.set_trace
698698

699699
@catch_config_error
700-
def initialize(self, argv=None):
700+
def initialize(self, argv=None) -> None:
701701
"""Initialize the application."""
702702
super().initialize(argv)
703703
if self.subapp is not None:
@@ -735,22 +735,18 @@ def initialize(self, argv=None):
735735
sys.stdout.flush()
736736
sys.stderr.flush()
737737

738-
def start(self) -> None:
739-
"""Start the application."""
738+
async def _start(self, backend: str) -> None:
739+
"""
740+
Async version of start, when the loop is not controlled by IPykernel
741+
742+
For example to be used in test suite with @pytest.mark.trio
743+
"""
740744
if self.subapp is not None:
741745
self.subapp.start()
742746
return
743747
if self.poller is not None:
744748
self.poller.start()
745-
backend = "trio" if self.trio_loop else "asyncio"
746-
run(partial(self.main, backend), backend=backend)
747-
return
748-
749-
async def _wait_to_enter_eventloop(self):
750-
await self.kernel._eventloop_set.wait()
751-
await self.kernel.enter_eventloop()
752749

753-
async def main(self, backend: str):
754750
if backend == "asyncio" and sys.platform == "win32":
755751
import asyncio
756752

@@ -760,16 +756,27 @@ async def main(self, backend: str):
760756

761757
selector = get_selector()
762758
selector._thread.pydev_do_not_trace = True
763-
# selector._thread.is_pydev_daemon_thread = True
764759

760+
await self.main()
761+
762+
def start(self) -> None:
763+
"""Start the application."""
764+
backend = "trio" if self.trio_loop else "asyncio"
765+
run(partial(self._start, backend), backend=backend)
766+
767+
async def _wait_to_enter_eventloop(self) -> None:
768+
await self.kernel._eventloop_set.wait()
769+
await self.kernel.enter_eventloop()
770+
771+
async def main(self) -> None:
765772
async with create_task_group() as tg:
766773
tg.start_soon(self._wait_to_enter_eventloop)
767774
tg.start_soon(self.kernel.start)
768775

769776
if self.kernel.eventloop:
770777
self.kernel._eventloop_set.set()
771778

772-
def stop(self):
779+
def stop(self) -> None:
773780
"""Stop the kernel, thread-safe."""
774781
self.kernel.stop()
775782

0 commit comments

Comments
 (0)