@@ -1000,5 +1000,204 @@ def test_exc_info_restored(self):
1000
1000
self .assertEqual (sys .exc_info (), (None , None , None ))
1001
1001
1002
1002
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
+
1003
1202
if __name__ == '__main__' :
1004
1203
unittest .main ()
0 commit comments