@@ -2577,6 +2577,22 @@ def meth(x): ...
25772577 class PG (Protocol [T ]):
25782578 def meth (x ): ...
25792579
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+
25802596 class BadP (Protocol ):
25812597 def meth (x ): ...
25822598
@@ -2586,8 +2602,15 @@ def meth(x): ...
25862602 class C :
25872603 def meth (x ): ...
25882604
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+
25912614 with self .assertRaises (TypeError ):
25922615 isinstance (C (), PG [T ])
25932616 with self .assertRaises (TypeError ):
@@ -2829,6 +2852,20 @@ def __init__(self, x):
28292852 self .assertIsInstance (C (1 ), P )
28302853 self .assertIsInstance (C (1 ), PG )
28312854
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+
28322869 def test_protocol_checks_after_subscript (self ):
28332870 class P (Protocol [T ]): pass
28342871 class C (P [T ]): pass
0 commit comments