Skip to content

Commit f7835fc

Browse files
authored
gh-74690: Don't set special protocol attributes on non-protocol subclasses of protocols (#104622)
Don't set special protocol attributes on non-protocol subclasses of protocols
1 parent aab2a36 commit f7835fc

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

Lib/test/test_typing.py

+15
Original file line numberDiff line numberDiff line change
@@ -3167,6 +3167,21 @@ def meth(self): pass
31673167
self.assertIsInstance(NonPR(), PR)
31683168
self.assertIsSubclass(NonPR, PR)
31693169

3170+
self.assertNotIn("__protocol_attrs__", vars(NonP))
3171+
self.assertNotIn("__protocol_attrs__", vars(NonPR))
3172+
self.assertNotIn("__callable_proto_members_only__", vars(NonP))
3173+
self.assertNotIn("__callable_proto_members_only__", vars(NonPR))
3174+
3175+
acceptable_extra_attrs = {
3176+
'_is_protocol', '_is_runtime_protocol', '__parameters__',
3177+
'__subclasshook__', '__abstractmethods__', '_abc_impl',
3178+
'__init__', '__annotations__',
3179+
}
3180+
self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs)
3181+
self.assertLessEqual(
3182+
vars(NonPR).keys(), vars(D).keys() | acceptable_extra_attrs
3183+
)
3184+
31703185
def test_custom_subclasshook(self):
31713186
class P(Protocol):
31723187
x = 1

Lib/typing.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -1779,12 +1779,13 @@ class _ProtocolMeta(ABCMeta):
17791779
# but is necessary for several reasons...
17801780
def __init__(cls, *args, **kwargs):
17811781
super().__init__(*args, **kwargs)
1782-
cls.__protocol_attrs__ = _get_protocol_attrs(cls)
1783-
# PEP 544 prohibits using issubclass()
1784-
# with protocols that have non-method members.
1785-
cls.__callable_proto_members_only__ = all(
1786-
callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
1787-
)
1782+
if getattr(cls, "_is_protocol", False):
1783+
cls.__protocol_attrs__ = _get_protocol_attrs(cls)
1784+
# PEP 544 prohibits using issubclass()
1785+
# with protocols that have non-method members.
1786+
cls.__callable_proto_members_only__ = all(
1787+
callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
1788+
)
17881789

17891790
def __subclasscheck__(cls, other):
17901791
if (

0 commit comments

Comments
 (0)