Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-joblib for openSUSE:Factory 
checked in at 2025-09-11 14:38:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-joblib (Old)
 and      /work/SRC/openSUSE:Factory/.python-joblib.new.1977 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-joblib"

Thu Sep 11 14:38:15 2025 rev:31 rq:1303623 version:1.5.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-joblib/python-joblib.changes      
2025-08-21 16:47:17.943749477 +0200
+++ /work/SRC/openSUSE:Factory/.python-joblib.new.1977/python-joblib.changes    
2025-09-11 14:39:29.712189070 +0200
@@ -1,0 +2,7 @@
+Wed Sep 10 08:42:39 UTC 2025 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 1.5.2
+  * Vendor ``loky3.5.6`` fixing the resource tracker for python 3.13.7+
+    https://github.com/joblib/joblib/pull/1740
+
+-------------------------------------------------------------------

Old:
----
  joblib-1.5.1.tar.gz

New:
----
  joblib-1.5.2.tar.gz

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

Other differences:
------------------
++++++ python-joblib.spec ++++++
--- /var/tmp/diff_new_pack.JENm3O/_old  2025-09-11 14:39:30.424219181 +0200
+++ /var/tmp/diff_new_pack.JENm3O/_new  2025-09-11 14:39:30.424219181 +0200
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-joblib
-Version:        1.5.1
+Version:        1.5.2
 Release:        0
 Summary:        Module for using Python functions as pipeline jobs
 License:        BSD-3-Clause
@@ -102,12 +102,6 @@
                 test_hashes_stay_the_same_with_numpy_objects or \
                 test_non_contiguous_array_pickling"
 fi
-# memmaping tests fail on Python 3.13.7 
https://github.com/joblib/loky/issues/459
-DISABLED_TESTS+=" or test_permission_error_windows_memmap_sent_to_parent or \
-               test_many_parallel_calls_on_same_object or \
-               test_memmapping_pool_for_large_arrays or \
-               test_memmapping_on_large_enough_dev_shm or \
-               test_memmapping_leaks"
 %pytest -k "not ($DISABLED_TESTS)"
 
 %files %{python_files}

++++++ joblib-1.5.1.tar.gz -> joblib-1.5.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/PKG-INFO new/joblib-1.5.2/PKG-INFO
--- old/joblib-1.5.1/PKG-INFO   2025-05-23 14:04:13.378306600 +0200
+++ new/joblib-1.5.2/PKG-INFO   2025-08-27 14:15:21.971439800 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: joblib
-Version: 1.5.1
+Version: 1.5.2
 Summary: Lightweight pipelining with Python functions
 Author-email: Gael Varoquaux <[email protected]>
 License: BSD 3-Clause
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/joblib/__init__.py 
new/joblib-1.5.2/joblib/__init__.py
--- old/joblib-1.5.1/joblib/__init__.py 2025-05-23 14:04:09.000000000 +0200
+++ new/joblib-1.5.2/joblib/__init__.py 2025-08-27 14:15:17.000000000 +0200
@@ -106,7 +106,7 @@
 # Dev branch marker is: 'X.Y.dev' or 'X.Y.devN' where N is an integer.
 # 'X.Y.dev0' is the canonical version of 'X.Y.dev'
 #
-__version__ = "1.5.1"
+__version__ = "1.5.2"
 
 
 import os
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/joblib/_store_backends.py 
new/joblib-1.5.2/joblib/_store_backends.py
--- old/joblib-1.5.1/joblib/_store_backends.py  2025-05-23 14:04:09.000000000 
+0200
+++ new/joblib-1.5.2/joblib/_store_backends.py  2025-08-27 14:15:17.000000000 
+0200
@@ -10,6 +10,7 @@
 import shutil
 import threading
 import time
+import uuid
 import warnings
 from abc import ABCMeta, abstractmethod
 from pickle import PicklingError
@@ -30,8 +31,14 @@
 
 def concurrency_safe_write(object_to_write, filename, write_func):
     """Writes an object into a unique file in a concurrency-safe way."""
+    # Temporary name is composed of UUID, process_id and thread_id to avoid
+    # collisions due to concurrent write.
+    # UUID is unique across nodes and time and help avoid collisions, even if
+    # the cache folder is shared by several Python processes with the same pid 
and
+    # thread id on different nodes of a cluster for instance.
     thread_id = id(threading.current_thread())
