Your message dated Sun, 06 Sep 2026 00:50:24 +0000
with message-id <[email protected]>
and subject line Bug#1145442: fixed in astroid 4.3.1-1
has caused the Debian Bug report #1145442,
regarding astroid: FTBFS against python 3.15rc1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1145442: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1145442
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: src:astroid
Version: 4.1.1-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 astroid fails to build from source [1].
The problems were already fixed upstream through two separate commits
[2] and [3].

I applied the upstream fixes in the sandbox [4] to be able to build the
packages that depend on astroid, please consider applying the patch to
support the upcoming 3.15 version.

Happy hacking,

[1]: 
https://debusine.debian.net/debian/r-python-python3.15/work-request/1090897/
[2]: 
https://github.com/pylint-dev/astroid/commit/341ef0a19c8f68e4b89c9ccafc535a66a59da0a4
[3]: 
https://github.com/pylint-dev/astroid/commit/3c9d1d9e78bb0096c8c55df96e6abcfb19e6aa32
[4]: 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 /\/\ /\ >< `/
commit 341ef0a19c8f68e4b89c9ccafc535a66a59da0a4
Author: Copilot <[email protected]>
Date:   Thu Apr 23 08:14:41 2026 +0200

    Add Python 3.15 compatibility: CI, ByteString stub, and test fixes (#3033)
    
    * Add initial support for Python 3.15
    
    * Fix for `test_typing_object_notsubscriptable_3`
    
    ---------
    
    Co-authored-by: DaniĆ«l van Noord <[email protected]>

Index: astroid/astroid/brain/brain_typing.py
===================================================================
--- astroid.orig/astroid/brain/brain_typing.py
+++ astroid/astroid/brain/brain_typing.py
@@ -15,7 +15,7 @@ from typing import Final
 from astroid import context, nodes
 from astroid.brain.helpers import register_module_extender
 from astroid.builder import AstroidBuilder, _extract_single_node, extract_node
-from astroid.const import PY312_PLUS, PY313_PLUS, PY314_PLUS
+from astroid.const import PY312_PLUS, PY313_PLUS, PY314_PLUS, PY315_PLUS
 from astroid.exceptions import (
     AstroidSyntaxError,
     AttributeInferenceError,
@@ -464,6 +464,13 @@ def _typing_transform():
         @classmethod
         def __class_getitem__(cls, item): return cls
     """)
+    if PY315_PLUS:
+        # typing.ByteString was removed from the typing module in Python 3.15
+        # (it was deprecated since 3.12 and present at module level until 3.14).
+        # Inject a stub so code using `typing.ByteString` can still be inferred.
+        code += textwrap.dedent("""
+    class ByteString: ...
+    """)
     return AstroidBuilder(AstroidManager()).string_build(code)
 
 
Index: astroid/astroid/const.py
===================================================================
--- astroid.orig/astroid/const.py
+++ astroid/astroid/const.py
@@ -10,6 +10,7 @@ PY312_PLUS = sys.version_info >= (3, 12)
 PY313 = sys.version_info[:2] == (3, 13)
 PY313_PLUS = sys.version_info >= (3, 13)
 PY314_PLUS = sys.version_info >= (3, 14)
+PY315_PLUS = sys.version_info >= (3, 15)
 
 WIN32 = sys.platform == "win32"
 
Index: astroid/astroid/protocols.py
===================================================================
--- astroid.orig/astroid/protocols.py
+++ astroid/astroid/protocols.py
@@ -545,7 +545,7 @@ ExceptionGroup
 """)))
         assigned = objects.ExceptionInstance(eg)
         assigned.instance_attrs["exceptions"] = [
-            nodes.List.from_elements(_generate_assigned())
+            nodes.Tuple.from_elements(_generate_assigned())
         ]
         yield assigned
     else:
Index: astroid/tests/brain/test_brain.py
===================================================================
--- astroid.orig/tests/brain/test_brain.py
+++ astroid/tests/brain/test_brain.py
@@ -15,7 +15,7 @@ import astroid
 from astroid import MANAGER, builder, nodes, objects, test_utils, util
 from astroid.bases import Instance
 from astroid.brain.brain_namedtuple_enum import _get_namedtuple_fields
-from astroid.const import PY312_PLUS, PY313_PLUS
+from astroid.const import PY312_PLUS, PY313_PLUS, PY315_PLUS
 from astroid.exceptions import (
     AttributeInferenceError,
     InferenceError,
@@ -787,7 +787,10 @@ class TypingBrain(unittest.TestCase):
         typing.ByteString
         """)
         inferred = next(right_node.infer())
-        check_metaclass_is_abc(inferred)
+        # From Python 3.15 we add a stub definition of `ByteString`. It doesn't need all properties
+        # of the original implementation.
+        if not PY315_PLUS:
+            check_metaclass_is_abc(inferred)
         with self.assertRaises(AttributeInferenceError):
             self.assertIsInstance(
                 inferred.getattr("__class_getitem__")[0], nodes.FunctionDef
Index: astroid/tests/test_group_exceptions.py
===================================================================
--- astroid.orig/tests/test_group_exceptions.py
+++ astroid/tests/test_group_exceptions.py
@@ -126,12 +126,12 @@ def test_star_exceptions_infer_exception
     assert isinstance(node, nodes.TryStar)
     inferred_ve = next(node.handlers[0].statement().name.infer())
     assert inferred_ve.name == "ExceptionGroup"
-    assert isinstance(inferred_ve.getattr("exceptions")[0], nodes.List)
+    assert isinstance(inferred_ve.getattr("exceptions")[0], nodes.Tuple)
     assert (
         inferred_ve.getattr("exceptions")[0].elts[0].pytype() == "builtins.ValueError"
     )
 
     inferred_te = next(node.handlers[1].statement().name.infer())
     assert inferred_te.name == "ExceptionGroup"
-    assert isinstance(inferred_te.getattr("exceptions")[0], nodes.List)
+    assert isinstance(inferred_te.getattr("exceptions")[0], nodes.Tuple)
     assert inferred_te.getattr("exceptions")[0].elts[0].pytype() == "builtins.TypeError"
Index: astroid/tests/test_regrtest.py
===================================================================
--- astroid.orig/tests/test_regrtest.py
+++ astroid/tests/test_regrtest.py
@@ -12,7 +12,7 @@ import pytest
 
 from astroid import MANAGER, Instance, bases, manager, nodes, parse, test_utils
 from astroid.builder import AstroidBuilder, _extract_single_node, extract_node
-from astroid.const import PY312_PLUS
+from astroid.const import PY312_PLUS, PY315_PLUS
 from astroid.context import InferenceContext
 from astroid.exceptions import AstroidSyntaxError, InferenceError
 from astroid.manager import AstroidManager
@@ -530,6 +530,9 @@ def test_regression_infer_namedtuple_inv
     assert inferred.value == Uninferable
 
 
+# On Python 3.15+ the parser emits a regular SyntaxError instead of a MemoryError for deeply nested
+# parentheses, so the special-case test here is no longer needed.
[email protected](PY315_PLUS, reason="No longer a MemoryError on Python 3.15+")
 def test_regression_parse_deeply_nested_parentheses() -> None:
     """Regression test for issue #2643."""
     with pytest.raises(AstroidSyntaxError, match="Parsing Python code failed:") as ctx:
Index: astroid/tox.ini
===================================================================
--- astroid.orig/tox.ini
+++ astroid/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py{39,310,311,312,313,314}
+envlist = py{39,310,311,312,313,314,315}
 skip_missing_interpreters = true
 isolated_build = true
 
commit 3c9d1d9e78bb0096c8c55df96e6abcfb19e6aa32
Author: Sai Asish Y <[email protected]>
Date:   Sat May 16 05:29:53 2026 -0700

    fix: handle Python 3.15 KW_ONLY and namespace .pth test behavior (#3047)
    
    
    Signed-off-by: SAY-5 <[email protected]>
    Co-authored-by: SAY-5 <[email protected]>
    Co-authored-by: Sai Asish Y <[email protected]>
    Co-authored-by: Pierre Sassoulas <[email protected]>

Index: astroid/astroid/brain/brain_dataclasses.py
===================================================================
--- astroid.orig/astroid/brain/brain_dataclasses.py
+++ astroid/astroid/brain/brain_dataclasses.py
@@ -556,10 +556,27 @@ def _get_field_default(field_call: nodes
 def _is_keyword_only_sentinel(node: nodes.NodeNG) -> bool:
     """Return True if node is the KW_ONLY sentinel."""
     inferred = safe_infer(node)
-    return (
-        isinstance(inferred, bases.Instance)
-        and inferred.qname() == "dataclasses._KW_ONLY_TYPE"
-    )
+    if not isinstance(inferred, bases.Instance):
+        return False
+    if inferred.qname() == "dataclasses._KW_ONLY_TYPE":
+        return True
+    if inferred.qname() != "builtins.sentinel":
+        return False
+    if isinstance(node, nodes.Name):
+        _, assignments = node.lookup(node.name)
+        return any(
+            isinstance(assignment, nodes.ImportFrom)
+            and assignment.modname == "dataclasses"
+            and any(imported == "KW_ONLY" for imported, _ in assignment.names)
+            for assignment in assignments
+        )
+    if isinstance(node, nodes.Attribute) and node.attrname == "KW_ONLY":
+        inferred_expr = safe_infer(node.expr)
+        return (
+            isinstance(inferred_expr, nodes.Module)
+            and inferred_expr.qname() == "dataclasses"
+        )
+    return False
 
 
 def _is_init_var(node: nodes.NodeNG) -> bool:
Index: astroid/tests/brain/test_dataclasses.py
===================================================================
--- astroid.orig/tests/brain/test_dataclasses.py
+++ astroid/tests/brain/test_dataclasses.py
@@ -728,7 +728,8 @@ def test_non_dataclass_is_not_dataclass(
 
 def test_kw_only_sentinel() -> None:
     """Test that the KW_ONLY sentinel doesn't get added to the fields."""
-    node_one, node_two = astroid.extract_node("""
+    node_one, node_two, node_three = astroid.extract_node("""
+    import dataclasses
     from dataclasses import dataclass, KW_ONLY
     from dataclasses import KW_ONLY as keyword_only
 
@@ -745,13 +746,37 @@ def test_kw_only_sentinel() -> None:
         y: str
 
     B.__init__  #@
+
+    @dataclass
+    class C:
+        _: dataclasses.KW_ONLY
+        y: str
+
+    C.__init__  #@
     """)
     expected = ["self", "y"]
-    init = next(node_one.infer())
-    assert [a.name for a in init.args.args] == expected
+    for node in (node_one, node_two, node_three):
+        init = next(node.infer())
+        assert [a.name for a in init.args.args] == expected
+
 
-    init = next(node_two.infer())
-    assert [a.name for a in init.args.args] == expected
+def test_kw_only_sentinel_other_dataclasses_attr() -> None:
+    """Annotating with another ``dataclasses`` attribute (e.g. ``MISSING``)
+    that also infers to ``builtins.sentinel`` on Python 3.15+ must not be
+    treated as ``KW_ONLY``."""
+    node = astroid.extract_node("""
+    import dataclasses
+    from dataclasses import dataclass
+
+    @dataclass
+    class C:
+        _: dataclasses.MISSING
+        y: str
+
+    C.__init__  #@
+    """)
+    init = next(node.infer())
+    assert [a.name for a in init.args.args] == ["self", "_", "y"]
 
 
 def test_kw_only_decorator() -> None:
Index: astroid/tests/test_manager.py
===================================================================
--- astroid.orig/tests/test_manager.py
+++ astroid/tests/test_manager.py
@@ -3,9 +3,10 @@
 # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
 
 import os
-import site
+import re
 import sys
 import time
+import types
 import unittest
 import warnings
 from collections.abc import Iterator
@@ -36,6 +37,51 @@ def _get_file_from_object(obj) -> str:
     return obj.__file__
 
 
+_NSPKG_PTH_PARTS_RE = re.compile(r"\*\(([^)]+)\)")
+
+
+def _parse_pth_package_parts(line: str) -> tuple[str, ...]:
+    """Extract the namespace package tuple from a setuptools nspkg .pth line."""
+    match = _NSPKG_PTH_PARTS_RE.search(line)
+    if not match:
+        return ()
+    parts = []
+    for token in match.group(1).split(","):
+        token = token.strip().strip("'\"")
+        if token:
+            parts.append(token)
+    return tuple(parts)
+
+
+def _load_namespace_package_pth(pth: str) -> None:
+    """Apply a setuptools-style namespace package .pth fixture without exec().
+
+    Each non-comment line in the fixture wires up one namespace package by
+    appending a directory under `resources.RESOURCE_PATH` to that package's
+    ``__path__``. We parse the package tuple out of the line and replay the
+    same effect here.
+    """
+    sitedir = str(resources.RESOURCE_PATH)
+    with (resources.RESOURCE_PATH / pth).open(encoding="utf-8") as pth_file:
+        for raw_line in pth_file:
+            line = raw_line.strip()
+            if not line or line.startswith("#"):
+                continue
+            parts = _parse_pth_package_parts(line)
+            if not parts:
+                continue
+            package_name = ".".join(parts)
+            package_path = os.path.join(sitedir, *parts)
+            if os.path.exists(os.path.join(package_path, "__init__.py")):
+                continue
+            module = sys.modules.setdefault(
+                package_name, types.ModuleType(package_name)
+            )
+            mod_path = module.__dict__.setdefault("__path__", [])
+            if package_path not in mod_path:
+                mod_path.append(package_path)
+
+
 class AstroidManagerTest(resources.SysPathSetup, unittest.TestCase):
     def setUp(self) -> None:
         super().setUp()
@@ -196,7 +242,7 @@ class AstroidManagerTest(resources.SysPa
     )
     def test_namespace_package_pth_support(self) -> None:
         pth = "foogle_fax-0.12.5-py2.7-nspkg.pth"
-        site.addpackage(resources.RESOURCE_PATH, pth, [])
+        _load_namespace_package_pth(pth)
 
         try:
             module = self.manager.ast_from_module_name("foogle.fax")
@@ -206,7 +252,8 @@ class AstroidManagerTest(resources.SysPa
             with self.assertRaises(AstroidImportError):
                 self.manager.ast_from_module_name("foogle.moogle")
         finally:
-            sys.modules.pop("foogle")
+            sys.modules.pop("foogle", None)
+            sys.modules.pop("foogle.crank", None)
 
     @pytest.mark.skipif(
         IS_PYPY,
@@ -214,23 +261,25 @@ class AstroidManagerTest(resources.SysPa
     )
     def test_nested_namespace_import(self) -> None:
         pth = "foogle_fax-0.12.5-py2.7-nspkg.pth"
-        site.addpackage(resources.RESOURCE_PATH, pth, [])
+        _load_namespace_package_pth(pth)
         try:
             self.manager.ast_from_module_name("foogle.crank")
         finally:
-            sys.modules.pop("foogle")
+            sys.modules.pop("foogle", None)
+            sys.modules.pop("foogle.crank", None)
 
     def test_namespace_and_file_mismatch(self) -> None:
         filepath = unittest.__file__
         ast = self.manager.ast_from_file(filepath)
         self.assertEqual(ast.name, "unittest")
         pth = "foogle_fax-0.12.5-py2.7-nspkg.pth"
-        site.addpackage(resources.RESOURCE_PATH, pth, [])
+        _load_namespace_package_pth(pth)
         try:
             with self.assertRaises(AstroidImportError):
                 self.manager.ast_from_module_name("unittest.foogle.fax")
         finally:
-            sys.modules.pop("foogle")
+            sys.modules.pop("foogle", None)
+            sys.modules.pop("foogle.crank", None)
 
     def _test_ast_from_zip(self, archive: str) -> None:
         sys.modules.pop("mypypa", None)
@@ -553,3 +602,23 @@ class ClearCacheTest(unittest.TestCase):
         isinstance_call = astroid.extract_node("isinstance(1, int)")
         inferred = next(isinstance_call.infer())
         self.assertIs(inferred.value, True)
+
+
+class NamespacePthParserTest(unittest.TestCase):
+    """Direct coverage for the .pth parsing helpers used by namespace tests."""
+
+    def test_parse_extracts_quoted_tuple(self) -> None:
+        line = "import sys; p = os.path.join(s, *('foogle', 'crank'))"
+        self.assertEqual(_parse_pth_package_parts(line), ("foogle", "crank"))
+
+    def test_parse_handles_double_quotes_and_whitespace(self) -> None:
+        line = '*(  "foo" ,  "bar" )'
+        self.assertEqual(_parse_pth_package_parts(line), ("foo", "bar"))
+
+    def test_parse_skips_empty_tokens(self) -> None:
+        line = "*('foo', '', 'bar',)"
+        self.assertEqual(_parse_pth_package_parts(line), ("foo", "bar"))
+
+    def test_parse_returns_empty_when_no_match(self) -> None:
+        self.assertEqual(_parse_pth_package_parts("# comment only"), ())
+        self.assertEqual(_parse_pth_package_parts(""), ())

--- End Message ---
--- Begin Message ---
Source: astroid
Source-Version: 4.3.1-1
Done: Daniel Echeverri <[email protected]>

We believe that the bug you reported is fixed in the latest version of
astroid, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Daniel Echeverri <[email protected]> (supplier of updated astroid package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Sat, 05 Sep 2026 18:33:52 -0500
Source: astroid
Architecture: source
Version: 4.3.1-1
Distribution: unstable
Urgency: medium
Maintainer: Debian Python Team <[email protected]>
Changed-By: Daniel Echeverri <[email protected]>
Closes: 1145442 1146029
Changes:
 astroid (4.3.1-1) unstable; urgency=medium
 .
   * New upstream version 4.3.1 (Closes: #1145442, #1146029)
   * debian/watch
     + Update to Version 5
Checksums-Sha1:
 e65f2cd09dccbb24e9d029437bd4ff7337992b2f 2329 astroid_4.3.1-1.dsc
 ab6b2a6716ccabcca34cb03328b3614dfdc535d9 523585 astroid_4.3.1.orig.tar.gz
 dc6195ab1fcbc4477b53f5d5e1a119753760b00a 5908 astroid_4.3.1-1.debian.tar.xz
 4f2bb2328364cbf9313f5d3aea71555601701ae3 7299 astroid_4.3.1-1_amd64.buildinfo
Checksums-Sha256:
 6d59e018daa108aabd1f6c8e9424209e1ef3850192996454db9c55bfe5a45e27 2329 
astroid_4.3.1-1.dsc
 7f55ce88c8af0c70cc748d66dfa37b958ba93aff6b6ec6a06ba20f37de682fca 523585 
astroid_4.3.1.orig.tar.gz
 e6de2cd2c75b6dd3def2c6d1c418186fccbb72e5dc1a4c4c5985757c7ed91dae 5908 
astroid_4.3.1-1.debian.tar.xz
 9c86b25de720b3d61b59405eb9bdd462cd1ef754c3353322ab1fef887f4243b7 7299 
astroid_4.3.1-1_amd64.buildinfo
Files:
 35a28fe5fd0b850f2d44e4cf13dbb16b 2329 python optional astroid_4.3.1-1.dsc
 d010100e9c64f2364fcd516d5f487607 523585 python optional 
astroid_4.3.1.orig.tar.gz
 a7b2b8fbd09fae5ecc2ce214184cd897 5908 python optional 
astroid_4.3.1-1.debian.tar.xz
 c785c8defec0ed7b818d45b2362072dd 7299 python optional 
astroid_4.3.1-1_amd64.buildinfo

-----BEGIN PGP SIGNATURE-----

iQJHBAEBCgAxFiEE0NCFsWnDv9lASFj6IfwpUEtSMNsFAmqcstATHGVwc2lsb25A
ZGViaWFuLm9yZwAKCRAh/ClQS1Iw2xs0D/45RK1WumEUtNsif6AjBFkNnVC/nHEo
2pJkd/8j5v0rvjDv97PyXxibYtkeaJDss6oascDXzkz6Fvwl3oezkWkgADnSW0Oc
HbEfV4T9IphbgiOgvfCjBhXNamElQEtDAU4rFxVmGHIdFSpTtZ1qfvVASLOPAQ3O
WIDiFrfVO7PeuJsFul5oxASUnuPa2uR9HdB29CorN6UggP8a9kpfsLKf2mIkI7P4
hHN2C/V97/DF3SIOffM+XNr6y/gyo+kRRzPU1LDU/x1ZUiemmumNT0BpdDdTljcW
zTCVI7y4+16p6pND/Fq3QHrK8/rLs9Pc8AUbmpdb1uMYzJAd5C1SGLfzdH7/07wX
jNBHlb2qM8WeZqd5e3cGobmt3FmxOocpTuh+I+SObPFIQWfkGnAlFeWB4437IRUA
sUC0tLLIULHvJXSR+yQGzsy51K4Kto3O9GximLR98OS2ukNOZ6t3F1r3zmWkv4am
Xo5F7GlzPIJDfLE2arwUC7s4jQ1OW/1Z1ghXD5E+Xq6JvTuHsgi3XSBuLpkgx3p+
aWqgLdvNT32iFI9MHa2hjmAyv7HQOQTlO7XtIdpZF77QK9mNGLZVUkEaZK2gCy7B
WhU8q0AMQxIPXlOhTtFObBKCxbkRDEIrd0yEABkZoH05rODB1a9eOYnvlKgPo239
G+qy7pDhbMEbjg==
=HDzE
-----END PGP SIGNATURE-----

Attachment: pgpo0bek5tpov.pgp
Description: PGP signature


--- End Message ---

Reply via email to