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