Skip to content

Commit

Permalink
gh-128078: Use PyErr_SetRaisedException in `_PyGen_SetStopIteration…
Browse files Browse the repository at this point in the history
…Value` (#128287)

Co-authored-by: Kumar Aditya <[email protected]>
  • Loading branch information
picnixz and kumaraditya303 authored Jan 13, 2025
1 parent 3efe28a commit 402b91d
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Lib/test/test_asyncgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ async def run():
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())

Expand Down
32 changes: 10 additions & 22 deletions Objects/genobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit 402b91d

Please sign in to comment.