diff options
author | Alex Waygood <Alex.Waygood@Gmail.com> | 2023-05-17 23:43:12 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-17 23:43:12 (GMT) |
commit | b27fe67f3c643e174c3619b669228ef34b6d87ee (patch) | |
tree | a296ecb2c5fd849e2bfb40a600d27d2ea6eac982 /Lib/typing.py | |
parent | 2f369cafeeb4a4886b00396abd8a5f33e555e1c3 (diff) | |
download | cpython-b27fe67f3c643e174c3619b669228ef34b6d87ee.zip cpython-b27fe67f3c643e174c3619b669228ef34b6d87ee.tar.gz cpython-b27fe67f3c643e174c3619b669228ef34b6d87ee.tar.bz2 |
gh-104555: Runtime-checkable protocols: Don't let previous calls to `isinstance()` influence whether `issubclass()` raises an exception (#104559)
Co-authored-by: Carl Meyer <carl@oddbird.net>
Diffstat (limited to 'Lib/typing.py')
-rw-r--r-- | Lib/typing.py | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/Lib/typing.py b/Lib/typing.py index 8210730..91b5fe5 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1775,8 +1775,8 @@ del _pickle_psargs, _pickle_pskwargs class _ProtocolMeta(ABCMeta): - # This metaclass is really unfortunate and exists only because of - # the lack of __instancehook__. + # This metaclass is somewhat unfortunate, + # but is necessary for several reasons... def __init__(cls, *args, **kwargs): super().__init__(*args, **kwargs) cls.__protocol_attrs__ = _get_protocol_attrs(cls) @@ -1786,6 +1786,17 @@ class _ProtocolMeta(ABCMeta): callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__ ) + def __subclasscheck__(cls, other): + if ( + getattr(cls, '_is_protocol', False) + and not cls.__callable_proto_members_only__ + and not _allow_reckless_class_checks(depth=2) + ): + raise TypeError( + "Protocols with non-method members don't support issubclass()" + ) + return super().__subclasscheck__(other) + def __instancecheck__(cls, instance): # We need this method for situations where attributes are # assigned in __init__. @@ -1869,11 +1880,6 @@ class Protocol(Generic, metaclass=_ProtocolMeta): raise TypeError("Instance and class checks can only be used with" " @runtime_checkable protocols") - if not cls.__callable_proto_members_only__ : - if _allow_reckless_class_checks(): - return NotImplemented - raise TypeError("Protocols with non-method members" - " don't support issubclass()") if not isinstance(other, type): # Same error message as for issubclass(1, int). raise TypeError('issubclass() arg 1 must be a class') |