From 31ec38aaeef5cbb53a17e1885c1915d487339a1c Mon Sep 17 00:00:00 2001 From: M Bussonnier Date: Thu, 30 Oct 2025 12:26:39 +0100 Subject: [PATCH 01/24] Test changing base method to async after #1295 (#1464) --- ipykernel/kernelbase.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index e241933a2..52d40b952 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -862,7 +862,7 @@ async def execute_request(self, stream, ident, parent): subshell_id = parent["header"].get("subshell_id") self._abort_queues(subshell_id) - def do_execute( + async def do_execute( self, code, silent, @@ -897,7 +897,7 @@ async def complete_request(self, stream, ident, parent): matches = json_clean(matches) self.session.send(stream, "complete_reply", matches, parent, ident) - def do_complete(self, code, cursor_pos): + async def do_complete(self, code, cursor_pos): """Override in subclasses to find completions.""" return { "matches": [], @@ -933,7 +933,7 @@ async def inspect_request(self, stream, ident, parent): msg = self.session.send(stream, "inspect_reply", reply_content, parent, ident) self.log.debug("%s", msg) - def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): + async def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): """Override in subclasses to allow introspection.""" return {"status": "ok", "data": {}, "metadata": {}, "found": False} @@ -957,7 +957,7 @@ async def history_request(self, stream, ident, parent): msg = self.session.send(stream, "history_reply", reply_content, parent, ident) self.log.debug("%s", msg) - def do_history( + async def do_history( self, hist_access_type, output, @@ -1097,7 +1097,7 @@ async def shutdown_request(self, stream, ident, parent): shell_io_loop = self.shell_stream.io_loop shell_io_loop.add_callback(shell_io_loop.stop) - def do_shutdown(self, restart): + async def do_shutdown(self, restart): """Override in subclasses to do things when the frontend shuts down the kernel. """ @@ -1123,7 +1123,7 @@ async def is_complete_request(self, stream, ident, parent): reply_msg = self.session.send(stream, "is_complete_reply", reply_content, parent, ident) self.log.debug("%s", reply_msg) - def do_is_complete(self, code): + async def do_is_complete(self, code): """Override in subclasses to find completions.""" return {"status": "unknown"} From d63090caac0d069d2daf2ac65d9b53778ddc209d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 21:18:47 +0000 Subject: [PATCH 02/24] chore: update pre-commit hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.2 → v0.14.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.2...v0.14.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 214d4cf10..53a0922af 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -73,7 +73,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.2 + rev: v0.14.3 hooks: - id: ruff-check types_or: [python, jupyter] From c71e621a364a2124142efc5275d50580cd2f3a24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 09:08:10 +0000 Subject: [PATCH 03/24] Bump actions/checkout from 5 to 6 in the actions group (#1479) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 20 ++++++++++---------- .github/workflows/downstream.yml | 14 +++++++------- .github/workflows/nightly.yml | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3dd030d5f..03ab0a0ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: @@ -94,7 +94,7 @@ jobs: needs: - build steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/report-coverage@v1 with: fail_under: 80 @@ -103,7 +103,7 @@ jobs: name: Test Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Run Linters run: | @@ -115,7 +115,7 @@ jobs: check_release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2 with: @@ -124,7 +124,7 @@ jobs: test_docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - name: Build API docs run: | @@ -146,7 +146,7 @@ jobs: python-version: ["3.10"] steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -169,7 +169,7 @@ jobs: timeout-minutes: 20 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: @@ -190,7 +190,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 with: @@ -204,7 +204,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/make-sdist@v1 @@ -220,6 +220,6 @@ jobs: link_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 - uses: jupyterlab/maintainer-tools/.github/actions/check-links@v1 diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index 601d322e1..ed9519dea 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -44,7 +44,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -60,7 +60,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -75,7 +75,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 @@ -92,7 +92,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 with: @@ -125,7 +125,7 @@ jobs: timeout-minutes: 20 steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 with: diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dc620e9fa..e892e2a00 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -17,7 +17,7 @@ jobs: python-version: ["3.12"] steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Base Setup uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1 From e4d02f603f204c68bbbd96071d171d6429008fc8 Mon Sep 17 00:00:00 2001 From: Matt Newville Date: Wed, 26 Nov 2025 03:13:08 -0600 Subject: [PATCH 04/24] add close event for wx timer app in loop_wx (#1478) --- ipykernel/eventloops.py | 42 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/ipykernel/eventloops.py b/ipykernel/eventloops.py index dd131172f..d79f7ee60 100644 --- a/ipykernel/eventloops.py +++ b/ipykernel/eventloops.py @@ -184,39 +184,45 @@ def _loop_wx(app): @register_integration("wx") def loop_wx(kernel): """Start a kernel with wx event loop support.""" - import wx - # Wx uses milliseconds - poll_interval = int(1000 * kernel._poll_interval) - - shell_stream = get_shell_stream(kernel) - - def wake(shell_stream): - """wake from wx""" - if shell_stream.flush(limit=1): - kernel.app.ExitMainLoop() - return - # We have to put the wx.Timer in a wx.Frame for it to fire properly. # We make the Frame hidden when we create it in the main app below. class TimerFrame(wx.Frame): # type:ignore[misc] - def __init__(self, func): + def __init__(self, kernel): + self.kernel = kernel + self.shell_stream = get_shell_stream(kernel) + wx.Frame.__init__(self, None, -1) self.timer = wx.Timer(self) - # Units for the timer are in milliseconds - self.timer.Start(poll_interval) + + self.Bind(wx.EVT_CLOSE, self.on_exit) self.Bind(wx.EVT_TIMER, self.on_timer) - self.func = func + + # Units for the timer are in milliseconds + self.timer.Start(int(1000 * self.kernel._poll_interval)) + + def wake(self): + """wake from wx""" + try: + if self.shell_stream.flush(limit=1): + self.kernel.app.ExitMainLoop() + except Exception: + pass def on_timer(self, event): - self.func() + self.wake() + + def on_exit(self, event): + self.timer.Stop() + self.wake() + self.Destroy() # We need a custom wx.App to create our Frame subclass that has the # wx.Timer to defer back to the tornado event loop. class IPWxApp(wx.App): # type:ignore[misc] def OnInit(self): - self.frame = TimerFrame(partial(wake, shell_stream)) + self.frame = TimerFrame(kernel) self.frame.Show(False) return True From 5b9f05bdc43ee224cc1410064471edc46106818a Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Wed, 26 Nov 2025 10:18:46 +0000 Subject: [PATCH 05/24] Fix linting errors (#1480) --- ipykernel/zmqshell.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ipykernel/zmqshell.py b/ipykernel/zmqshell.py index b70b1e5fd..9e9ded064 100644 --- a/ipykernel/zmqshell.py +++ b/ipykernel/zmqshell.py @@ -352,7 +352,7 @@ def edit(self, parameter_s="", last_call=None): payload = {"source": "edit_magic", "filename": filename, "line_number": lineno} assert self.shell is not None - self.shell.payload_manager.write_payload(payload) # type: ignore[unreachable] + self.shell.payload_manager.write_payload(payload) # type: ignore[union-attr] # A few magics that are adapted to the specifics of using pexpect and a # remote terminal @@ -361,7 +361,7 @@ def edit(self, parameter_s="", last_call=None): def clear(self, arg_s): """Clear the terminal.""" assert self.shell is not None - if os.name == "posix": # type: ignore[unreachable] + if os.name == "posix": self.shell.system("clear") else: self.shell.system("cls") @@ -383,7 +383,7 @@ def less(self, arg_s): if arg_s.endswith(".py"): assert self.shell is not None - cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False)) # type: ignore[unreachable] + cont = self.shell.pycolorize(openpy.read_py_file(arg_s, skip_encoding_cookie=False)) else: with open(arg_s) as fid: cont = fid.read() @@ -398,7 +398,7 @@ def less(self, arg_s): def man(self, arg_s): """Find the man page for the given command and display in pager.""" assert self.shell is not None - page.page(self.shell.getoutput("man %s | col -b" % arg_s, split=False)) # type: ignore[unreachable] + page.page(self.shell.getoutput("man %s | col -b" % arg_s, split=False)) @line_magic def connect_info(self, arg_s): From 6475f86c0d92437159daf972a87a1a1803d98f9f Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Mon, 1 Dec 2025 14:29:52 +0530 Subject: [PATCH 06/24] feat: Add dynamic skip rules for kernel modules to debugpy configuration. --- ipykernel/debugger.py | 8 +++++++- ipykernel/ipkernel.py | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index cfa976107..7a158ba5b 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -326,7 +326,7 @@ class Debugger: ] def __init__( - self, log, debugpy_stream, event_callback, shell_socket, session, just_my_code=True + self, log, debugpy_stream, event_callback, shell_socket, session, kernel_modules, just_my_code=True ): """Initialize the debugger.""" self.log = log @@ -335,6 +335,7 @@ def __init__( self.session = session self.is_started = False self.event_callback = event_callback + self.kernel_modules = kernel_modules self.just_my_code = just_my_code self.stopped_queue: Queue[t.Any] = Queue() @@ -574,6 +575,11 @@ async def attach(self, message): # Set debugOptions for breakpoints in python standard library source. if not self.just_my_code: message["arguments"]["debugOptions"] = ["DebugStdLib"] + + # Dynamic skip rules (computed at kernel startup) + rules = [{"path": path, "include": False} for path in self.kernel_modules] + message["arguments"]["rules"] = rules + return await self._forward_message(message) async def configurationDone(self, message): diff --git a/ipykernel/ipkernel.py b/ipykernel/ipkernel.py index e1505a9a7..620f0bb4e 100644 --- a/ipykernel/ipkernel.py +++ b/ipykernel/ipkernel.py @@ -119,6 +119,12 @@ def __init__(self, **kwargs): from .debugger import _is_debugpy_available + self._kernel_modules = [ + m.__file__ + for m in sys.modules.values() + if hasattr(m, "__file__") and m.__file__ + ] + # Initialize the Debugger if _is_debugpy_available: self.debugger = self.debugger_class( @@ -127,6 +133,7 @@ def __init__(self, **kwargs): self._publish_debug_event, self.debug_shell_socket, self.session, + self._kernel_modules, self.debug_just_my_code, ) From 7993c995794948e9cef93ce947bb5cbbb4d43c90 Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Mon, 1 Dec 2025 15:07:04 +0530 Subject: [PATCH 07/24] Introduce `filter_internal_frames` option to control internal frame filtering --- ipykernel/debugger.py | 8 +++++--- ipykernel/ipkernel.py | 1 + ipykernel/kernelbase.py | 9 ++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index 7a158ba5b..49383810f 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -326,7 +326,7 @@ class Debugger: ] def __init__( - self, log, debugpy_stream, event_callback, shell_socket, session, kernel_modules, just_my_code=True + self, log, debugpy_stream, event_callback, shell_socket, session, kernel_modules, just_my_code=False, filter_internal_frames=True ): """Initialize the debugger.""" self.log = log @@ -337,6 +337,7 @@ def __init__( self.event_callback = event_callback self.kernel_modules = kernel_modules self.just_my_code = just_my_code + self.filter_internal_frames = filter_internal_frames self.stopped_queue: Queue[t.Any] = Queue() self.started_debug_handlers = {} @@ -577,8 +578,9 @@ async def attach(self, message): message["arguments"]["debugOptions"] = ["DebugStdLib"] # Dynamic skip rules (computed at kernel startup) - rules = [{"path": path, "include": False} for path in self.kernel_modules] - message["arguments"]["rules"] = rules + if self.filter_internal_frames: + rules = [{"path": path, "include": False} for path in self.kernel_modules] + message["arguments"]["rules"] = rules return await self._forward_message(message) diff --git a/ipykernel/ipkernel.py b/ipykernel/ipkernel.py index 620f0bb4e..2a89d9ea9 100644 --- a/ipykernel/ipkernel.py +++ b/ipykernel/ipkernel.py @@ -135,6 +135,7 @@ def __init__(self, **kwargs): self.session, self._kernel_modules, self.debug_just_my_code, + self.filter_internal_frames, ) # Initialize the InteractiveShell subclass diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index 52d40b952..7fa1fb9dc 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -179,11 +179,18 @@ def _default_ident(self): # The ipykernel source is in the call stack, so the user # has to manipulate the step-over and step-into in a wize way. debug_just_my_code = Bool( - True, + False, help="""Set to False if you want to debug python standard and dependent libraries. """, ).tag(config=True) + # Experimental option to filter internal frames from the stack trace and stepping. + filter_internal_frames = Bool( + True, + help="""Set to False if you want to debug kernel modules. + """, + ).tag(config=True) + # track associations with current request # Private interface From fa1bd64f330a0227fd2db3d36fecda88f904c7d2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:16:27 +0000 Subject: [PATCH 08/24] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ipykernel/debugger.py | 10 +++++++++- ipykernel/ipkernel.py | 4 +--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index 49383810f..a3f604f70 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -326,7 +326,15 @@ class Debugger: ] def __init__( - self, log, debugpy_stream, event_callback, shell_socket, session, kernel_modules, just_my_code=False, filter_internal_frames=True + self, + log, + debugpy_stream, + event_callback, + shell_socket, + session, + kernel_modules, + just_my_code=False, + filter_internal_frames=True, ): """Initialize the debugger.""" self.log = log diff --git a/ipykernel/ipkernel.py b/ipykernel/ipkernel.py index 2a89d9ea9..aa22bbb0f 100644 --- a/ipykernel/ipkernel.py +++ b/ipykernel/ipkernel.py @@ -120,9 +120,7 @@ def __init__(self, **kwargs): from .debugger import _is_debugpy_available self._kernel_modules = [ - m.__file__ - for m in sys.modules.values() - if hasattr(m, "__file__") and m.__file__ + m.__file__ for m in sys.modules.values() if hasattr(m, "__file__") and m.__file__ ] # Initialize the Debugger From dc865b87415e28aa4fd08dcc82cb2bc059afc4aa Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Mon, 1 Dec 2025 16:14:34 +0530 Subject: [PATCH 09/24] remove ipykernel stack frame filtering from stackTrace response --- ipykernel/debugger.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index a3f604f70..15952710e 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -509,23 +509,6 @@ async def source(self, message): async def stackTrace(self, message): """Handle a stack trace message.""" reply = await self._forward_message(message) - # The stackFrames array can have the following content: - # { frames from the notebook} - # ... - # { 'id': xxx, 'name': '', ... } <= this is the first frame of the code from the notebook - # { frames from ipykernel } - # ... - # {'id': yyy, 'name': '', ... } <= this is the first frame of ipykernel code - # or only the frames from the notebook. - # We want to remove all the frames from ipykernel when they are present. - try: - sf_list = reply["body"]["stackFrames"] - module_idx = len(sf_list) - next( - i for i, v in enumerate(reversed(sf_list), 1) if v["name"] == "" and i != 1 - ) - reply["body"]["stackFrames"] = reply["body"]["stackFrames"][: module_idx + 1] - except StopIteration: - pass return reply def accept_variable(self, variable_name): From a97f48afc436ee9ca78f11824033537a95a8f780 Mon Sep 17 00:00:00 2001 From: arjxn-py Date: Mon, 1 Dec 2025 18:41:15 +0530 Subject: [PATCH 10/24] remove unnecessary assignment --- ipykernel/debugger.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ipykernel/debugger.py b/ipykernel/debugger.py index 15952710e..24fe92849 100644 --- a/ipykernel/debugger.py +++ b/ipykernel/debugger.py @@ -508,8 +508,7 @@ async def source(self, message): async def stackTrace(self, message): """Handle a stack trace message.""" - reply = await self._forward_message(message) - return reply + return await self._forward_message(message) def accept_variable(self, variable_name): """Accept a variable by name.""" From d7aaa3e5f16267efbef7cf21f3b4c984402b8484 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 22:02:52 +0000 Subject: [PATCH 11/24] Bump scientific-python/upload-nightly-action in the actions group Bumps the actions group with 1 update: [scientific-python/upload-nightly-action](https://github.com/scientific-python/upload-nightly-action). Updates `scientific-python/upload-nightly-action` from 0.6.2 to 0.6.3 - [Release notes](https://github.com/scientific-python/upload-nightly-action/releases) - [Commits](https://github.com/scientific-python/upload-nightly-action/compare/b36e8c0c10dbcfd2e05bf95f17ef8c14fd708dbf...5748273c71e2d8d3a61f3a11a16421c8954f9ecf) --- updated-dependencies: - dependency-name: scientific-python/upload-nightly-action dependency-version: 0.6.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] --- .github/workflows/nightly.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e892e2a00..ba566e1af 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -27,7 +27,7 @@ jobs: python -m pip install build python -m build - name: Upload wheel - uses: scientific-python/upload-nightly-action@b36e8c0c10dbcfd2e05bf95f17ef8c14fd708dbf # 0.6.2 + uses: scientific-python/upload-nightly-action@5748273c71e2d8d3a61f3a11a16421c8954f9ecf # 0.6.3 with: artifacts_path: dist anaconda_nightly_upload_token: ${{secrets.UPLOAD_TOKEN}} From 82c3047c7296b35d718cf910e72c530aeb999817 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Thu, 8 Jan 2026 10:52:50 +0100 Subject: [PATCH 12/24] Removed spyder downstream tests --- .github/workflows/downstream.yml | 64 -------------------------------- 1 file changed, 64 deletions(-) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index ed9519dea..894c8626f 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -86,67 +86,3 @@ jobs: cd jupyter_kernel_test pip install -e ".[test]" python test_ipykernel.py - - qtconsole: - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: "3.10" - architecture: "x64" - - name: Install System Packages - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev - - name: Install qtconsole dependencies - shell: bash -l {0} - run: | - cd ${GITHUB_WORKSPACE}/.. - git clone https://github.com/spyder-ide/qtconsole.git - cd qtconsole - ${pythonLocation}/bin/python -m pip install -e ".[test]" - ${pythonLocation}/bin/python -m pip install pyqt5 - - name: Install Ipykernel changes - shell: bash -l {0} - run: ${pythonLocation}/bin/python -m pip install -e . - - name: Test qtconsole - shell: bash -l {0} - run: | - cd ${GITHUB_WORKSPACE}/../qtconsole - xvfb-run --auto-servernum ${pythonLocation}/bin/python -m pytest -x -vv -s --full-trace --color=yes qtconsole -k "not test_scroll" - - spyder_kernels: - runs-on: ubuntu-latest - if: false - timeout-minutes: 20 - steps: - - name: Checkout - uses: actions/checkout@v6 - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: "3.10" - architecture: "x64" - - name: Install System Packages - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends libgl1 libglx-mesa0 - - name: Install spyder-kernels dependencies - shell: bash -l {0} - run: | - cd ${GITHUB_WORKSPACE}/.. - git clone https://github.com/spyder-ide/spyder-kernels.git - cd spyder-kernels - ${pythonLocation}/bin/python -m pip install -e ".[test]" - - name: Install IPykernel changes - shell: bash -l {0} - run: ${pythonLocation}/bin/python -m pip install -e . - - name: Test spyder-kernels - shell: bash -l {0} - run: | - cd ${GITHUB_WORKSPACE}/../spyder-kernels - xvfb-run --auto-servernum ${pythonLocation}/bin/python -m pytest -x -vv -s --full-trace --color=yes spyder_kernels From 9f0489b20009e79247493706e4eef84389d7ee87 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Thu, 18 Dec 2025 16:46:45 +0100 Subject: [PATCH 13/24] Replaced PUB socket with XPUB socket --- ipykernel/inprocess/ipkernel.py | 2 +- ipykernel/iostream.py | 66 ++++++++++++++++++++++++++++++++- ipykernel/kernelapp.py | 4 +- tests/conftest.py | 2 +- tests/test_io.py | 5 ++- 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/ipykernel/inprocess/ipkernel.py b/ipykernel/inprocess/ipkernel.py index b68bec442..7ed47443b 100644 --- a/ipykernel/inprocess/ipkernel.py +++ b/ipykernel/inprocess/ipkernel.py @@ -56,7 +56,7 @@ class InProcessKernel(IPythonKernel): @default("iopub_thread") def _default_iopub_thread(self): - thread = IOPubThread(self._underlying_iopub_socket) + thread = IOPubThread(self._underlying_iopub_socket, self.session) thread.start() return thread diff --git a/ipykernel/iostream.py b/ipykernel/iostream.py index 0a2115f3b..9681c3f6f 100644 --- a/ipykernel/iostream.py +++ b/ipykernel/iostream.py @@ -47,7 +47,7 @@ class IOPubThread: whose IO is always run in a thread. """ - def __init__(self, socket, pipe=False): + def __init__(self, socket, session, pipe=False): """Create IOPub thread Parameters @@ -59,6 +59,7 @@ def __init__(self, socket, pipe=False): piped from subprocesses. """ self.socket = socket + self.session = session self._stopped = False self.background_socket = BackgroundSocket(self) self._master_pid = os.getpid() @@ -73,12 +74,73 @@ def __init__(self, socket, pipe=False): self._event_pipe_gc_seconds: float = 10 self._event_pipe_gc_task: asyncio.Task[Any] | None = None self._setup_event_pipe() + self._setup_xpub_listener() self.thread = threading.Thread(target=self._thread_main, name="IOPub") self.thread.daemon = True self.thread.pydev_do_not_trace = True # type:ignore[attr-defined] self.thread.is_pydev_daemon_thread = True # type:ignore[attr-defined] self.thread.name = "IOPub" + def _setup_xpub_listener(self): + """Setup listener for XPUB subscription events""" + + # Checks the socket is not a DummySocket + if not hasattr(self.socket, "getsockopt"): + return + + socket_type = self.socket.getsockopt(zmq.TYPE) + if socket_type == zmq.XPUB: + self._xpub_stream = ZMQStream(self.socket, self.io_loop) + self._xpub_stream.on_recv(self._handle_subscription) + + def _handle_subscription(self, frames): + """Handle subscription/unsubscription events from XPUB socket + + XPUB sockets receive: + - subscribe: single frame with b'\\x01' + topic + - unsubscribe: single frame with b'\\x00' + topic + """ + + for frame in frames: + event_type = frame[0] + if event_type == 1: + subscription = frame[1:] if len(frame) > 1 else b"" + try: + subscription_str = subscription.decode("utf-8") + except UnicodeDecodeError: + continue + self._send_welcome_message(subscription_str) + + def _send_welcome_message(self, subscription): + """Send iopub_welcome message for new subscription + + Parameters + ---------- + subscription : str + The subscription topic (UTF-8 decoded) + """ + + content = {"subscription": subscription} + + header = self.session.msg_header("iopub_welcome") + msg = { + "header": header, + "parent_header": {}, + "metadata": {}, + "content": content, + "buffers": [], + } + + msg_list = self.session.serialize(msg) + + if subscription: + identity = subscription.encode("utf-8") + full_msg = [identity, *msg_list] + else: + full_msg = msg_list + # Send directly on socket (we're already in IO thread context) + self.socket.send_multipart(full_msg) + def _thread_main(self): """The inner loop that's actually run in a thread""" @@ -447,7 +509,7 @@ def __init__( DeprecationWarning, stacklevel=2, ) - pub_thread = IOPubThread(pub_thread) + pub_thread = IOPubThread(pub_thread, self.session) pub_thread.start() self.pub_thread = pub_thread self.name = name diff --git a/ipykernel/kernelapp.py b/ipykernel/kernelapp.py index 86b275a82..a450d6ca7 100644 --- a/ipykernel/kernelapp.py +++ b/ipykernel/kernelapp.py @@ -377,12 +377,12 @@ def init_control(self, context): def init_iopub(self, context): """Initialize the iopub channel.""" - self.iopub_socket = context.socket(zmq.PUB) + self.iopub_socket = context.socket(zmq.XPUB) self.iopub_socket.linger = 1000 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port) self.log.debug("iopub PUB Channel on port: %i", self.iopub_port) self.configure_tornado_logger() - self.iopub_thread = IOPubThread(self.iopub_socket, pipe=True) + self.iopub_thread = IOPubThread(self.iopub_socket, self.session, pipe=True) self.iopub_thread.start() # backward-compat: wrap iopub socket API in background thread self.iopub_socket = self.iopub_thread.background_socket diff --git a/tests/conftest.py b/tests/conftest.py index 540ad36c3..ad6c5830a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -48,7 +48,7 @@ class KernelMixin: def _initialize(self): self.context = context = zmq.Context() - self.iopub_socket = context.socket(zmq.PUB) + self.iopub_socket = context.socket(zmq.XPUB) self.stdin_socket = context.socket(zmq.ROUTER) self.session = Session() self.test_sockets = [self.iopub_socket] diff --git a/tests/test_io.py b/tests/test_io.py index c7320af84..da1000f4e 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -26,8 +26,9 @@ def ctx(): @pytest.fixture() def iopub_thread(ctx): + session = Session() with ctx.socket(zmq.PUB) as pub: - thread = IOPubThread(pub) + thread = IOPubThread(pub, session) thread.start() yield thread @@ -155,7 +156,7 @@ def subprocess_test_echo_watch(): # use PUSH socket to avoid subscription issues with zmq.Context() as ctx, ctx.socket(zmq.PUSH) as pub: pub.connect(os.environ["IOPUB_URL"]) - iopub_thread = IOPubThread(pub) + iopub_thread = IOPubThread(pub, session) iopub_thread.start() stdout_fd = sys.stdout.fileno() sys.stdout.flush() From 4634d3fb3c73a895c576b1b095b57b1eab5e3b65 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Mon, 22 Dec 2025 15:12:20 +0100 Subject: [PATCH 14/24] FIxes ipyparallel --- ipykernel/iostream.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ipykernel/iostream.py b/ipykernel/iostream.py index 9681c3f6f..a426139ed 100644 --- a/ipykernel/iostream.py +++ b/ipykernel/iostream.py @@ -47,7 +47,7 @@ class IOPubThread: whose IO is always run in a thread. """ - def __init__(self, socket, session, pipe=False): + def __init__(self, socket, session=None, pipe=False): """Create IOPub thread Parameters @@ -120,6 +120,15 @@ def _send_welcome_message(self, subscription): The subscription topic (UTF-8 decoded) """ + # TODO: This early return is for backward-compatibility with ipyparallel. + # This should be removed when ipykernel has been released with support of + # xpub and ipyparallel has been updated to pass the session parameter + # to IOPubThread upon construction. + # (NB: the call to fix is here: + # https://github.com/ipython/ipyparallel/blob/main/ipyparallel/engine/app.py#L679 + if self.session is None: + return + content = {"subscription": subscription} header = self.session.msg_header("iopub_welcome") From fc185cc5161b8db62f05accee8a5f5151a2318b4 Mon Sep 17 00:00:00 2001 From: ianthomas23 Date: Thu, 8 Jan 2026 11:03:20 +0000 Subject: [PATCH 15/24] Publish 7.2.0a0 SHA256 hashes: ipykernel-7.2.0a0-py3-none-any.whl: 5faaba2b9ffa4f0224ec1ad66efaa9656452f9da426c903185d8b03e3a64ad9c ipykernel-7.2.0a0.tar.gz: 914085b822867126f659f55237f0b07a2eab50dfc647019f3c2dc287bafba1f0 --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++-- ipykernel/_version.py | 2 +- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fef0c497..d99d12641 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,42 @@ +## 7.2.0a0 + +([Full Changelog](https://github.com/ipython/ipykernel/compare/v7.1.0...6786ddd040c1f0e8aaeae7e261eec511e2a37fd9)) + +### New features added + +- Replaced PUB socket with XPUB socket [#1482](https://github.com/ipython/ipykernel/pull/1482) ([@JohanMabille](https://github.com/JohanMabille), [@SylvainCorlay](https://github.com/SylvainCorlay)) + +### Enhancements made + +- Implement kernel-side callstack filtering for internal frames [#1481](https://github.com/ipython/ipykernel/pull/1481) ([@arjxn-py](https://github.com/arjxn-py), [@JohanMabille](https://github.com/JohanMabille)) + +### Bugs fixed + +- add close event for wx timer app in loop_wx [#1478](https://github.com/ipython/ipykernel/pull/1478) ([@newville](https://github.com/newville), [@ianthomas23](https://github.com/ianthomas23)) + +### Maintenance and upkeep improvements + +- Removed spyder downstream tests [#1486](https://github.com/ipython/ipykernel/pull/1486) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Bump scientific-python/upload-nightly-action from 0.6.2 to 0.6.3 in the actions group [#1484](https://github.com/ipython/ipykernel/pull/1484) ([@JohanMabille](https://github.com/JohanMabille)) +- Fix linting errors [#1480](https://github.com/ipython/ipykernel/pull/1480) ([@ianthomas23](https://github.com/ianthomas23)) +- Bump actions/checkout from 5 to 6 in the actions group [#1479](https://github.com/ipython/ipykernel/pull/1479) ([@ianthomas23](https://github.com/ianthomas23)) +- chore: update pre-commit hooks [#1467](https://github.com/ipython/ipykernel/pull/1467) ([@JohanMabille](https://github.com/JohanMabille)) +- Test changing base method to async after #1295 [#1464](https://github.com/ipython/ipykernel/pull/1464) ([@Carreau](https://github.com/Carreau), [@ianthomas23](https://github.com/ianthomas23)) + +### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/ipython/ipykernel/graphs/contributors?from=2025-10-27&to=2026-01-08&type=c)) + +@arjxn-py ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aarjxn-py+updated%3A2025-10-27..2026-01-08&type=Issues)) | @Carreau ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ACarreau+updated%3A2025-10-27..2026-01-08&type=Issues)) | @ianthomas23 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2025-10-27..2026-01-08&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AJohanMabille+updated%3A2025-10-27..2026-01-08&type=Issues)) | @newville ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Anewville+updated%3A2025-10-27..2026-01-08&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ASylvainCorlay+updated%3A2025-10-27..2026-01-08&type=Issues)) + + + ## 7.1.0 IPykernel 7.1.0 fixes an issue where display outputs such as Matplotlib plots were not included when using `%notebook` magic to save sessions as `.ipynb` files (#1435). This is enabled using the traitlet `ZMQDisplayPublisher.store_display_history` which defaults to the previous behaviour of False. This is a minor release rather than a patch release due to the addition of the new traitlet. @@ -36,8 +72,6 @@ This release also fixes bugs that were introduced into the 7.x branch relating t [@Carreau](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ACarreau+updated%3A2025-10-14..2025-10-27&type=Issues) | [@Darshan808](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ADarshan808+updated%3A2025-10-14..2025-10-27&type=Issues) | [@dfalbel](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Adfalbel+updated%3A2025-10-14..2025-10-27&type=Issues) | [@ianthomas23](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2025-10-14..2025-10-27&type=Issues) | [@krassowski](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Akrassowski+updated%3A2025-10-14..2025-10-27&type=Issues) | [@lumberbot-app](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Alumberbot-app+updated%3A2025-10-14..2025-10-27&type=Issues) | [@minrk](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aminrk+updated%3A2025-10-14..2025-10-27&type=Issues) | [@ptosco](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aptosco+updated%3A2025-10-14..2025-10-27&type=Issues) - - ## 7.0.1 IPykernel 7.0.1 is a bug fix release to support CPython 3.14. diff --git a/ipykernel/_version.py b/ipykernel/_version.py index 806193c97..736ce47c7 100644 --- a/ipykernel/_version.py +++ b/ipykernel/_version.py @@ -5,7 +5,7 @@ import re # Version string must appear intact for hatch versioning -__version__ = "7.1.0" +__version__ = "7.2.0a0" # Build up version_info tuple for backwards compatibility pattern = r"(?P\d+).(?P\d+).(?P\d+)(?P.*)" From 29c2422885216359d0855887b5073f4cd72632f6 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Thu, 8 Jan 2026 16:26:51 +0100 Subject: [PATCH 16/24] Upgrade to jupyter_client 8.8.0 (#1487) --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 85d7515e9..ac31b558e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,11 +23,11 @@ dependencies = [ "ipython>=7.23.1", "comm>=0.1.1", "traitlets>=5.4.0", - "jupyter_client>=8.0.0", - "jupyter_core>=4.12,!=5.0.*", + "jupyter_client>=8.8.0", + "jupyter_core>=5.1,!=6.0.*", # For tk event loop support only. "nest_asyncio>=1.4", - "tornado>=6.2", + "tornado>=6.4.1", "matplotlib-inline>=0.1", 'appnope>=0.1.2;platform_system=="Darwin"', "pyzmq>=25", From ad85e4203c348074df86d98ad26fbf01562e772d Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Thu, 18 Dec 2025 17:51:18 +0100 Subject: [PATCH 17/24] Added kernel_protocol_version to kernelspec --- ipykernel/kernelspec.py | 1 + tests/test_kernelspec.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index c0cc9ffe7..a9990c90a 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -67,6 +67,7 @@ def get_kernel_dict( "display_name": "Python %i (ipykernel)" % sys.version_info[0], "language": "python", "metadata": {"debugger": True}, + "kernel_protocol_version": "5.4", } diff --git a/tests/test_kernelspec.py b/tests/test_kernelspec.py index c3b62b21a..4deca842b 100644 --- a/tests/test_kernelspec.py +++ b/tests/test_kernelspec.py @@ -35,6 +35,7 @@ def assert_kernel_dict(d): assert d["argv"] == make_ipkernel_cmd() assert d["display_name"] == "Python %i (ipykernel)" % sys.version_info[0] assert d["language"] == "python" + assert d["kernel_protocol_version"] == "5.4" def test_get_kernel_dict(): @@ -46,6 +47,7 @@ def assert_kernel_dict_with_profile(d): assert d["argv"] == make_ipkernel_cmd(extra_arguments=["--profile", "test"]) assert d["display_name"] == "Python %i (ipykernel)" % sys.version_info[0] assert d["language"] == "python" + assert d["kernel_protocol_version"] == "5.4" def test_get_kernel_dict_with_profile(): From 59f0c6525cd3b23c28e5af7257f5db6bb8f78ae6 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Thu, 8 Jan 2026 17:28:57 +0100 Subject: [PATCH 18/24] Advertizes kernel protocol 5.5 --- ipykernel/kernelspec.py | 2 +- tests/test_kernelspec.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ipykernel/kernelspec.py b/ipykernel/kernelspec.py index a9990c90a..f08005a24 100644 --- a/ipykernel/kernelspec.py +++ b/ipykernel/kernelspec.py @@ -67,7 +67,7 @@ def get_kernel_dict( "display_name": "Python %i (ipykernel)" % sys.version_info[0], "language": "python", "metadata": {"debugger": True}, - "kernel_protocol_version": "5.4", + "kernel_protocol_version": "5.5", } diff --git a/tests/test_kernelspec.py b/tests/test_kernelspec.py index 4deca842b..66fce69b7 100644 --- a/tests/test_kernelspec.py +++ b/tests/test_kernelspec.py @@ -35,7 +35,7 @@ def assert_kernel_dict(d): assert d["argv"] == make_ipkernel_cmd() assert d["display_name"] == "Python %i (ipykernel)" % sys.version_info[0] assert d["language"] == "python" - assert d["kernel_protocol_version"] == "5.4" + assert d["kernel_protocol_version"] == "5.5" def test_get_kernel_dict(): @@ -47,7 +47,7 @@ def assert_kernel_dict_with_profile(d): assert d["argv"] == make_ipkernel_cmd(extra_arguments=["--profile", "test"]) assert d["display_name"] == "Python %i (ipykernel)" % sys.version_info[0] assert d["language"] == "python" - assert d["kernel_protocol_version"] == "5.4" + assert d["kernel_protocol_version"] == "5.5" def test_get_kernel_dict_with_profile(): From 56b2e29a29236a5aee494c332c2832cf78bb5f21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:03:00 +0000 Subject: [PATCH 19/24] Update pytest requirement in the actions group across 1 directory Updates the requirements on [pytest](https://github.com/pytest-dev/pytest) to permit the latest version. Updates `pytest` to 9.0.2 - [Release notes](https://github.com/pytest-dev/pytest/releases) - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest/compare/7.0.0...9.0.2) --- updated-dependencies: - dependency-name: pytest dependency-version: 9.0.2 dependency-type: direct:development dependency-group: actions ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ac31b558e..8ce0eb4c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ docs = [ "trio" ] test = [ - "pytest>=7.0,<9", + "pytest>=7.0,<10", "pytest-cov", # 'pytest-xvfb; platform_system == "Linux"', "flaky", From 220a3c6e8b24ffb3f8678925712ff3644aafb41e Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Fri, 30 Jan 2026 11:22:26 +0100 Subject: [PATCH 20/24] Made IOPubThread constructor backward compatible (#1492) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- ipykernel/inprocess/ipkernel.py | 2 +- ipykernel/iostream.py | 4 ++-- ipykernel/kernelapp.py | 2 +- tests/test_io.py | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ipykernel/inprocess/ipkernel.py b/ipykernel/inprocess/ipkernel.py index 7ed47443b..e61af4277 100644 --- a/ipykernel/inprocess/ipkernel.py +++ b/ipykernel/inprocess/ipkernel.py @@ -56,7 +56,7 @@ class InProcessKernel(IPythonKernel): @default("iopub_thread") def _default_iopub_thread(self): - thread = IOPubThread(self._underlying_iopub_socket, self.session) + thread = IOPubThread(self._underlying_iopub_socket, session=self.session) thread.start() return thread diff --git a/ipykernel/iostream.py b/ipykernel/iostream.py index a426139ed..33213d167 100644 --- a/ipykernel/iostream.py +++ b/ipykernel/iostream.py @@ -47,7 +47,7 @@ class IOPubThread: whose IO is always run in a thread. """ - def __init__(self, socket, session=None, pipe=False): + def __init__(self, socket, pipe=False, session=False): """Create IOPub thread Parameters @@ -518,7 +518,7 @@ def __init__( DeprecationWarning, stacklevel=2, ) - pub_thread = IOPubThread(pub_thread, self.session) + pub_thread = IOPubThread(pub_thread, session=self.session) pub_thread.start() self.pub_thread = pub_thread self.name = name diff --git a/ipykernel/kernelapp.py b/ipykernel/kernelapp.py index a450d6ca7..b2f614ea9 100644 --- a/ipykernel/kernelapp.py +++ b/ipykernel/kernelapp.py @@ -382,7 +382,7 @@ def init_iopub(self, context): self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port) self.log.debug("iopub PUB Channel on port: %i", self.iopub_port) self.configure_tornado_logger() - self.iopub_thread = IOPubThread(self.iopub_socket, self.session, pipe=True) + self.iopub_thread = IOPubThread(self.iopub_socket, pipe=True, session=self.session) self.iopub_thread.start() # backward-compat: wrap iopub socket API in background thread self.iopub_socket = self.iopub_thread.background_socket diff --git a/tests/test_io.py b/tests/test_io.py index da1000f4e..217680a4f 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -28,7 +28,7 @@ def ctx(): def iopub_thread(ctx): session = Session() with ctx.socket(zmq.PUB) as pub: - thread = IOPubThread(pub, session) + thread = IOPubThread(pub, session=session) thread.start() yield thread @@ -156,7 +156,7 @@ def subprocess_test_echo_watch(): # use PUSH socket to avoid subscription issues with zmq.Context() as ctx, ctx.socket(zmq.PUSH) as pub: pub.connect(os.environ["IOPUB_URL"]) - iopub_thread = IOPubThread(pub, session) + iopub_thread = IOPubThread(pub, session=session) iopub_thread.start() stdout_fd = sys.stdout.fileno() sys.stdout.flush() From 06c9aee5793896c497e900796145a6a3a23feb25 Mon Sep 17 00:00:00 2001 From: ianthomas23 Date: Fri, 30 Jan 2026 10:35:59 +0000 Subject: [PATCH 21/24] Publish 7.2.0a1 SHA256 hashes: ipykernel-7.2.0a1-py3-none-any.whl: c6bb11acd2709516b249b2d79b9d21a081c2ae9f0a752730a364bb6e31602cc9 ipykernel-7.2.0a1.tar.gz: 0518cde8025c07f628b4dab09a84a7bd68aa456439f146d3a271185c4064f446 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++-- ipykernel/_version.py | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d99d12641..06b7caa15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,35 @@ +## 7.2.0a1 + +([Full Changelog](https://github.com/ipython/ipykernel/compare/v7.2.0a0...220a3c6e8b24ffb3f8678925712ff3644aafb41e)) + +### New features added + +- Added kernel_protocol_version to kernelspec [#1483](https://github.com/ipython/ipykernel/pull/1483) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) + +### Enhancements made + +- Made IOPubThread constructor backward compatible [#1492](https://github.com/ipython/ipykernel/pull/1492) ([@JohanMabille](https://github.com/JohanMabille), [@SylvainCorlay](https://github.com/SylvainCorlay), [@ianthomas23](https://github.com/ianthomas23)) +- Advertizes kernel protocol 5.5 [#1488](https://github.com/ipython/ipykernel/pull/1488) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Upgrade to jupyter_client 8.8.0 [#1487](https://github.com/ipython/ipykernel/pull/1487) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) + +### Maintenance and upkeep improvements + +- Update pytest requirement from \<9,>=7.0 to >=7.0,\<10 in the actions group across 1 directory [#1489](https://github.com/ipython/ipykernel/pull/1489) ([@JohanMabille](https://github.com/JohanMabille)) + +### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/ipython/ipykernel/graphs/contributors?from=2026-01-08&to=2026-01-30&type=c)) + +@ianthomas23 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2026-01-08..2026-01-30&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AJohanMabille+updated%3A2026-01-08..2026-01-30&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ASylvainCorlay+updated%3A2026-01-08..2026-01-30&type=Issues)) + + + ## 7.2.0a0 ([Full Changelog](https://github.com/ipython/ipykernel/compare/v7.1.0...6786ddd040c1f0e8aaeae7e261eec511e2a37fd9)) @@ -36,8 +65,6 @@ See [our definition of contributors](https://github-activity.readthedocs.io/en/l @arjxn-py ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aarjxn-py+updated%3A2025-10-27..2026-01-08&type=Issues)) | @Carreau ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ACarreau+updated%3A2025-10-27..2026-01-08&type=Issues)) | @ianthomas23 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2025-10-27..2026-01-08&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AJohanMabille+updated%3A2025-10-27..2026-01-08&type=Issues)) | @newville ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Anewville+updated%3A2025-10-27..2026-01-08&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ASylvainCorlay+updated%3A2025-10-27..2026-01-08&type=Issues)) - - ## 7.1.0 IPykernel 7.1.0 fixes an issue where display outputs such as Matplotlib plots were not included when using `%notebook` magic to save sessions as `.ipynb` files (#1435). This is enabled using the traitlet `ZMQDisplayPublisher.store_display_history` which defaults to the previous behaviour of False. This is a minor release rather than a patch release due to the addition of the new traitlet. diff --git a/ipykernel/_version.py b/ipykernel/_version.py index 736ce47c7..35e3142f2 100644 --- a/ipykernel/_version.py +++ b/ipykernel/_version.py @@ -5,7 +5,7 @@ import re # Version string must appear intact for hatch versioning -__version__ = "7.2.0a0" +__version__ = "7.2.0a1" # Build up version_info tuple for backwards compatibility pattern = r"(?P\d+).(?P\d+).(?P\d+)(?P.*)" From a2d47a2ca372509e553737b196f995f313949b2c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 30 Jan 2026 11:07:58 +0000 Subject: [PATCH 22/24] chore: update pre-commit hooks (#1472) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Ian Thomas --- .pre-commit-config.yaml | 6 +++--- CHANGELOG.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 53a0922af..9efa63150 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.34.1 + rev: 0.36.1 hooks: - id: check-github-workflows @@ -39,7 +39,7 @@ repos: types_or: [yaml, html, json] - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v1.18.2" + rev: "v1.19.1" hooks: - id: mypy files: ipykernel @@ -73,7 +73,7 @@ repos: - id: rst-inline-touching-normal - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.14.3 + rev: v0.14.14 hooks: - id: ruff-check types_or: [python, jupyter] diff --git a/CHANGELOG.md b/CHANGELOG.md index 06b7caa15..fa732e346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ ### Enhancements made - Made IOPubThread constructor backward compatible [#1492](https://github.com/ipython/ipykernel/pull/1492) ([@JohanMabille](https://github.com/JohanMabille), [@SylvainCorlay](https://github.com/SylvainCorlay), [@ianthomas23](https://github.com/ianthomas23)) -- Advertizes kernel protocol 5.5 [#1488](https://github.com/ipython/ipykernel/pull/1488) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Advertises kernel protocol 5.5 [#1488](https://github.com/ipython/ipykernel/pull/1488) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) - Upgrade to jupyter_client 8.8.0 [#1487](https://github.com/ipython/ipykernel/pull/1487) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) ### Maintenance and upkeep improvements From 8086199395f1dc069c46582e2a7373b00a25b8b8 Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Fri, 30 Jan 2026 11:34:55 +0000 Subject: [PATCH 23/24] Temporarily revert "Test changing base method to async after (#1464)" This reverts commit 31ec38aaeef5cbb53a17e1885c1915d487339a1c. --- ipykernel/kernelbase.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ipykernel/kernelbase.py b/ipykernel/kernelbase.py index 7fa1fb9dc..05bc10e90 100644 --- a/ipykernel/kernelbase.py +++ b/ipykernel/kernelbase.py @@ -869,7 +869,7 @@ async def execute_request(self, stream, ident, parent): subshell_id = parent["header"].get("subshell_id") self._abort_queues(subshell_id) - async def do_execute( + def do_execute( self, code, silent, @@ -904,7 +904,7 @@ async def complete_request(self, stream, ident, parent): matches = json_clean(matches) self.session.send(stream, "complete_reply", matches, parent, ident) - async def do_complete(self, code, cursor_pos): + def do_complete(self, code, cursor_pos): """Override in subclasses to find completions.""" return { "matches": [], @@ -940,7 +940,7 @@ async def inspect_request(self, stream, ident, parent): msg = self.session.send(stream, "inspect_reply", reply_content, parent, ident) self.log.debug("%s", msg) - async def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): + def do_inspect(self, code, cursor_pos, detail_level=0, omit_sections=()): """Override in subclasses to allow introspection.""" return {"status": "ok", "data": {}, "metadata": {}, "found": False} @@ -964,7 +964,7 @@ async def history_request(self, stream, ident, parent): msg = self.session.send(stream, "history_reply", reply_content, parent, ident) self.log.debug("%s", msg) - async def do_history( + def do_history( self, hist_access_type, output, @@ -1104,7 +1104,7 @@ async def shutdown_request(self, stream, ident, parent): shell_io_loop = self.shell_stream.io_loop shell_io_loop.add_callback(shell_io_loop.stop) - async def do_shutdown(self, restart): + def do_shutdown(self, restart): """Override in subclasses to do things when the frontend shuts down the kernel. """ @@ -1130,7 +1130,7 @@ async def is_complete_request(self, stream, ident, parent): reply_msg = self.session.send(stream, "is_complete_reply", reply_content, parent, ident) self.log.debug("%s", reply_msg) - async def do_is_complete(self, code): + def do_is_complete(self, code): """Override in subclasses to find completions.""" return {"status": "unknown"} From 4b37e7504b1e7563b434b23961d2d6b75dc95ed1 Mon Sep 17 00:00:00 2001 From: ianthomas23 Date: Fri, 6 Feb 2026 16:43:14 +0000 Subject: [PATCH 24/24] Publish 7.2.0 SHA256 hashes: ipykernel-7.2.0-py3-none-any.whl: 3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661 ipykernel-7.2.0.tar.gz: 18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e --- CHANGELOG.md | 45 +++++++++++++++++++++++++++++++++++++++++-- ipykernel/_version.py | 2 +- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa732e346..ac5d7ada4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,49 @@ +## 7.2.0 + +([Full Changelog](https://github.com/ipython/ipykernel/compare/39eaf96a...1630c4f7d5365918c4f06cf3caee3c278b52afc2)) + +### New features added + +- Added kernel_protocol_version to kernelspec [#1483](https://github.com/ipython/ipykernel/pull/1483) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Replaced PUB socket with XPUB socket [#1482](https://github.com/ipython/ipykernel/pull/1482) ([@JohanMabille](https://github.com/JohanMabille), [@SylvainCorlay](https://github.com/SylvainCorlay), [@ccordoba12](https://github.com/ccordoba12), [@ianthomas23](https://github.com/ianthomas23), [@minrk](https://github.com/minrk)) + +### Enhancements made + +- Made IOPubThread constructor backward compatible [#1492](https://github.com/ipython/ipykernel/pull/1492) ([@JohanMabille](https://github.com/JohanMabille), [@SylvainCorlay](https://github.com/SylvainCorlay), [@ianthomas23](https://github.com/ianthomas23), [@minrk](https://github.com/minrk)) +- Advertizes kernel protocol 5.5 [#1488](https://github.com/ipython/ipykernel/pull/1488) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Upgrade to jupyter_client 8.8.0 [#1487](https://github.com/ipython/ipykernel/pull/1487) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Implement kernel-side callstack filtering for internal frames [#1481](https://github.com/ipython/ipykernel/pull/1481) ([@arjxn-py](https://github.com/arjxn-py), [@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) + +### Bugs fixed + +- add close event for wx timer app in loop_wx [#1478](https://github.com/ipython/ipykernel/pull/1478) ([@newville](https://github.com/newville), [@ianthomas23](https://github.com/ianthomas23)) + +### Maintenance and upkeep improvements + +- Temporarily revert "Test changing base method to async after (#1464)" [#1493](https://github.com/ipython/ipykernel/pull/1493) ([@ianthomas23](https://github.com/ianthomas23), [@JohanMabille](https://github.com/JohanMabille)) +- Update pytest requirement from \<9,>=7.0 to >=7.0,\<10 in the actions group across 1 directory [#1489](https://github.com/ipython/ipykernel/pull/1489) ([@JohanMabille](https://github.com/JohanMabille)) +- Removed spyder downstream tests [#1486](https://github.com/ipython/ipykernel/pull/1486) ([@JohanMabille](https://github.com/JohanMabille), [@ianthomas23](https://github.com/ianthomas23)) +- Bump scientific-python/upload-nightly-action from 0.6.2 to 0.6.3 in the actions group [#1484](https://github.com/ipython/ipykernel/pull/1484) ([@JohanMabille](https://github.com/JohanMabille)) +- Fix linting errors [#1480](https://github.com/ipython/ipykernel/pull/1480) ([@ianthomas23](https://github.com/ianthomas23)) +- Bump actions/checkout from 5 to 6 in the actions group [#1479](https://github.com/ipython/ipykernel/pull/1479) ([@ianthomas23](https://github.com/ianthomas23)) +- chore: update pre-commit hooks [#1472](https://github.com/ipython/ipykernel/pull/1472) ([@ianthomas23](https://github.com/ianthomas23)) +- chore: update pre-commit hooks [#1467](https://github.com/ipython/ipykernel/pull/1467) ([@JohanMabille](https://github.com/JohanMabille)) +- Test changing base method to async after #1295 [#1464](https://github.com/ipython/ipykernel/pull/1464) ([@Carreau](https://github.com/Carreau), [@ianthomas23](https://github.com/ianthomas23)) + +### Contributors to this release + +The following people contributed discussions, new ideas, code and documentation contributions, and review. +See [our definition of contributors](https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports). + +([GitHub contributors page for this release](https://github.com/ipython/ipykernel/graphs/contributors?from=2025-10-27&to=2026-02-06&type=c)) + +@arjxn-py ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aarjxn-py+updated%3A2025-10-27..2026-02-06&type=Issues)) | @Carreau ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ACarreau+updated%3A2025-10-27..2026-02-06&type=Issues)) | @ccordoba12 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Accordoba12+updated%3A2025-10-27..2026-02-06&type=Issues)) | @ianthomas23 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2025-10-27..2026-02-06&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AJohanMabille+updated%3A2025-10-27..2026-02-06&type=Issues)) | @minrk ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aminrk+updated%3A2025-10-27..2026-02-06&type=Issues)) | @newville ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Anewville+updated%3A2025-10-27..2026-02-06&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ASylvainCorlay+updated%3A2025-10-27..2026-02-06&type=Issues)) + + + ## 7.2.0a1 ([Full Changelog](https://github.com/ipython/ipykernel/compare/v7.2.0a0...220a3c6e8b24ffb3f8678925712ff3644aafb41e)) @@ -29,8 +72,6 @@ See [our definition of contributors](https://github-activity.readthedocs.io/en/l @ianthomas23 ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2026-01-08..2026-01-30&type=Issues)) | @JohanMabille ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3AJohanMabille+updated%3A2026-01-08..2026-01-30&type=Issues)) | @SylvainCorlay ([activity](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3ASylvainCorlay+updated%3A2026-01-08..2026-01-30&type=Issues)) - - ## 7.2.0a0 ([Full Changelog](https://github.com/ipython/ipykernel/compare/v7.1.0...6786ddd040c1f0e8aaeae7e261eec511e2a37fd9)) diff --git a/ipykernel/_version.py b/ipykernel/_version.py index 35e3142f2..4c4be1dc4 100644 --- a/ipykernel/_version.py +++ b/ipykernel/_version.py @@ -5,7 +5,7 @@ import re # Version string must appear intact for hatch versioning -__version__ = "7.2.0a1" +__version__ = "7.2.0" # Build up version_info tuple for backwards compatibility pattern = r"(?P\d+).(?P\d+).(?P\d+)(?P.*)"