Skip to content

Commit a2c6c88

Browse files
authored
Don't reimplement runtime_checkable on py38+ (python#194)
1 parent d826561 commit a2c6c88

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Unreleased
22

3+
- Due to changes in the implementation of `typing_extensions.Protocol`,
4+
`typing.runtime_checkable` can now be used on `typing_extensions.Protocol`
5+
(previously, users had to use `typing_extensions.runtime_checkable` if they
6+
were using `typing_extensions.Protocol`).
37
- Align the implementation of `TypedDict` with the implementation in the
48
standard library on Python 3.9 and higher.
59
`typing_extensions.TypedDict` is now a function instead of a class. The

src/test_typing_extensions.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1783,6 +1783,22 @@ def __init__(self):
17831783
self.assertIsInstance(Bar(), Foo)
17841784
self.assertNotIsInstance(object(), Foo)
17851785

1786+
@skipUnless(
1787+
hasattr(typing, "runtime_checkable"),
1788+
"Test is only relevant if typing.runtime_checkable exists"
1789+
)
1790+
def test_typing_dot_runtimecheckable_on_Protocol(self):
1791+
@typing.runtime_checkable
1792+
class Foo(Protocol):
1793+
x: int
1794+
1795+
class Bar:
1796+
def __init__(self):
1797+
self.x = 42
1798+
1799+
self.assertIsInstance(Bar(), Foo)
1800+
self.assertNotIsInstance(object(), Foo)
1801+
17861802
def test_no_instantiation(self):
17871803
class P(Protocol): pass
17881804
with self.assertRaises(TypeError):
@@ -4743,7 +4759,7 @@ def test_typing_extensions_defers_when_possible(self):
47434759
exclude |= {'final', 'Any', 'NewType'}
47444760
if sys.version_info < (3, 12):
47454761
exclude |= {
4746-
'Protocol', 'runtime_checkable', 'SupportsAbs', 'SupportsBytes',
4762+
'Protocol', 'SupportsAbs', 'SupportsBytes',
47474763
'SupportsComplex', 'SupportsFloat', 'SupportsIndex', 'SupportsInt',
47484764
'SupportsRound', 'TypedDict', 'is_typeddict', 'NamedTuple', 'Unpack',
47494765
}

src/typing_extensions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,6 @@ def _caller(depth=2):
545545
# so we backport the 3.12 version of Protocol to Python <=3.11
546546
if sys.version_info >= (3, 12):
547547
Protocol = typing.Protocol
548-
runtime_checkable = typing.runtime_checkable
549548
else:
550549
def _allow_reckless_class_checks(depth=3):
551550
"""Allow instance and class checks for special stdlib modules.
@@ -805,6 +804,10 @@ def __init_subclass__(cls, *args, **kwargs):
805804
if cls.__init__ is Protocol.__init__:
806805
cls.__init__ = _no_init
807806

807+
808+
if sys.version_info >= (3, 8):
809+
runtime_checkable = typing.runtime_checkable
810+
else:
808811
def runtime_checkable(cls):
809812
"""Mark a protocol class as a runtime protocol, so that it
810813
can be used with isinstance() and issubclass(). Raise TypeError

0 commit comments

Comments
 (0)