]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-128078: Use `PyErr_SetRaisedException` in `_PyGen_SetStopIterationValue...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 3 Feb 2025 23:34:02 +0000 (00:34 +0100)
committerGitHub <noreply@github.com>
Mon, 3 Feb 2025 23:34:02 +0000 (00:34 +0100)
gh-128078: Use `PyErr_SetRaisedException` in `_PyGen_SetStopIterationValue` (GH-128287)
(cherry picked from commit 402b91da87052878b4e7e8946ba91bdf4ee4bebe)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Lib/test/test_asyncgen.py
Objects/genobject.c

index 16164492b25690550f9c60266f2a0ea9391755e6..951c5502803789bfd79b0dd1c04d87eb398a6121 100644 (file)
@@ -1165,7 +1165,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
             with self.assertRaises(StopAsyncIteration):
                 await it.__anext__()
             res = await anext(it, ('a', 'b'))
-            self.assertEqual(res, ('a', 'b'))
+            self.assertTupleEqual(res, ('a', 'b'))
 
         self.loop.run_until_complete(run())
 
index 524cda1487813c7d2e9c84ebece1bf18de4dd0ac..3a9af4d4c182a3006c7769385d37f25f1cbcb550 100644 (file)
@@ -605,30 +605,18 @@ int
 _PyGen_SetStopIterationValue(PyObject *value)
 {
     assert(!PyErr_Occurred());
-    PyObject *e;
-
-    if (value == NULL ||
-        (!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
-    {
-        /* Delay exception instantiation if we can */
-        PyErr_SetObject(PyExc_StopIteration, value);
-        return 0;
-    }
-    /* Construct an exception instance manually with
-     * PyObject_CallOneArg and pass it to PyErr_SetObject.
-     *
-     * We do this to handle a situation when "value" is a tuple, in which
-     * case PyErr_SetObject would set the value of StopIteration to
-     * the first element of the tuple.
-     *
-     * (See PyErr_SetObject/_PyErr_CreateException code for details.)
-     */
-    e = PyObject_CallOneArg(PyExc_StopIteration, value);
-    if (e == NULL) {
+    // Construct an exception instance manually with PyObject_CallOneArg()
+    // but use PyErr_SetRaisedException() instead of PyErr_SetObject() as
+    // PyErr_SetObject(exc_type, value) has a fast path when 'value'
+    // is a tuple, where the value of the StopIteration exception would be
+    // set to 'value[0]' instead of 'value'.
+    PyObject *exc = value == NULL
+        ? PyObject_CallNoArgs(PyExc_StopIteration)
+        : PyObject_CallOneArg(PyExc_StopIteration, value);
+    if (exc == NULL) {
         return -1;
     }
-    PyErr_SetObject(PyExc_StopIteration, e);
-    Py_DECREF(e);
+    PyErr_SetRaisedException(exc /* stolen */);
     return 0;
 }