Skip to content

Commit

Permalink
gh-99553: fix bug where an ExceptionGroup subclass can wrap a BaseExc…
Browse files Browse the repository at this point in the history
…eption (GH-99572)

(cherry picked from commit c8c6113)

Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
  • Loading branch information
miss-islington and iritkatriel committed Nov 18, 2022
1 parent bbac9a8 commit 82ab9e6
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Doc/library/exceptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,10 @@ their subgroups based on the types of the contained exceptions.
def derive(self, excs):
return Errors(excs, self.exit_code)

Like :exc:`ExceptionGroup`, any subclass of :exc:`BaseExceptionGroup` which
is also a subclass of :exc:`Exception` can only wrap instances of
:exc:`Exception`.

.. versionadded:: 3.11


Expand Down
22 changes: 18 additions & 4 deletions Lib/test/test_exception_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,30 @@ def test_BEG_wraps_BaseException__creates_BEG(self):
beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
self.assertIs(type(beg), BaseExceptionGroup)

def test_EG_subclass_wraps_anything(self):
def test_EG_subclass_wraps_non_base_exceptions(self):
class MyEG(ExceptionGroup):
pass

self.assertIs(
type(MyEG("eg", [ValueError(12), TypeError(42)])),
MyEG)
self.assertIs(
type(MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])),
MyEG)

def test_EG_subclass_does_not_wrap_base_exceptions(self):
class MyEG(ExceptionGroup):
pass

msg = "Cannot nest BaseExceptions in 'MyEG'"
with self.assertRaisesRegex(TypeError, msg):
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])

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

msg = "Cannot nest BaseExceptions in 'MyEG'"
with self.assertRaisesRegex(TypeError, msg):
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])


def test_BEG_subclass_wraps_anything(self):
class MyBEG(BaseExceptionGroup):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix bug where an :exc:`ExceptionGroup` subclass can wrap a
:exc:`BaseException`.
14 changes: 13 additions & 1 deletion Objects/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,19 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
}
else {
/* Do nothing - we don't interfere with subclasses */
/* user-defined subclass */
if (nested_base_exceptions) {
int nonbase = PyObject_IsSubclass((PyObject*)cls, PyExc_Exception);
if (nonbase == -1) {
goto error;
}
else if (nonbase == 1) {
PyErr_Format(PyExc_TypeError,
"Cannot nest BaseExceptions in '%.200s'",
cls->tp_name);
goto error;
}
}
}

if (!cls) {
Expand Down

0 comments on commit 82ab9e6

Please sign in to comment.