Hey Ron,
There was an interesting discussion on Reddit recently about asyncio and how many projects are reimplementing various stacks on top of it. One of the core developers for Requests chimed with an interesting comment.
The money quote from that comment, to me, was this:
What we as a community need to be doing is to write synchronous stacks that don’t do I/O, and then write thin wrapper libraries around them that work well in the specific concurrency and I/O model being used.
That got me thinking: Does it make sense to somehow take AsyncSSH and separate the core SSH implementation from the parts that depend on asyncio for I/O? Perhaps there could be a core sshlib
library that, like Cory described, doesn’t do any I/O. AsyncSSH would then be a wrapper around that library that uses asyncio as its concurrency model and I/O interface.
If I understood Cory’s comment correctly, that would open the door for other wrappers around this new sshlib
core that use different I/O or concurrency models. Perhaps then there could be a wrapper that uses curio, and another one that offers a strictly synchronous interface.
What are your thoughts on this? I remember you mentioned wanting to separate parts of the core implementation from asyncio the last time we discussed curio.
This likely only works in scenarios where the authors of the non-I/O portions are also authoring the various I/O models to work with them.The problem is that in order to provide an API for the non I/O portions of your code, it helps tremendously to know what the possible I/O or concurrency models are going to be! 80% of the code ends up being the I/O portion anyway, and will be opinionated and distinct from its sync/async counterpart.The result is that you don't end up benefitting as much as you might expect from reusing non-IO modules. What does make sense about this is the idea that the module authors should be authoring the sync/async interfaces simultaneously.