[Python-checkins] gh-74690: Don't set special protocol attributes on non-protocol subclasses of protocols (#104622)

AlexWaygood webhook-mailer at python.org
Thu May 18 19:34:48 EDT 2023


https://github.com/python/cpython/commit/f7835fc7e9617cefd87e72002916e258f589c857
commit: f7835fc7e9617cefd87e72002916e258f589c857
branch: main
author: Alex Waygood <Alex.Waygood at Gmail.com>
committer: AlexWaygood <Alex.Waygood at Gmail.com>
date: 2023-05-19T00:34:40+01:00
summary:

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

files:
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index bf038bf143a6..450c85967dd7 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -3167,6 +3167,21 @@ def meth(self): pass
         self.assertIsInstance(NonPR(), PR)
         self.assertIsSubclass(NonPR, PR)
 
+        self.assertNotIn("__protocol_attrs__", vars(NonP))
+        self.assertNotIn("__protocol_attrs__", vars(NonPR))
+        self.assertNotIn("__callable_proto_members_only__", vars(NonP))
+        self.assertNotIn("__callable_proto_members_only__", vars(NonPR))
+
+        acceptable_extra_attrs = {
+            '_is_protocol', '_is_runtime_protocol', '__parameters__',
+            '__subclasshook__', '__abstractmethods__', '_abc_impl',
+            '__init__', '__annotations__',
+        }
+        self.assertLessEqual(vars(NonP).keys(), vars(C).keys() | acceptable_extra_attrs)
+        self.assertLessEqual(
+            vars(NonPR).keys(), vars(D).keys() | acceptable_extra_attrs
+        )
+
     def test_custom_subclasshook(self):
         class P(Protocol):
             x = 1
diff --git a/Lib/typing.py b/Lib/typing.py
index 91b5fe5b87e6..b60eb94351f9 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1779,12 +1779,13 @@ class _ProtocolMeta(ABCMeta):
     # but is necessary for several reasons...
     def __init__(cls, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        cls.__protocol_attrs__ = _get_protocol_attrs(cls)
-        # PEP 544 prohibits using issubclass()
-        # with protocols that have non-method members.
-        cls.__callable_proto_members_only__ = all(
-            callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
-        )
+        if getattr(cls, "_is_protocol", False):
+            cls.__protocol_attrs__ = _get_protocol_attrs(cls)
+            # PEP 544 prohibits using issubclass()
+            # with protocols that have non-method members.
+            cls.__callable_proto_members_only__ = all(
+                callable(getattr(cls, attr, None)) for attr in cls.__protocol_attrs__
+            )
 
     def __subclasscheck__(cls, other):
         if (



More information about the Python-checkins mailing list