Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 10 additions & 3 deletions Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading