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/

Reply via email to