python-trio / async_generator

Making it easy to write async iterators in Python 3.5
Other
95 stars 24 forks source link

asynccontextmanager decorated functions return False but when using contextlib they return None #31

Closed gsalgado closed 4 years ago

gsalgado commented 4 years ago

I don't know if this is intentional, but contextlib's asynccontextmanager decorated functions return None whereas here they'd return False. The snippet below shows that:

import asyncio
import contextlib
from async_generator import asynccontextmanager

@contextlib.asynccontextmanager
async def f():
    yield

@asynccontextmanager
async def g():
    yield

async def main():
    ctx1 = f()
    ctx2 = g()
    await asyncio.gather(*(ctx.__aenter__() for ctx in [ctx1, ctx2]))
    exits = await asyncio.gather(*(ctx.__aexit__(None, None, None) for ctx in [ctx1, ctx2]))
    print(exits)

l = asyncio.get_event_loop()
l.run_until_complete(main())
oremanj commented 4 years ago

Both approaches adhere to the context manager protocol, since both returns test as false. Are you running into an issue where the difference is relevant to your application?

It looks like the synchronous @contextlib.contextmanager returns False in this case, which is where async_generator got its behavior from. And @contextlib.asynccontextmanager returns False in some cases and None in others. I think the stdlib @asynccontextmanager is the odd one out here.

gsalgado commented 4 years ago

Not really relevant to my application, but I was writing some tests that checked for the yielded values and noticed the discrepancy so I thought maybe it was worth reporting. Feel free to ~ignore~close if you think it has no practical implications

njsmith commented 4 years ago

If it's not causing any problems then let's let it be. We can always re-open if it somehow starts causing problems in the future :-)