-
-
Notifications
You must be signed in to change notification settings - Fork 384
Description
There are some very obscure edge cases where using async generators does the wrong thing. For example, this code
import trio
async def fail():
raise ValueError
async def main():
async with trio.open_nursery() as nursery:
nursery.spawn(fail)
raise StopIteration
trio.run(main)Ought to raise a MultiError([StopIteration(), ValueError()]), but instead it raises a MultiError([RuntimeError(), ValueError()]). This is because you can't throw a StopIteration into an async_generator-based async generator (for details see here) – it gets wrapped into a RuntimeError. If we let that RuntimeError propagate, then acontextmanager could turn it back, but here it gets wrapped into a MultiError instead so the magic doesn't work.
I guess we could make acontextmanager smart enough to look inside MultiErrors? Or stop using acontextmanager and write this context manager directly? Or just not worry about it until we can drop 3.5 support and switch to using native async generators, which don't have this problem? It's very unusual to have free-floating StopIteration exceptions wandering around like this, and that's the only case that's affected. But I figured we should record the problem in any case.