summaryrefslogtreecommitdiffstats
path: root/Lib/typing.py
diff options
context:
space:
mode:
authorAlex Waygood <Alex.Waygood@Gmail.com>2023-05-31 17:02:25 (GMT)
committerGitHub <noreply@github.com>2023-05-31 17:02:25 (GMT)
commitc05c31db8c9dfd708b9857bb57f8e5f3ce40266d (patch)
tree631aeb4d3767f70ebf917c0cea2306ca687af5d3 /Lib/typing.py
parentdf396b59af9d50892e5e30463300e8458cb84263 (diff)
downloadcpython-c05c31db8c9dfd708b9857bb57f8e5f3ce40266d.zip
cpython-c05c31db8c9dfd708b9857bb57f8e5f3ce40266d.tar.gz
cpython-c05c31db8c9dfd708b9857bb57f8e5f3ce40266d.tar.bz2
gh-105144: Runtime-checkable protocols: move all 'sanity checks' to `_ProtocolMeta.__subclasscheck__` (#105152)
Diffstat (limited to 'Lib/typing.py')
-rw-r--r--Lib/typing.py34
1 files changed, 15 insertions, 19 deletions
diff --git a/Lib/typing.py b/Lib/typing.py
index 8c87479..f589be7 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1727,7 +1727,7 @@ def _caller(depth=1, default='__main__'):
pass
return None
-def _allow_reckless_class_checks(depth=3):
+def _allow_reckless_class_checks(depth=2):
"""Allow instance and class checks for special stdlib modules.
The abc and functools modules indiscriminately call isinstance() and
@@ -1782,14 +1782,22 @@ class _ProtocolMeta(ABCMeta):
)
def __subclasscheck__(cls, other):
+ if not isinstance(other, type):
+ # Same error message as for issubclass(1, int).
+ raise TypeError('issubclass() arg 1 must be a class')
if (
getattr(cls, '_is_protocol', False)
- and not cls.__callable_proto_members_only__
- and not _allow_reckless_class_checks(depth=2)
+ and not _allow_reckless_class_checks()
):
- raise TypeError(
- "Protocols with non-method members don't support issubclass()"
- )
+ if not cls.__callable_proto_members_only__:
+ raise TypeError(
+ "Protocols with non-method members don't support issubclass()"
+ )
+ if not getattr(cls, '_is_runtime_protocol', False):
+ raise TypeError(
+ "Instance and class checks can only be used with "
+ "@runtime_checkable protocols"
+ )
return super().__subclasscheck__(other)
def __instancecheck__(cls, instance):
@@ -1801,7 +1809,7 @@ class _ProtocolMeta(ABCMeta):
if (
not getattr(cls, '_is_runtime_protocol', False) and
- not _allow_reckless_class_checks(depth=2)
+ not _allow_reckless_class_checks()
):
raise TypeError("Instance and class checks can only be used with"
" @runtime_checkable protocols")
@@ -1869,18 +1877,6 @@ class Protocol(Generic, metaclass=_ProtocolMeta):
if not cls.__dict__.get('_is_protocol', False):
return NotImplemented
- # First, perform various sanity checks.
- if not getattr(cls, '_is_runtime_protocol', False):
- if _allow_reckless_class_checks():
- return NotImplemented
- raise TypeError("Instance and class checks can only be used with"
- " @runtime_checkable protocols")
-
- if not isinstance(other, type):
- # Same error message as for issubclass(1, int).
- raise TypeError('issubclass() arg 1 must be a class')
-
- # Second, perform the actual structural compatibility check.
for attr in cls.__protocol_attrs__:
for base in other.__mro__:
# Check if the members appears in the class dictionary...