0

The toy script shows an application using a class that is dependent on an implementation that is not asyncio-aware, and obviously doesn't work.

How would the fetch method of MyFetcher be implemented, using the asyncio-aware client, while still maintaining the contract with the _internal_validator method of FetcherApp? To be very clear, FetcherApp and AbstractFetcher cannot be modified.

c0dem4gnetic
  • 932
  • 1
  • 7
  • 24
  • What's the point of using an asynchronous library in a synchronous application? – Vincent Apr 20 '16 at 11:00
  • It's the other way around, sorry if that wasn't clear. In my case I'm looking at integrating https://github.com/idan/oauthlib with aiohttp.web. The module has a class RequestValidator which I'm supposed to implement, and then pass the implementation to the library. I tried my best to illustrate this with the toy script. It all boils down to using async operations in the RequestValidator. – c0dem4gnetic Apr 20 '16 at 20:07
  • Did you look into [aioauth-client](https://github.com/klen/aioauth-client)? – Vincent Apr 20 '16 at 21:14
  • It's the provider/server part of oauthlib I'm looking to use. I have yet to find one for asyncio. – c0dem4gnetic Apr 21 '16 at 10:33

1 Answers1

1

To use async fetch_data function inside fetch both fetch and is_fetched_data_valid functions should be async too. You can change them in child classes without modify parent:

import asyncio


class AsyncFetcherApp(FetcherApp):
    async def is_fetched_data_valid(self):  # async here
        data = await self.fetcher_implementation.fetch()  # await here
        return self._internal_validator(data)


class AsyncMyFetcher(AbstractFetcher):
    def __init__(self, client):
        super().__init__()
        self.client = client

    async def fetch(self):  # async here
        result = await self.client.fetch_data()  # await here
        return result


class AsyncClient:
    async def fetch_data(self):
        await asyncio.sleep(1)  # Just to sure it works
        return 1



async def main():
    async_client = AsyncClient()
    my_fetcher = AsyncMyFetcher(async_client)
    fetcherApp = AsyncFetcherApp(my_fetcher)
    # ...
    is_valid = await fetcherApp.is_fetched_data_valid()  # await here
    print(repr(is_valid))


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
Mikhail Gerasimov
  • 36,989
  • 16
  • 116
  • 159
  • Looking at this, I'm seeing that I need to essentially reimplement all methods of the "sealed" module? As in, port the module to fit with asyncio? – c0dem4gnetic Apr 20 '16 at 20:11
  • 1
    @c0dem4gnetic "reimplement all methods" - more specifically: only those what will use async functions. `async` and `await` should be explicit by `asyncio` module design. Alternatives to `asyncio`: use threads (`ThreadPoolExecutor`) or may be `greenlet` (it's designed for non-explicit asynchronous execution). – Mikhail Gerasimov Apr 20 '16 at 20:25
  • 1
    @c0dem4gnetic, actually, one more way - is to use synchronous code with asyncio running first in async thread. See example here: http://stackoverflow.com/a/33399896/1113207 (last snippet). I can't tell exactly if it would work for current task. – Mikhail Gerasimov Apr 20 '16 at 20:30