@@ -1825,8 +1825,8 @@ class _TypingEllipsis:
18251825
18261826_TYPING_INTERNALS = frozenset ({
18271827 '__parameters__' , '__orig_bases__' , '__orig_class__' ,
1828- '_is_protocol' , '_is_runtime_protocol' , '__protocol_attrs__ ' ,
1829- '__non_callable_proto_members__' , '__type_params__' ,
1828+ '_is_protocol' , '_is_runtime_protocol' , '_is_deprecated_inherited_runtime_protocol ' ,
1829+ '__protocol_attrs__' , ' __non_callable_proto_members__' , '__type_params__' ,
18301830})
18311831
18321832_SPECIAL_NAMES = frozenset ({
@@ -2015,6 +2015,16 @@ def __subclasscheck__(cls, other):
20152015 "Instance and class checks can only be used with "
20162016 "@runtime_checkable protocols"
20172017 )
2018+ if getattr (cls , '_is_deprecated_inherited_runtime_protocol' , False ):
2019+ # See GH-132604.
2020+ import warnings
2021+ depr_message = (
2022+ f"{ cls !r} isn't explicitly decorated with @runtime_checkable but "
2023+ "it is used in issubclass() or isinstance(). Instance and class "
2024+ "checks can only be used with @runtime_checkable protocols. "
2025+ "This may stop working in Python 3.20."
2026+ )
2027+ warnings .warn (depr_message , category = DeprecationWarning , stacklevel = 2 )
20182028 if (
20192029 # this attribute is set by @runtime_checkable:
20202030 cls .__non_callable_proto_members__
@@ -2044,6 +2054,18 @@ def __instancecheck__(cls, instance):
20442054 raise TypeError ("Instance and class checks can only be used with"
20452055 " @runtime_checkable protocols" )
20462056
2057+ if getattr (cls , '_is_deprecated_inherited_runtime_protocol' , False ):
2058+ # See GH-132604.
2059+ import warnings
2060+
2061+ depr_message = (
2062+ f"{ cls !r} isn't explicitly decorated with @runtime_checkable but "
2063+ "it is used in issubclass() or isinstance(). Instance and class "
2064+ "checks can only be used with @runtime_checkable protocols. "
2065+ "This may stop working in Python 3.20."
2066+ )
2067+ warnings .warn (depr_message , category = DeprecationWarning , stacklevel = 2 )
2068+
20472069 if _abc_instancecheck (cls , instance ):
20482070 return True
20492071
@@ -2136,6 +2158,10 @@ def __init_subclass__(cls, *args, **kwargs):
21362158 if not cls .__dict__ .get ('_is_protocol' , False ):
21372159 cls ._is_protocol = any (b is Protocol for b in cls .__bases__ )
21382160
2161+ # Mark inherited runtime checkability (deprecated). See GH-132604.
2162+ if cls ._is_protocol and getattr (cls , '_is_runtime_protocol' , False ):
2163+ cls ._is_deprecated_inherited_runtime_protocol = True
2164+
21392165 # Set (or override) the protocol subclass hook.
21402166 if '__subclasshook__' not in cls .__dict__ :
21412167 cls .__subclasshook__ = _proto_hook
@@ -2282,6 +2308,9 @@ def close(self): ...
22822308 raise TypeError ('@runtime_checkable can be only applied to protocol classes,'
22832309 ' got %r' % cls )
22842310 cls ._is_runtime_protocol = True
2311+ # See GH-132604.
2312+ if hasattr (cls , '_is_deprecated_inherited_runtime_protocol' ):
2313+ cls ._is_deprecated_inherited_runtime_protocol = False
22852314 # PEP 544 prohibits using issubclass()
22862315 # with protocols that have non-method members.
22872316 # See gh-113320 for why we compute this attribute here,
0 commit comments