@@ -1905,7 +1905,8 @@ class _TypingEllipsis:
19051905
19061906_TYPING_INTERNALS = frozenset ({
19071907 '__parameters__' , '__orig_bases__' , '__orig_class__' ,
1908- '_is_protocol' , '_is_runtime_protocol'
1908+ '_is_protocol' , '_is_runtime_protocol' , '__protocol_attrs__' ,
1909+ '__callable_proto_members_only__' ,
19091910})
19101911
19111912_SPECIAL_NAMES = frozenset ({
@@ -1935,11 +1936,6 @@ def _get_protocol_attrs(cls):
19351936 return attrs
19361937
19371938
1938- def _is_callable_members_only (cls , protocol_attrs ):
1939- # PEP 544 prohibits using issubclass() with protocols that have non-method members.
1940- return all (callable (getattr (cls , attr , None )) for attr in protocol_attrs )
1941-
1942-
19431939def _no_init_or_replace_init (self , * args , ** kwargs ):
19441940 cls = type (self )
19451941
@@ -2012,6 +2008,15 @@ def _lazy_load_getattr_static():
20122008class _ProtocolMeta (ABCMeta ):
20132009 # This metaclass is really unfortunate and exists only because of
20142010 # the lack of __instancehook__.
2011+ def __init__ (cls , * args , ** kwargs ):
2012+ super ().__init__ (* args , ** kwargs )
2013+ cls .__protocol_attrs__ = _get_protocol_attrs (cls )
2014+ # PEP 544 prohibits using issubclass()
2015+ # with protocols that have non-method members.
2016+ cls .__callable_proto_members_only__ = all (
2017+ callable (getattr (cls , attr , None )) for attr in cls .__protocol_attrs__
2018+ )
2019+
20152020 def __instancecheck__ (cls , instance ):
20162021 # We need this method for situations where attributes are
20172022 # assigned in __init__.
@@ -2029,7 +2034,7 @@ def __instancecheck__(cls, instance):
20292034
20302035 if is_protocol_cls :
20312036 getattr_static = _lazy_load_getattr_static ()
2032- for attr in _get_protocol_attrs ( cls ) :
2037+ for attr in cls . __protocol_attrs__ :
20332038 try :
20342039 val = getattr_static (instance , attr )
20352040 except AttributeError :
@@ -2095,9 +2100,7 @@ def _proto_hook(other):
20952100 raise TypeError ("Instance and class checks can only be used with"
20962101 " @runtime_checkable protocols" )
20972102
2098- protocol_attrs = _get_protocol_attrs (cls )
2099-
2100- if not _is_callable_members_only (cls , protocol_attrs ):
2103+ if not cls .__callable_proto_members_only__ :
21012104 if _allow_reckless_class_checks ():
21022105 return NotImplemented
21032106 raise TypeError ("Protocols with non-method members"
@@ -2107,7 +2110,7 @@ def _proto_hook(other):
21072110 raise TypeError ('issubclass() arg 1 must be a class' )
21082111
21092112 # Second, perform the actual structural compatibility check.
2110- for attr in protocol_attrs :
2113+ for attr in cls . __protocol_attrs__ :
21112114 for base in other .__mro__ :
21122115 # Check if the members appears in the class dictionary...
21132116 if attr in base .__dict__ :
0 commit comments