@@ -1931,9 +1931,9 @@ def _get_protocol_attrs(cls):
19311931 return attrs
19321932
19331933
1934- def _is_callable_members_only (cls ):
1934+ def _is_callable_members_only (cls , protocol_attrs ):
19351935 # PEP 544 prohibits using issubclass() with protocols that have non-method members.
1936- return all (callable (getattr (cls , attr , None )) for attr in _get_protocol_attrs ( cls ) )
1936+ return all (callable (getattr (cls , attr , None )) for attr in protocol_attrs )
19371937
19381938
19391939def _no_init_or_replace_init (self , * args , ** kwargs ):
@@ -2000,24 +2000,32 @@ class _ProtocolMeta(ABCMeta):
20002000 def __instancecheck__ (cls , instance ):
20012001 # We need this method for situations where attributes are
20022002 # assigned in __init__.
2003+ is_protocol_cls = getattr (cls , "_is_protocol" , False )
20032004 if (
2004- getattr ( cls , '_is_protocol' , False ) and
2005+ is_protocol_cls and
20052006 not getattr (cls , '_is_runtime_protocol' , False ) and
20062007 not _allow_reckless_class_checks (depth = 2 )
20072008 ):
20082009 raise TypeError ("Instance and class checks can only be used with"
20092010 " @runtime_checkable protocols" )
20102011
2011- if ((not getattr (cls , '_is_protocol' , False ) or
2012- _is_callable_members_only (cls )) and
2013- issubclass (instance .__class__ , cls )):
2012+ if not is_protocol_cls and issubclass (instance .__class__ , cls ):
20142013 return True
2015- if cls ._is_protocol :
2014+
2015+ protocol_attrs = _get_protocol_attrs (cls )
2016+
2017+ if (
2018+ _is_callable_members_only (cls , protocol_attrs )
2019+ and issubclass (instance .__class__ , cls )
2020+ ):
2021+ return True
2022+
2023+ if is_protocol_cls :
20162024 if all (hasattr (instance , attr ) and
20172025 # All *methods* can be blocked by setting them to None.
20182026 (not callable (getattr (cls , attr , None )) or
20192027 getattr (instance , attr ) is not None )
2020- for attr in _get_protocol_attrs ( cls ) ):
2028+ for attr in protocol_attrs ):
20212029 return True
20222030 return super ().__instancecheck__ (instance )
20232031
@@ -2074,7 +2082,10 @@ def _proto_hook(other):
20742082 return NotImplemented
20752083 raise TypeError ("Instance and class checks can only be used with"
20762084 " @runtime_checkable protocols" )
2077- if not _is_callable_members_only (cls ):
2085+
2086+ protocol_attrs = _get_protocol_attrs (cls )
2087+
2088+ if not _is_callable_members_only (cls , protocol_attrs ):
20782089 if _allow_reckless_class_checks ():
20792090 return NotImplemented
20802091 raise TypeError ("Protocols with non-method members"
@@ -2084,7 +2095,7 @@ def _proto_hook(other):
20842095 raise TypeError ('issubclass() arg 1 must be a class' )
20852096
20862097 # Second, perform the actual structural compatibility check.
2087- for attr in _get_protocol_attrs ( cls ) :
2098+ for attr in protocol_attrs :
20882099 for base in other .__mro__ :
20892100 # Check if the members appears in the class dictionary...
20902101 if attr in base .__dict__ :
0 commit comments