https://github.com/python/cpython/commit/5707837049e8eade92e29f20f055112821b75cd0
commit: 5707837049e8eade92e29f20f055112821b75cd0
branch: main
author: Jelle Zijlstra <jelle.zijls...@gmail.com>
committer: JelleZijlstra <jelle.zijls...@gmail.com>
date: 2025-04-17T16:03:53Z
summary:

gh-132493: Avoid eager import of annotationlib in typing (again) (#132596)

Co-authored-by: Alex Waygood <alex.wayg...@gmail.com>

files:
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 81474a81be645d..4fd3d53b72c01b 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -3149,6 +3149,21 @@ def x(self): ...
         with self.assertRaisesRegex(TypeError, only_classes_allowed):
             issubclass(1, BadPG)
 
+    def 
test_isinstance_against_superproto_doesnt_affect_subproto_instance(self):
+        @runtime_checkable
+        class Base(Protocol):
+            x: int
+
+        @runtime_checkable
+        class Child(Base, Protocol):
+            y: str
+
+        class Capybara:
+            x = 43
+
+        self.assertIsInstance(Capybara(), Base)
+        self.assertNotIsInstance(Capybara(), Child)
+
     def test_implicit_issubclass_between_two_protocols(self):
         @runtime_checkable
         class CallableMembersProto(Protocol):
@@ -6323,7 +6338,7 @@ def test_lazy_import(self):
             "inspect",
             "re",
             "contextlib",
-            # "annotationlib",  # TODO
+            "annotationlib",
         })
 
 
diff --git a/Lib/typing.py b/Lib/typing.py
index 245592b5678957..f70dcd0b5b7b5c 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1801,9 +1801,13 @@ def _get_protocol_attrs(cls):
     for base in cls.__mro__[:-1]:  # without object
         if base.__name__ in {'Protocol', 'Generic'}:
             continue
-        annotations = _lazy_annotationlib.get_annotations(
-            base, format=_lazy_annotationlib.Format.FORWARDREF
-        )
+        try:
+            annotations = base.__annotations__
+        except Exception:
+            # Only go through annotationlib to handle deferred annotations if 
we need to
+            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)
@@ -2020,14 +2024,17 @@ def _proto_hook(cls, other):
                 break
 
             # ...or in annotations, if it is a sub-protocol.
-            if (
-                issubclass(other, Generic)
-                and getattr(other, "_is_protocol", False)
-                and attr in _lazy_annotationlib.get_annotations(
-                    base, format=_lazy_annotationlib.Format.FORWARDREF
-                )
-            ):
-                break
+            if issubclass(other, Generic) and getattr(other, "_is_protocol", 
False):
+                # We avoid the slower path through annotationlib here because 
in most
+                # cases it should be unnecessary.
+                try:
+                    annos = base.__annotations__
+                except Exception:
+                    annos = _lazy_annotationlib.get_annotations(
+                        base, format=_lazy_annotationlib.Format.FORWARDREF
+                    )
+                if attr in annos:
+                    break
         else:
             return NotImplemented
     return True

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to