]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-110682: Ignore `__match_args__` from `__instancecheck__` in protocols (#110683)
authorNikita Sobolev <mail@sobolevn.me>
Thu, 12 Oct 2023 02:20:20 +0000 (05:20 +0300)
committerGitHub <noreply@github.com>
Thu, 12 Oct 2023 02:20:20 +0000 (19:20 -0700)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Lib/test/test_typing.py
Lib/typing.py
Misc/NEWS.d/next/Library/2023-10-11-11-00-11.gh-issue-110682.bXRFaX.rst [new file with mode: 0644]

index c24cf3bc776fc1e9ac12599e2288d5874b82dcee..66812f317c76566868d5c4d974d57eeefce39228 100644 (file)
@@ -3801,6 +3801,39 @@ class ProtocolTests(BaseTestCase):
 
             self.assertIsInstance(E(), D)
 
+    def test_runtime_checkable_with_match_args(self):
+        @runtime_checkable
+        class P_regular(Protocol):
+            x: int
+            y: int
+
+        @runtime_checkable
+        class P_match(Protocol):
+            __match_args__ = ('x', 'y')
+            x: int
+            y: int
+
+        class Regular:
+            def __init__(self, x: int, y: int):
+                self.x = x
+                self.y = y
+
+        class WithMatch:
+            __match_args__ = ('x', 'y', 'z')
+            def __init__(self, x: int, y: int, z: int):
+                self.x = x
+                self.y = y
+                self.z = z
+
+        class Nope: ...
+
+        self.assertIsInstance(Regular(1, 2), P_regular)
+        self.assertIsInstance(Regular(1, 2), P_match)
+        self.assertIsInstance(WithMatch(1, 2, 3), P_regular)
+        self.assertIsInstance(WithMatch(1, 2, 3), P_match)
+        self.assertNotIsInstance(Nope(), P_regular)
+        self.assertNotIsInstance(Nope(), P_match)
+
     def test_supports_int(self):
         self.assertIsSubclass(int, typing.SupportsInt)
         self.assertNotIsSubclass(str, typing.SupportsInt)
index d1f371377b88f802262106a7431c90819392b26b..14845b36028ca12b7f2d07cd1cba875341383287 100644 (file)
@@ -1669,7 +1669,8 @@ _TYPING_INTERNALS = frozenset({
 _SPECIAL_NAMES = frozenset({
     '__abstractmethods__', '__annotations__', '__dict__', '__doc__',
     '__init__', '__module__', '__new__', '__slots__',
-    '__subclasshook__', '__weakref__', '__class_getitem__'
+    '__subclasshook__', '__weakref__', '__class_getitem__',
+    '__match_args__',
 })
 
 # These special attributes will be not collected as protocol members.
diff --git a/Misc/NEWS.d/next/Library/2023-10-11-11-00-11.gh-issue-110682.bXRFaX.rst b/Misc/NEWS.d/next/Library/2023-10-11-11-00-11.gh-issue-110682.bXRFaX.rst
new file mode 100644 (file)
index 0000000..b935d9a
--- /dev/null
@@ -0,0 +1,4 @@
+:func:`runtime-checkable protocols <typing.runtime_checkable>` used
+to consider ``__match_args__`` a protocol member in
+``__instancecheck__`` if it was present on the protocol. Now, this attribute is
+ignored if it is present.