Skip to content

PyIter_Next clears a StopException, where tp_iternext does not #29

@mattip

Description

@mattip

Consider this code:

async def gen():
    yield 123

def test_last_yield(g):
    ai = g.__aiter__()
    an = ai.__anext__()
    try:
        next(an) 
    except StopIteration as ex:
        return ex.args
    else:
        return None 

ret = test_last_yield(gen())
assert ret[0] == 123

There are two ways to convert next(an) to C: either PyIter_Next(an) or an.tp_iternext(). There is a subtle difference: PyIter_Next will return NULL, signaling that the iteration is complete, and clear the StopIteration exception, erasing the ex.args. Calling tp_iternext will not clear the exception, so the yield value will be available through the ex.args. This came up in cython since it tends not to use the slot functions on non-CPython (in this case PyPy). As far as I can tell, there is no PyIter_* function to only call tp_iternext without clearing the exception.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions