diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2022-11-18 08:10:55 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-18 08:10:55 -0800 |
commit | 82ab9e6b7938484724a19e293a640d956111a012 (patch) | |
tree | 71e603440c9c07a233dda45a3e816624def46d73 | |
parent | bbac9a8bcc4d7c0692e8b4f62a955f7ca107b496 (diff) | |
download | cpython3-82ab9e6b7938484724a19e293a640d956111a012.tar.gz |
gh-99553: fix bug where an ExceptionGroup subclass can wrap a BaseException (GH-99572)
(cherry picked from commit c8c6113398ee9a7867fe9b08bc539cceb61e2aaa)
Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
-rw-r--r-- | Doc/library/exceptions.rst | 4 | ||||
-rw-r--r-- | Lib/test/test_exception_group.py | 22 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2022-11-18-11-24-25.gh-issue-99553.F64h-n.rst | 2 | ||||
-rw-r--r-- | Objects/exceptions.c | 14 |
4 files changed, 37 insertions, 5 deletions
diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index fc856277d6..4271a30de7 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -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 diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index 2cfd873830..7fb45462e2 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -79,16 +79,30 @@ class InstanceCreation(unittest.TestCase): 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): diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-11-18-11-24-25.gh-issue-99553.F64h-n.rst b/Misc/NEWS.d/next/Core and Builtins/2022-11-18-11-24-25.gh-issue-99553.F64h-n.rst new file mode 100644 index 0000000000..8d9f55d6d9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-11-18-11-24-25.gh-issue-99553.F64h-n.rst @@ -0,0 +1,2 @@ +Fix bug where an :exc:`ExceptionGroup` subclass can wrap a +:exc:`BaseException`. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 01522aa806..4fba9b0a62 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -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) { |