Skip to content

Commit 402b91d

Browse files
gh-128078: Use PyErr_SetRaisedException in _PyGen_SetStopIterationValue (#128287)
Co-authored-by: Kumar Aditya <[email protected]>
1 parent 3efe28a commit 402b91d

File tree

2 files changed

+11
-23
lines changed

2 files changed

+11
-23
lines changed

Lib/test/test_asyncgen.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ async def run():
11651165
with self.assertRaises(StopAsyncIteration):
11661166
await it.__anext__()
11671167
res = await anext(it, ('a', 'b'))
1168-
self.assertEqual(res, ('a', 'b'))
1168+
self.assertTupleEqual(res, ('a', 'b'))
11691169

11701170
self.loop.run_until_complete(run())
11711171

Objects/genobject.c

+10-22
Original file line numberDiff line numberDiff line change
@@ -634,30 +634,18 @@ int
634634
_PyGen_SetStopIterationValue(PyObject *value)
635635
{
636636
assert(!PyErr_Occurred());
637-
PyObject *e;
638-
639-
if (value == NULL ||
640-
(!PyTuple_Check(value) && !PyExceptionInstance_Check(value)))
641-
{
642-
/* Delay exception instantiation if we can */
643-
PyErr_SetObject(PyExc_StopIteration, value);
644-
return 0;
645-
}
646-
/* Construct an exception instance manually with
647-
* PyObject_CallOneArg and pass it to PyErr_SetObject.
648-
*
649-
* We do this to handle a situation when "value" is a tuple, in which
650-
* case PyErr_SetObject would set the value of StopIteration to
651-
* the first element of the tuple.
652-
*
653-
* (See PyErr_SetObject/_PyErr_CreateException code for details.)
654-
*/
655-
e = PyObject_CallOneArg(PyExc_StopIteration, value);
656-
if (e == NULL) {
637+
// Construct an exception instance manually with PyObject_CallOneArg()
638+
// but use PyErr_SetRaisedException() instead of PyErr_SetObject() as
639+
// PyErr_SetObject(exc_type, value) has a fast path when 'value'
640+
// is a tuple, where the value of the StopIteration exception would be
641+
// set to 'value[0]' instead of 'value'.
642+
PyObject *exc = value == NULL
643+
? PyObject_CallNoArgs(PyExc_StopIteration)
644+
: PyObject_CallOneArg(PyExc_StopIteration, value);
645+
if (exc == NULL) {
657646
return -1;
658647
}
659-
PyErr_SetObject(PyExc_StopIteration, e);
660-
Py_DECREF(e);
648+
PyErr_SetRaisedException(exc /* stolen */);
661649
return 0;
662650
}
663651

0 commit comments

Comments
 (0)