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 2023-07-04 15:22:03 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ipykernel (Old) and /work/SRC/openSUSE:Factory/.python-ipykernel.new.23466 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ipykernel" Tue Jul 4 15:22:03 2023 rev:38 rq:1096638 version:6.23.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ipykernel/python-ipykernel.changes 2023-06-04 00:12:42.273570604 +0200 +++ /work/SRC/openSUSE:Factory/.python-ipykernel.new.23466/python-ipykernel.changes 2023-07-04 15:22:32.542264197 +0200 @@ -1,0 +2,18 @@ +Sun Jul 2 06:34:01 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Fix test suite hangs +- Don't assume only Tumbleweed can have more than one flavor + +------------------------------------------------------------------- +Sat Jul 1 16:27:15 UTC 2023 - Ben Greiner <c...@bnavigator.de> + +- Update to 6.23.3 + * Check existence of connection_file before writing #1127 + (@fecet) +- Release 6.23.2 + * Avoid ResourceWarning on implicitly closed event pipe sockets + #1125 (@minrk) + * fix: protect stdout/stderr restoration in + InProcessKernel._redirected_io #1122 (@charles-cooper) + +------------------------------------------------------------------- Old: ---- ipykernel-6.23.1.tar.gz New: ---- ipykernel-6.23.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ipykernel.spec ++++++ --- /var/tmp/diff_new_pack.Sz6K4l/_old 2023-07-04 15:22:33.298268741 +0200 +++ /var/tmp/diff_new_pack.Sz6K4l/_new 2023-07-04 15:22:33.302268765 +0200 @@ -16,15 +16,15 @@ # +%{?sle15_python_module_pythons} Name: python-ipykernel -Version: 6.23.1 +Version: 6.23.3 Release: 0 Summary: IPython Kernel for Jupyter License: BSD-3-Clause Group: Development/Languages/Python URL: https://github.com/ipython/ipykernel Source: https://files.pythonhosted.org/packages/source/i/ipykernel/ipykernel-%{version}.tar.gz -Requires: jupyter-jupyter-client >= 6.1.12 Provides: python-jupyter_ipykernel = %{version} Obsoletes: python-jupyter_ipykernel < %{version} Provides: %{python_module ipykernel-doc = %{version}} @@ -55,6 +55,7 @@ BuildRequires: %{python_module tornado >= 6.1} BuildRequires: %{python_module traitlets >= 5.1.0} BuildRequires: %{python_module jupyter-core >= 5.1 or (%python-jupyter-core >= 4.12 with %python-jupyter-core < 5.0)} +Requires: jupyter-jupyter-client >= 6.1.12 Requires: python-comm >= 0.1.1 Requires: python-debugpy >= 1.6.5 Requires: python-ipython >= 7.23.1 @@ -96,7 +97,6 @@ %install %pyproject_install -%if 0%{?suse_version} >= 1550 # use the symlink for the default python3 flavor, which was installed during the install but used python3.X name # from the primary flavor. sed -i "s|$(readlink -f python3)|python3|" %{buildroot}%{_jupyter_kernel_dir}/python3/kernel.json @@ -107,15 +107,14 @@ --name python%{$python_bin_suffix} \ --display-name 'Python %{$python_bin_suffix} (ipykernel)' } -%endif %python_expand %fdupes %{buildroot}%{$python_sitelib} %fdupes %{buildroot}%{_jupyter_kernel_dir} %check -# flaky: bad timings in obs often cause this to fail -donttest="test_shutdown_subprocesses" # fails in obs setups ignoretests="--ignore ipykernel/tests/test_debugger.py" +# flaky obs timeouts +donttest="test_init_ipc_socket" # we don't want ipyparallel and its dependencies in Ring1 ignoretests="$ignoretests --ignore ipykernel/tests/test_pickleutil.py" donttest="$donttest or test_do_apply" @@ -128,9 +127,7 @@ %{python_sitelib}/ipykernel_launcher.py %{python_sitelib}/ipykernel-%{version}*-info %pycache_only %{python_sitelib}/__pycache__/ipykernel_launcher*.pyc -%if 0%{?suse_version} >= 1550 %{_jupyter_kernel_dir}/python%{python_bin_suffix} -%endif %if "%{python_flavor}" == "python3" || "%{python_provides}" == "python3" %{_jupyter_kernel_dir}/python3 %endif ++++++ ipykernel-6.23.1.tar.gz -> ipykernel-6.23.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/.pre-commit-config.yaml new/ipykernel-6.23.3/.pre-commit-config.yaml --- old/ipykernel-6.23.1/.pre-commit-config.yaml 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/.pre-commit-config.yaml 2020-02-02 01:00:00.000000000 +0100 @@ -21,7 +21,7 @@ - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.22.0 + rev: 0.23.1 hooks: - id: check-github-workflows @@ -36,7 +36,7 @@ - id: black - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.263 + rev: v0.0.270 hooks: - id: ruff args: ["--fix"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/CHANGELOG.md new/ipykernel-6.23.3/CHANGELOG.md --- old/ipykernel-6.23.1/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/CHANGELOG.md 2020-02-02 01:00:00.000000000 +0100 @@ -2,6 +2,39 @@ <!-- <START NEW CHANGELOG ENTRY> --> +## 6.23.3 + +([Full Changelog](https://github.com/ipython/ipykernel/compare/v6.23.2...ea3e6479aca70f87282ec0b60412f2cfba59eb35)) + +### Bugs fixed + +- Check existence of connection_file before writing [#1127](https://github.com/ipython/ipykernel/pull/1127) ([@fecet](https://github.com/fecet)) + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/ipython/ipykernel/graphs/contributors?from=2023-06-12&to=2023-06-23&type=c)) + +[@blink1073](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Ablink1073+updated%3A2023-06-12..2023-06-23&type=Issues) | [@fecet](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Afecet+updated%3A2023-06-12..2023-06-23&type=Issues) + +<!-- <END NEW CHANGELOG ENTRY> --> + +## 6.23.2 + +([Full Changelog](https://github.com/ipython/ipykernel/compare/v6.23.1...112ca66da0ee8156b983094b2c8e2926ed63cfcb)) + +### Bugs fixed + +- Avoid ResourceWarning on implicitly closed event pipe sockets [#1125](https://github.com/ipython/ipykernel/pull/1125) ([@minrk](https://github.com/minrk)) +- fix: protect stdout/stderr restoration in `InProcessKernel._redirected_io` [#1122](https://github.com/ipython/ipykernel/pull/1122) ([@charles-cooper](https://github.com/charles-cooper)) + +### Maintenance and upkeep improvements + +### Contributors to this release + +([GitHub contributors page for this release](https://github.com/ipython/ipykernel/graphs/contributors?from=2023-05-15&to=2023-06-12&type=c)) + +[@charles-cooper](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Acharles-cooper+updated%3A2023-05-15..2023-06-12&type=Issues) | [@minrk](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aminrk+updated%3A2023-05-15..2023-06-12&type=Issues) | [@pre-commit-ci](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Apre-commit-ci+updated%3A2023-05-15..2023-06-12&type=Issues) + ## 6.23.1 ([Full Changelog](https://github.com/ipython/ipykernel/compare/v6.23.0...d63c33afb9872f2781997b2428d7e9e0c1d23d41)) @@ -20,8 +53,6 @@ [@minrk](https://github.com/search?q=repo%3Aipython%2Fipykernel+involves%3Aminrk+updated%3A2023-05-08..2023-05-15&type=Issues) -<!-- <END NEW CHANGELOG ENTRY> --> - ## 6.23.0 ([Full Changelog](https://github.com/ipython/ipykernel/compare/v6.22.0...3dd6dc9712ff6eb0a53cf79969dcefa0ba1b086e)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/PKG-INFO new/ipykernel-6.23.3/PKG-INFO --- old/ipykernel-6.23.1/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/PKG-INFO 2020-02-02 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: ipykernel -Version: 6.23.1 +Version: 6.23.3 Summary: IPython Kernel for Jupyter Project-URL: Homepage, https://ipython.org Author-email: IPython Development Team <ipython-...@scipy.org> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/_version.py new/ipykernel-6.23.3/ipykernel/_version.py --- old/ipykernel-6.23.1/ipykernel/_version.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.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.23.1" +__version__ = "6.23.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.23.1/ipykernel/eventloops.py new/ipykernel-6.23.3/ipykernel/eventloops.py --- old/ipykernel-6.23.1/ipykernel/eventloops.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/eventloops.py 2020-02-02 01:00:00.000000000 +0100 @@ -419,10 +419,9 @@ loop = asyncio.get_event_loop() - @asyncio.coroutine - def close_loop(): + async def close_loop(): if hasattr(loop, "shutdown_asyncgens"): - yield from loop.shutdown_asyncgens() + yield loop.shutdown_asyncgens() loop._should_close = True # type:ignore[attr-defined] loop.stop() @@ -430,7 +429,7 @@ close_loop() elif not loop.is_closed(): - loop.run_until_complete(close_loop) # type:ignore[call-overload] + loop.run_until_complete(close_loop) # type:ignore loop.close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/inprocess/ipkernel.py new/ipykernel-6.23.3/ipykernel/inprocess/ipkernel.py --- old/ipykernel-6.23.1/ipykernel/inprocess/ipkernel.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/inprocess/ipkernel.py 2020-02-02 01:00:00.000000000 +0100 @@ -121,9 +121,11 @@ def _redirected_io(self): """Temporarily redirect IO to the kernel.""" sys_stdout, sys_stderr = sys.stdout, sys.stderr - sys.stdout, sys.stderr = self.stdout, self.stderr - yield - sys.stdout, sys.stderr = sys_stdout, sys_stderr + try: + sys.stdout, sys.stderr = self.stdout, self.stderr + yield + finally: + sys.stdout, sys.stderr = sys_stdout, sys_stderr # ------ Trait change handlers -------------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/inprocess/tests/test_kernelmanager.py new/ipykernel-6.23.3/ipykernel/inprocess/tests/test_kernelmanager.py --- old/ipykernel-6.23.1/ipykernel/inprocess/tests/test_kernelmanager.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/inprocess/tests/test_kernelmanager.py 2020-02-02 01:00:00.000000000 +0100 @@ -3,6 +3,8 @@ import unittest +from flaky import flaky + from ipykernel.inprocess.manager import InProcessKernelManager # ----------------------------------------------------------------------------- @@ -18,6 +20,7 @@ if self.km.has_kernel: self.km.shutdown_kernel() + @flaky def test_interface(self): """Does the in-process kernel manager implement the basic KM interface?""" km = self.km diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/iostream.py new/ipykernel-6.23.3/ipykernel/iostream.py --- old/ipykernel-6.23.1/ipykernel/iostream.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/iostream.py 2020-02-02 01:00:00.000000000 +0100 @@ -3,6 +3,7 @@ # Copyright (c) IPython Development Team. # Distributed under the terms of the Modified BSD License. +import asyncio import atexit import io import os @@ -14,8 +15,7 @@ from collections import deque from io import StringIO, TextIOBase from threading import local -from typing import Any, Callable, Deque, Optional -from weakref import WeakSet +from typing import Any, Callable, Deque, Dict, Optional import zmq from jupyter_client.session import extract_header @@ -63,7 +63,10 @@ self._setup_pipe_in() self._local = threading.local() self._events: Deque[Callable[..., Any]] = deque() - self._event_pipes: WeakSet[Any] = WeakSet() + self._event_pipes: Dict[threading.Thread, Any] = {} + self._event_pipe_gc_lock: threading.Lock = threading.Lock() + self._event_pipe_gc_seconds: float = 10 + self._event_pipe_gc_task: Optional[asyncio.Task] = None self._setup_event_pipe() self.thread = threading.Thread(target=self._thread_main, name="IOPub") self.thread.daemon = True @@ -73,7 +76,18 @@ def _thread_main(self): """The inner loop that's actually run in a thread""" + + def _start_event_gc(): + self._event_pipe_gc_task = asyncio.ensure_future(self._run_event_pipe_gc()) + + self.io_loop.run_sync(_start_event_gc) self.io_loop.start() + if self._event_pipe_gc_task is not None: + # cancel gc task to avoid pending task warnings + async def _cancel(): + self._event_pipe_gc_task.cancel() # type:ignore + + self.io_loop.run_sync(_cancel) self.io_loop.close(all_fds=True) def _setup_event_pipe(self): @@ -88,6 +102,26 @@ self._event_puller = ZMQStream(pipe_in, self.io_loop) self._event_puller.on_recv(self._handle_event) + async def _run_event_pipe_gc(self): + """Task to run event pipe gc continuously""" + while True: + await asyncio.sleep(self._event_pipe_gc_seconds) + try: + await self._event_pipe_gc() + except Exception as e: + print(f"Exception in IOPubThread._event_pipe_gc: {e}", file=sys.__stderr__) + + async def _event_pipe_gc(self): + """run a single garbage collection on event pipes""" + if not self._event_pipes: + # don't acquire the lock if there's nothing to do + return + with self._event_pipe_gc_lock: + for thread, socket in list(self._event_pipes.items()): + if not thread.is_alive(): + socket.close() + del self._event_pipes[thread] + @property def _event_pipe(self): """thread-local event pipe for signaling events that should be processed in the thread""" @@ -100,9 +134,11 @@ event_pipe.linger = 0 event_pipe.connect(self._event_interface) self._local.event_pipe = event_pipe - # WeakSet so that event pipes will be closed by garbage collection - # when their threads are terminated - self._event_pipes.add(event_pipe) + # associate event pipes to their threads + # so they can be closed explicitly + # implicit close on __del__ throws a ResourceWarning + with self._event_pipe_gc_lock: + self._event_pipes[threading.current_thread()] = event_pipe return event_pipe def _handle_event(self, msg): @@ -188,7 +224,7 @@ # close *all* event pipes, created in any thread # event pipes can only be used from other threads while self.thread.is_alive() # so after thread.join, this should be safe - for event_pipe in self._event_pipes: + for _thread, event_pipe in self._event_pipes.items(): event_pipe.close() def close(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/kernelapp.py new/ipykernel-6.23.3/ipykernel/kernelapp.py --- old/ipykernel-6.23.1/ipykernel/kernelapp.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/kernelapp.py 2020-02-02 01:00:00.000000000 +0100 @@ -260,6 +260,9 @@ def write_connection_file(self): """write connection info to JSON file""" cf = self.abs_connection_file + if os.path.exists(cf): + self.log.debug("Connection file %s already exists", cf) + return self.log.debug("Writing connection file: %s", cf) write_connection_file( cf, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/tests/test_debugger.py new/ipykernel-6.23.3/ipykernel/tests/test_debugger.py --- old/ipykernel-6.23.1/ipykernel/tests/test_debugger.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/tests/test_debugger.py 2020-02-02 01:00:00.000000000 +0100 @@ -121,7 +121,7 @@ assert reply["body"]["breakpoints"][0]["source"]["path"] == source r = wait_for_debug_request(kernel_with_debug, "debugInfo") - assert source in map(lambda b: b["source"], r["body"]["breakpoints"]) # type:ignore # noqa + assert source in map(lambda b: b["source"], r["body"]["breakpoints"]) # noqa r = wait_for_debug_request(kernel_with_debug, "configurationDone") assert r["success"] @@ -208,7 +208,7 @@ get_reply(kernel_with_debug, msg_id) r = wait_for_debug_request(kernel_with_debug, "inspectVariables") - assert var_name in list(map(lambda v: v["name"], r["body"]["variables"])) # type:ignore # noqa + assert var_name in list(map(lambda v: v["name"], r["body"]["variables"])) # noqa reply = wait_for_debug_request( kernel_with_debug, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/ipykernel/tests/test_io.py new/ipykernel-6.23.3/ipykernel/tests/test_io.py --- old/ipykernel-6.23.1/ipykernel/tests/test_io.py 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/ipykernel/tests/test_io.py 2020-02-02 01:00:00.000000000 +0100 @@ -4,8 +4,10 @@ import os import subprocess import sys +import threading import time import warnings +from concurrent.futures import Future, ThreadPoolExecutor from unittest import mock import pytest @@ -114,6 +116,39 @@ assert stream.writable() +async def test_event_pipe_gc(iopub_thread): + session = Session(key=b'abc') + stream = OutStream( + session, + iopub_thread, + "stdout", + isatty=True, + watchfd=False, + ) + save_stdout = sys.stdout + assert iopub_thread._event_pipes == {} + with stream, mock.patch.object(sys, "stdout", stream), ThreadPoolExecutor(1) as pool: + pool.submit(print, "x").result() + pool_thread = pool.submit(threading.current_thread).result() + assert list(iopub_thread._event_pipes) == [pool_thread] + + # run gc once in the iopub thread + f: Future = Future() + + async def run_gc(): + try: + await iopub_thread._event_pipe_gc() + except Exception as e: + f.set_exception(e) + else: + f.set_result(None) + + iopub_thread.io_loop.add_callback(run_gc) + # wait for call to finish in iopub thread + f.result() + assert iopub_thread._event_pipes == {} + + def subprocess_test_echo_watch(): # handshake Pub subscription session = Session(key=b'abc') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipykernel-6.23.1/pyproject.toml new/ipykernel-6.23.3/pyproject.toml --- old/ipykernel-6.23.1/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 +++ new/ipykernel-6.23.3/pyproject.toml 2020-02-02 01:00:00.000000000 +0100 @@ -117,7 +117,7 @@ test = "mypy --install-types --non-interactive {args:.}" [tool.hatch.envs.lint] -dependencies = ["black==23.3.0", "mdformat>0.7", "ruff==0.0.263"] +dependencies = ["black==23.3.0", "mdformat>0.7", "ruff==0.0.270"] detached = true [tool.hatch.envs.lint.scripts] style = [