]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-74690: Add more tests for runtime-checkable protocols (GH-103347)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 7 Apr 2023 17:47:49 +0000 (10:47 -0700)
committerGitHub <noreply@github.com>
Fri, 7 Apr 2023 17:47:49 +0000 (10:47 -0700)
(cherry picked from commit 800382a2b0980c21dfb2a8ac02aaf1e881f987b9)

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Lib/test/test_typing.py

index 4de24472c2c026b4450bc9b872ebf9d50b722f5a..46cff6ad5085b85ce3af7771662ea74f9140012e 100644 (file)
@@ -2572,6 +2572,22 @@ class ProtocolTests(BaseTestCase):
         class PG(Protocol[T]):
             def meth(x): ...
 
+        @runtime_checkable
+        class WeirdProto(Protocol):
+            meth = str.maketrans
+
+        @runtime_checkable
+        class WeirdProto2(Protocol):
+            meth = lambda *args, **kwargs: None
+
+        class CustomCallable:
+            def __call__(self, *args, **kwargs):
+                pass
+
+        @runtime_checkable
+        class WeirderProto(Protocol):
+            meth = CustomCallable()
+
         class BadP(Protocol):
             def meth(x): ...
 
@@ -2581,8 +2597,15 @@ class ProtocolTests(BaseTestCase):
         class C:
             def meth(x): ...
 
-        self.assertIsInstance(C(), P)
-        self.assertIsInstance(C(), PG)
+        class C2:
+            def __init__(self):
+                self.meth = lambda: None
+
+        for klass in C, C2:
+            for proto in P, PG, WeirdProto, WeirdProto2, WeirderProto:
+                with self.subTest(klass=klass.__name__, proto=proto.__name__):
+                    self.assertIsInstance(klass(), proto)
+
         with self.assertRaises(TypeError):
             isinstance(C(), PG[T])
         with self.assertRaises(TypeError):
@@ -2735,6 +2758,20 @@ class ProtocolTests(BaseTestCase):
         self.assertIsInstance(C(1), P)
         self.assertIsInstance(C(1), PG)
 
+    def test_protocols_isinstance_monkeypatching(self):
+        @runtime_checkable
+        class HasX(Protocol):
+            x: int
+
+        class Foo: ...
+
+        f = Foo()
+        self.assertNotIsInstance(f, HasX)
+        f.x = 42
+        self.assertIsInstance(f, HasX)
+        del f.x
+        self.assertNotIsInstance(f, HasX)
+
     def test_protocol_checks_after_subscript(self):
         class P(Protocol[T]): pass
         class C(P[T]): pass