Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-ipykernel for 
openSUSE:Factory checked in at 2024-03-06 23:03:02
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ipykernel (Old)
 and      /work/SRC/openSUSE:Factory/.python-ipykernel.new.1770 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ipykernel"

Wed Mar  6 23:03:02 2024 rev:47 rq:1155310 version:6.29.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ipykernel/python-ipykernel.changes        
2024-02-08 19:01:54.578527791 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-ipykernel.new.1770/python-ipykernel.changes  
    2024-03-06 23:03:04.822156256 +0100
@@ -1,0 +2,16 @@
+Tue Mar  5 15:11:37 UTC 2024 - Dominique Leuenberger <dims...@opensuse.org>
+
+- Skip build for python 3.9: python-ipython is no longer available.
+
+-------------------------------------------------------------------
+Sat Mar  2 11:25:38 UTC 2024 - Ben Greiner <c...@bnavigator.de>
+
+- Update to 6.29.3
+  ## Enhancements made
+  * Eventloop scheduling improvements for stop_on_error_timeout and
+    schedule_next #1212 (@jdranczewski)
+  ## Bugs fixed
+  * Disable frozen modules by default, add a toggle #1213
+    (@krassowski)
+
+-------------------------------------------------------------------

Old:
----
  ipykernel-6.29.2.tar.gz

New:
----
  ipykernel-6.29.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-ipykernel.spec ++++++
--- /var/tmp/diff_new_pack.5d9CLU/_old  2024-03-06 23:03:06.110202954 +0100
+++ /var/tmp/diff_new_pack.5d9CLU/_new  2024-03-06 23:03:06.110202954 +0100
@@ -17,8 +17,9 @@
 
 
 %{?sle15_python_module_pythons}
+%define skip_python39 1
 Name:           python-ipykernel
-Version:        6.29.2
+Version:        6.29.3
 Release:        0
 Summary:        IPython Kernel for Jupyter
 License:        BSD-3-Clause
@@ -73,7 +74,7 @@
 BuildRequires:  %{python_module flaky}
 BuildRequires:  %{python_module matplotlib}
 BuildRequires:  %{python_module pytest >= 7.0}
-BuildRequires:  %{python_module pytest-asyncio}
+BuildRequires:  %{python_module pytest-asyncio >= 0.23.5}
 BuildRequires:  %{python_module pytest-timeout}
 # we don't want ipyparallel and its dependencies in Ring1, see below
 #BuildRequires:  #{python_module ipyparallel}

++++++ ipykernel-6.29.2.tar.gz -> ipykernel-6.29.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/CHANGELOG.md 
new/ipykernel-6.29.3/CHANGELOG.md
--- old/ipykernel-6.29.2/CHANGELOG.md   2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/CHANGELOG.md   2020-02-02 01:00:00.000000000 +0100
@@ -2,6 +2,35 @@
 
 <!-- <START NEW CHANGELOG ENTRY> -->
 
