11import contextlib
22import collections
3+ import collections .abc
34from collections import defaultdict
45from functools import lru_cache , wraps
56import inspect
@@ -2722,19 +2723,41 @@ def x(self): ...
27222723 self .assertIsSubclass (C , PG )
27232724 self .assertIsSubclass (BadP , PG )
27242725
2725- with self .assertRaises (TypeError ):
2726+ no_subscripted_generics = (
2727+ "Subscripted generics cannot be used with class and instance checks"
2728+ )
2729+
2730+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
27262731 issubclass (C , PG [T ])
2727- with self .assertRaises (TypeError ):
2732+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
27282733 issubclass (C , PG [C ])
2729- with self .assertRaises (TypeError ):
2734+
2735+ only_runtime_checkable_protocols = (
2736+ "Instance and class checks can only be used with "
2737+ "@runtime_checkable protocols"
2738+ )
2739+
2740+ with self .assertRaisesRegex (TypeError , only_runtime_checkable_protocols ):
27302741 issubclass (C , BadP )
2731- with self .assertRaises (TypeError ):
2742+ with self .assertRaisesRegex (TypeError , only_runtime_checkable_protocols ):
27322743 issubclass (C , BadPG )
2733- with self .assertRaises (TypeError ):
2744+
2745+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
27342746 issubclass (P , PG [T ])
2735- with self .assertRaises (TypeError ):
2747+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
27362748 issubclass (PG , PG [int ])
27372749
2750+ only_classes_allowed = r"issubclass\(\) arg 1 must be a class"
2751+
2752+ with self .assertRaisesRegex (TypeError , only_classes_allowed ):
2753+ issubclass (1 , P )
2754+ with self .assertRaisesRegex (TypeError , only_classes_allowed ):
2755+ issubclass (1 , PG )
2756+ with self .assertRaisesRegex (TypeError , only_classes_allowed ):
2757+ issubclass (1 , BadP )
2758+ with self .assertRaisesRegex (TypeError , only_classes_allowed ):
2759+ issubclass (1 , BadPG )
2760+
27382761 def test_protocols_issubclass_non_callable (self ):
27392762 class C :
27402763 x = 1
@@ -2743,12 +2766,19 @@ class C:
27432766 class PNonCall (Protocol ):
27442767 x = 1
27452768
2746- with self .assertRaises (TypeError ):
2769+ non_callable_members_illegal = (
2770+ "Protocols with non-method members don't support issubclass()"
2771+ )
2772+
2773+ with self .assertRaisesRegex (TypeError , non_callable_members_illegal ):
27472774 issubclass (C , PNonCall )
2775+
27482776 self .assertIsInstance (C (), PNonCall )
27492777 PNonCall .register (C )
2750- with self .assertRaises (TypeError ):
2778+
2779+ with self .assertRaisesRegex (TypeError , non_callable_members_illegal ):
27512780 issubclass (C , PNonCall )
2781+
27522782 self .assertIsInstance (C (), PNonCall )
27532783
27542784 # check that non-protocol subclasses are not affected
@@ -2759,7 +2789,8 @@ class D(PNonCall): ...
27592789 D .register (C )
27602790 self .assertIsSubclass (C , D )
27612791 self .assertIsInstance (C (), D )
2762- with self .assertRaises (TypeError ):
2792+
2793+ with self .assertRaisesRegex (TypeError , non_callable_members_illegal ):
27632794 issubclass (D , PNonCall )
27642795
27652796 def test_no_weird_caching_with_issubclass_after_isinstance (self ):
@@ -2778,7 +2809,10 @@ def __init__(self) -> None:
27782809 # as the cached result of the isinstance() check immediately above
27792810 # would mean the issubclass() call would short-circuit
27802811 # before we got to the "raise TypeError" line
2781- with self .assertRaises (TypeError ):
2812+ with self .assertRaisesRegex (
2813+ TypeError ,
2814+ "Protocols with non-method members don't support issubclass()"
2815+ ):
27822816 issubclass (Eggs , Spam )
27832817
27842818 def test_no_weird_caching_with_issubclass_after_isinstance_2 (self ):
@@ -2795,7 +2829,10 @@ class Eggs: ...
27952829 # as the cached result of the isinstance() check immediately above
27962830 # would mean the issubclass() call would short-circuit
27972831 # before we got to the "raise TypeError" line
2798- with self .assertRaises (TypeError ):
2832+ with self .assertRaisesRegex (
2833+ TypeError ,
2834+ "Protocols with non-method members don't support issubclass()"
2835+ ):
27992836 issubclass (Eggs , Spam )
28002837
28012838 def test_no_weird_caching_with_issubclass_after_isinstance_3 (self ):
@@ -2816,7 +2853,10 @@ def __getattr__(self, attr):
28162853 # as the cached result of the isinstance() check immediately above
28172854 # would mean the issubclass() call would short-circuit
28182855 # before we got to the "raise TypeError" line
2819- with self .assertRaises (TypeError ):
2856+ with self .assertRaisesRegex (
2857+ TypeError ,
2858+ "Protocols with non-method members don't support issubclass()"
2859+ ):
28202860 issubclass (Eggs , Spam )
28212861
28222862 def test_no_weird_caching_with_issubclass_after_isinstance_pep695 (self ):
@@ -2835,7 +2875,10 @@ def __init__(self, x: T) -> None:
28352875 # as the cached result of the isinstance() check immediately above
28362876 # would mean the issubclass() call would short-circuit
28372877 # before we got to the "raise TypeError" line
2838- with self .assertRaises (TypeError ):
2878+ with self .assertRaisesRegex (
2879+ TypeError ,
2880+ "Protocols with non-method members don't support issubclass()"
2881+ ):
28392882 issubclass (Eggs , Spam )
28402883
28412884 def test_protocols_isinstance (self ):
@@ -2883,13 +2926,21 @@ def __init__(self):
28832926 with self .subTest (klass = klass .__name__ , proto = proto .__name__ ):
28842927 self .
BB4C
assertIsInstance (klass (), proto )
28852928
2886- with self .assertRaises (TypeError ):
2929+ no_subscripted_generics = "Subscripted generics cannot be used with class and instance checks"
2930+
2931+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
28872932 isinstance (C (), PG [T ])
2888- with self .assertRaises (TypeError ):
2933+ with self .assertRaisesRegex (TypeError , no_subscripted_generics ):
28892934 isinstance (C (), PG [C ])
2890- with self .assertRaises (TypeError ):
2935+
2936+ only_runtime_checkable_msg = (
2937+ "Instance and class checks can only be used "
2938+ "with @runtime_checkable protocols"
2939+ )
2940+
2941+ with self .assertRaisesRegex (TypeError , only_runtime_checkable_msg ):
28912942 isinstance (C (), BadP )
2892- with self .assertRaises (TypeError ):
2943+ with self .assertRaisesRegex (TypeError , only_runtime_checkable_msg ):
28932944 isinstance (C (), BadPG )
28942945
28952946 def test_protocols_isinstance_properties_and_descriptors (self ):
@@ -3274,7 +3325,7 @@ class P(Protocol):
32743325
32753326 class C : pass
32763327
3277- with self .assertRaises (TypeError ):
3328+ with self .assertRaisesRegex (TypeError , r"issubclass\(\) arg 1 must be a class" ):
32783329 issubclass (C (), P )
32793330
32803331 def test_defining_generic_protocols (self ):
@@ -3654,6 +3705,28 @@ def __init__(self):
36543705
36553706 Foo () # Previously triggered RecursionError
36563707
3708+ def test_interaction_with_isinstance_checks_on_superclasses_with_ABCMeta (self ):
3709+ # Ensure the cache is empty, or this test won't work correctly
3710+ collections .abc .Sized ._abc_registry_clear ()
3711+
3712+ class Foo (collections .abc .Sized , Protocol ): pass
3713+
3714+ # gh-105144: this previously raised TypeError
3715+ # if a Protocol subclass of Sized had been created
3716+ # before any isinstance() checks against Sized
3717+ self .assertNotIsInstance (1 , collections .abc .Sized )
3718+
3719+ def test_interaction_with_isinstance_checks_on_superclasses_with_ABCMeta_2 (self ):
3720+ # Ensure the cache is empty, or this test won't work correctly
3721+ collections .abc .Sized ._abc_registry_clear ()
3722+
3723+ class Foo (typing .Sized , Protocol ): pass
3724+
3725+ # gh-105144: this previously raised TypeError
3726+ # if a Protocol subclass of Sized had been created
3727+ # before any isinstance() checks against Sized
3728+ self .assertNotIsInstance (1 , typing .Sized )
3729+
36573730
36583731class GenericTests (BaseTestCase ):
36593732
0 commit comments