mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
gh-105144: Runtime-checkable protocols: move all 'sanity checks' to _ProtocolMeta.__subclasscheck__
(#105152)
This commit is contained in:
parent
df396b59af
commit
c05c31db8c
3 changed files with 111 additions and 37 deletions
|
@ -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...
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue