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