This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author dfee
Recipients asvetlov, dfee, yselivanov
Date 2018-09-19.00:27:24
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1537316846.03.0.956365154283.issue34730@psf.upfronthosting.co.za>
In-reply-to
Content
I expected an async-generator's aclose() method to cancel it's __anext__(). Instead, the task isn't cancelled, and (it seems) manually cleanup is necessary.


@pytest.mark.asyncio
async def test_aclose_cancels():
    done = False
    event = asyncio.Event()
    agen = None

    async def make_agen():
        try:
            await event.wait()
            raise NotImplementedError()
            yield  # pylint: disable=W0101, unreachable
        finally:
            nonlocal done
            done = True

    async def run():
        nonlocal agen
        agen = make_agen()
        await agen.__anext__()

    task = asyncio.ensure_future(run())
    await asyncio.sleep(.01)

    await agen.aclose()
    await asyncio.sleep(.01)

    assert done
    assert task.done() and task.exception()


Looking at the tests for CPython, the implementation seems to expect it, but I'm unclear if PEP-525 actually intends for this to be the case: https://github.com/python/cpython/blob/e42b705188271da108de42b55d9344642170aa2b/Lib/test/test_asyncgen.py#L657

Alternatively, maybe I shouldn't be calling aclose, and instead I should be cancelling the task:

@pytest.mark.asyncio
async def test_cancel_finalizes():
    done = False
    event = asyncio.Event()
    agen = None

    async def make_agen():
        try:
            await event.wait()
            raise NotImplementedError()
            yield  # pylint: disable=W0101, unreachable
        finally:
            nonlocal done
            done = True

    async def run():
        nonlocal agen
        agen = make_agen()
        await agen.__anext__()

    task = asyncio.ensure_future(run())
    await asyncio.sleep(.01)
    task.cancel()
    await asyncio.sleep(.01)

    assert done
    assert task.done()

So the "bug" here is one of PEP-525 clarification.
History
Date User Action Args
2018-09-19 00:27:27dfeesetrecipients: + dfee, asvetlov, yselivanov
2018-09-19 00:27:26dfeesetmessageid: <1537316846.03.0.956365154283.issue34730@psf.upfronthosting.co.za>
2018-09-19 00:27:25dfeelinkissue34730 messages
2018-09-19 00:27:24dfeecreate