Skip to content

Commit

Permalink
test_exception_group from CPython 3.12.2
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowone committed Apr 22, 2024
1 parent d446321 commit 0e816c1
Showing 1 changed file with 32 additions and 76 deletions.
108 changes: 32 additions & 76 deletions Lib/test/test_exception_group.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import collections.abc
import traceback
import types
import unittest

from test.support import C_RECURSION_LIMIT

class TestExceptionGroupTypeHierarchy(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_exception_group_types(self):
self.assertTrue(issubclass(ExceptionGroup, Exception))
self.assertTrue(issubclass(ExceptionGroup, BaseExceptionGroup))
Expand Down Expand Up @@ -38,17 +35,13 @@ def test_bad_EG_construction__too_many_args(self):
with self.assertRaisesRegex(TypeError, MSG):
ExceptionGroup('eg', [ValueError('too')], [TypeError('many')])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_bad_EG_construction__bad_message(self):
MSG = 'argument 1 must be str, not '
with self.assertRaisesRegex(TypeError, MSG):
ExceptionGroup(ValueError(12), SyntaxError('bad syntax'))
with self.assertRaisesRegex(TypeError, MSG):
ExceptionGroup(None, [ValueError(12)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_bad_EG_construction__bad_excs_sequence(self):
MSG = r'second argument \(exceptions\) must be a sequence'
with self.assertRaisesRegex(TypeError, MSG):
Expand All @@ -60,8 +53,6 @@ def test_bad_EG_construction__bad_excs_sequence(self):
with self.assertRaisesRegex(ValueError, MSG):
ExceptionGroup("eg", [])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_bad_EG_construction__nested_non_exceptions(self):
MSG = (r'Item [0-9]+ of second argument \(exceptions\)'
' is not an exception')
Expand All @@ -72,24 +63,18 @@ def test_bad_EG_construction__nested_non_exceptions(self):


class InstanceCreation(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_EG_wraps_Exceptions__creates_EG(self):
excs = [ValueError(1), TypeError(2)]
self.assertIs(
type(ExceptionGroup("eg", excs)),
ExceptionGroup)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_BEG_wraps_Exceptions__creates_EG(self):
excs = [ValueError(1), TypeError(2)]
self.assertIs(
type(BaseExceptionGroup("beg", excs)),
ExceptionGroup)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_EG_wraps_BaseException__raises_TypeError(self):
MSG= "Cannot nest BaseExceptions in an ExceptionGroup"
with self.assertRaisesRegex(TypeError, MSG):
Expand All @@ -99,8 +84,6 @@ def test_BEG_wraps_BaseException__creates_BEG(self):
beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
self.assertIs(type(beg), BaseExceptionGroup)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_EG_subclass_wraps_non_base_exceptions(self):
class MyEG(ExceptionGroup):
pass
Expand All @@ -109,8 +92,6 @@ class MyEG(ExceptionGroup):
type(MyEG("eg", [ValueError(12), TypeError(42)])),
MyEG)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_EG_subclass_does_not_wrap_base_exceptions(self):
class MyEG(ExceptionGroup):
pass
Expand All @@ -119,8 +100,6 @@ class MyEG(ExceptionGroup):
with self.assertRaisesRegex(TypeError, msg):
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_BEG_and_E_subclass_does_not_wrap_base_exceptions(self):
class MyEG(BaseExceptionGroup, ValueError):
pass
Expand All @@ -129,6 +108,21 @@ class MyEG(BaseExceptionGroup, ValueError):
with self.assertRaisesRegex(TypeError, msg):
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])

def test_EG_and_specific_subclass_can_wrap_any_nonbase_exception(self):
class MyEG(ExceptionGroup, ValueError):
pass

# The restriction is specific to Exception, not "the other base class"
MyEG("eg", [ValueError(12), Exception()])

def test_BEG_and_specific_subclass_can_wrap_any_nonbase_exception(self):
class MyEG(BaseExceptionGroup, ValueError):
pass

# The restriction is specific to Exception, not "the other base class"
MyEG("eg", [ValueError(12), Exception()])


def test_BEG_subclass_wraps_anything(self):
class MyBEG(BaseExceptionGroup):
pass
Expand All @@ -142,8 +136,6 @@ class MyBEG(BaseExceptionGroup):


class StrAndReprTests(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_ExceptionGroup(self):
eg = BaseExceptionGroup(
'flat', [ValueError(1), TypeError(2)])
Expand All @@ -164,8 +156,6 @@ def test_ExceptionGroup(self):
"ExceptionGroup('flat', "
"[ValueError(1), TypeError(2)]), TypeError(2)])")

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_BaseExceptionGroup(self):
eg = BaseExceptionGroup(
'flat', [ValueError(1), KeyboardInterrupt(2)])
Expand All @@ -188,8 +178,6 @@ def test_BaseExceptionGroup(self):
"BaseExceptionGroup('flat', "
"[ValueError(1), KeyboardInterrupt(2)])])")

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_custom_exception(self):
class MyEG(ExceptionGroup):
pass
Expand Down Expand Up @@ -245,8 +233,6 @@ def create_simple_eg():


class ExceptionGroupFields(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_basics_ExceptionGroup_fields(self):
eg = create_simple_eg()

Expand Down Expand Up @@ -276,8 +262,6 @@ def test_basics_ExceptionGroup_fields(self):
self.assertIsNone(tb.tb_next)
self.assertEqual(tb.tb_lineno, tb_linenos[1][i])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_fields_are_readonly(self):
eg = ExceptionGroup('eg', [TypeError(1), OSError(2)])

Expand All @@ -293,8 +277,6 @@ def test_fields_are_readonly(self):


class ExceptionGroupTestBase(unittest.TestCase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def assertMatchesTemplate(self, exc, exc_type, template):
""" Assert that the exception matches the template
Expand Down Expand Up @@ -324,7 +306,6 @@ def setUp(self):
self.eg = create_simple_eg()
self.eg_template = [ValueError(1), TypeError(int), ValueError(2)]

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_split__bad_arg_type(self):
bad_args = ["bad arg",
OSError('instance not type'),
Expand All @@ -336,20 +317,16 @@ def test_basics_subgroup_split__bad_arg_type(self):
with self.assertRaises(TypeError):
self.eg.split(arg)


@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_type__passthrough(self):
eg = self.eg
self.assertIs(eg, eg.subgroup(BaseException))
self.assertIs(eg, eg.subgroup(Exception))
self.assertIs(eg, eg.subgroup(BaseExceptionGroup))
self.assertIs(eg, eg.subgroup(ExceptionGroup))

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_type__no_match(self):
self.assertIsNone(self.eg.subgroup(OSError))

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_type__match(self):
eg = self.eg
testcases = [
Expand All @@ -364,15 +341,12 @@ def test_basics_subgroup_by_type__match(self):
self.assertEqual(subeg.message, eg.message)
self.assertMatchesTemplate(subeg, ExceptionGroup, template)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_predicate__passthrough(self):
self.assertIs(self.eg, self.eg.subgroup(lambda e: True))

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_predicate__no_match(self):
self.assertIsNone(self.eg.subgroup(lambda e: False))

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_subgroup_by_predicate__match(self):
eg = self.eg
testcases = [
Expand All @@ -392,7 +366,6 @@ def setUp(self):
self.eg = create_simple_eg()
self.eg_template = [ValueError(1), TypeError(int), ValueError(2)]

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_type__passthrough(self):
for E in [BaseException, Exception,
BaseExceptionGroup, ExceptionGroup]:
Expand All @@ -401,14 +374,12 @@ def test_basics_split_by_type__passthrough(self):
match, ExceptionGroup, self.eg_template)
self.assertIsNone(rest)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_type__no_match(self):
match, rest = self.eg.split(OSError)
self.assertIsNone(match)
self.assertMatchesTemplate(
rest, ExceptionGroup, self.eg_template)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_type__match(self):
eg = self.eg
VE = ValueError
Expand All @@ -433,19 +404,16 @@ def test_basics_split_by_type__match(self):
else:
self.assertIsNone(rest)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_predicate__passthrough(self):
match, rest = self.eg.split(lambda e: True)
self.assertMatchesTemplate(match, ExceptionGroup, self.eg_template)
self.assertIsNone(rest)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_predicate__no_match(self):
match, rest = self.eg.split(lambda e: False)
self.assertIsNone(match)
self.assertMatchesTemplate(rest, ExceptionGroup, self.eg_template)

@unittest.skip("TODO: RUSTPYTHON")
def test_basics_split_by_predicate__match(self):
eg = self.eg
VE = ValueError
Expand All @@ -471,19 +439,15 @@ def test_basics_split_by_predicate__match(self):
class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
def make_deep_eg(self):
e = TypeError(1)
for i in range(2000):
for i in range(C_RECURSION_LIMIT + 1):
e = ExceptionGroup('eg', [e])
return e

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_deep_split(self):
e = self.make_deep_eg()
with self.assertRaises(RecursionError):
e.split(TypeError)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_deep_subgroup(self):
e = self.make_deep_eg()
with self.assertRaises(RecursionError):
Expand All @@ -507,11 +471,9 @@ def leaf_generator(exc, tbs=None):

class LeafGeneratorTest(unittest.TestCase):
# The leaf_generator is mentioned in PEP 654 as a suggestion
# on how to iterate over leaf nodes of an EG. It is also
# on how to iterate over leaf nodes of an EG. Is is also
# used below as a test utility. So we test it here.

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_leaf_generator(self):
eg = create_simple_eg()

Expand Down Expand Up @@ -549,25 +511,19 @@ def create_nested_eg():


class NestedExceptionGroupBasicsTest(ExceptionGroupTestBase):
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nested_group_matches_template(self):
eg = create_nested_eg()
self.assertMatchesTemplate(
eg,
ExceptionGroup,
[[TypeError(bytes)], ValueError(1)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nested_group_chaining(self):
eg = create_nested_eg()
self.assertIsInstance(eg.exceptions[1].__context__, MemoryError)
self.assertIsInstance(eg.exceptions[1].__cause__, MemoryError)
self.assertIsInstance(eg.exceptions[0].__context__, TypeError)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_nested_exception_group_tracebacks(self):
eg = create_nested_eg()

Expand All @@ -581,8 +537,6 @@ def test_nested_exception_group_tracebacks(self):
self.assertEqual(tb.tb_lineno, expected)
self.assertIsNone(tb.tb_next)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_iteration_full_tracebacks(self):
eg = create_nested_eg()
# check that iteration over leaves
Expand Down Expand Up @@ -670,8 +624,6 @@ def tb_linenos(tbs):

class NestedExceptionGroupSplitTest(ExceptionGroupSplitTestBase):

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_by_type(self):
class MyExceptionGroup(ExceptionGroup):
pass
Expand Down Expand Up @@ -771,8 +723,6 @@ def level3(i):
self.assertMatchesTemplate(match, ExceptionGroup, [eg_template[0]])
self.assertMatchesTemplate(rest, ExceptionGroup, [eg_template[1]])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_BaseExceptionGroup(self):
def exc(ex):
try:
Expand Down Expand Up @@ -813,8 +763,6 @@ def exc(ex):
self.assertMatchesTemplate(
rest, ExceptionGroup, [ValueError(1)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_copies_notes(self):
# make sure each exception group after a split has its own __notes__ list
eg = ExceptionGroup("eg", [ValueError(1), TypeError(2)])
Expand Down Expand Up @@ -846,11 +794,23 @@ def test_split_does_not_copy_non_sequence_notes(self):
self.assertFalse(hasattr(match, '__notes__'))
self.assertFalse(hasattr(rest, '__notes__'))

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_drive_invalid_return_value(self):
class MyEg(ExceptionGroup):
def derive(self, excs):
return 42

eg = MyEg('eg', [TypeError(1), ValueError(2)])
msg = "derive must return an instance of BaseExceptionGroup"
with self.assertRaisesRegex(TypeError, msg):
eg.split(TypeError)
with self.assertRaisesRegex(TypeError, msg):
eg.subgroup(TypeError)


class NestedExceptionGroupSubclassSplitTest(ExceptionGroupSplitTestBase):

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_ExceptionGroup_subclass_no_derive_no_new_override(self):
class EG(ExceptionGroup):
pass
Expand Down Expand Up @@ -893,8 +853,6 @@ class EG(ExceptionGroup):
self.assertMatchesTemplate(match, ExceptionGroup, [[TypeError(2)]])
self.assertMatchesTemplate(rest, ExceptionGroup, [ValueError(1)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_BaseExceptionGroup_subclass_no_derive_new_override(self):
class EG(BaseExceptionGroup):
def __new__(cls, message, excs, unused):
Expand Down Expand Up @@ -937,8 +895,6 @@ def __new__(cls, message, excs, unused):
match, BaseExceptionGroup, [KeyboardInterrupt(2)])
self.assertMatchesTemplate(rest, ExceptionGroup, [ValueError(1)])

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_split_ExceptionGroup_subclass_derive_and_new_overrides(self):
class EG(ExceptionGroup):
def __new__(cls, message, excs, code):
Expand Down

0 comments on commit 0e816c1

Please sign in to comment.