New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added AnyIO support #169
Added AnyIO support #169
Conversation
This is fantastic @agronholm, thank you! There's a difficult decision to take here wrt. to which of the following we'd want to proceed with...
My main concern about pulling it in as an outright replacement for our backend implementations would be that we're taking a small amount of surfaced code, and replacing it with a larger amount of submerged code, in the form of a dependancy. That gets really awkward in particular when we're dealing with issues such as bugs in the asyncio implementation that we're having to work around, because there's an extra layer in there for us to consider. And the extra layer in the stack is just generally something I'd prefer to avoid if possible, even if it means we have a little more code than we might otherwise. Although I am super keen on us being able to share expertise - this implementation comes out really nice & clean, and there's one or two nice little nuggets in there, such as using the One other thought here... both this PR and #168 unsurprisingly both change the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very interesting, thank you so much for pulling this off!
I'm curious about something... What if, instead of adding a new and separate AnyIOBackend
, we changed the implementation of AutoBackend
to use anyio
(and removed the other backends since they're not needed anymore)? So, no new backend class, but just an overhaul of AutoBackend
so that it uses anyio
instead of using our own backend classes (all of which is an implementation detail)?
Eventually we could very much just have a direct AsyncBackend
, and drop the rest of the base classes and interfaces (since the async environment abstraction is done by anyio
now).
I'm not saying we should do this in this PR or right now, but it's interesting to see how much code could actually be dropped if we switched to anyio entirely (which I guess is the eventual goal of this work?).
Fine by me. My next goal was to indeed do away with all the code rendered useless by this PR.
Also, do you plan on having other sync backends too? I was wondering why there is a lone sync backend. Was it just because there were multiple async backends? Maybe you want to support gevent directly or something?
Quite a lot, I'd say :) |
The primary purpose of AnyIO was to relieve library authors of the burden of having to support multiple async backends. Generally AnyIO also works around those bugs on your behalf. I get that the project is relatively new (2018-) so it doesn't have much of a track record. I can only hope that I'll be able to convince you. |
@tomchristie you said:
so I created #170 |
Right, probably worth updating this against master now that #170 is in, since it'll have a slightly smaller footprint now. |
95a4dde
to
68adf67
Compare
I've rebased against the latest master and wasted at least 30 minutes trying to play whack-a-mole with 4 different linters. |
A tox configuration file would be nice so that I wouldn't have to wait for Github Actions to tell me what I did wrong. |
Running If there are linting issues the you can run |
It doesn't seem like black is respecting its own configuration. |
From the test runs, the issue looks like the async/sync codebases being out of sync with each other. If you want to resolve that without running any of the other linting, then run |
It seems that I needed to edit the unasync script which I hadn't done. Now there seems to be a new method in the interface I have to implement. I'll get back to you on that. |
The test suite does not pass yet. Something unexpected happens on the asyncio backend. |
There are two tests that fail almost consistently: the |
I checked the results of
What struck me as odd was the accuracy of the timestamps: they were only accurate to the millisecond. The stdlib asyncio event loop demonstrably produces timestamps accurate to the microsecond, but uvloop limits them to the millisecond. Since the condition is I can modify the backend options so that asyncio tests don't use uvloop, but would it be possible to modify the condition to |
Sounds sensible, yup. |
What's the next step? |
There are a couple of unrelated changes here that ideally should be dealt with in separate, isolated PRs:
Also, what do we think of this...? Instead of the removing usage of Thanks so much for championing this, as often in case of relatively major changes there are a couple of small adjustments to make as preliminary work, but we'll get there! :) |
Also, there is one planned API change in AnyIO before v2.0 final. That will affect this PR and it has to be modified. |
One thing out of the way: #171 |
And another one for fixing Black havoc: #172 |
Rebased against master again. |
Which classes are we talking about here? The ones in httpcore that currently take a |
Okay, so #179 adds a That'd allow users to override the current auto-detection with an explicit selection. It's also useful at this point in time, because it'd allow us to add "anyio" as an option without making a hard switch to it. Once that's merged I think the route to getting this pull request in would be...
For the purposes of keeping the PR tested with minimal changes I'd also suggest that the PR could then switch the test cases in There shouldn't be any other changes in the test suite, such as switching to The last change after that would be parameterizing the test suite so that the async test cases end up running both |
This means we'll be running the tests against every backend twice: one with the direct backends and once via anyio (6 variations in total). |
Eventually yes, and the existing testing approach of testing against a live server means the test suite will end up 2x even lower than it is now, but I guess we can roll with that for now (we're tracking the need to switch to a local server via #109). |
@agronholm - Pushed up #180 to show how I think we ought to add (Tho I'd also be happy to finish up the work directly in #180 if that's easier from your POV) |
Things that we can then keep as separate, isolated PRs...
And thanks so much for being patient with all this work. I know that this gradual incremental approach is a bit cautious, but it's a really good way for us to have a high degree of confidence at each step. 🙂 |
I've created a PR to address this: #181 |
The footprint of this PR will go down somewhat when #183 is merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great!
def is_connection_dropped(self) -> bool: | ||
raw_socket = self.stream.extra(SocketAttribute.raw_socket) | ||
rready, _wready, _xready = select.select([raw_socket], [], [], 0) | ||
return bool(rready) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to look into #182 some more before deciding that this trick is worth committing to. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense for us to approach it in this order?...
- Merge this PR.
- Update Tweak dropped connection detection #185 to include curio and anyio.
- Get Tweak dropped connection detection #185 merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure yup, #185 isn't blocking us from merging this, just wanted to clarify that this select() approach needed a bit of refining. :)
Co-authored-by: Florimond Manca <florimond.manca@gmail.com>
Co-authored-by: Florimond Manca <florimond.manca@gmail.com>
Is there anything more you need from me here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're good rolling with this one now, thank you so much @agronholm!
I'll go back to #185 and include the tweak for the curio and anyio backend's. :) |
🎉 |
No description provided.