Skip to content

Commit 5f72b82

Browse files
committed
Better fix
1 parent b5cc9cd commit 5f72b82

File tree

1 file changed

+15
-16
lines changed

1 file changed

+15
-16
lines changed

Lib/typing.py

+15-16
Original file line numberDiff line numberDiff line change
@@ -1775,8 +1775,8 @@ def _pickle_pskwargs(pskwargs):
17751775

17761776

17771777
class _ProtocolMeta(ABCMeta):
1778-
# This metaclass is really unfortunate and exists only because of
1779-
# the lack of __instancehook__.
1778+
# This metaclass is somewhat unfortunate,
1779+
# but is necessary for several reasons...
17801780
def __init__(cls, *args, **kwargs):
17811781
super().__init__(*args, **kwargs)
17821782
cls.__protocol_attrs__ = _get_protocol_attrs(cls)
@@ -1786,6 +1786,17 @@ def __init__(cls, *args, **kwargs):
17861786
callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
17871787
)
17881788

1789+
def __subclasscheck__(cls, other):
1790+
if (
1791+
getattr(cls, '_is_protocol', False)
1792+
and not cls.__callable_proto_members_only__
1793+
and not _allow_reckless_class_checks(depth=2)
1794+
):
1795+
raise TypeError(
1796+
"Protocols with non-method members don't support issubclass()"
1797+
)
1798+
return super().__subclasscheck__(other)
1799+
17891800
def __instancecheck__(cls, instance):
17901801
# We need this method for situations where attributes are
17911802
# assigned in __init__.
@@ -1798,17 +1809,10 @@ def __instancecheck__(cls, instance):
17981809
raise TypeError("Instance and class checks can only be used with"
17991810
" @runtime_checkable protocols")
18001811

1801-
# gh-104555: Don't call super().__instancecheck__ here,
1802-
# ABCMeta.__instancecheck__ would erroneously use it to populate the cache,
1803-
# which would cause incorrect results for *issubclass()* calls
1804-
if type.__instancecheck__(cls, instance):
1812+
if super().__instancecheck__(instance):
18051813
return True
18061814

18071815
if is_protocol_cls:
1808-
# Fast path for protocols with only callable members
1809-
if cls.__callable_proto_members_only__ and issubclass(type(instance), cls):
1810-
return True
1811-
18121816
getattr_static = _lazy_load_getattr_static()
18131817
for attr in cls.__protocol_attrs__:
18141818
try:
@@ -1820,7 +1824,7 @@ def __instancecheck__(cls, instance):
18201824
else:
18211825
return True
18221826

1823-
return super().__instancecheck__(instance)
1827+
return False
18241828

18251829

18261830
class Protocol(Generic, metaclass=_ProtocolMeta):
@@ -1876,11 +1880,6 @@ def _proto_hook(other):
18761880
raise TypeError("Instance and class checks can only be used with"
18771881
" @runtime_checkable protocols")
18781882

1879-
if not cls.__callable_proto_members_only__ :
1880-
if _allow_reckless_class_checks():
1881-
return NotImplemented
1882-
raise TypeError("Protocols with non-method members"
1883-
" don't support issubclass()")
18841883
if not isinstance(other, type):
18851884
# Same error message as for issubclass(1, int).
18861885
raise TypeError('issubclass() arg 1 must be a class')

0 commit comments

Comments
 (0)