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
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: