Skip to content

Commit 53d5008

Browse files
committed
Fix issue when non runtime_protocol does not raise TypeError
1 parent 5010c04 commit 53d5008

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

Lib/test/test_typing.py

+11
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,17 @@ class CustomProtocol(TestCase, Protocol):
14221422
class CustomContextManager(typing.ContextManager, Protocol):
14231423
pass
14241424

1425+
def test_non_runtime_protocol_isinstance_check(self):
1426+
class P(Protocol):
1427+
pass
1428+
1429+
class A:
1430+
pass
1431+
1432+
with self.assertRaises(TypeError):
1433+
isinstance(A(), P)
1434+
1435+
14251436
class GenericTests(BaseTestCase):
14261437

14271438
def test_basics(self):

Lib/typing.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -1343,14 +1343,14 @@ def _no_init(self, *args, **kwargs):
13431343
raise TypeError('Protocols cannot be instantiated')
13441344

13451345

1346-
def _allow_reckless_class_checks():
1346+
def _allow_reckless_class_checks(depth=3):
13471347
"""Allow instance and class checks for special stdlib modules.
13481348
13491349
The abc and functools modules indiscriminately call isinstance() and
13501350
issubclass() on the whole MRO of a user class, which may contain protocols.
13511351
"""
13521352
try:
1353-
return sys._getframe(3).f_globals['__name__'] in ['abc', 'functools']
1353+
return sys._getframe(depth).f_globals['__name__'] in ['abc', 'functools']
13541354
except (AttributeError, ValueError): # For platforms without _getframe().
13551355
return True
13561356

@@ -1370,6 +1370,14 @@ class _ProtocolMeta(ABCMeta):
13701370
def __instancecheck__(cls, instance):
13711371
# We need this method for situations where attributes are
13721372
# assigned in __init__.
1373+
if (
1374+
getattr(cls, '_is_protocol', False) and
1375+
not getattr(cls, '_is_runtime_protocol', False) and
1376+
not _allow_reckless_class_checks(depth=2)
1377+
):
1378+
raise TypeError("Instance and class checks can only be used with"
1379+
" @runtime_checkable protocols")
1380+
13731381
if ((not getattr(cls, '_is_protocol', False) or
13741382
_is_callable_members_only(cls)) and
13751383
issubclass(instance.__class__, cls)):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix issue when non runtime_protocol does not raise TypeError and return
2+
False instead. Patch provided by Yurii Karabas.

0 commit comments

Comments
 (0)