<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><div><div style="font-family: Calibri,sans-serif; font-size: 11pt;">Big +1 here, and an implicit -1 on the other suggestions. <br><br>asyncio != async/await<br><br>Cheers,<br>Steve<br><br>Top-posted from my Windows Phone</div></div><div dir="ltr"><hr><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">From: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:njs@pobox.com">Nathaniel Smith</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Sent: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">‎2/‎28/‎2017 23:19</span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">To: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:ncoghlan@gmail.com">Nick Coghlan</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Cc: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;"><a href="mailto:python-dev@python.org">python-dev@python.org</a></span><br><span style="font-family: Calibri,sans-serif; font-size: 11pt; font-weight: bold;">Subject: </span><span style="font-family: Calibri,sans-serif; font-size: 11pt;">Re: [Python-Dev] API design: where to add async variants ofexisting stdlib APIs?</span><br><br></div>On Tue, Feb 28, 2017 at 9:42 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:<br>> Short version:<br>><br>> - there are some reasonable requests for async variants of contextlib APIs<br>> for 3.7<br>> - prompted by Raymond, I'm thinking it actually makes more sense to add<br>> these in a new `asyncio.contextlib` module than it does to add them directly<br>> to the existing module<br>> - would anyone object strongly to my asking authors of the affected PRs to<br>> take their changes in that direction?<br><br>IMHO this is a good idea *iff* the new APIs really are bound to<br>asyncio, rather than being generic across all uses of async/await.<br><br>It sounds like that's not the case, though? There are definitely use<br>cases for acontextmanager in programs that don't use asyncio at all<br>(but rather use twisted, curio, ...). Guido's even suggested that he'd<br>like to see a PEP for an "asyncio2" within the 3.7/3.8 timeframe:<br>https://mail.python.org/pipermail/async-sig/2016-November/000175.html<br><br>asyncio is an important use case for async/await, but it's definitely<br>not the only one. In cases where it's possible to write generic<br>machinery in terms of async/await semantics, without assuming any<br>particular coroutine runner's semantics, then I strongly urge you to<br>do so.<br><br>> Longer version:<br>><br>> There are a couple of open issues requesting async variants of some<br>> contextlib APIs (asynccontextmanager and AsyncExitStack). I'm inclined to<br>> accept both of them, but Raymond raised a good question regarding our<br>> general design philosophy for these kinds of additions: would it make more<br>> sense to put these in an "asyncio.contextlib" module than it would to add<br>> them directly to contextlib itself?<br>><br>> The main advantage I see to the idea is that if someone proposed adding an<br>> "asyncio" dependency to contextlib, I'd say no. For the existing<br>> asynccontextmanager PR, I even said no to adding that dependency to the<br>> standard contextlib test suite, and instead asked that the new tests be<br>> moved out to a separate file, so the existing tests could continue to run<br>> even if asyncio was unavailable for some reason.<br><br>asyncio is a stable, non-provisional part of the standard library;<br>it's not going anywhere. Personally I wouldn't be bothered about<br>depending on it for tests. (My async_generator library is in a similar<br>position: it isn't tied to any particular framework, and I don't even<br>use asyncio myself, but the test suite depends on asyncio because hey,<br>whatever, everyone already has it and it plays the role of generic<br>coroutine runner as well as anything else does.)<br><br>OTOH if you don't need to do any I/O then it's actually pretty easy to<br>write a trivial coroutine runner. I think something like this should<br>be sufficient to write any test you might want:<br><br>@types.coroutine<br>def send_me(value):<br>    return yield ("value", value)<br><br>@types.coroutine<br>def throw_me(exc):<br>    yield ("error", exc)<br><br>async def yield_briefly():<br>    await send_me(None)<br><br>def run(async_fn, *args, **kwargs):<br>    coro = async_fn(*args, **kwargs)<br>    next_msg = ("value", None)<br>    try:<br>        while True:<br>            if next_msg[0] == "value":<br>                next_msg = coro.send(next_msg[1])<br>            else:<br>                next_msg = coro.throw(next_msg[1])<br>    except StopIteration as exc:<br>        return exc.value<br><br>> While rejecting the idea of an asyncio dependency isn't a problem for<br>> asyncontextmanager specifically (it's low level enough for it not to<br>> matter), it's likely to be more of a concern for the AsyncExitStack API,<br>> where the "asyncio.iscoroutinefunction" introspection API is likely to be<br>> quite helpful, as are other APIs like `asyncio.ensure_future()`.<br><br>FYI FWIW, every time I've tried to use iscoroutinefunction so far I've<br>ended up regretting it and ripping it out again :-). The problem is<br>that people will do things like apply a decorator to a coroutine<br>function, and get a wrapped function that returns a coroutine object<br>and which is interchangeable with a real coroutine function in every<br>way except that iscoroutinefunction returns False. And there's no<br>collections.abc.CoroutineFunction (not sure how that would even work).<br>Better to just call the thing and then do an isinstance(...,<br>collections.abc.Coroutine) on the return value.<br><br>I haven't had a reason to try porting ExitStack to handle async<br>context managers yet, so I can't speak to it beyond that :-).<br><br>-n<br><br>-- <br>Nathaniel J. Smith -- https://vorpus.org<br>_______________________________________________<br>Python-Dev mailing list<br>Python-Dev@python.org<br>https://mail.python.org/mailman/listinfo/python-dev<br>Unsubscribe: https://mail.python.org/mailman/options/python-dev/steve.dower%40python.org<br></body></html>