1
1
import collections .abc
2
- import traceback
3
2
import types
4
3
import unittest
5
-
4
+ from test . support import C_RECURSION_LIMIT
6
5
7
6
class TestExceptionGroupTypeHierarchy (unittest .TestCase ):
8
- # TODO: RUSTPYTHON
9
- @unittest .expectedFailure
10
7
def test_exception_group_types (self ):
11
8
self .assertTrue (issubclass (ExceptionGroup , Exception ))
12
9
self .assertTrue (issubclass (ExceptionGroup , BaseExceptionGroup ))
@@ -38,17 +35,13 @@ def test_bad_EG_construction__too_many_args(self):
38
35
with self .assertRaisesRegex (TypeError , MSG ):
39
36
ExceptionGroup ('eg' , [ValueError ('too' )], [TypeError ('many' )])
40
37
41
- # TODO: RUSTPYTHON
42
- @unittest .expectedFailure
43
38
def test_bad_EG_construction__bad_message (self ):
44
39
MSG = 'argument 1 must be str, not '
45
40
with self .assertRaisesRegex (TypeError , MSG ):
46
41
ExceptionGroup (ValueError (12 ), SyntaxError ('bad syntax' ))
47
42
with self .assertRaisesRegex (TypeError , MSG ):
48
43
ExceptionGroup (None , [ValueError (12 )])
49
44
50
- # TODO: RUSTPYTHON
51
- @unittest .expectedFailure
52
45
def test_bad_EG_construction__bad_excs_sequence (self ):
53
46
MSG = r'second argument \(exceptions\) must be a sequence'
54
47
with self .assertRaisesRegex (TypeError , MSG ):
@@ -60,8 +53,6 @@ def test_bad_EG_construction__bad_excs_sequence(self):
60
53
with self .assertRaisesRegex (ValueError , MSG ):
61
54
ExceptionGroup ("eg" , [])
62
55
63
- # TODO: RUSTPYTHON
64
- @unittest .expectedFailure
65
56
def test_bad_EG_construction__nested_non_exceptions (self ):
66
57
MSG = (r'Item [0-9]+ of second argument \(exceptions\)'
67
58
' is not an exception' )
@@ -78,16 +69,12 @@ def test_EG_wraps_Exceptions__creates_EG(self):
78
69
type (ExceptionGroup ("eg" , excs )),
79
70
ExceptionGroup )
80
71
81
- # TODO: RUSTPYTHON
82
- @unittest .expectedFailure
83
72
def test_BEG_wraps_Exceptions__creates_EG (self ):
84
73
excs = [ValueError (1 ), TypeError (2 )]
85
74
self .assertIs (
86
75
type (BaseExceptionGroup ("beg" , excs )),
87
76
ExceptionGroup )
88
77
89
- # TODO: RUSTPYTHON
90
- @unittest .expectedFailure
91
78
def test_EG_wraps_BaseException__raises_TypeError (self ):
92
79
MSG = "Cannot nest BaseExceptions in an ExceptionGroup"
93
80
with self .assertRaisesRegex (TypeError , MSG ):
@@ -105,8 +92,6 @@ class MyEG(ExceptionGroup):
105
92
type (MyEG ("eg" , [ValueError (12 ), TypeError (42 )])),
106
93
MyEG )
107
94
108
- # TODO: RUSTPYTHON
109
- @unittest .expectedFailure
110
95
def test_EG_subclass_does_not_wrap_base_exceptions (self ):
111
96
class MyEG (ExceptionGroup ):
112
97
pass
@@ -115,8 +100,6 @@ class MyEG(ExceptionGroup):
115
100
with self .assertRaisesRegex (TypeError , msg ):
116
101
MyEG ("eg" , [ValueError (12 ), KeyboardInterrupt (42 )])
117
102
118
- # TODO: RUSTPYTHON
119
- @unittest .expectedFailure
120
103
def test_BEG_and_E_subclass_does_not_wrap_base_exceptions (self ):
121
104
class MyEG (BaseExceptionGroup , ValueError ):
122
105
pass
@@ -125,6 +108,21 @@ class MyEG(BaseExceptionGroup, ValueError):
125
108
with self .assertRaisesRegex (TypeError , msg ):
126
109
MyEG ("eg" , [ValueError (12 ), KeyboardInterrupt (42 )])
127
110
111
+ def test_EG_and_specific_subclass_can_wrap_any_nonbase_exception (self ):
112
+ class MyEG (ExceptionGroup , ValueError ):
113
+ pass
114
+
115
+ # The restriction is specific to Exception, not "the other base class"
116
+ MyEG ("eg" , [ValueError (12 ), Exception ()])
117
+
118
+ def test_BEG_and_specific_subclass_can_wrap_any_nonbase_exception (self ):
119
+ class MyEG (BaseExceptionGroup , ValueError ):
120
+ pass
121
+
122
+ # The restriction is specific to Exception, not "the other base class"
123
+ MyEG ("eg" , [ValueError (12 ), Exception ()])
124
+
125
+
128
126
def test_BEG_subclass_wraps_anything (self ):
129
127
class MyBEG (BaseExceptionGroup ):
130
128
pass
@@ -138,8 +136,6 @@ class MyBEG(BaseExceptionGroup):
138
136
139
137
140
138
class StrAndReprTests (unittest .TestCase ):
141
- # TODO: RUSTPYTHON
142
- @unittest .expectedFailure
143
139
def test_ExceptionGroup (self ):
144
140
eg = BaseExceptionGroup (
145
141
'flat' , [ValueError (1 ), TypeError (2 )])
@@ -160,8 +156,6 @@ def test_ExceptionGroup(self):
160
156
"ExceptionGroup('flat', "
161
157
"[ValueError(1), TypeError(2)]), TypeError(2)])" )
162
158
163
- # TODO: RUSTPYTHON
164
- @unittest .expectedFailure
165
159
def test_BaseExceptionGroup (self ):
166
160
eg = BaseExceptionGroup (
167
161
'flat' , [ValueError (1 ), KeyboardInterrupt (2 )])
@@ -184,8 +178,6 @@ def test_BaseExceptionGroup(self):
184
178
"BaseExceptionGroup('flat', "
185
179
"[ValueError(1), KeyboardInterrupt(2)])])" )
186
180
187
- # TODO: RUSTPYTHON
188
- @unittest .expectedFailure
189
181
def test_custom_exception (self ):
190
182
class MyEG (ExceptionGroup ):
191
183
pass
@@ -270,8 +262,6 @@ def test_basics_ExceptionGroup_fields(self):
270
262
self .assertIsNone (tb .tb_next )
271
263
self .assertEqual (tb .tb_lineno , tb_linenos [1 ][i ])
272
264
273
- # TODO: RUSTPYTHON
274
- @unittest .expectedFailure
275
265
def test_fields_are_readonly (self ):
276
266
eg = ExceptionGroup ('eg' , [TypeError (1 ), OSError (2 )])
277
267
@@ -287,8 +277,6 @@ def test_fields_are_readonly(self):
287
277
288
278
289
279
class ExceptionGroupTestBase (unittest .TestCase ):
290
- # TODO: RUSTPYTHON
291
- @unittest .expectedFailure
292
280
def assertMatchesTemplate (self , exc , exc_type , template ):
293
281
""" Assert that the exception matches the template
294
282
@@ -318,7 +306,6 @@ def setUp(self):
318
306
self .eg = create_simple_eg ()
319
307
self .eg_template = [ValueError (1 ), TypeError (int ), ValueError (2 )]
320
308
321
- @unittest .skip ("TODO: RUSTPYTHON" )
322
309
def test_basics_subgroup_split__bad_arg_type (self ):
323
310
bad_args = ["bad arg" ,
324
311
OSError ('instance not type' ),
@@ -330,20 +317,16 @@ def test_basics_subgroup_split__bad_arg_type(self):
330
317
with self .assertRaises (TypeError ):
331
318
self .eg .split (arg )
332
319
333
-
334
- @unittest .skip ("TODO: RUSTPYTHON" )
335
320
def test_basics_subgroup_by_type__passthrough (self ):
336
321
eg = self .eg
337
322
self .assertIs (eg , eg .subgroup (BaseException ))
338
323
self .assertIs (eg , eg .subgroup (Exception ))
339
324
self .assertIs (eg , eg .subgroup (BaseExceptionGroup ))
340
325
self .assertIs (eg , eg .subgroup (ExceptionGroup ))
341
326
342
- @unittest .skip ("TODO: RUSTPYTHON" )
343
327
def test_basics_subgroup_by_type__no_match (self ):
344
328
self .assertIsNone (self .eg .subgroup (OSError ))
345
329
346
- @unittest .skip ("TODO: RUSTPYTHON" )
347
330
def test_basics_subgroup_by_type__match (self ):
348
331
eg = self .eg
349
332
testcases = [
@@ -358,15 +341,12 @@ def test_basics_subgroup_by_type__match(self):
358
341
self .assertEqual (subeg .message , eg .message )
359
342
self .assertMatchesTemplate (subeg , ExceptionGroup , template )
360
343
361
- @unittest .skip ("TODO: RUSTPYTHON" )
362
344
def test_basics_subgroup_by_predicate__passthrough (self ):
363
345
self .assertIs (self .eg , self .eg .subgroup (lambda e : True ))
364
346
365
- @unittest .skip ("TODO: RUSTPYTHON" )
366
347
def test_basics_subgroup_by_predicate__no_match (self ):
367
348
self .assertIsNone (self .eg .subgroup (lambda e : False ))
368
349
369
- @unittest .skip ("TODO: RUSTPYTHON" )
370
350
def test_basics_subgroup_by_predicate__match (self ):
371
351
eg = self .eg
372
352
testcases = [
@@ -386,7 +366,6 @@ def setUp(self):
386
366
self .eg = create_simple_eg ()
387
367
self .eg_template = [ValueError (1 ), TypeError (int ), ValueError (2 )]
388
368
389
- @unittest .skip ("TODO: RUSTPYTHON" )
390
369
def test_basics_split_by_type__passthrough (self ):
391
370
for E in [BaseException , Exception ,
392
371
BaseExceptionGroup , ExceptionGroup ]:
@@ -395,14 +374,12 @@ def test_basics_split_by_type__passthrough(self):
395
374
match , ExceptionGroup , self .eg_template )
396
375
self .assertIsNone (rest )
397
376
398
- @unittest .skip ("TODO: RUSTPYTHON" )
399
377
def test_basics_split_by_type__no_match (self ):
400
378
match , rest = self .eg .split (OSError )
401
379
self .assertIsNone (match )
402
380
self .assertMatchesTemplate (
403
381
rest , ExceptionGroup , self .eg_template )
404
382
405
- @unittest .skip ("TODO: RUSTPYTHON" )
406
383
def test_basics_split_by_type__match (self ):
407
384
eg = self .eg
408
385
VE = ValueError
@@ -427,19 +404,16 @@ def test_basics_split_by_type__match(self):
427
404
else :
428
405
self .assertIsNone (rest )
429
406
430
- @unittest .skip ("TODO: RUSTPYTHON" )
431
407
def test_basics_split_by_predicate__passthrough (self ):
432
408
match , rest = self .eg .split (lambda e : True )
433
409
self .assertMatchesTemplate (match , ExceptionGroup , self .eg_template )
434
410
self .assertIsNone (rest )
435
411
436
- @unittest .skip ("TODO: RUSTPYTHON" )
437
412
def test_basics_split_by_predicate__no_match (self ):
438
413
match , rest = self .eg .split (lambda e : False )
439
414
self .assertIsNone (match )
440
415
self .assertMatchesTemplate (rest , ExceptionGroup , self .eg_template )
441
416
442
- @unittest .skip ("TODO: RUSTPYTHON" )
443
417
def test_basics_split_by_predicate__match (self ):
444
418
eg = self .eg
445
419
VE = ValueError
@@ -465,19 +439,15 @@ def test_basics_split_by_predicate__match(self):
465
439
class DeepRecursionInSplitAndSubgroup (unittest .TestCase ):
466
440
def make_deep_eg (self ):
467
441
e = TypeError (1 )
468
- for i in range (2000 ):
442
+ for i in range (C_RECURSION_LIMIT + 1 ):
469
443
e = ExceptionGroup ('eg' , [e ])
470
444
return e
471
445
472
- # TODO: RUSTPYTHON
473
- @unittest .expectedFailure
474
446
def test_deep_split (self ):
475
447
e = self .make_deep_eg ()
476
448
with self .assertRaises (RecursionError ):
477
449
e .split (TypeError )
478
450
479
- # TODO: RUSTPYTHON
480
- @unittest .expectedFailure
481
451
def test_deep_subgroup (self ):
482
452
e = self .make_deep_eg ()
483
453
with self .assertRaises (RecursionError ):
@@ -501,7 +471,7 @@ def leaf_generator(exc, tbs=None):
501
471
502
472
class LeafGeneratorTest (unittest .TestCase ):
503
473
# The leaf_generator is mentioned in PEP 654 as a suggestion
504
- # on how to iterate over leaf nodes of an EG. It is also
474
+ # on how to iterate over leaf nodes of an EG. Is is also
505
475
# used below as a test utility. So we test it here.
506
476
507
477
def test_leaf_generator (self ):
@@ -654,8 +624,6 @@ def tb_linenos(tbs):
654
624
655
625
class NestedExceptionGroupSplitTest (ExceptionGroupSplitTestBase ):
656
626
657
- # TODO: RUSTPYTHON
658
- @unittest .expectedFailure
659
627
def test_split_by_type (self ):
660
628
class MyExceptionGroup (ExceptionGroup ):
661
629
pass
@@ -755,8 +723,6 @@ def level3(i):
755
723
self .assertMatchesTemplate (match , ExceptionGroup , [eg_template [0 ]])
756
724
self .assertMatchesTemplate (rest , ExceptionGroup , [eg_template [1 ]])
757
725
758
- # TODO: RUSTPYTHON
759
- @unittest .expectedFailure
760
726
def test_split_BaseExceptionGroup (self ):
761
727
def exc (ex ):
762
728
try :
@@ -797,8 +763,6 @@ def exc(ex):
797
763
self .assertMatchesTemplate (
798
764
rest , ExceptionGroup , [ValueError (1 )])
799
765
800
- # TODO: RUSTPYTHON
801
- @unittest .expectedFailure
802
766
def test_split_copies_notes (self ):
803
767
# make sure each exception group after a split has its own __notes__ list
804
768
eg = ExceptionGroup ("eg" , [ValueError (1 ), TypeError (2 )])
@@ -830,11 +794,23 @@ def test_split_does_not_copy_non_sequence_notes(self):
830
794
self .assertFalse (hasattr (match , '__notes__' ))
831
795
self .assertFalse (hasattr (rest , '__notes__' ))
832
796
797
+ # TODO: RUSTPYTHON
798
+ @unittest .expectedFailure
799
+ def test_drive_invalid_return_value (self ):
800
+ class MyEg (ExceptionGroup ):
801
+ def derive (self , excs ):
802
+ return 42
803
+
804
+ eg = MyEg ('eg' , [TypeError (1 ), ValueError (2 )])
805
+ msg = "derive must return an instance of BaseExceptionGroup"
806
+ with self .assertRaisesRegex (TypeError , msg ):
807
+ eg .split (TypeError )
808
+ with self .assertRaisesRegex (TypeError , msg ):
809
+ eg .subgroup (TypeError )
810
+
833
811
834
812
class NestedExceptionGroupSubclassSplitTest (ExceptionGroupSplitTestBase ):
835
813
836
- # TODO: RUSTPYTHON
837
- @unittest .expectedFailure
838
814
def test_split_ExceptionGroup_subclass_no_derive_no_new_override (self ):
839
815
class EG (ExceptionGroup ):
840
816
pass
@@ -877,8 +853,6 @@ class EG(ExceptionGroup):
877
853
self .assertMatchesTemplate (match , ExceptionGroup , [[TypeError (2 )]])
878
854
self .assertMatchesTemplate (rest , ExceptionGroup , [ValueError (1 )])
879
855
880
- # TODO: RUSTPYTHON
881
- @unittest .expectedFailure
882
856
def test_split_BaseExceptionGroup_subclass_no_derive_new_override (self ):
883
857
class EG (BaseExceptionGroup ):
884
858
def __new__ (cls , message , excs , unused ):
@@ -921,8 +895,6 @@ def __new__(cls, message, excs, unused):
921
895
match , BaseExceptionGroup , [KeyboardInterrupt (2 )])
922
896
self .assertMatchesTemplate (rest , ExceptionGroup , [ValueError (1 )])
923
897
924
- # TODO: RUSTPYTHON
925
- @unittest .expectedFailure
926
898
def test_split_ExceptionGroup_subclass_derive_and_new_overrides (self ):
927
899
class EG (ExceptionGroup ):
928
900
def __new__ (cls , message , excs , code ):
0 commit comments