From dd25f94ac965dd9d0360e60ff4a0c99557d17fc1 Mon Sep 17 00:00:00 2001 From: Gal Sakuri Date: Thu, 16 Apr 2026 21:57:28 +0300 Subject: [PATCH] stubtest: don't flag __class_getitem__ missing for PEP 695 generic stubs PEP 695 generic syntax (class Foo[T]: ...) implicitly provides __class_getitem__ at runtime. When a stub uses this syntax and the runtime class defines __class_getitem__ explicitly, stubtest was incorrectly reporting it as missing from the stub. Fix: in verify_typeinfo(), discard "__class_getitem__" from the set of attributes to check when the stub class has PEP 695 type parameters (ClassDef.type_args is not None). Fixes: https://github.com/python/mypy/issues/21253 --- mypy/stubtest.py | 4 ++++ mypy/test/teststubtest.py | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/mypy/stubtest.py b/mypy/stubtest.py index ac0378cc54689..a3292178f0f48 100644 --- a/mypy/stubtest.py +++ b/mypy/stubtest.py @@ -700,6 +700,10 @@ def verify_typeinfo( to_check.discard("__init__") if is_runtime_typeddict: to_check.discard("__new__") + # PEP 695 generic syntax (class Foo[T]: ...) implicitly provides __class_getitem__ + # at runtime, so don't require an explicit stub definition. + if stub.defn.type_args is not None: + to_check.discard("__class_getitem__") for entry in sorted(to_check): mangled_entry = entry diff --git a/mypy/test/teststubtest.py b/mypy/test/teststubtest.py index ada69fc6e47cf..b467079a23786 100644 --- a/mypy/test/teststubtest.py +++ b/mypy/test/teststubtest.py @@ -1825,6 +1825,19 @@ def test_dunders(self) -> Iterator[Case]: runtime="class D:\n def __class_getitem__(cls, type): ...", error=None, ) + if sys.version_info >= (3, 12): + # PEP 695 generic syntax implicitly provides __class_getitem__ at runtime + yield Case( + stub="class D2[T]: ...", + runtime="class D2:\n def __class_getitem__(cls, _): return cls", + error=None, + ) + # Non-generic stub still reports missing __class_getitem__ + yield Case( + stub="class D3: ...", + runtime="class D3:\n def __class_getitem__(cls, _): return cls", + error="D3.__class_getitem__", + ) yield Case( stub="class E:\n def __getitem__(self, item: object) -> object: ...", runtime="class E:\n def __getitem__(self, item: object, /) -> object: ...",