Skip to content

Commit 57aae62

Browse files
authored
Fix isinstance check for Generic classes on Python 3.7 (#188)
1 parent f62fa3f commit 57aae62

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Unreleased
2+
3+
- Fix regression in version 4.6.1 where comparing a generic class against a
4+
runtime-checkable protocol using `isinstance()` would cause `AttributeError`
5+
to be raised if using Python 3.7
6+
17
# Release 4.6.1 (May 23, 2023)
28

39
- Change deprecated `@runtime` to formal API `@runtime_checkable` in the error

src/test_typing_extensions.py

+23
Original file line numberDiff line numberDiff line change
@@ -2246,6 +2246,28 @@ class Foo: ...
22462246
del f.x
22472247
self.assertNotIsInstance(f, HasX)
22482248

2249+
def test_protocols_isinstance_generic_classes(self):
2250+
T = TypeVar("T")
2251+
2252+
class Foo(Generic[T]):
2253+
x: T
2254+
2255+
def __init__(self, x):
2256+
self.x = x
2257+
2258+
class Bar(Foo[int]):
2259+
...
2260+
2261+
@runtime_checkable
2262+
class HasX(Protocol):
2263+
x: int
2264+
2265+
foo = Foo(1)
2266+
self.assertIsInstance(foo, HasX)
2267+
2268+
bar = Bar(2)
2269+
self.assertIsInstance(bar, HasX)
2270+
22492271
def test_protocols_support_register(self):
22502272
@runtime_checkable
22512273
class P(Protocol):
@@ -4330,6 +4352,7 @@ class Y(Generic[T], NamedTuple):
43304352

43314353
a = A(3)
43324354
self.assertIs(type(a), G)
4355+
self.assertIsInstance(a, G)
43334356
self.assertEqual(a.x, 3)
43344357

43354358
things = "arguments" if sys.version_info >= (3, 11) else "parameters"

src/typing_extensions.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import typing
1010
import warnings
1111

12-
1312
__all__ = [
1413
# Super-special typing primitives.
1514
'Any',
@@ -659,7 +658,9 @@ def _proto_hook(cls, other):
659658
isinstance(annotations, collections.abc.Mapping)
660659
and attr in annotations
661660
and issubclass(other, (typing.Generic, _ProtocolMeta))
662-
and other._is_protocol
661+
# All subclasses of Generic have an _is_proto attribute on 3.8+
662+
# But not on 3.7
663+
and getattr(other, "_is_protocol", False)
663664
):
664665
break
665666
else:

0 commit comments

Comments
 (0)