@@ -1000,5 +1000,204 @@ def test_exc_info_restored(self):
10001000 self .assertEqual (sys .exc_info (), (None , None , None ))
10011001
10021002
1003+ class TestExceptStar_WeirdLeafExceptions (ExceptStarTest ):
1004+ # Test that except* works when leaf exceptions are
1005+ # unhashable or have a bad custom __eq__
1006+
1007+ class UnhashableExc (ValueError ):
1008+ __hash__ = None
1009+
1010+ class AlwaysEqualExc (ValueError ):
1011+ def __eq__ (self , other ):
1012+ return True
1013+
1014+ class NeverEqualExc (ValueError ):
1015+ def __eq__ (self , other ):
1016+ return False
1017+
1018+ class BrokenEqualExc (ValueError ):
1019+ def __eq__ (self , other ):
1020+ raise RuntimeError ()
1021+
1022+ def setUp (self ):
1023+ self .bad_types = [self .UnhashableExc ,
1024+ self .AlwaysEqualExc ,
1025+ self .NeverEqualExc ,
1026+ self .BrokenEqualExc ]
1027+
1028+ def except_type (self , eg , type ):
1029+ match , rest = None , None
1030+ try :
1031+ try :
1032+ raise eg
1033+ except* type as e :
1034+ match = e
1035+ except Exception as e :
1036+ rest = e
1037+ return match , rest
1038+
1039+ def test_catch_unhashable_leaf_exception (self ):
1040+ for Bad in self .bad_types :
1041+ with self .subTest (Bad ):
1042+ eg = ExceptionGroup ("eg" , [TypeError (1 ), Bad (2 )])
1043+ match , rest = self .except_type (eg , Bad )
1044+ self .assertExceptionIsLike (
1045+ match , ExceptionGroup ("eg" , [Bad (2 )]))
1046+ self .assertExceptionIsLike (
1047+ rest , ExceptionGroup ("eg" , [TypeError (1 )]))
1048+
1049+ def test_propagate_unhashable_leaf (self ):
1050+ for Bad in self .bad_types :
1051+ with self .subTest (Bad ):
1052+ eg = ExceptionGroup ("eg" , [TypeError (1 ), Bad (2 )])
1053+ match , rest = self .except_type (eg , TypeError )
1054+ self .assertExceptionIsLike (
1055+ match , ExceptionGroup ("eg" , [TypeError (1 )]))
1056+ self .assertExceptionIsLike (
1057+ rest , ExceptionGroup ("eg" , [Bad (2 )]))
1058+
1059+ def test_catch_nothing_unhashable_leaf (self ):
1060+ for Bad in self .bad_types :
1061+ with self .subTest (Bad ):
1062+ eg = ExceptionGroup ("eg" , [TypeError (1 ), Bad (2 )])
1063+ match , rest = self .except_type (eg , OSError )
1064+ self .assertIsNone (match )
1065+ self .assertExceptionIsLike (rest , eg )
1066+
1067+ def test_catch_everything_unhashable_leaf (self ):
1068+ for Bad in self .bad_types :
1069+ with self .subTest (Bad ):
1070+ eg = ExceptionGroup ("eg" , [TypeError (1 ), Bad (2 )])
1071+ match , rest = self .except_type (eg , Exception )
1072+ self .assertExceptionIsLike (match , eg )
1073+ self .assertIsNone (rest )
1074+
1075+ def test_reraise_unhashable_leaf (self ):
1076+ for Bad in self .bad_types :
1077+ with self .subTest (Bad ):
1078+ eg = ExceptionGroup (
1079+ "eg" , [TypeError (1 ), Bad (2 ), ValueError (3 )])
1080+
1081+ try :
1082+ try :
1083+ raise eg
1084+ except* TypeError :
1085+ pass
1086+ except* Bad :
1087+ raise
1088+ except Exception as e :
1089+ exc = e
1090+
1091+ self .assertExceptionIsLike (
1092+ exc , ExceptionGroup ("eg" , [Bad (2 ), ValueError (3 )]))
1093+
1094+
1095+ class TestExceptStar_WeirdExceptionGroupSubclass (ExceptStarTest ):
1096+ # Test that except* works with exception groups that are
1097+ # unhashable or have a bad custom __eq__
1098+
1099+ class UnhashableEG (ExceptionGroup ):
1100+ __hash__ = None
1101+
1102+ def derive (self , excs ):
1103+ return type (self )(self .message , excs )
1104+
1105+ class AlwaysEqualEG (ExceptionGroup ):
1106+ def __eq__ (self , other ):
1107+ return True
1108+
1109+ def derive (self , excs ):
1110+ return type (self )(self .message , excs )
1111+
1112+ class NeverEqualEG (ExceptionGroup ):
1113+ def __eq__ (self , other ):
1114+ return False
1115+
1116+ def derive (self , excs ):
1117+ return type (self )(self .message , excs )
1118+
1119+ class BrokenEqualEG (ExceptionGroup ):
1120+ def __eq__ (self , other ):
1121+ raise RuntimeError ()
1122+
1123+ def derive (self , excs ):
1124+ return type (self )(self .message , excs )
1125+
1126+ def setUp (self ):
1127+ self .bad_types = [self .UnhashableEG ,
1128+ self .AlwaysEqualEG ,
1129+ self .NeverEqualEG ,
1130+ self .BrokenEqualEG ]
1131+
1132+ def except_type (self , eg , type ):
1133+ match , rest = None , None
1134+ try :
1135+ try :
1136+ raise eg
1137+ except* type as e :
1138+ match = e
1139+ except Exception as e :
1140+ rest = e
1141+ return match , rest
1142+
1143+ def test_catch_some_unhashable_exception_group_subclass (self ):
1144+ for BadEG in self .bad_types :
1145+ with self .subTest (BadEG ):
1146+ eg = BadEG ("eg" ,
1147+ [TypeError (1 ),
1148+ BadEG ("nested" , [ValueError (2 )])])
1149+
1150+ match , rest = self .except_type (eg , TypeError )
1151+ self .assertExceptionIsLike (match , BadEG ("eg" , [TypeError (1 )]))
1152+ self .assertExceptionIsLike (rest ,
1153+ BadEG ("eg" , [BadEG ("nested" , [ValueError (2 )])]))
1154+
1155+ def test_catch_none_unhashable_exception_group_subclass (self ):
1156+ for BadEG in self .bad_types :
1157+ with self .subTest (BadEG ):
1158+
1159+ eg = BadEG ("eg" ,
1160+ [TypeError (1 ),
1161+ BadEG ("nested" , [ValueError (2 )])])
1162+
1163+ match , rest = self .except_type (eg , OSError )
1164+ self .assertIsNone (match )
1165+ self .assertExceptionIsLike (rest , eg )
1166+
1167+ def test_catch_all_unhashable_exception_group_subclass (self ):
1168+ for BadEG in self .bad_types :
1169+ with self .subTest (BadEG ):
1170+
1171+ eg = BadEG ("eg" ,
1172+ [TypeError (1 ),
1173+ BadEG ("nested" , [ValueError (2 )])])
1174+
1175+ match , rest = self .except_type (eg , Exception )
1176+ self .assertExceptionIsLike (match , eg )
1177+ self .assertIsNone (rest )
1178+
1179+ def test_reraise_unhashable_eg (self ):
1180+ for BadEG in self .bad_types :
1181+ with self .subTest (BadEG ):
1182+
1183+ eg = BadEG ("eg" ,
1184+ [TypeError (1 ), ValueError (2 ),
1185+ BadEG ("nested" , [ValueError (3 ), OSError (4 )])])
1186+
1187+ try :
1188+ try :
1189+ raise eg
1190+ except* ValueError :
1191+ pass
1192+ except* OSError :
1193+ raise
1194+ except Exception as e :
1195+ exc = e
1196+
1197+ self .assertExceptionIsLike (
1198+ exc , BadEG ("eg" , [TypeError (1 ),
1199+ BadEG ("nested" , [OSError (4 )])]))
1200+
1201+
10031202if __name__ == '__main__' :
10041203 unittest .main ()
0 commit comments