@@ -2572,6 +2572,22 @@ def meth(x): ...
25722572 class PG (Protocol [T ]):
25732573 def meth (x ): ...
25742574
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+
25752591 class BadP (Protocol ):
25762592 def meth (x ): ...
25772593
@@ -2581,8 +2597,15 @@ def meth(x): ...
25812597 class C :
25822598 def meth (x ): ...
25832599
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+
25862609 with self .assertRaises (TypeError ):
25872610 isinstance (C (), PG [T ])
25882611 with self .assertRaises (TypeError ):
@@ -2735,6 +2758,20 @@ def __init__(self, x):
27352758 self .assertIsInstance (C (1 ), P )
27362759 self .assertIsInstance (C (1 ), PG )
27372760
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+
27382775 def test_protocol_checks_after_subscript (self ):
27392776 class P (Protocol [T ]): pass
27402777 class C (P [T ]): pass
0 commit comments