Hello, Manuel.

The answer to your problem is to refactor the libraries in the "sans I/O" style.

Take a look here:
http://sans-io.readthedocs.io/


On Thu, 8 Jun 2017 at 19:32 manuel miranda <manu.mirandad@gmail.com> wrote:
Hello everyone,

After using asyncio for a while, I'm struggling to find information about how to support both synchronous and asynchronous use cases for the same library.

I.e. imagine you have a package for http requests and you want to give the user the choice to use a synchronous or an asynchronous interface. Right now the approach the community is following is creating separate libraries one for each version. This is far from ideal for several reasons, some I can think of:

- Code duplication, most of the functionality is the same in both libraries, only difference is the sync/async behaviors
- Some new async libraries lack functionality compared to their sync siblings. Others will introduce bugs that the sync version already solved long ago, etc.
- Different interfaces for the user for the same exact functionality.

In summary, in some cases it looks like reinventing the wheel. So now comes the question, is there any documentation, guide on what would be best practice supporting this kind of duality? I've been playing a bit with that on my own but I really don't know if I'm doing something stupid or not. Simple example:

"""
import asyncio


class MyConnector:

    @classmethod
    async def get(cls, key):
        return key


class AsyncClient:

    async def get(self, key):
        return await MyConnector.get(key)


class SyncClient:

    def __init__(self):
        self.loop = asyncio.get_event_loop()

    def get(self, key):
        return self.loop.run_until_complete(MyConnector.get(key))


def sync_call():
    client = SyncClient()
    print(client.get("sync_key"))


async def async_call():
    client = AsyncClient()
    print(await client.get("async_key"))


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(async_call())
    sync_call()
"""

This is in case the underlying connector is asynchronous already. If its synchronous and you want to support both modes, you have to rewrite the IO interactions of MyConnector into a new AsyncMyConnector to support asyncio and then use one or the other accordingly in the upper classes.

Am I doing it right or there is another better/alternative way?

Thanks for your time,

Manuel
_______________________________________________
Async-sig mailing list
Async-sig@python.org
https://mail.python.org/mailman/listinfo/async-sig
Code of Conduct: https://www.python.org/psf/codeofconduct/
--
Luciano Ramalho
|  Author of Fluent Python (O'Reilly, 2015)
|     http://shop.oreilly.com/product/0636920032519.do
|  Technical Principal at ThoughtWorks
|  Twitter: @ramalhoorg