Package: src:poetry
Version: 2.3.4-2
User: [email protected]
Usertags: python3.15
Tags: patch, ftbfs, forky, sid
Severity: important

Hi!

While rebuilding the python related packages against the Python 3.15rc2
version we found that poetry fails to build from source [1].

To fix it, I've added a backport of upstream commit f47e6b2f: [PATCH]
Fix MetadataNotFound from importlib.metadata on Python 3.15+ (#10860)
[2].

I've applied the upstream fix in the sandbox [3] to verify that it
builds successfully, please consider applying the patch to support the
upcoming 3.15 version.

BTW, upstream is already at 2.4.3, which includes this fix and other
fixes. Upgrading to the latest upstream version would also fix this
issue.

Setting the severity to important for now. Once Python 3.15 is released,
it will be added to python3-defaults and this bug will become release
critical.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4524773/
[2]: 
https://github.com/python-poetry/poetry/commit/f47e6b2f73e6ea6e1f81fa8963ec0fde30815345
[3]: 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 f47e6b2f73e6ea6e1f81fa8963ec0fde30815345 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lum=C3=ADr=20=27Frenzy=27=20Balhar?= <[email protected]>
Date: Fri, 1 May 2026 06:41:17 +0200
Subject: [PATCH] Fix MetadataNotFound from importlib.metadata on Python 3.15+
 (#10860)

In Python 3.15, importlib.metadata raises MetadataNotFound
(a FileNotFoundError subclass) when a dist-info directory has no
METADATA file. Previously, it returned None.
---
 src/poetry/repositories/installed_repository.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/poetry/repositories/installed_repository.py b/src/poetry/repositories/installed_repository.py
index 9a28ada0..81cf888c 100644
--- a/src/poetry/repositories/installed_repository.py
+++ b/src/poetry/repositories/installed_repository.py
@@ -270,7 +270,12 @@ class InstalledRepository(Repository):
                 if path in skipped:
                     continue
 
-                dist_metadata = distribution.metadata  # type: ignore[attr-defined]
+                try:
+                    dist_metadata = distribution.metadata  # type: ignore[attr-defined]
+                except FileNotFoundError:
+                    # Python 3.15+ raises MetadataNotFound (a FileNotFoundError subclass)
+                    # when a dist-info directory has no METADATA file
+                    dist_metadata = None
                 name = (
                     dist_metadata.get("name")  # type: ignore[attr-defined]
                     if dist_metadata
-- 
Index: poetry/tests/console/commands/debug/test_info.py
===================================================================
--- poetry.orig/tests/console/commands/debug/test_info.py
+++ poetry/tests/console/commands/debug/test_info.py
@@ -63,7 +63,7 @@ Platform:   darwin
 OS:         posix
 Python:     {".".join(str(v) for v in sys.version_info[:3])}
 Path:       {Path("/base/prefix")}
-Executable: python
+Executable: python3
 """
 
     assert tester.io.fetch_output() == expected
Index: poetry/tests/console/test_application_command_not_found.py
===================================================================
--- poetry.orig/tests/console/test_application_command_not_found.py
+++ poetry/tests/console/test_application_command_not_found.py
@@ -21,7 +21,6 @@ def tester() -> ApplicationTester:
 @pytest.mark.parametrize(
     ("command", "suggested"),
     [
-        ("x", None),
         ("en", ["env activate", "env info", "env list", "env remove", "env use"]),
         ("sou", ["source add", "source remove", "source show"]),
     ],
Index: poetry/tests/utils/env/python/test_manager.py
===================================================================
--- poetry.orig/tests/utils/env/python/test_manager.py
+++ poetry/tests/utils/env/python/test_manager.py
@@ -137,7 +137,7 @@ def test_get_by_name_version(
 
 
 def test_get_by_name_python(without_mocked_findpython: None) -> None:
-    python = Python.get_by_name("python")
+    python = Python.get_by_name("python3")
     assert python is not None
     assert python.version.major == 3
     assert python.version.minor == sys.version_info.minor
Index: poetry/tests/utils/env/test_env.py
===================================================================
--- poetry.orig/tests/utils/env/test_env.py
+++ poetry/tests/utils/env/test_env.py
@@ -464,7 +464,7 @@ def test_env_finds_fallback_executables_
         venv._bin_dir.joinpath(major_executable).unlink(missing_ok=True)
         venv._bin_dir.joinpath(major_pip_executable).unlink(missing_ok=True)
 
-        expected_executable = default_executable
+        expected_executable = default_executable + "3"
         expected_pip_executable = default_pip_executable
 
     else:
Index: poetry/tests/utils/test_python_manager.py
===================================================================
--- poetry.orig/tests/utils/test_python_manager.py
+++ poetry/tests/utils/test_python_manager.py
@@ -61,7 +61,7 @@ def test_python_get_preferred_default(co
     python = Python.get_preferred_python(config)
 
     assert python.executable.resolve() == Path(sys.executable).resolve()
-    assert python.version == python_version
+    assert python.version in {python_version, Python.get_system_python().version}
 
 
 def test_get_preferred_python_use_poetry_python_disabled(

Reply via email to