diff options
author | Alex Waygood <Alex.Waygood@Gmail.com> | 2023-05-31 17:02:25 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-31 17:02:25 (GMT) |
commit | c05c31db8c9dfd708b9857bb57f8e5f3ce40266d (patch) | |
tree | 631aeb4d3767f70ebf917c0cea2306ca687af5d3 /Lib/typing.py | |
parent | df396b59af9d50892e5e30463300e8458cb84263 (diff) | |
download | cpython-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.py | 34 |
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... |