-    temporary_filename = "{}.thread-{}-pid-{}".format(filename, thread_id, 
os.getpid())
+    temporary_filename = 
f"{filename}.{uuid.uuid4().hex}-{os.getpid()}-{thread_id}"
+
     write_func(object_to_write, temporary_filename)
 
     return temporary_filename
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/joblib/externals/loky/__init__.py 
new/joblib-1.5.2/joblib/externals/loky/__init__.py
--- old/joblib-1.5.1/joblib/externals/loky/__init__.py  2025-05-23 
14:04:09.000000000 +0200
+++ new/joblib-1.5.2/joblib/externals/loky/__init__.py  2025-08-27 
14:15:17.000000000 +0200
@@ -42,4 +42,4 @@
 ]
 
 
-__version__ = "3.5.5"
+__version__ = "3.5.6"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/joblib-1.5.1/joblib/externals/loky/backend/resource_tracker.py 
new/joblib-1.5.2/joblib/externals/loky/backend/resource_tracker.py
--- old/joblib-1.5.1/joblib/externals/loky/backend/resource_tracker.py  
2025-05-23 14:04:09.000000000 +0200
+++ new/joblib-1.5.2/joblib/externals/loky/backend/resource_tracker.py  
2025-08-27 14:15:17.000000000 +0200
@@ -43,7 +43,6 @@
 import sys
 import signal
 import warnings
-from _multiprocessing import sem_unlink
 from multiprocessing import util
 from multiprocessing.resource_tracker import (
     ResourceTracker as _ResourceTracker,
@@ -62,10 +61,31 @@
 _HAVE_SIGMASK = hasattr(signal, "pthread_sigmask")
 _IGNORED_SIGNALS = (signal.SIGINT, signal.SIGTERM)
 
-_CLEANUP_FUNCS = {"folder": shutil.rmtree, "file": os.unlink}
+
+def cleanup_noop(name):
+    raise RuntimeError("noop should never be registered or cleaned up")
+
+
+_CLEANUP_FUNCS = {
+    "noop": cleanup_noop,
+    "folder": shutil.rmtree,
+    "file": os.unlink,
+}
 
 if os.name == "posix":
-    _CLEANUP_FUNCS["semlock"] = sem_unlink
+    import _multiprocessing
+
+    # Use sem_unlink() to clean up named semaphores.
+    #
+    # sem_unlink() may be missing if the Python build process detected the
+    # absence of POSIX named semaphores. In that case, no named semaphores were
+    # ever opened, so no cleanup would be necessary.
+    if hasattr(_multiprocessing, "sem_unlink"):
+        _CLEANUP_FUNCS.update(
+            {
+                "semlock": _multiprocessing.sem_unlink,
+            }
+        )
 
 
 VERBOSE = False
@@ -88,92 +108,135 @@
 
     def maybe_unlink(self, name, rtype):
         """Decrement the refcount of a resource, and delete it if it hits 0"""
-        self.ensure_running()
         self._send("MAYBE_UNLINK", name, rtype)
 
     def ensure_running(self):
         """Make sure that resource tracker process is running.
 
         This can be run from any process.  Usually a child process will use
-        the resource created by its parent."""
-        with self._lock:
-            if self._fd is not None:
-                # resource tracker was launched before, is it still running?
-                if self._check_alive():
-                    # => still alive
-                    return
-                # => dead, launch it again
-                os.close(self._fd)
-                if os.name == "posix":
-                    try:
-                        # At this point, the resource_tracker process has been
-                        # killed or crashed. Let's remove the process entry
-                        # from the process table to avoid zombie processes.
-                        os.waitpid(self._pid, 0)
-                    except OSError:
-                        # The process was terminated or is a child from an
-                        # ancestor of the current process.
-                        pass
-                self._fd = None
-                self._pid = None
+        the resource created by its parent.
 
-                warnings.warn(
-                    "resource_tracker: process died unexpectedly, "
-                    "relaunching.  Some folders/sempahores might "
-                    "leak."
-                )
-
-            fds_to_pass = []
+        This function is necessary for backward compatibility with python
+        versions before 3.13.7.
+        """
+        return self._ensure_running_and_write()
+
+    def _teardown_dead_process(self):
+        # Override this function for compatibility with windows and
+        # for python version before 3.13.7
+
+        # At this point, the resource_tracker process has been killed
+        # or crashed.
+        os.close(self._fd)
+
+        # Let's remove the process entry from the process table on POSIX system
+        # to avoid zombie processes.
+        if os.name == "posix":
             try:
-                fds_to_pass.append(sys.stderr.fileno())
-            except Exception:
+                # _pid can be None if this process is a child from another
+                # python process, which has started the resource_tracker.
+                if self._pid is not None:
+                    os.waitpid(self._pid, 0)
+            except OSError:
+                # The resource_tracker has already been terminated.
                 pass
+        self._fd = None
+        self._pid = None
+
+        warnings.warn(
+            "resource_tracker: process died unexpectedly, relaunching. "
+            "Some folders/semaphores might leak."
+        )
+
+    def _launch(self):
+        # This is the overridden part of the resource tracker, which launches
+        # loky's version, which is compatible with windows and allow to track
+        # folders with external ref counting.
+
+        fds_to_pass = []
+        try:
+            fds_to_pass.append(sys.stderr.fileno())
+        except Exception:
+            pass
+
+        # Create a pipe for posix and windows
+        r, w = os.pipe()
+        if sys.platform == "win32":
+            _r = duplicate(msvcrt.get_osfhandle(r), inheritable=True)
+            os.close(r)
+            r = _r
 
-            r, w = os.pipe()
+        cmd = f"from {main.__module__} import main; main({r}, {VERBOSE})"
+        try:
+            fds_to_pass.append(r)
+            # process will out live us, so no need to wait on pid
+            exe = spawn.get_executable()
+            args = [exe, *util._args_from_interpreter_flags(), "-c", cmd]
+            util.debug(f"launching resource tracker: {args}")
+            # bpo-33613: Register a signal mask that will block the
+            # signals.  This signal mask will be inherited by the child
+            # that is going to be spawned and will protect the child from a
+            # race condition that can make the child die before it
+            # registers signal handlers for SIGINT and SIGTERM. The mask is
+            # unregistered after spawning the child.
+            try:
+                if _HAVE_SIGMASK:
+                    signal.pthread_sigmask(signal.SIG_BLOCK, _IGNORED_SIGNALS)
+                pid = spawnv_passfds(exe, args, fds_to_pass)
+            finally:
+                if _HAVE_SIGMASK:
+                    signal.pthread_sigmask(
+                        signal.SIG_UNBLOCK, _IGNORED_SIGNALS
+                    )
+        except BaseException:
+            os.close(w)
+            raise
+        else:
+            self._fd = w
+            self._pid = pid
+        finally:
             if sys.platform == "win32":
-                _r = duplicate(msvcrt.get_osfhandle(r), inheritable=True)
+                _winapi.CloseHandle(r)
+            else:
                 os.close(r)
-                r = _r
 
-            cmd = f"from {main.__module__} import main; main({r}, {VERBOSE})"
-            try:
-                fds_to_pass.append(r)
-                # process will out live us, so no need to wait on pid
-                exe = spawn.get_executable()
-                args = [exe, *util._args_from_interpreter_flags(), "-c", cmd]
-                util.debug(f"launching resource tracker: {args}")
-                # bpo-33613: Register a signal mask that will block the
-                # signals.  This signal mask will be inherited by the child
-                # that is going to be spawned and will protect the child from a
-                # race condition that can make the child die before it
-                # registers signal handlers for SIGINT and SIGTERM. The mask is
-                # unregistered after spawning the child.
+    def _ensure_running_and_write(self, msg=None):
+        """Make sure that resource tracker process is running.
+
+        This can be run from any process.  Usually a child process will use
+        the resource created by its parent.
+
+
+        This function is added for compatibility with python version before 
3.13.7.
+        """
+        with self._lock:
+            if (
+                self._fd is not None
+            ):  # resource tracker was launched before, is it still running?
+                if msg is None:
+                    to_send = b"PROBE:0:noop\n"
+                else:
+                    to_send = msg
                 try:
-                    if _HAVE_SIGMASK:
-                        signal.pthread_sigmask(
-                            signal.SIG_BLOCK, _IGNORED_SIGNALS
-                        )
-                    pid = spawnv_passfds(exe, args, fds_to_pass)
-                finally:
-                    if _HAVE_SIGMASK:
-                        signal.pthread_sigmask(
-                            signal.SIG_UNBLOCK, _IGNORED_SIGNALS
-                        )
-            except BaseException:
-                os.close(w)
-                raise
+                    self._write(to_send)
+                except OSError:
+                    self._teardown_dead_process()
+                    self._launch()
+
+                msg = None  # message was sent in probe
             else:
-                self._fd = w
-                self._pid = pid
-            finally:
-                if sys.platform == "win32":
-                    _winapi.CloseHandle(r)
-                else:
-                    os.close(r)
+                self._launch()
+
+        if msg is not None:
+            self._write(msg)
+
+    def _write(self, msg):
+        nbytes = os.write(self._fd, msg)
+        assert nbytes == len(msg), f"{nbytes=} != {len(msg)=}"
 
     def __del__(self):
         # ignore error due to trying to clean up child process which has 
already been
-        # shutdown on windows See https://github.com/joblib/loky/pull/450
+        # shutdown on windows. See https://github.com/joblib/loky/pull/450
         # This is only required if __del__ is defined
         if not hasattr(_ResourceTracker, "__del__"):
             return
@@ -193,10 +256,10 @@
 
 def main(fd, verbose=0):
     """Run resource tracker."""
-    # protect the process from ^C and "killall python" etc
     if verbose:
         util.log_to_stderr(level=util.DEBUG)
 
+    # protect the process from ^C and "killall python" etc
     signal.signal(signal.SIGINT, signal.SIG_IGN)
     signal.signal(signal.SIGTERM, signal.SIG_IGN)
 
@@ -213,15 +276,13 @@
         util.debug("Main resource tracker is running")
 
     registry = {rtype: {} for rtype in _CLEANUP_FUNCS.keys()}
+
     try:
-        # keep track of registered/unregistered resources
         if sys.platform == "win32":
             fd = msvcrt.open_osfhandle(fd, os.O_RDONLY)
+        # keep track of registered/unregistered resources
         with open(fd, "rb") as f:
-            while True:
-                line = f.readline()
-                if line == b"":  # EOF
-                    break
+            for line in f:
                 try:
                     splitted = line.strip().decode("ascii").split(":")
                     # name can potentially contain separator symbols (for
@@ -232,9 +293,6 @@
                         splitted[-1],
                     )
 
-                    if cmd == "PROBE":
-                        continue
-
                     if rtype not in _CLEANUP_FUNCS:
                         raise ValueError(
                             f"Cannot register {name} for automatic cleanup: "
@@ -243,7 +301,9 @@
                             f"{list(_CLEANUP_FUNCS.keys())}"
                         )
 
-                    if cmd == "REGISTER":
+                    if cmd == "PROBE":
+                        pass
+                    elif cmd == "REGISTER":
                         if name not in registry[rtype]:
                             registry[rtype][name] = 1
                         else:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/joblib/memory.py 
new/joblib-1.5.2/joblib/memory.py
--- old/joblib-1.5.1/joblib/memory.py   2025-05-23 14:04:09.000000000 +0200
+++ new/joblib-1.5.2/joblib/memory.py   2025-08-27 14:15:17.000000000 +0200
@@ -1101,7 +1101,7 @@
         if self.store_backend is None:
             cls = (
                 AsyncNotMemorizedFunc
-                if asyncio.iscoroutinefunction(func)
+                if inspect.iscoroutinefunction(func)
                 else NotMemorizedFunc
             )
             return cls(func)
@@ -1111,7 +1111,7 @@
             mmap_mode = self.mmap_mode
         if isinstance(func, MemorizedFunc):
             func = func.func
-        cls = AsyncMemorizedFunc if asyncio.iscoroutinefunction(func) else 
MemorizedFunc
+        cls = AsyncMemorizedFunc if inspect.iscoroutinefunction(func) else 
MemorizedFunc
         return cls(
             func,
             location=self.store_backend,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/joblib-1.5.1/joblib.egg-info/PKG-INFO 
new/joblib-1.5.2/joblib.egg-info/PKG-INFO
--- old/joblib-1.5.1/joblib.egg-info/PKG-INFO   2025-05-23 14:04:13.000000000 
+0200
+++ new/joblib-1.5.2/joblib.egg-info/PKG-INFO   2025-08-27 14:15:21.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: joblib
-Version: 1.5.1
+Version: 1.5.2
 Summary: Lightweight pipelining with Python functions
 Author-email: Gael Varoquaux <[email protected]>
 License: BSD 3-Clause

Reply via email to