diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index 5f4f232b1f..21b92137b2 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -89,6 +89,16 @@ async def child(x): await task.wait() assert task.result.unwrap() == 20 +async def test_nursery_warn_use_async_with(): + with pytest.raises(RuntimeError) as excinfo: + on = _core.open_nursery() + with on as nursery: + pass # pragma: no cover + excinfo.match(r"use 'async with open_nursery\(...\)', not 'with open_nursery\(...\)'") + + # avoid unawaited coro. + async with on: + pass async def test_child_crash_basic(): exc = ValueError("uh oh") diff --git a/trio/_util.py b/trio/_util.py index 0986e02440..a779183b48 100644 --- a/trio/_util.py +++ b/trio/_util.py @@ -83,6 +83,7 @@ async def __aiter__(*args, **kwargs): # Copyright © 2001-2017 Python Software Foundation; All Rights Reserved class _AsyncGeneratorContextManager: def __init__(self, func, args, kwds): + self._func_name = func.__name__ self._agen = func(*args, **kwds).__aiter__() async def __aenter__(self): @@ -135,6 +136,13 @@ async def __aexit__(self, type, value, traceback): if sys.exc_info()[1] is not value: raise + def __enter__(self): + raise RuntimeError("use 'async with {func_name}(...)', not 'with {func_name}(...)'".format(func_name=self._func_name)) + + def __exit__(self): # pragma: no cover + assert False, """Never called, but should be defined""" + + def acontextmanager(func): """Like @contextmanager, but async.""" if not async_generator.isasyncgenfunction(func):