From 6786dbdc25e74c0dcc318e96b4a3b91860c8b71a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 22 Mar 2022 09:28:35 +0000 Subject: [PATCH] shallow copy the notes in split(), if it's a sequence --- Lib/test/test_exception_group.py | 20 ++++++++++++++++++++ Objects/exceptions.c | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py index 15a1659c056158..158c2863b25ef5 100644 --- a/Lib/test/test_exception_group.py +++ b/Lib/test/test_exception_group.py @@ -665,6 +665,26 @@ def exc(ex): self.assertMatchesTemplate( rest, ExceptionGroup, [ValueError(1)]) + 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)]) + eg.add_note("note1") + eg.add_note("note2") + orig_notes = list(eg.__notes__) + match, rest = eg.split(TypeError) + self.assertEqual(eg.__notes__, orig_notes) + self.assertEqual(match.__notes__, orig_notes) + self.assertEqual(rest.__notes__, orig_notes) + self.assertIsNot(eg.__notes__, match.__notes__) + self.assertIsNot(eg.__notes__, rest.__notes__) + self.assertIsNot(match.__notes__, rest.__notes__) + eg.add_note("eg") + match.add_note("match") + rest.add_note("rest") + self.assertEqual(eg.__notes__, orig_notes + ["eg"]) + self.assertEqual(match.__notes__, orig_notes + ["match"]) + self.assertEqual(rest.__notes__, orig_notes + ["rest"]) + class NestedExceptionGroupSubclassSplitTest(ExceptionGroupSplitTestBase): diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 09eb1ed90a88ba..70cdc2d5829cf4 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -923,6 +923,16 @@ exceptiongroup_subset( if (notes == NULL) { goto error; } + if (PySequence_Check(notes)) { + /* make a copy so the parts have independent notes. + * If __notes__ is not a sequence, we don't know how to copy it */ + PyObject *notes_copy = PySequence_List(notes); + Py_DECREF(notes); + if (notes_copy == NULL) { + goto error; + } + notes = notes_copy; + } if (PyObject_SetAttr(eg, &_Py_ID(__notes__), notes) < 0) { Py_DECREF(notes); goto error;