Hi Laurent, I'm still a dilettante, so take my comments with a grain of salt:
1. Target Python 3.6 only. (i.e. drop 3.5; look at 3.7 obv, but you want users now) (i.e. forget `yield from`, none will remember/get it next year) (if 2.7 or 3.3 must be supported, provide synch package) 2. Use futures (unless it's a stream) 3. Shield liberally 4. Provide context managers Naive user code might look like that: req = lib.request(...) await req.ready() # optional return await req.json()["something"] That's sane and pretty similar to http://aiohttp.readthedocs.io/en/stable/client.html thus your users will get it :) A more advanced use will be `[async] with lib.request(...) as r: await r.json()` (you probably want `async with` unless you can ensure synchronous timely termination) Personally I'd prefer `ready` and `json` without parentheses, but it seems I'm in a minority. Cheers, d. On 12 July 2017 at 00:26, Laurent Mazuel via Async-sig <async-sig@python.org> wrote: > Hello, > > Iām working currently with Brett Cannon to bring asyncio support to our SDK. > We wanted to check with you one of the scenario, since we got a loooong > discussion on it together š. And we want to do it using the best reasonable > practice with your opinion. > > We have an api that is clearly async and will gain a lot to be converted to > asyncio. However, it's a two-step operation. Operation 1 asks for the > creation of a resource and is not async, operation 2 is *optional* and wait > for completion of this creation (with nightmare threads currently and I > removed a lot of code moving to asyncio - happiness). There is perfectly > legit scenarios where operation 2 is not needed and avoid it is better, but > it has to be prepared at the same time of operation 1. Current code looks > like this: > > sync_poller = client.create(**parameters) > obj = sync_poller.resource() # Get the initial resource information, but > the object is not actually created yet. > obj = sync_poller.result() # OPTIONAL. This is a blocking call with > thread, if you want to wait for actual creation and get updated metadatas > > My first prototype was to split and return a tuple (resource, coroutine): > > obj, optional_poller = client.create(**parameters) > obj = await optional_poller # OPTIONAL > > But I got a warning if I decide to do not use this poller, RuntimeWarning: > coroutine 'foo' was never awaited > > I was surprised honestly that I can't do that, since I feel like I'm not > leaking anything. I didn't run the operation, so there is no wasted resource > at my knowledge. But I remember wasting time because of a forgotten "yield > from", so I guess it's fair š. But I would be curious to understand what I > did badly. > > I found 2 solutions to avoid the warning, and I currently prefer solution 2: > 1- Return a function to call, and not a coroutine. The "await" statement > becomes: > > obj = await optional_poller() > > 2- Return my initial object with an async method. This allows me to write > (something finally close to the current code): > > async_poller = client.create(**parameters) > obj = async_poller.resource() # Get the initial resource information, but > the object is not actually created yet. > obj = await async_poller.result() # OPTIONAL > > My async_poller object being something like: > > class PollerOperation: > async def result(self): > ...async version of previous sync result()... > > So the questions are: > - Does this seem a correct pattern? > - Is there a simple way to achieve something like this: > > obj = await async_poller > > meaning, I can win the "result()" syntax and directly "await" on the object > and get the result from magic function. I tried by subclassing some ABC > coroutine/awaitable, but wasn't able to find a correct syntax. I'm not even > sure this makes sense and respects the zen of Python š > > If it helps, I'm willing to use 3.5 as minimal requirement to get async > behavior. > > Thank you!! > > Laurent > _______________________________________________ > 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/ _______________________________________________ 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/