Package: src:joblib
Version: 1.5.3-2
User: [email protected]
Usertags: python3.15
Tags: patch, ftbfs, forky, sid
Hi!
While rebuilding the python related packages against the Python 3.15rc1
version we found that joblib fails to build from source [1].
In order to fix the issue, I had to:
- Run the tests in autopkg tests with the conftest file (Fixes #1140861)
- Backport loky's _decode_message function to support Python 3.14+
(Fixes #1141207).
- Change the condition for using multiprocessing in the random parallel
example (needs to be forwarded upstream).
I applied these fixes in the sandbox [2] to be able to build the
packages that depend on joblib, please consider applying the patch to
support the upcoming 3.15 version.
Happy hacking,
[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4496152/
[2]: https://debusine.debian.net/debian/r-python-python3.15/
--
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
diff -Nru joblib-1.5.3/debian/changelog joblib-1.5.3/debian/changelog
--- joblib-1.5.3/debian/changelog 2026-06-24 18:31:44.000000000 +0200
+++ joblib-1.5.3/debian/changelog 2026-09-02 16:13:04.000000000 +0200
@@ -1,3 +1,11 @@
+joblib (1.5.3-2.1) UNRELEASED; urgency=medium
+
+ * Non-maintainer upload.
+ * Add patch: forkserver-examples, to avoid hanging forkservers in the tests
+ * Backport loky's _decode_message
+
+ -- Maximiliano Curia <[email protected]> Wed, 02 Sep 2026 16:13:04 +0200
+
joblib (1.5.3-2) unstable; urgency=medium
* Team upload.
diff -Nru joblib-1.5.3/debian/patches/forkserver-examples
joblib-1.5.3/debian/patches/forkserver-examples
--- joblib-1.5.3/debian/patches/forkserver-examples 1970-01-01
01:00:00.000000000 +0100
+++ joblib-1.5.3/debian/patches/forkserver-examples 2026-09-02
16:13:04.000000000 +0200
@@ -0,0 +1,48 @@
+Description: Only use multiprocessing backend in examples when start method is
fork
+ In Python 3.14+, multiprocessing defaults to the forkserver start method on
+ POSIX. When using the multiprocessing backend on top-level functions without
+ the fork start method, worker processes cannot deserialize the functions.
+Index: joblib/examples/parallel_random_state.py
+===================================================================
+--- joblib.orig/examples/parallel_random_state.py
++++ joblib/examples/parallel_random_state.py
+@@ -87,7 +87,7 @@ print_vector(random_vector, backend)
+
+ import multiprocessing as mp
+
+-if mp.get_start_method() != "spawn":
++if mp.get_start_method() == "fork":
+ backend = "multiprocessing"
+ random_vector = Parallel(n_jobs=2, backend=backend)(
+ delayed(stochastic_function)(10) for _ in range(n_vectors)
+@@ -115,7 +115,7 @@ def stochastic_function_seeded(max_value
+ # reset this seed by passing ``None`` at every function call. In this case, we
+ # see that the generated vectors are all different.
+
+-if mp.get_start_method() != "spawn":
++if mp.get_start_method() == "fork":
+ random_vector = Parallel(n_jobs=2, backend=backend)(
+ delayed(stochastic_function_seeded)(10, None) for _ in
range(n_vectors)
+ )
+@@ -133,7 +133,7 @@ if mp.get_start_method() != "spawn":
+ #
+ # .. [1] https://numpy.org/doc/stable/reference/random/parallel.html
+
+-if mp.get_start_method() != "spawn":
++if mp.get_start_method() == "fork":
+ seed = 42
+ random_vector = Parallel(n_jobs=2, backend=backend)(
+ delayed(stochastic_function_seeded)(10, [i, seed]) for i in
range(n_vectors)
+Index: joblib/examples/serialization_and_wrappers.py
+===================================================================
+--- joblib.orig/examples/serialization_and_wrappers.py
++++ joblib/examples/serialization_and_wrappers.py
+@@ -68,7 +68,7 @@ print(
+
+ import multiprocessing as mp
+
+-if mp.get_start_method() != "spawn":
++if mp.get_start_method() == "fork":
+
+ def func_async(i, *args):
+ return 2 * i
diff -Nru joblib-1.5.3/debian/patches/py315-resource-tracker
joblib-1.5.3/debian/patches/py315-resource-tracker
--- joblib-1.5.3/debian/patches/py315-resource-tracker 1970-01-01
01:00:00.000000000 +0100
+++ joblib-1.5.3/debian/patches/py315-resource-tracker 2026-09-02
16:13:04.000000000 +0200
@@ -0,0 +1,61 @@
+Description: Backport loky's _decode_message to support python 3.15
+Index: joblib/joblib/externals/loky/backend/resource_tracker.py
+===================================================================
+--- joblib.orig/joblib/externals/loky/backend/resource_tracker.py
++++ joblib/joblib/externals/loky/backend/resource_tracker.py
+@@ -38,6 +38,8 @@
+ # resources once all processes connected to the resource tracker have exited.
+
+
++import base64
++import json
+ import os
+ import shutil
+ import sys
+@@ -254,6 +256,30 @@ unregister = _resource_tracker.unregiste
+ getfd = _resource_tracker.getfd
+
+
++def _decode_message(line):
++ if line.startswith(b'{'):
++ try:
++ obj = json.loads(line.decode('ascii'))
++ except Exception as e:
++ raise ValueError("malformed resource_tracker message: %r" %
(line,)) from e
++
++ cmd = obj["cmd"]
++ rtype = obj["rtype"]
++ b64 = obj.get("base64_name", "")
++
++ if not isinstance(cmd, str) or not isinstance(rtype, str) or not
isinstance(b64, str):
++ raise ValueError("malformed resource_tracker fields: %r" % (obj,))
++
++ try:
++ name = base64.urlsafe_b64decode(b64).decode('utf-8',
'surrogateescape')
++ except ValueError as e:
++ raise ValueError("malformed resource_tracker base64_name: %r" %
(b64,)) from e
++ else:
++ cmd, rest = line.strip().decode('ascii').split(':', maxsplit=1)
++ name, rtype = rest.rsplit(':', maxsplit=1)
++ return cmd, rtype, name
++
++
+ def main(fd, verbose=0):
+ """Run resource tracker."""
+ if verbose:
+@@ -284,14 +310,7 @@ def main(fd, verbose=0):
+ with open(fd, "rb") as f:
+ for line in f:
+ try:
+- splitted = line.strip().decode("ascii").split(":")
+- # name can potentially contain separator symbols (for
+- # instance folders on Windows)
+- cmd, name, rtype = (
+- splitted[0],
+- ":".join(splitted[1:-1]),
+- splitted[-1],
+- )
++ cmd, name, rtype = _decode_message(line)
+
+ if rtype not in _CLEANUP_FUNCS:
+ raise ValueError(
diff -Nru joblib-1.5.3/debian/patches/series joblib-1.5.3/debian/patches/series
--- joblib-1.5.3/debian/patches/series 2026-06-24 16:57:28.000000000 +0200
+++ joblib-1.5.3/debian/patches/series 2026-09-02 16:13:04.000000000 +0200
@@ -4,3 +4,5 @@
intersphinx-inventory
deb_test_memory
privacy
+forkserver-examples
+py315-resource-tracker
diff -Nru joblib-1.5.3/debian/tests/pytest joblib-1.5.3/debian/tests/pytest
--- joblib-1.5.3/debian/tests/pytest 2026-06-24 16:57:28.000000000 +0200
+++ joblib-1.5.3/debian/tests/pytest 2026-09-02 16:13:04.000000000 +0200
@@ -19,5 +19,5 @@
for py in $(py3versions -s); do
echo "Testing with $py:"
- $py -m pytest -v -k "${TEST_KEYWORDS}" --pyargs joblib
+ $py -m pytest -v -k "${TEST_KEYWORDS}" -p conftest --pyargs joblib
done
--
debian-science-maintainers mailing list
[email protected]
https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/debian-science-maintainers