Package: src:ros2-colcon-core
Version: 0.20.1-1
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 ros2-colcon-core fails to build from source [1].
To fix the errors, I had to apply the following upstream patches:
- upstream commit dbc75ee [2]: Adjust executor test for broader
  compatibility (#739)
- upstream commit c0dbc29 [3]: Fall back when setuptools is too recent
  for symlink install (#735)
- upstream commit 41fb554 [4]: Adjust Python build tests to support
  setuptools >= 80 (#737) (fixes #1146464)

I applied these fixes in the sandbox [5] to be able to build the
packages that depend on ros2-colcon-core, please consider applying the
patches to support the upcoming 3.15 version.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4541776/
[2]: 
https://github.com/colcon/colcon-core/commit/dbc75eeb851b103db74faec1dd5bfdbb0636b02e
[3]: 
https://github.com/colcon/colcon-core/commit/c0dbc292b823101d3de71da7bd3d91fdb0b39258
[4]: 
https://github.com/colcon/colcon-core/commit/41fb5542d4a1d884aa0324f928e5a05396a70179
[5]: 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 /\/\ /\ >< `/
From dbc75eeb851b103db74faec1dd5bfdbb0636b02e Mon Sep 17 00:00:00 2001
From: Scott K Logan <[email protected]>
Date: Mon, 22 Jun 2026 11:14:43 -0500
Subject: [PATCH] Adjust executor test for broader compatibility (#739)

It looks like Python 3.15 is adding some additional checks on entry
point values, and the hyphen character in `eC-prime` makes it invalid.
Just convert it to an underscore instead.
---
 test/test_extension_point.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/test/test_extension_point.py b/test/test_extension_point.py
index f0fa804..6f8eecf 100644
--- a/test/test_extension_point.py
+++ b/test/test_extension_point.py
@@ -184,7 +184,7 @@ def test_redefined_extension_point():
     def _duped_distributions():
         yield from _distributions()
         yield _FakeDistribution({
-            'group2': [('extC', 'eC-prime')],
+            'group2': [('extC', 'eC_prime')],
         })
 
     def _duped_entry_points():
@@ -202,13 +202,13 @@ def test_redefined_extension_point():
             ):
                 clear_entry_point_cache()
                 extension_points = get_all_extension_points()
-                assert 'eC-prime' == extension_points['group2']['extC'][0]
+                assert 'eC_prime' == extension_points['group2']['extC'][0]
                 assert error.call_count == 1
 
                 error.reset_mock()
                 clear_entry_point_cache()
                 extension_points = get_extension_points('group2')
-                assert 'eC-prime' == extension_points.get('extC')
+                assert 'eC_prime' == extension_points.get('extC')
                 assert error.call_count == 1
 
 
-- 
2.53.0

From 41fb5542d4a1d884aa0324f928e5a05396a70179 Mon Sep 17 00:00:00 2001
From: Scott K Logan <[email protected]>
Date: Tue, 21 Jul 2026 15:28:12 -0500
Subject: [PATCH] Adjust Python build tests to support setuptools >= 80 (#737)

We should assert the behavior that we want colcon to exhibit (even
though I'm not happy about it).

Fixes c0dbc292b823101d3de71da7bd3d91fdb0b39258
---
 test/test_build_python.py | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/test_build_python.py b/test/test_build_python.py
index d8e11c0..29f4dd7 100644
--- a/test/test_build_python.py
+++ b/test/test_build_python.py
@@ -53,6 +53,16 @@ def _test_build_package(
     if setup_cfg and data_files:
         pytest.importorskip('setuptools', minversion='40.5.0')
 
+    if symlink_install:
+        try:
+            pytest.importorskip('setuptools', minversion='80')
+        except pytest.skip.Exception:  # noqa: B902
+            pass
+        else:
+            # We expect setuptools >= 80 to fall back to standard
+            # install behavior.
+            symlink_install = False
+
     event_loop = new_event_loop()
     asyncio.set_event_loop(event_loop)
     try:
-- 
2.53.0

From c0dbc292b823101d3de71da7bd3d91fdb0b39258 Mon Sep 17 00:00:00 2001
From: Scott K Logan <[email protected]>
Date: Fri, 29 May 2026 13:42:19 -0500
Subject: [PATCH] Fall back when setuptools is too recent for symlink install
 (#735)

The latest releases of setuptools drop support for the `--editable`
option to the `develop` verb, which colcon relies on when performing a
`--symlink-install`. While colcon declares incompatibility with newer
setuptools versions, it's certainly possible to end up in a situation
where colcon is used with newer setuptools versions. When that happens,
we should behave similarly to how colcon handles versions of setuptools
which are too old to support `--symlink-install` and fall back to a full
install.
---
 colcon_core/task/python/build.py | 38 +++++++++++++++++++++++++++++++-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/colcon_core/task/python/build.py b/colcon_core/task/python/build.py
index 13ba546..d200e46 100644
--- a/colcon_core/task/python/build.py
+++ b/colcon_core/task/python/build.py
@@ -100,7 +100,23 @@ class PythonBuildTask(TaskExtensionPoint):
         available_commands = await self._get_available_commands(
             args.path, env)
 
-        if not args.symlink_install or 'develop' not in available_commands:
+        symlink_install = False
+        if args.symlink_install:
+            if 'develop' in available_commands:
+                available_options = await self._get_available_options(
+                    args.path, env, 'develop')
+                if '--editable' in available_options:
+                    symlink_install = True
+                else:
+                    logger.info(
+                        "No '--editable' capability in setuptools, falling "
+                        'back to full install')
+            else:
+                logger.info(
+                    "No 'develop' capability in setuptools, falling back to "
+                    'full install')
+
+        if not symlink_install:
             rc = await self._undo_develop(pkg, args, env)
             if rc:
                 return rc
@@ -209,8 +225,28 @@ class PythonBuildTask(TaskExtensionPoint):
                 continue
             commands.add(
                 line[2:index].decode(locale.getpreferredencoding(False)))
+        logger.debug(f"Available setuptools commands: {', '.join(commands)}")
         return commands
 
+    async def _get_available_options(self, path, env, command):
+        output = await check_output(
+            _PYTHON_CMD + ['setup.py', '--help', command], cwd=path, env=env)
+        options = set()
+        for line in output.splitlines():
+            if not line.startswith(b'  --'):
+                continue
+            try:
+                index = line.index(b' ', 4)
+            except ValueError:
+                continue
+            if index == 4:
+                continue
+            options.add(
+                line[2:index].decode(locale.getpreferredencoding(False)))
+        logger.debug(
+            f"Available setuptools '{command}' options: {', '.join(options)}")
+        return options
+
     async def _undo_develop(self, pkg, args, env):
         """
         Undo a previously run 'develop' command.
-- 
2.53.0

Reply via email to