Author yselivanov
Recipients asvetlov, gvanrossum, lukasz.langa, njs, rhettinger, xtreak, yselivanov
Date 2019-09-24.01:56:23
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
Nathaniel, thanks for the summary!

A few comments to address some points:

> So Yury and I are tentatively thinking we'll make some kind of PEP for the 3.9 timescale, probably just for the core ABCs

Yes!  At the very least for things like asynchronous version of "closable", e.g. an object with an "aclose()" coroutine method.  I'm sure there are some other straightforward design patterns that we can codify.  Maybe we can do that for streams too -- see some thoughts below.

> First decision point: will asyncio.Stream implement the ABCs directly, or will you need some kind of adapter?

I'd love asyncio.Stream to implement the ABCs directly.  The only problem is that Trio isn't yet settled on the design of those ABCs and we need to make some decisions for asyncio *now*.

I hope that the Trio project can minimize the number of methods they want to add to those ABCs so that we don't need to duplicate a lot of functionality in asyncio.Stream.  E.g. in the new asyncio.Stream there's a Stream.write() coroutine; in Trio it's Stream.send_all().  I'm not entirely convinced that "send_all()" is a good name, for example, even though I now understand the motivation.  We can discuss that later in a relevant issue though.

Another important point to consider: if the new Trio Stream ABCs are *significantly different* from asyncio.Stream and would require us to alias too many methods or to do heavy refactoring and deprecations, then Trio will have to show some real world usage and traction of its APIs first.

> If we completely separated the old StreamReader/StreamWriter functions from the new Stream functions, then it would also have another advantage: we could clean up several issues with Stream that are only needed for compatibility with the old APIs. In particular, we could get rid of the optional-await hacks on 'write' and 'close', and turn them into regular coroutines.

We'd like to avoid that and have one asyncio.Stream class in asyncio.  Using legacy StreamReader/StreamWriter functions for subprocesses alone (long term) isn't a solution for us, since there're real problems with .write() and .close() not being awaitables.  Sticking to having a new asyncio.Stream API and old StreamReader/StreamWriter for subprocesses isn't an acceptable solution either.  We'd like to minimize the API surface that asyncio users have to deal with.

> The obvious change would be to leave out __aiter__ from asyncio.Stream in 3.8.

> Option 1: Keep the Stream code as-is, and accept that using asyncio.Stream with future ABC-based code will require some compromises

Nathaniel, I think it's important to emphasize that those compromises should be mutual.  I'm willing to support changing "Stream.close()" to "Stream.aclose()" and to perhaps alias some methods.  We can also implement "Stream.chunks()".  But changing the semantics of "__aiter__" is, unfortunately, not on the table, at least for me.

If Trio doesn't want to change the __aiter__ semantics of its Stream ABC (which is only a *proposal* right now!), then:

- Fragmenting asyncio APIs by letting subprocesses use old StreamReader/StreamWriter while we have new asyncio.Stream isn't an option.

- Asking us to implement new subprocess APIs just for the sake of having different Stream implementation for Process.std* channels isn't an option either.  

Adding new APIs and deprecating old ones is a huge burden on asyncio maintainers and users.  So the "obvious change" for *me* would be using "Stream.chunks()" iterator in Trio.  For Trio it's a question of whether the new API is pretty; for asyncio it's a question of how many APIs we need to deprecate/change.  I hope you understand my position and why I am strong -1 on the "Option 2".

> Right now we don't have any path to fixing 'write'/'close' at all;

Andrew and I discussed that this morning.  Here's the plan:

1. We add "aclose()" and "write()" coroutines to the new "asyncio.Stream()".  It won't have "wait_closed()" or "drain()" or "close()".

2. We add a _LegacyStream class derived from the new asyncio.Stream.  We will use it for subprocesses. Its "write()" method will return an "OptionallyAwaitable" wrapper that will nudge users to add an await in front of "stdin.write()".  _LegacyStream will be completely backwards compatible.

This path enables us to add a decent new streaming API while retaining consistency and backwards compatibility.

> BTW Andrew, while writing that I realized that there's also overlap between your new Server classes and Trio's ABC for servers, and I think it'd be interesting to chat about how they compare maybe? But it's not relevant to this issue, so maybe gitter or another issue or something?

If possible please use email/bpo/github.  I don't use gitter and I'd like to be part of that discussion (or at least be able to follow it).
Date User Action Args
2019-09-24 01:56:24yselivanovsetrecipients: + yselivanov, gvanrossum, rhettinger, njs, asvetlov, lukasz.langa, xtreak
2019-09-24 01:56:24yselivanovsetmessageid: <>
2019-09-24 01:56:24yselivanovlinkissue38242 messages
2019-09-24 01:56:23yselivanovcreate