@@ -2572,6 +2572,22 @@ def meth(x): ...
2572
2572
class PG (Protocol [T ]):
2573
2573
def meth (x ): ...
2574
2574
2575
+ @runtime_checkable
2576
+ class WeirdProto (Protocol ):
2577
+ meth = str .maketrans
2578
+
2579
+ @runtime_checkable
2580
+ class WeirdProto2 (Protocol ):
2581
+ meth = lambda * args , ** kwargs : None
2582
+
2583
+ class CustomCallable :
2584
+ def __call__ (self , * args , ** kwargs ):
2585
+ pass
2586
+
2587
+ @runtime_checkable
2588
+ class WeirderProto (Protocol ):
2589
+ meth = CustomCallable ()
2590
+
2575
2591
class BadP (Protocol ):
2576
2592
def meth (x ): ...
2577
2593
@@ -2581,8 +2597,15 @@ def meth(x): ...
2581
2597
class C :
2582
2598
def meth (x ): ...
2583
2599
2584
- self .assertIsInstance (C (), P )
2585
- self .assertIsInstance (C (), PG )
2600
+ class C2 :
2601
+ def __init__ (self ):
2602
+ self .meth = lambda : None
2603
+
2604
+ for klass in C , C2 :
2605
+ for proto in P , PG , WeirdProto , WeirdProto2 , WeirderProto :
2606
+ with self .subTest (klass = klass .__name__ , proto = proto .__name__ ):
2607
+ self .assertIsInstance (klass (), proto )
2608
+
2586
2609
with self .assertRaises (TypeError ):
2587
2610
isinstance (C (), PG [T ])
2588
2611
with self .assertRaises (TypeError ):
@@ -2735,6 +2758,20 @@ def __init__(self, x):
2735
2758
self .assertIsInstance (C (1 ), P )
2736
2759
self .assertIsInstance (C (1 ), PG )
2737
2760
2761
+ def test_protocols_isinstance_monkeypatching (self ):
2762
+ @runtime_checkable
2763
+ class HasX (Protocol ):
2764
+ x : int
2765
+
2766
+ class Foo : ...
2767
+
2768
+ f = Foo ()
2769
+ self .assertNotIsInstance (f , HasX )
2770
+ f .x = 42
2771
+ self .assertIsInstance (f , HasX )
2772
+ del f .x
2773
+ self .assertNotIsInstance (f , HasX )
2774
+
2738
2775
def test_protocol_checks_after_subscript (self ):
2739
2776
class P (Protocol [T ]): pass
2740
2777
class C (P [T ]): pass
0 commit comments