@@ -2577,6 +2577,22 @@ def meth(x): ...
2577
2577
class PG (Protocol [T ]):
2578
2578
def meth (x ): ...
2579
2579
2580
+ @runtime_checkable
2581
+ class WeirdProto (Protocol ):
2582
+ meth = str .maketrans
2583
+
2584
+ @runtime_checkable
2585
+ class WeirdProto2 (Protocol ):
2586
+ meth = lambda * args , ** kwargs : None
2587
+
2588
+ class CustomCallable :
2589
+ def __call__ (self , * args , ** kwargs ):
2590
+ pass
2591
+
2592
+ @runtime_checkable
2593
+ class WeirderProto (Protocol ):
2594
+ meth = CustomCallable ()
2595
+
2580
2596
class BadP (Protocol ):
2581
2597
def meth (x ): ...
2582
2598
@@ -2586,8 +2602,15 @@ def meth(x): ...
2586
2602
class C :
2587
2603
def meth (x ): ...
2588
2604
2589
- self .assertIsInstance (C (), P )
2590
- self .assertIsInstance (C (), PG )
2605
+ class C2 :
2606
+ def __init__ (self ):
2607
+ self .meth = lambda : None
2608
+
2609
+ for klass in C , C2 :
2610
+ for proto in P , PG , WeirdProto , WeirdProto2 , WeirderProto :
2611
+ with self .subTest (klass = klass .__name__ , proto = proto .__name__ ):
2612
+ self .assertIsInstance (klass (), proto )
2613
+
2591
2614
with self .assertRaises (TypeError ):
2592
2615
isinstance (C (), PG [T ])
2593
2616
with self .assertRaises (TypeError ):
@@ -2829,6 +2852,20 @@ def __init__(self, x):
2829
2852
self .assertIsInstance (C (1 ), P )
2830
2853
self .assertIsInstance (C (1 ), PG )
2831
2854
2855
+ def test_protocols_isinstance_monkeypatching (self ):
2856
+ @runtime_checkable
2857
+ class HasX (Protocol ):
2858
+ x : int
2859
+
2860
+ class Foo : ...
2861
+
2862
+ f = Foo ()
2863
+ self .assertNotIsInstance (f , HasX )
2864
+ f .x = 42
2865
+ self .assertIsInstance (f , HasX )
2866
+ del f .x
2867
+ self .assertNotIsInstance (f , HasX )
2868
+
2832
2869
def test_protocol_checks_after_subscript (self ):
2833
2870
class P (Protocol [T ]): pass
2834
2871
class C (P [T ]): pass
0 commit comments