+## 6.29.3
+
+([Full 
Changelog](https://github.com/ipython/ipykernel/compare/v6.29.2...de2221ce155668c343084fde37b77fb6b1671dc9))
+
+### Enhancements made
+
+- Eventloop scheduling improvements for stop_on_error_timeout and 
schedule_next [#1212](https://github.com/ipython/ipykernel/pull/1212) 
([@jdranczewski](https://github.com/jdranczewski))
+
+### Bugs fixed
+
+- Disable frozen modules by default, add a toggle 
[#1213](https://github.com/ipython/ipykernel/pull/1213) 
([@krassowski](https://github.com/krassowski))
+
+### Maintenance and upkeep improvements
+
+- Fix typings and update project urls 
[#1214](https://github.com/ipython/ipykernel/pull/1214) 
([@blink1073](https://github.com/blink1073))
+- Unpin pytest-asyncio and update ruff config 
[#1209](https://github.com/ipython/ipykernel/pull/1209) 
([@blink1073](https://github.com/blink1073))
+
+### Documentation improvements
+
+- Correct spelling mistake 
[#1208](https://github.com/ipython/ipykernel/pull/1208) 
([@joouha](https://github.com/joouha))
+
+### Contributors to this release
+
+([GitHub contributors page for this 
release](https://github.com/ipython/ipykernel/graphs/contributors?from=2024-02-07&to=2024-02-26&type=c))
+
+[@blink1073](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Ablink1073+updated%3A2024-02-07..2024-02-26&type=Issues)
 | 
[@ccordoba12](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Accordoba12+updated%3A2024-02-07..2024-02-26&type=Issues)
 | 
[@jdranczewski](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Ajdranczewski+updated%3A2024-02-07..2024-02-26&type=Issues)
 | 
[@joouha](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Ajoouha+updated%3A2024-02-07..2024-02-26&type=Issues)
 | 
[@krassowski](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Akrassowski+updated%3A2024-02-07..2024-02-26&type=Issues)
+
+<!-- <END NEW CHANGELOG ENTRY> -->
+
 ## 6.29.2
 
 ([Full 
Changelog](https://github.com/ipython/ipykernel/compare/v6.29.1...d45fe71990d26c0bd5b7b3b2a4ccd3d1f6609899))
@@ -20,8 +49,6 @@
 
 
[@ianthomas23](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aianthomas23+updated%3A2024-02-06..2024-02-07&type=Issues)
 | 
[@stdll00](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Astdll00+updated%3A2024-02-06..2024-02-07&type=Issues)
 
-<!-- <END NEW CHANGELOG ENTRY> -->
-
 ## 6.29.1
 
 ([Full 
Changelog](https://github.com/ipython/ipykernel/compare/v6.29.0...09c9b2ad9c15202c5d1896ba24ec978b726c073b))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/PKG-INFO 
new/ipykernel-6.29.3/PKG-INFO
--- old/ipykernel-6.29.2/PKG-INFO       2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/PKG-INFO       2020-02-02 01:00:00.000000000 +0100
@@ -1,8 +1,12 @@
 Metadata-Version: 2.1
 Name: ipykernel
-Version: 6.29.2
+Version: 6.29.3
 Summary: IPython Kernel for Jupyter
 Project-URL: Homepage, https://ipython.org
+Project-URL: Documentation, https://ipykernel.readthedocs.io
+Project-URL: Funding, https://numfocus.org/donate
+Project-URL: Source, https://github.com/ipython/ipykernel
+Project-URL: Tracker, https://github.com/ipython/ipykernel/issues
 Author-email: IPython Development Team <ipython-...@scipy.org>
 License: BSD 3-Clause License
         
@@ -78,7 +82,7 @@
 Requires-Dist: flaky; extra == 'test'
 Requires-Dist: ipyparallel; extra == 'test'
 Requires-Dist: pre-commit; extra == 'test'
-Requires-Dist: pytest-asyncio==0.23.4; extra == 'test'
+Requires-Dist: pytest-asyncio>=0.23.5; extra == 'test'
 Requires-Dist: pytest-cov; extra == 'test'
 Requires-Dist: pytest-timeout; extra == 'test'
 Requires-Dist: pytest>=7.0; extra == 'test'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/docs/conf.py 
new/ipykernel-6.29.3/docs/conf.py
--- old/ipykernel-6.29.2/docs/conf.py   2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/docs/conf.py   2020-02-02 01:00:00.000000000 +0100
@@ -37,7 +37,7 @@
 ]
 
 try:
-    import enchant
+    import enchant  # noqa: F401
 
     extensions += ["sphinxcontrib.spelling"]
 except ImportError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/hatch_build.py 
new/ipykernel-6.29.3/hatch_build.py
--- old/ipykernel-6.29.2/hatch_build.py 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/hatch_build.py 2020-02-02 01:00:00.000000000 +0100
@@ -1,5 +1,4 @@
 """A custom hatch build hook for ipykernel."""
-import os
 import shutil
 import sys
 from pathlib import Path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/__init__.py 
new/ipykernel-6.29.3/ipykernel/__init__.py
--- old/ipykernel-6.29.2/ipykernel/__init__.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/__init__.py  2020-02-02 01:00:00.000000000 
+0100
@@ -4,4 +4,4 @@
     kernel_protocol_version_info,
     version_info,
 )
-from .connect import *
+from .connect import *  # noqa: F403
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/_version.py 
new/ipykernel-6.29.3/ipykernel/_version.py
--- old/ipykernel-6.29.2/ipykernel/_version.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/_version.py  2020-02-02 01:00:00.000000000 
+0100
@@ -5,7 +5,7 @@
 from typing import List
 
 # Version string must appear intact for hatch versioning
-__version__ = "6.29.2"
+__version__ = "6.29.3"
 
 # Build up version_info tuple for backwards compatibility
 pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/compiler.py 
new/ipykernel-6.29.3/ipykernel/compiler.py
--- old/ipykernel-6.29.2/ipykernel/compiler.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/compiler.py  2020-02-02 01:00:00.000000000 
+0100
@@ -45,7 +45,7 @@
     return h
 
 
-convert_to_long_pathname = lambda filename: filename
+convert_to_long_pathname = lambda filename: filename  # noqa: E731
 
 if sys.platform == "win32":
     try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/datapub.py 
new/ipykernel-6.29.3/ipykernel/datapub.py
--- old/ipykernel-6.29.2/ipykernel/datapub.py   2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/datapub.py   2020-02-02 01:00:00.000000000 
+0100
@@ -1,17 +1,11 @@
+# Copyright (c) IPython Development Team.
+# Distributed under the terms of the Modified BSD License.
+
 """Publishing native (typically pickled) objects.
 """
 
 import warnings
 
-warnings.warn(
-    "ipykernel.datapub is deprecated. It has moved to ipyparallel.datapub",
-    DeprecationWarning,
-    stacklevel=2,
-)
-
-# Copyright (c) IPython Development Team.
-# Distributed under the terms of the Modified BSD License.
-
 from traitlets import Any, CBytes, Dict, Instance
 from traitlets.config import Configurable
 
@@ -26,6 +20,12 @@
 
 from jupyter_client.session import Session, extract_header
 
+warnings.warn(
+    "ipykernel.datapub is deprecated. It has moved to ipyparallel.datapub",
+    DeprecationWarning,
+    stacklevel=2,
+)
+
 
 class ZMQDataPublisher(Configurable):
     """A zmq data publisher."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/debugger.py 
new/ipykernel-6.29.3/ipykernel/debugger.py
--- old/ipykernel-6.29.2/ipykernel/debugger.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/debugger.py  2020-02-02 01:00:00.000000000 
+0100
@@ -21,7 +21,7 @@
 
 try:
     # This import is required to have the next ones working...
-    from debugpy.server import api
+    from debugpy.server import api  # noqa: F401
 
     from _pydevd_bundle import pydevd_frame_utils  # isort: skip
     from _pydevd_bundle.pydevd_suspended_frames import (  # isort: skip
@@ -610,7 +610,7 @@
         }
 
     async def inspectVariables(self, message):
-        """Handle an insepct variables message."""
+        """Handle an inspect variables message."""
         self.variable_explorer.untrack_all()
         # looks like the implementation of untrack_all in ptvsd
         # destroys objects we nee din track. We have no choice but
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/eventloops.py 
new/ipykernel-6.29.3/ipykernel/eventloops.py
--- old/ipykernel-6.29.2/ipykernel/eventloops.py        2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/eventloops.py        2020-02-02 
01:00:00.000000000 +0100
@@ -82,6 +82,11 @@
         def enum_helper(name):
             return 
operator.attrgetter(name.rpartition(".")[0])(sys.modules[QtCore.__package__])
 
+    def exit_loop():
+        """fall back to main loop"""
+        kernel._qt_notifier.setEnabled(False)
+        kernel.app.qt_event_loop.quit()
+
     def process_stream_events():
         """fall back to main loop when there's a socket event"""
         # call flush to ensure that the stream doesn't lose events
@@ -89,8 +94,7 @@
         # flush returns the number of events consumed.
         # if there were any, wake it up
         if kernel.shell_stream.flush(limit=1):
-            kernel._qt_notifier.setEnabled(False)
-            kernel.app.qt_event_loop.quit()
+            exit_loop()
 
     if not hasattr(kernel, "_qt_notifier"):
         fd = kernel.shell_stream.getsockopt(zmq.FD)
@@ -101,6 +105,23 @@
     else:
         kernel._qt_notifier.setEnabled(True)
 
+    # allow for scheduling exits from the loop in case a timeout needs to
+    # be set from the kernel level
+    def _schedule_exit(delay):
+        """schedule fall back to main loop in [delay] seconds"""
+        # The signatures of QtCore.QTimer.singleShot are inconsistent between 
PySide and PyQt
+        # if setting the TimerType, so we create a timer explicitly and store 
it
+        # to avoid a memory leak.
+        # PreciseTimer is needed so we exit after _at least_ the specified 
delay, not within 5% of it
+        if not hasattr(kernel, "_qt_timer"):
+            kernel._qt_timer = QtCore.QTimer(kernel.app)
+            kernel._qt_timer.setSingleShot(True)
+            
kernel._qt_timer.setTimerType(enum_helper("QtCore.Qt.TimerType").PreciseTimer)
+            kernel._qt_timer.timeout.connect(exit_loop)
+        kernel._qt_timer.start(int(1000 * delay))
+
+    loop_qt._schedule_exit = _schedule_exit
+
     # there may already be unprocessed events waiting.
     # these events will not wake zmq's edge-triggered FD
     # since edge-triggered notification only occurs on new i/o activity.
@@ -108,11 +129,7 @@
     # so we start in a clean state ensuring that any new i/o events will 
notify.
     # schedule first call on the eventloop as soon as it's running,
     # so we don't block here processing events
-    if not hasattr(kernel, "_qt_timer"):
-        kernel._qt_timer = QtCore.QTimer(kernel.app)
-        kernel._qt_timer.setSingleShot(True)
-        kernel._qt_timer.timeout.connect(process_stream_events)
-    kernel._qt_timer.start(0)
+    QtCore.QTimer.singleShot(0, process_stream_events)
 
 
 @register_integration("qt", "qt5", "qt6")
@@ -229,23 +246,33 @@
                 self.app = app
                 self.app.withdraw()
 
-        def process_stream_events(stream, *a, **kw):
+        def exit_loop():
+            """fall back to main loop"""
+            app.tk.deletefilehandler(kernel.shell_stream.getsockopt(zmq.FD))
+            app.quit()
+            app.destroy()
+            del kernel.app_wrapper
+
+        def process_stream_events(*a, **kw):
             """fall back to main loop when there's a socket event"""
-            if stream.flush(limit=1):
-                app.tk.deletefilehandler(stream.getsockopt(zmq.FD))
-                app.quit()
-                app.destroy()
-                del kernel.app_wrapper
+            if kernel.shell_stream.flush(limit=1):
+                exit_loop()
+
+        # allow for scheduling exits from the loop in case a timeout needs to
+        # be set from the kernel level
+        def _schedule_exit(delay):
+            """schedule fall back to main loop in [delay] seconds"""
+            app.after(int(1000 * delay), exit_loop)
+
+        loop_tk._schedule_exit = _schedule_exit
 
         # For Tkinter, we create a Tk object and call its withdraw method.
         kernel.app_wrapper = BasicAppWrapper(app)
-
-        notifier = partial(process_stream_events, kernel.shell_stream)
-        # seems to be needed for tk
-        notifier.__name__ = "notifier"  # type:ignore[attr-defined]
-        app.tk.createfilehandler(kernel.shell_stream.getsockopt(zmq.FD), 
READABLE, notifier)
+        app.tk.createfilehandler(
+            kernel.shell_stream.getsockopt(zmq.FD), READABLE, 
process_stream_events
+        )
         # schedule initial call after start
-        app.after(0, notifier)
+        app.after(0, process_stream_events)
 
         app.mainloop()
 
@@ -484,24 +511,24 @@
     else:
         if gui == "qt5":
             try:
-                import PyQt5
+                import PyQt5  # noqa: F401
 
                 os.environ["QT_API"] = "pyqt5"
             except ImportError:
                 try:
-                    import PySide2
+                    import PySide2  # noqa: F401
 
                     os.environ["QT_API"] = "pyside2"
                 except ImportError:
                     os.environ["QT_API"] = "pyqt5"
         elif gui == "qt6":
             try:
-                import PyQt6
+                import PyQt6  # noqa: F401
 
                 os.environ["QT_API"] = "pyqt6"
             except ImportError:
                 try:
-                    import PySide6
+                    import PySide6  # noqa: F401
 
                     os.environ["QT_API"] = "pyside6"
                 except ImportError:
@@ -516,7 +543,7 @@
 
     # Do the actual import now that the environment variable is set to make 
sure it works.
     try:
-        from IPython.external.qt_for_kernel import QtCore, QtGui
+        pass
     except Exception as e:
         # Clear the environment variable for the next attempt.
         if "QT_API" in os.environ:
@@ -560,6 +587,10 @@
         # User wants to turn off integration; clear any evidence if Qt was the 
last one.
         if hasattr(kernel, "app"):
             delattr(kernel, "app")
+        if hasattr(kernel, "_qt_notifier"):
+            delattr(kernel, "_qt_notifier")
+        if hasattr(kernel, "_qt_timer"):
+            delattr(kernel, "_qt_timer")
     else:
         if gui.startswith("qt"):
             # Prepare the kernel here so any exceptions are displayed in the 
client.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/gui/gtk3embed.py 
new/ipykernel-6.29.3/ipykernel/gui/gtk3embed.py
--- old/ipykernel-6.29.2/ipykernel/gui/gtk3embed.py     2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/gui/gtk3embed.py     2020-02-02 
01:00:00.000000000 +0100
@@ -14,16 +14,16 @@
 import sys
 import warnings
 
-warnings.warn(
-    "The Gtk3 event loop for ipykernel is deprecated", 
category=DeprecationWarning, stacklevel=2
-)
-
 # Third-party
 import gi
 
 gi.require_version("Gdk", "3.0")
 gi.require_version("Gtk", "3.0")
-from gi.repository import GObject, Gtk
+from gi.repository import GObject, Gtk  # noqa: E402
+
+warnings.warn(
+    "The Gtk3 event loop for ipykernel is deprecated", 
category=DeprecationWarning, stacklevel=2
+)
 
 # -----------------------------------------------------------------------------
 # Classes and functions
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/gui/gtkembed.py 
new/ipykernel-6.29.3/ipykernel/gui/gtkembed.py
--- old/ipykernel-6.29.2/ipykernel/gui/gtkembed.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/gui/gtkembed.py      2020-02-02 
01:00:00.000000000 +0100
@@ -14,14 +14,14 @@
 import sys
 import warnings
 
-warnings.warn(
-    "The Gtk3 event loop for ipykernel is deprecated", 
category=DeprecationWarning, stacklevel=2
-)
-
 # Third-party
 import gobject
 import gtk
 
+warnings.warn(
+    "The Gtk3 event loop for ipykernel is deprecated", 
category=DeprecationWarning, stacklevel=2
+)
+
 # -----------------------------------------------------------------------------
 # Classes and functions
 # -----------------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/ipkernel.py 
new/ipykernel-6.29.3/ipykernel/ipkernel.py
--- old/ipykernel-6.29.2/ipykernel/ipkernel.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/ipkernel.py  2020-02-02 01:00:00.000000000 
+0100
@@ -381,7 +381,7 @@
             should_run_async = shell.should_run_async
             accepts_params = _accepts_parameters(run_cell, ["cell_id"])
         else:
-            should_run_async = lambda cell: False  # noqa: ARG005
+            should_run_async = lambda cell: False  # noqa: ARG005, E731
             # older IPython,
             # use blocking run_cell and wrap it in coroutine
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/kernelbase.py 
new/ipykernel-6.29.3/ipykernel/kernelbase.py
--- old/ipykernel-6.29.2/ipykernel/kernelbase.py        2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/kernelbase.py        2020-02-02 
01:00:00.000000000 +0100
@@ -472,7 +472,7 @@
             self.log.info("Exiting as there is no eventloop")
             return
 
-        def advance_eventloop():
+        async def advance_eventloop():
             # check if eventloop changed:
             if self.eventloop is not eventloop:
                 self.log.info("exiting eventloop %s", eventloop)
@@ -494,10 +494,13 @@
 
         def schedule_next():
             """Schedule the next advance of the eventloop"""
-            # flush the eventloop every so often,
-            # giving us a chance to handle messages in the meantime
+            # call_later allows the io_loop to process other events if needed.
+            # Going through schedule_dispatch ensures all other dispatches on 
msg_queue
+            # are processed before we enter the eventloop, even if the 
previous dispatch was
+            # already consumed from the queue by process_one and the queue is
+            # technically empty.
             self.log.debug("Scheduling eventloop advance")
-            self.io_loop.call_later(0.001, advance_eventloop)
+            self.io_loop.call_later(0.001, partial(self.schedule_dispatch, 
advance_eventloop))
 
         # begin polling the eventloop
         schedule_next()
@@ -1202,9 +1205,18 @@
         # before we reset the flag
         schedule_stop_aborting = partial(self.schedule_dispatch, stop_aborting)
 
-        # if we have a delay, give messages this long to arrive on the queue
-        # before we stop aborting requests
-        asyncio.get_event_loop().call_later(self.stop_on_error_timeout, 
schedule_stop_aborting)
+        if self.stop_on_error_timeout:
+            # if we have a delay, give messages this long to arrive on the 
queue
+            # before we stop aborting requests
+            self.io_loop.call_later(self.stop_on_error_timeout, 
schedule_stop_aborting)
+            # If we have an eventloop, it may interfere with the call_later 
above.
+            # If the loop has a _schedule_exit method, we call that so the 
loop exits
+            # after stop_on_error_timeout, returning to the main io_loop and 
letting
+            # the call_later fire.
+            if self.eventloop is not None and hasattr(self.eventloop, 
"_schedule_exit"):
+                self.eventloop._schedule_exit(self.stop_on_error_timeout + 
0.01)
+        else:
+            schedule_stop_aborting()
 
     def _send_abort_reply(self, stream, msg, idents):
         """Send a reply to an aborted request"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/kernelspec.py 
new/ipykernel-6.29.3/ipykernel/kernelspec.py
--- old/ipykernel-6.29.2/ipykernel/kernelspec.py        2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/kernelspec.py        2020-02-02 
01:00:00.000000000 +0100
@@ -8,6 +8,7 @@
 import errno
 import json
 import os
+import platform
 import shutil
 import stat
 import sys
@@ -17,11 +18,7 @@
 
 from jupyter_client.kernelspec import KernelSpecManager
 from traitlets import Unicode
-
-try:
-    from .debugger import _is_debugpy_available
-except ImportError:
-    _is_debugpy_available = False
+from traitlets.config import Application
 
 pjoin = os.path.join
 
@@ -35,6 +32,7 @@
     mod: str = "ipykernel_launcher",
     executable: str | None = None,
     extra_arguments: list[str] | None = None,
+    python_arguments: list[str] | None = None,
 ) -> list[str]:
     """Build Popen command list for launching an IPython kernel.
 
@@ -54,16 +52,18 @@
     if executable is None:
         executable = sys.executable
     extra_arguments = extra_arguments or []
-    arguments = [executable, "-m", mod, "-f", "{connection_file}"]
-    arguments.extend(extra_arguments)
+    python_arguments = python_arguments or []
+    return [executable, *python_arguments, "-m", mod, "-f", 
"{connection_file}", *extra_arguments]
 
-    return arguments
 
-
-def get_kernel_dict(extra_arguments: list[str] | None = None) -> dict[str, 
Any]:
+def get_kernel_dict(
+    extra_arguments: list[str] | None = None, python_arguments: list[str] | 
None = None
+) -> dict[str, Any]:
     """Construct dict for kernel.json"""
     return {
-        "argv": make_ipkernel_cmd(extra_arguments=extra_arguments),
+        "argv": make_ipkernel_cmd(
+            extra_arguments=extra_arguments, python_arguments=python_arguments
+        ),
         "display_name": "Python %i (ipykernel)" % sys.version_info[0],
         "language": "python",
         "metadata": {"debugger": True},
@@ -74,6 +74,7 @@
     path: Path | str | None = None,
     overrides: dict[str, Any] | None = None,
     extra_arguments: list[str] | None = None,
+    python_arguments: list[str] | None = None,
 ) -> str:
     """Write a kernel spec directory to `path`
 
@@ -94,7 +95,7 @@
         Path(path).chmod(mask | stat.S_IWUSR)
 
     # write kernel.json
-    kernel_dict = get_kernel_dict(extra_arguments)
+    kernel_dict = get_kernel_dict(extra_arguments, python_arguments)
 
     if overrides:
         kernel_dict.update(overrides)
@@ -112,6 +113,7 @@
     prefix: str | None = None,
     profile: str | None = None,
     env: dict[str, str] | None = None,
+    frozen_modules: bool = False,
 ) -> str:
     """Install the IPython kernelspec for Jupyter
 
@@ -136,6 +138,12 @@
         A dictionary of extra environment variables for the kernel.
         These will be added to the current environment variables before the
         kernel is started
+    frozen_modules : bool, optional
+        Whether to use frozen modules for potentially faster kernel startup.
+        Using frozen modules prevents debugging inside of some built-in
+        Python modules, such as io, abc, posixpath, ntpath, or stat.
+        The frozen modules are used in CPython for faster interpreter startup.
+        Ignored for cPython <3.11 and for other Python implementations.
 
     Returns
     -------
@@ -144,6 +152,9 @@
     if kernel_spec_manager is None:
         kernel_spec_manager = KernelSpecManager()
 
+    if env is None:
+        env = {}
+
     if (kernel_name != KERNEL_NAME) and (display_name is None):
         # kernel_name is specified and display_name is not
         # default display_name to kernel_name
@@ -158,9 +169,24 @@
             overrides["display_name"] = "Python %i [profile=%s]" % 
(sys.version_info[0], profile)
     else:
         extra_arguments = None
+
+    python_arguments = None
+
+    # addresses the debugger warning from debugpy about frozen modules
+    if sys.version_info >= (3, 11) and platform.python_implementation() == 
"CPython":
+        if not frozen_modules:
+            # disable frozen modules
+            python_arguments = ["-Xfrozen_modules=off"]
+        elif "PYDEVD_DISABLE_FILE_VALIDATION" not in env:
+            # user opted-in to have frozen modules, and we warned them about
+            # consequences for the - disable the debugger warning
+            env["PYDEVD_DISABLE_FILE_VALIDATION"] = "1"
+
     if env:
         overrides["env"] = env
-    path = write_kernel_spec(overrides=overrides, 
extra_arguments=extra_arguments)
+    path = write_kernel_spec(
+        overrides=overrides, extra_arguments=extra_arguments, 
python_arguments=python_arguments
+    )
     dest = kernel_spec_manager.install_kernel_spec(
         path, kernel_name=kernel_name, user=user, prefix=prefix
     )
@@ -171,8 +197,6 @@
 
 # Entrypoint
 
-from traitlets.config import Application
-
 
 class InstallIPythonKernelSpecApp(Application):
     """Dummy app wrapping argparse"""
@@ -237,6 +261,12 @@
             metavar=("ENV", "VALUE"),
             help="Set environment variables for the kernel.",
         )
+        parser.add_argument(
+            "--frozen_modules",
+            action="store_true",
+            help="Enable frozen modules for potentially faster startup."
+            " This has a downside of preventing the debugger from navigating 
to certain built-in modules.",
+        )
         opts = parser.parse_args(self.argv)
         if opts.env:
             opts.env = dict(opts.env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/pickleutil.py 
new/ipykernel-6.29.3/ipykernel/pickleutil.py
--- old/ipykernel-6.29.2/ipykernel/pickleutil.py        2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/pickleutil.py        2020-02-02 
01:00:00.000000000 +0100
@@ -2,25 +2,23 @@
 
 # Copyright (c) IPython Development Team.
 # Distributed under the terms of the Modified BSD License.
-import typing
-import warnings
-
-warnings.warn(
-    "ipykernel.pickleutil is deprecated. It has moved to ipyparallel.",
-    DeprecationWarning,
-    stacklevel=2,
-)
-
 import copy
 import pickle
 import sys
+import typing
+import warnings
 from types import FunctionType
 
 # This registers a hook when it's imported
-from ipyparallel.serialize import codeutil
 from traitlets.log import get_logger
 from traitlets.utils.importstring import import_item
 
+warnings.warn(
+    "ipykernel.pickleutil is deprecated. It has moved to ipyparallel.",
+    DeprecationWarning,
+    stacklevel=2,
+)
+
 buffer = memoryview
 class_type = type
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/pylab/backend_inline.py 
new/ipykernel-6.29.3/ipykernel/pylab/backend_inline.py
--- old/ipykernel-6.29.2/ipykernel/pylab/backend_inline.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/pylab/backend_inline.py      2020-02-02 
01:00:00.000000000 +0100
@@ -5,7 +5,7 @@
 
 import warnings
 
-from matplotlib_inline.backend_inline import *  # type:ignore[import-untyped] 
# analysis: ignore
+from matplotlib_inline.backend_inline import *  # type:ignore[import-untyped] 
# noqa: F403  # analysis: ignore
 
 warnings.warn(
     "`ipykernel.pylab.backend_inline` is deprecated, directly "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/pylab/config.py 
new/ipykernel-6.29.3/ipykernel/pylab/config.py
--- old/ipykernel-6.29.2/ipykernel/pylab/config.py      2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/ipykernel/pylab/config.py      2020-02-02 
01:00:00.000000000 +0100
@@ -5,7 +5,7 @@
 
 import warnings
 
-from matplotlib_inline.config import *  # type:ignore[import-untyped] # 
analysis: ignore
+from matplotlib_inline.config import *  # type:ignore[import-untyped] # noqa: 
F403 # analysis: ignore
 
 warnings.warn(
     "`ipykernel.pylab.config` is deprecated, directly use 
`matplotlib_inline.config`",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/serialize.py 
new/ipykernel-6.29.3/ipykernel/serialize.py
--- old/ipykernel-6.29.2/ipykernel/serialize.py 2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/serialize.py 2020-02-02 01:00:00.000000000 
+0100
@@ -3,15 +3,8 @@
 # Copyright (c) IPython Development Team.
 # Distributed under the terms of the Modified BSD License.
 
-import warnings
-
-warnings.warn(
-    "ipykernel.serialize is deprecated. It has moved to ipyparallel.serialize",
-    DeprecationWarning,
-    stacklevel=2,
-)
-
 import pickle
+import warnings
 from itertools import chain
 
 try:
@@ -41,6 +34,12 @@
 
 from jupyter_client.session import MAX_BYTES, MAX_ITEMS
 
+warnings.warn(
+    "ipykernel.serialize is deprecated. It has moved to ipyparallel.serialize",
+    DeprecationWarning,
+    stacklevel=2,
+)
+
 # -----------------------------------------------------------------------------
 # Serialization Functions
 # -----------------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/ipykernel/zmqshell.py 
new/ipykernel-6.29.3/ipykernel/zmqshell.py
--- old/ipykernel-6.29.2/ipykernel/zmqshell.py  2020-02-02 01:00:00.000000000 
+0100
+++ new/ipykernel-6.29.3/ipykernel/zmqshell.py  2020-02-02 01:00:00.000000000 
+0100
@@ -612,7 +612,7 @@
         """Initialize magics."""
         super().init_magics()
         self.register_magics(KernelMagics)
-        self.magics_manager.register_alias("ed", "edit")  # 
type:ignore[union-attr]
+        self.magics_manager.register_alias("ed", "edit")
 
     def init_virtualenv(self):
         """Initialize virtual environment."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/pyproject.toml 
new/ipykernel-6.29.3/pyproject.toml
--- old/ipykernel-6.29.2/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/pyproject.toml 2020-02-02 01:00:00.000000000 +0100
@@ -18,7 +18,6 @@
     "Programming Language :: Python",
     "Programming Language :: Python :: 3",
 ]
-urls = {Homepage = "https://ipython.org"}
 requires-python = ">=3.8"
 dependencies = [
     "debugpy>=1.6.5",
@@ -37,6 +36,13 @@
     "packaging",
 ]
 
+[project.urls]
+Homepage = "https://ipython.org";
+Documentation = "https://ipykernel.readthedocs.io";
+Funding = "https://numfocus.org/donate";
+Source = "https://github.com/ipython/ipykernel";
+Tracker = "https://github.com/ipython/ipykernel/issues";
+
 [project.optional-dependencies]
 docs = [
   "sphinx",
@@ -53,7 +59,7 @@
     "flaky",
     "ipyparallel",
     "pre-commit",
-    "pytest-asyncio==0.23.4",
+    "pytest-asyncio>=0.23.5",
     "pytest-timeout"
 ]
 cov = [
@@ -209,29 +215,29 @@
 line-length = 100
 
 [tool.ruff.lint]
-select = [
-  "B",           # flake8-bugbear
-  "I",           # isort
-  "ARG",         # flake8-unused-arguments
-  "C4",          # flake8-comprehensions
-  "EM",          # flake8-errmsg
-  "ICN",         # flake8-import-conventions
-  "G",           # flake8-logging-format
-  "PGH",         # pygrep-hooks
-  "PIE",         # flake8-pie
-  "PL",          # pylint
-  "PT",          # flake8-pytest-style
-  "PTH",         # flake8-use-pathlib
-  "RET",         # flake8-return
-  "RUF",         # Ruff-specific
-  "SIM",         # flake8-simplify
-  "T20",         # flake8-print
-  "UP",          # pyupgrade
-  "YTT",         # flake8-2020
-  "EXE",         # flake8-executable
-  "NPY",         # NumPy specific rules
-  "PD",          # pandas-vet
-  "PYI",         # flake8-pyi
+extend-select = [
+  "B",        # flake8-bugbear
+  "I",        # isort
+  "ARG",      # flake8-unused-arguments
+  "C4",       # flake8-comprehensions
+  "EM",       # flake8-errmsg
+  "ICN",      # flake8-import-conventions
+  "G",        # flake8-logging-format
+  "PGH",      # pygrep-hooks
+  "PIE",      # flake8-pie
+  "PL",       # pylint
+  "PT",       # flake8-pytest-style
+  "PTH",      # flake8-use-pathlib
+  "RET",      # flake8-return
+  "RUF",      # Ruff-specific
+  "SIM",      # flake8-simplify
+  "T20",      # flake8-print
+  "UP",       # pyupgrade
+  "YTT",      # flake8-2020
+  "EXE",      # flake8-executable
+  "NPY",      # NumPy specific rules
+  "PD",       # pandas-vet
+  "PYI",      # flake8-pyi
 ]
 ignore = [
   "PLR",    # Design related pylint codes
@@ -265,6 +271,9 @@
   "T201",
   # Don't touch noqa lines
   "RUF100",
+  # Don't touch imports
+  "F401",
+  "F403"
 ]
 
 [tool.ruff.lint.per-file-ignores]
@@ -277,6 +286,7 @@
 # B018 Found useless expression. Either assign it to a variable or remove it.
 # S603 `subprocess` call: check for execution of untrusted input
 "tests/*" = ["B011", "C408", "T201", "B007", "EM", "PTH", "PLW", "PLC1901", 
"B018", "S603", "ARG", "RET", "PGH"]
+"*/__init__.py" = ["F401"]
 
 [tool.interrogate]
 ignore-init-module=true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ipykernel-6.29.2/tests/test_kernelspec.py 
new/ipykernel-6.29.3/tests/test_kernelspec.py
--- old/ipykernel-6.29.2/tests/test_kernelspec.py       2020-02-02 
01:00:00.000000000 +0100
+++ new/ipykernel-6.29.3/tests/test_kernelspec.py       2020-02-02 
01:00:00.000000000 +0100
@@ -3,6 +3,7 @@
 
 import json
 import os
+import platform
 import shutil
 import sys
 import tempfile
@@ -22,6 +23,7 @@
 )
 
 pjoin = os.path.join
+is_cpython = platform.python_implementation() == "CPython"
 
 
 def test_make_ipkernel_cmd():
@@ -144,3 +146,49 @@
             assert spec["env"][k] == v
     else:
         assert "env" not in spec
+
+
+@pytest.mark.skipif(sys.version_info < (3, 11) or not is_cpython, 
reason="requires cPython 3.11")
+def test_install_frozen_modules_on():
+    system_jupyter_dir = tempfile.mkdtemp()
+
+    with mock.patch("jupyter_client.kernelspec.SYSTEM_JUPYTER_PATH", 
[system_jupyter_dir]):
+        install(frozen_modules=True)
+
+    spec_file = os.path.join(system_jupyter_dir, "kernels", KERNEL_NAME, 
"kernel.json")
+    with open(spec_file) as f:
+        spec = json.load(f)
+    assert spec["env"]["PYDEVD_DISABLE_FILE_VALIDATION"] == "1"
+    assert "-Xfrozen_modules=off" not in spec["argv"]
+
+
+@pytest.mark.skipif(sys.version_info < (3, 11) or not is_cpython, 
reason="requires cPython 3.11")
+def test_install_frozen_modules_off():
+    system_jupyter_dir = tempfile.mkdtemp()
+
+    with mock.patch("jupyter_client.kernelspec.SYSTEM_JUPYTER_PATH", 
[system_jupyter_dir]):
+        install(frozen_modules=False)
+
+    spec_file = os.path.join(system_jupyter_dir, "kernels", KERNEL_NAME, 
"kernel.json")
+    with open(spec_file) as f:
+        spec = json.load(f)
+    assert "env" not in spec
+    assert spec["argv"][1] == "-Xfrozen_modules=off"
+
+
+@pytest.mark.skipif(
+    sys.version_info >= (3, 11) or is_cpython,
+    reason="checks versions older than 3.11 and other Python implementations",
+)
+def test_install_frozen_modules_no_op():
+    # ensure we do not add add Xfrozen_modules on older Python versions
+    # (although cPython does not error out on unknown X options as of 3.8)
+    system_jupyter_dir = tempfile.mkdtemp()
+
+    with mock.patch("jupyter_client.kernelspec.SYSTEM_JUPYTER_PATH", 
[system_jupyter_dir]):
+        install(frozen_modules=False)
+
+    spec_file = os.path.join(system_jupyter_dir, "kernels", KERNEL_NAME, 
"kernel.json")
+    with open(spec_file) as f:
+        spec = json.load(f)
+    assert "-Xfrozen_modules=off" not in spec["argv"]

Reply via email to