diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 042604ed7c1a42..2725f0089baba2 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4254,6 +4254,19 @@ def meth(self): self.assertEqual(frozenset(typing._get_protocol_attrs(PG)), frozenset({'x', 'meth'})) + def test_protocol_with_annotate_method_does_not_crash(self): + # gh-146643: defining a Protocol whose member is named __annotate__ + # (a reserved name whose value is not a usable annotate function) + # used to crash protocol attribute collection with a TypeError. + class CanAnnotate(Protocol): + def __annotate__(self, format, /): ... + + self.assertIs(CanAnnotate._is_protocol, True) + # __annotate__ is an excluded special name, so it is not collected as + # a protocol member, but creating the class must not raise. + self.assertNotIn('__annotate__', + typing._get_protocol_attrs(CanAnnotate)) + def test_no_runtime_deco_on_nominal(self): with self.assertRaises(TypeError): @runtime_checkable diff --git a/Lib/typing.py b/Lib/typing.py index 1579f492003f74..16227c0f445bd5 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1874,9 +1874,16 @@ def _get_protocol_attrs(cls): annotations = base.__annotations__ except Exception: # Only go through annotationlib to handle deferred annotations if we need to - annotations = annotationlib.get_annotations( - base, format=annotationlib.Format.FORWARDREF - ) + try: + annotations = annotationlib.get_annotations( + base, format=annotationlib.Format.FORWARDREF + ) + except Exception: + # The annotations cannot be retrieved at all, e.g. the base + # defines an ``__annotate__`` member that is not a usable + # annotate function (gh-146643). Treat it as un-annotated + # rather than letting the class definition fail. + annotations = {} for attr in (*base.__dict__, *annotations): if not attr.startswith('_abc_') and attr not in EXCLUDED_ATTRIBUTES: attrs.add(attr) diff --git a/Misc/NEWS.d/next/Library/2026-06-22-14-15-00.gh-issue-146643.Lm5wTq.rst b/Misc/NEWS.d/next/Library/2026-06-22-14-15-00.gh-issue-146643.Lm5wTq.rst new file mode 100644 index 00000000000000..868837df2ac605 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-22-14-15-00.gh-issue-146643.Lm5wTq.rst @@ -0,0 +1,3 @@ +Fix a :exc:`TypeError` raised when defining a :class:`typing.Protocol` whose +body (or one of its bases) declares a member named ``__annotate__`` that is not +a usable annotate function. Such a class can now be created without error.