https://github.com/python/cpython/commit/cbb415e992df78e92244caa0611d2d7952f1719d
commit: cbb415e992df78e92244caa0611d2d7952f1719d
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: AlexWaygood <[email protected]>
date: 2025-10-11T15:36:44Z
summary:

[3.13] gh-139905: Provide suggestion in error message if 
`Generic.__init_subclass__` was not called (GH-139943) (#139956)

gh-139905: Provide suggestion in error message if `Generic.__init_subclass__` 
was not called (GH-139943)
(cherry picked from commit 5776d0d2e08f4d93dcd62d875bae8c1396a04ba4)

Co-authored-by: Stan Ulbrych <[email protected]>

files:
A Misc/NEWS.d/next/Library/2025-10-11-10-02-56.gh-issue-139905.UyJIR_.rst
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 5f49bf757096f0..fb4cf26982d3b5 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -4582,6 +4582,34 @@ class D(Generic[T]): pass
         with self.assertRaises(TypeError):
             D[()]
 
+    def test_generic_init_subclass_not_called_error(self):
+        notes = ["Note: this exception may have been caused by "
+                 
r"'GenericTests.test_generic_init_subclass_not_called_error.<locals>.Base.__init_subclass__'
 "
+                 "(or the '__init_subclass__' method on a superclass) not 
calling 'super().__init_subclass__()'"]
+
+        class Base:
+            def __init_subclass__(cls) -> None:
+                # Oops, I forgot super().__init_subclass__()!
+                pass
+
+        with self.subTest():
+            class Sub(Base, Generic[T]):
+                pass
+
+            with self.assertRaises(AttributeError) as cm:
+                Sub[int]
+
+            self.assertEqual(cm.exception.__notes__, notes)
+
+        with self.subTest():
+            class Sub[U](Base):
+                pass
+
+            with self.assertRaises(AttributeError) as cm:
+                Sub[int]
+
+            self.assertEqual(cm.exception.__notes__, notes)
+
     def test_generic_subclass_checks(self):
         for typ in [list[int], List[int],
                     tuple[int, str], Tuple[int, str],
diff --git a/Lib/typing.py b/Lib/typing.py
index f9141640997933..95e469c4fff74a 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1236,14 +1236,26 @@ def _generic_class_getitem(cls, args):
                 f"Parameters to {cls.__name__}[...] must all be unique")
     else:
         # Subscripting a regular Generic subclass.
-        for param in cls.__parameters__:
+        try:
+            parameters = cls.__parameters__
+        except AttributeError as e:
+            init_subclass = getattr(cls, '__init_subclass__', None)
+            if init_subclass not in {None, Generic.__init_subclass__}:
+                e.add_note(
+                    f"Note: this exception may have been caused by "
+                    f"{init_subclass.__qualname__!r} (or the "
+                    f"'__init_subclass__' method on a superclass) not "
+                    f"calling 'super().__init_subclass__()'"
+                )
+            raise
+        for param in parameters:
             prepare = getattr(param, '__typing_prepare_subst__', None)
             if prepare is not None:
                 args = prepare(cls, args)
         _check_generic_specialization(cls, args)
 
         new_args = []
-        for param, new_arg in zip(cls.__parameters__, args):
+        for param, new_arg in zip(parameters, args):
             if isinstance(param, TypeVarTuple):
                 new_args.extend(new_arg)
             else:
diff --git 
a/Misc/NEWS.d/next/Library/2025-10-11-10-02-56.gh-issue-139905.UyJIR_.rst 
b/Misc/NEWS.d/next/Library/2025-10-11-10-02-56.gh-issue-139905.UyJIR_.rst
new file mode 100644
index 00000000000000..a6876ca2df8299
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-10-11-10-02-56.gh-issue-139905.UyJIR_.rst
@@ -0,0 +1,3 @@
+Add suggestion to error message for :class:`typing.Generic` subclasses when
+``cls.__parameters__`` is missing due to a parent class failing to call
+:meth:`super().__init_subclass__() <object.__init_subclass__>` in its 
``__init_subclass__``.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to