diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 9f9e3eb17b9fc9..fc893807837eb9 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4554,6 +4554,15 @@ class Commentable(Protocol): ) self.assertIs(type(exc.__cause__), CustomError) + def test_deferred_evaluation_of_annotations(self): + class DeferredProto(Protocol): + x: DoesNotExist + self.assertEqual(get_protocol_members(DeferredProto), {"x"}) + self.assertEqual( + annotationlib.get_annotations(DeferredProto, format=annotationlib.Format.STRING), + {'x': 'DoesNotExist'} + ) + class GenericTests(BaseTestCase): diff --git a/Lib/typing.py b/Lib/typing.py index e5d14b03a4fc94..08b2ba356fc014 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1801,7 +1801,9 @@ def _get_protocol_attrs(cls): for base in cls.__mro__[:-1]: # without object if base.__name__ in {'Protocol', 'Generic'}: continue - annotations = getattr(base, '__annotations__', {}) + annotations = _lazy_annotationlib.get_annotations( + base, format=_lazy_annotationlib.Format.FORWARDREF + ) 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/2025-04-13-21-35-50.gh-issue-132493.5SAQJn.rst b/Misc/NEWS.d/next/Library/2025-04-13-21-35-50.gh-issue-132493.5SAQJn.rst new file mode 100644 index 00000000000000..bda09e2356d56d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-13-21-35-50.gh-issue-132493.5SAQJn.rst @@ -0,0 +1,2 @@ +Support creation of :class:`typing.Protocol` classes with annotations that +cannot be resolved at class creation time.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: