]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-128078: Use `PyErr_SetRaisedException` in `_PyGen_SetStopIterationValue` (#128287)
authorBénédikt Tran <10796600+picnixz@users.noreply.github.com>
Mon, 13 Jan 2025 15:54:13 +0000 (16:54 +0100)
committerGitHub <noreply@github.com>
Mon, 13 Jan 2025 15:54:13 +0000 (21:24 +0530)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Lib/test/test_asyncgen.py
Objects/genobject.c

index 3f631a03c9bf720dce607839cf8ad05e81d97132..b81187871753b9e6fc03f59c0d08c5efd0ef8cc5 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 a4872de296e2cf593c68a416df7bed67c28a6d02..b32140766c4a386c8291aa6c54ea92159ec4dfb5 100644 (file)
@@ -634,30 +634,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;
 }