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' )
@@ -72,24 +63,18 @@ def test_bad_EG_construction__nested_non_exceptions(self):
72
63
73
64
74
65
class InstanceCreation (unittest .TestCase ):
75
- # TODO: RUSTPYTHON
76
- @unittest .expectedFailure
77
66
def test_EG_wraps_Exceptions__creates_EG (self ):
78
67
excs = [ValueError (1 ), TypeError (2 )]
79
68
self .assertIs (
80
69
type (ExceptionGroup ("eg" , excs )),
81
70
ExceptionGroup )
82
71
83
- # TODO: RUSTPYTHON
84
- @unittest .expectedFailure
85
72
def test_BEG_wraps_Exceptions__creates_EG (self ):
86
73
excs = [ValueError (1 ), TypeError (2 )]
87
74
self .assertIs (
88
75
type (BaseExceptionGroup ("beg" , excs )),
89
76
ExceptionGroup )
90
77
91
- # TODO: RUSTPYTHON
92
- @unittest .expectedFailure
93
78
def test_EG_wraps_BaseException__raises_TypeError (self ):
94
79
MSG = "Cannot nest BaseExceptions in an ExceptionGroup"
95
80
with self .assertRaisesRegex (TypeError , MSG ):
@@ -99,8 +84,6 @@ def test_BEG_wraps_BaseException__creates_BEG(self):
99
84
beg = BaseExceptionGroup ("beg" , [ValueError (1 ), KeyboardInterrupt (2 )])
100
85
self .assertIs (type (beg ), BaseExceptionGroup )
101
86
102
- # TODO: RUSTPYTHON
103
- @unittest .expectedFailure
104
87
def test_EG_subclass_wraps_non_base_exceptions (self ):
105
88
class MyEG (ExceptionGroup ):
106
89
pass
@@ -109,8 +92,6 @@ class MyEG(ExceptionGroup):
109
92
type (MyEG ("eg" , [ValueError (12 ), TypeError (42 )])),
110
93
MyEG )
111
94
112
- # TODO: RUSTPYTHON
113
- @unittest .expectedFailure
114
95
def test_EG_subclass_does_not_wrap_base_exceptions (self ):
115
96
class MyEG (ExceptionGroup ):
116
97
pass
@@ -119,8 +100,6 @@ class MyEG(ExceptionGroup):
119
100
with self .assertRaisesRegex (TypeError , msg ):
120
101
MyEG ("eg" , [ValueError (12 ), KeyboardInterrupt (42 )])
121
102
122
- # TODO: RUSTPYTHON
123
- @unittest .expectedFailure
124
103
def test_BEG_and_E_subclass_does_not_wrap_base_exceptions (self ):
125
104
class MyEG (BaseExceptionGroup , ValueError ):
126
105
pass
@@ -129,6 +108,21 @@ class MyEG(BaseExceptionGroup, ValueError):
129
108
with self .assertRaisesRegex (TypeError , msg ):
130
109
MyEG ("eg" , [ValueError (12 ), KeyboardInterrupt (42 )])
131
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
+
132
126
def test_BEG_subclass_wraps_anything (self ):
133
127
class MyBEG (BaseExceptionGroup ):
134
128
pass
@@ -142,8 +136,6 @@ class MyBEG(BaseExceptionGroup):
142
136
143
137
144
138
class StrAndReprTests (unittest .TestCase ):
145
- # TODO: RUSTPYTHON
146
- @unittest .expectedFailure
147
139
def test_ExceptionGroup (self ):
148
140
eg = BaseExceptionGroup (
149
141
'flat' , [ValueError (1 ), TypeError (2 )])
@@ -164,8 +156,6 @@ def test_ExceptionGroup(self):
164
156
"ExceptionGroup('flat', "
165
157
"[ValueError(1), TypeError(2)]), TypeError(2)])" )
166
158
167
- # TODO: RUSTPYTHON
168
- @unittest .expectedFailure
169
159
def test_BaseExceptionGroup (self ):
170
160
eg = BaseExceptionGroup (
171
161
'flat' , [ValueError (1 ), KeyboardInterrupt (2 )])
@@ -188,8 +178,6 @@ def test_BaseExceptionGroup(self):
188
178
"BaseExceptionGroup('flat', "
189
179
"[ValueError(1), KeyboardInterrupt(2)])])" )
190
180
191
- # TODO: RUSTPYTHON
192
- @unittest .expectedFailure
193
181
def test_custom_exception (self ):
194
182
class MyEG (ExceptionGroup ):
195
183
pass
@@ -245,8 +233,6 @@ def create_simple_eg():
245
233
246
234
247
235
class ExceptionGroupFields (unittest .TestCase ):
248
- # TODO: RUSTPYTHON
249
- @unittest .expectedFailure
250
236
def test_basics_ExceptionGroup_fields (self ):
251
237
eg = create_simple_eg ()
252
238
@@ -276,8 +262,6 @@ def test_basics_ExceptionGroup_fields(self):
276
262
self .assertIsNone (tb .tb_next )
277
263
self .assertEqual (tb .tb_lineno , tb_linenos [1 ][i ])
278
264
279
- # TODO: RUSTPYTHON
280
- @unittest .expectedFailure
281
265
def test_fields_are_readonly (self ):
282
266
eg = ExceptionGroup ('eg' , [TypeError (1 ), OSError (2 )])
283
267
@@ -293,8 +277,6 @@ def test_fields_are_readonly(self):
293
277
294
278
295
279
class ExceptionGroupTestBase (unittest .TestCase ):
296
- # TODO: RUSTPYTHON
297
- @unittest .expectedFailure
298
280
def assertMatchesTemplate (self , exc , exc_type , template ):
299
281
""" Assert that the exception matches the template
300
282
@@ -324,7 +306,6 @@ def setUp(self):
324
306
self .eg = create_simple_eg ()
325
307
self .eg_template = [ValueError (1 ), TypeError (int ), ValueError (2 )]
326
308
327
- @unittest .skip ("TODO: RUSTPYTHON" )
328
309
def test_basics_subgroup_split__bad_arg_type (self ):
329
310
bad_args = ["bad arg" ,
330
311
OSError ('instance not type' ),
@@ -336,20 +317,16 @@ def test_basics_subgroup_split__bad_arg_type(self):
336
317
with self .assertRaises (TypeError ):
337
318
self .eg .split (arg )
338
319
339
-
340
- @unittest .skip ("TODO: RUSTPYTHON" )
341
320
def test_basics_subgroup_by_type__passthrough (self ):
342
321
eg = self .eg
343
322
self .assertIs (eg , eg .subgroup (BaseException ))
344
323
self .assertIs (eg , eg .subgroup (Exception ))
345
324
self .assertIs (eg , eg .subgroup (BaseExceptionGroup ))
346
325
self .assertIs (eg , eg .subgroup (ExceptionGroup ))
347
326
348
- @unittest .skip ("TODO: RUSTPYTHON" )
349
327
def test_basics_subgroup_by_type__no_match (self ):
350
328
self .assertIsNone (self .eg .subgroup (OSError ))
351
329
352
- @unittest .skip ("TODO: RUSTPYTHON" )
353
330
def test_basics_subgroup_by_type__match (self ):
354
331
eg = self .eg
355
332
testcases = [
@@ -364,15 +341,12 @@ def test_basics_subgroup_by_type__match(self):
364
341
self .assertEqual (subeg .message , eg .message )
365
342
self .assertMatchesTemplate (subeg , ExceptionGroup , template )
366
343
367
- @unittest .skip ("TODO: RUSTPYTHON" )
368
344
def test_basics_subgroup_by_predicate__passthrough (self ):
369
345
self .assertIs (self .eg , self .eg .subgroup (lambda e : True ))
370
346
371
- @unittest .skip ("TODO: RUSTPYTHON" )
372
347
def test_basics_subgroup_by_predicate__no_match (self ):
373
348
self .assertIsNone (self .eg .subgroup (lambda e : False ))
374
349
375
- @unittest .skip ("TODO: RUSTPYTHON" )
376
350
def test_basics_subgroup_by_predicate__match (self ):
377
351
eg = self .eg
378
352
testcases = [
@@ -392,7 +366,6 @@ def setUp(self):
392
366
self .eg = create_simple_eg ()
393
367
self .eg_template = [ValueError (1 ), TypeError (int ), ValueError (2 )]
394
368
395
- @unittest .skip ("TODO: RUSTPYTHON" )
396
369
def test_basics_split_by_type__passthrough (self ):
397
370
for E in [BaseException , Exception ,
398
371
BaseExceptionGroup , ExceptionGroup ]:
@@ -401,14 +374,12 @@ def test_basics_split_by_type__passthrough(self):
401
374
match , ExceptionGroup , self .eg_template )
402
375
self .assertIsNone (rest )
403
376
404
- @unittest .skip ("TODO: RUSTPYTHON" )
405
377
def test_basics_split_by_type__no_match (self ):
406
378
match , rest = self .eg .split (OSError )
407
379
self .assertIsNone (match )
408
380
self .assertMatchesTemplate (
409
381
rest , ExceptionGroup , self .eg_template )
410
382
411
- @unittest .skip ("TODO: RUSTPYTHON" )
412
383
def test_basics_split_by_type__match (self ):
413
384
eg = self .eg
414
385
VE = ValueError
@@ -433,19 +404,16 @@ def test_basics_split_by_type__match(self):
433
404
else :
434
405
self .assertIsNone (rest )
435
406
436
- @unittest .skip ("TODO: RUSTPYTHON" )
437
407
def test_basics_split_by_predicate__passthrough (self ):
438
408
match , rest = self .eg .split (lambda e : True )
439
409
self .assertMatchesTemplate (match , ExceptionGroup , self .eg_template )
440
410
self .assertIsNone (rest )
441
411
442
- @unittest .skip ("TODO: RUSTPYTHON" )
443
412
def test_basics_split_by_predicate__no_match (self ):
444
413
match , rest = self .eg .split (lambda e : False )
445
414
self .assertIsNone (match )
446
415
self .assertMatchesTemplate (rest , ExceptionGroup , self .eg_template )
447
416
448
- @unittest .skip ("TODO: RUSTPYTHON" )
449
417
def test_basics_split_by_predicate__match (self ):
450
418
eg = self .eg
451
419
VE = ValueError
@@ -471,19 +439,15 @@ def test_basics_split_by_predicate__match(self):
471
439
class DeepRecursionInSplitAndSubgroup (unittest .TestCase ):
472
440
def make_deep_eg (self ):
473
441
e = TypeError (1 )
474
- for i in range (2000 ):
442
+ for i in range (C_RECURSION_LIMIT + 1 ):
475
443
e = ExceptionGroup ('eg' , [e ])
476
444
return e
477
445
478
- # TODO: RUSTPYTHON
479
- @unittest .expectedFailure
480
446
def test_deep_split (self ):
481
447
e = self .make_deep_eg ()
482
448
with self .assertRaises (RecursionError ):
483
449
e .split (TypeError )
484
450
485
- # TODO: RUSTPYTHON
486
- @unittest .expectedFailure
487
451
def test_deep_subgroup (self ):
488
452
e = self .make_deep_eg ()
489
453
with self .assertRaises (RecursionError ):
@@ -507,11 +471,9 @@ def leaf_generator(exc, tbs=None):
507
471
508
472
class LeafGeneratorTest (unittest .TestCase ):
509
473
# The leaf_generator is mentioned in PEP 654 as a suggestion
510
- # 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
511
475
# used below as a test utility. So we test it here.
512
476
513
- # TODO: RUSTPYTHON
514
- @unittest .expectedFailure
515
477
def test_leaf_generator (self ):
516
478
eg = create_simple_eg ()
517
479
@@ -549,25 +511,19 @@ def create_nested_eg():
549
511
550
512
551
513
class NestedExceptionGroupBasicsTest (ExceptionGroupTestBase ):
552
- # TODO: RUSTPYTHON
553
- @unittest .expectedFailure
554
514
def test_nested_group_matches_template (self ):
555
515
eg = create_nested_eg ()
556
516
self .assertMatchesTemplate (
557
517
eg ,
558
518
ExceptionGroup ,
559
519
[[TypeError (bytes )], ValueError (1 )])
560
520
561
- # TODO: RUSTPYTHON
562
- @unittest .expectedFailure
563
521
def test_nested_group_chaining (self ):
564
522
eg = create_nested_eg ()
565
523
self .assertIsInstance (eg .exceptions [1 ].__context__ , MemoryError )
566
524
self .assertIsInstance (eg .exceptions [1 ].__cause__ , MemoryError )
567
525
self .assertIsInstance (eg .exceptions [0 ].__context__ , TypeError )
568
526
569
- # TODO: RUSTPYTHON
570
- @unittest .expectedFailure
571
527
def test_nested_exception_group_tracebacks (self ):
572
528
eg = create_nested_eg ()
573
529
@@ -581,8 +537,6 @@ def test_nested_exception_group_tracebacks(self):
581
537
self .assertEqual (tb .tb_lineno , expected )
582
538
self .assertIsNone (tb .tb_next )
583
539
584
- # TODO: RUSTPYTHON
585
- @unittest .expectedFailure
586
540
def test_iteration_full_tracebacks (self ):
587
541
eg = create_nested_eg ()
588
542
# check that iteration over leaves
@@ -670,8 +624,6 @@ def tb_linenos(tbs):
670
624
671
625
class NestedExceptionGroupSplitTest (ExceptionGroupSplitTestBase ):
672
626
673
- # TODO: RUSTPYTHON
674
- @unittest .expectedFailure
675
627
def test_split_by_type (self ):
676
628
class MyExceptionGroup (ExceptionGroup ):
677
629
pass
@@ -771,8 +723,6 @@ def level3(i):
771
723
self .assertMatchesTemplate (match , ExceptionGroup , [eg_template [0 ]])
772
724
self .assertMatchesTemplate (rest , ExceptionGroup , [eg_template [1 ]])
773
725
774
- # TODO: RUSTPYTHON
775
- @unittest .expectedFailure
776
726
def test_split_BaseExceptionGroup (self ):
777
727
def exc (ex ):
778
728
try :
@@ -813,8 +763,6 @@ def exc(ex):
813
763
self .assertMatchesTemplate (
814
764
rest , ExceptionGroup , [ValueError (1 )])
815
765
816
- # TODO: RUSTPYTHON
817
- @unittest .expectedFailure
818
766
def test_split_copies_notes (self ):
819
767
# make sure each exception group after a split has its own __notes__ list
820
768
eg = ExceptionGroup ("eg" , [ValueError (1 ), TypeError (2 )])
@@ -846,11 +794,23 @@ def test_split_does_not_copy_non_sequence_notes(self):
846
794
self .assertFalse (hasattr (match , '__notes__' ))
847
795
self .assertFalse (hasattr (rest , '__notes__' ))
848
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
+
849
811
850
812
class NestedExceptionGroupSubclassSplitTest (ExceptionGroupSplitTestBase ):
851
813
852
- # TODO: RUSTPYTHON
853
- @unittest .expectedFailure
854
814
def test_split_ExceptionGroup_subclass_no_derive_no_new_override (self ):
855
815
class EG (ExceptionGroup ):
856
816
pass
@@ -893,8 +853,6 @@ class EG(ExceptionGroup):
893
853
self .assertMatchesTemplate (match , ExceptionGroup , [[TypeError (2 )]])
894
854
self .assertMatchesTemplate (rest , ExceptionGroup , [ValueError (1 )])
895
855
896
- # TODO: RUSTPYTHON
897
- @unittest .expectedFailure
898
856
def test_split_BaseExceptionGroup_subclass_no_derive_new_override (self ):
899
857
class EG (BaseExceptionGroup ):
900
858
def __new__ (cls , message , excs , unused ):
@@ -937,8 +895,6 @@ def __new__(cls, message, excs, unused):
937
895
match , BaseExceptionGroup , [KeyboardInterrupt (2 )])
938
896
self .assertMatchesTemplate (rest , ExceptionGroup , [ValueError (1 )])
939
897
940
- # TODO: RUSTPYTHON
941
- @unittest .expectedFailure
942
898
def test_split_ExceptionGroup_subclass_derive_and_new_overrides (self ):
943
899
class EG (ExceptionGroup ):
944
900
def __new__ (cls , message , excs , code ):
0 commit comments