From 758fdb036f685d5cb0d92f0ec761f01badbfd6a8 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sun, 13 Apr 2025 21:35:53 -0700 Subject: [PATCH] gh-132493: Support deferred annotations in Protocols --- Lib/test/test_typing.py | 9 +++++++++ Lib/typing.py | 4 +++- .../2025-04-13-21-35-50.gh-issue-132493.5SAQJn.rst | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2025-04-13-21-35-50.gh-issue-132493.5SAQJn.rst 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. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy