gh-99553: fix bug where an ExceptionGroup subclass can wrap a BaseException (GH-99572)

This commit is contained in:
Irit Katriel 2022-11-18 15:44:43 +00:00 committed by GitHub
parent a220c6d1ee
commit c8c6113398
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 5 deletions

View file

@ -965,6 +965,10 @@ their subgroups based on the types of the contained exceptions.
def derive(self, excs): def derive(self, excs):
return Errors(excs, self.exit_code) 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 .. versionadded:: 3.11

View file

@ -78,16 +78,30 @@ class InstanceCreation(unittest.TestCase):
beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)]) beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
self.assertIs(type(beg), BaseExceptionGroup) self.assertIs(type(beg), BaseExceptionGroup)
def test_EG_subclass_wraps_anything(self): def test_EG_subclass_wraps_non_base_exceptions(self):
class MyEG(ExceptionGroup): class MyEG(ExceptionGroup):
pass pass
self.assertIs( self.assertIs(
type(MyEG("eg", [ValueError(12), TypeError(42)])), type(MyEG("eg", [ValueError(12), TypeError(42)])),
MyEG) MyEG)
self.assertIs(
type(MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])), def test_EG_subclass_does_not_wrap_base_exceptions(self):
MyEG) 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): def test_BEG_subclass_wraps_anything(self):
class MyBEG(BaseExceptionGroup): class MyBEG(BaseExceptionGroup):

View file

@ -0,0 +1,2 @@
Fix bug where an :exc:`ExceptionGroup` subclass can wrap a
:exc:`BaseException`.

View file

@ -753,7 +753,19 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
} }
} }
else { 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) { if (!cls) {