diff --git a/docs/source/history.rst b/docs/source/history.rst index 7aca27ec..b2e04676 100644 --- a/docs/source/history.rst +++ b/docs/source/history.rst @@ -5,6 +5,56 @@ Release history .. towncrier release notes start +trio-asyncio 0.12.0 (2021-01-07) +-------------------------------- + +Bugfixes +~~~~~~~~ + +- trio-asyncio now cancels any Trio tasks that were started inside a trio-asyncio + loop (using e.g. :func:`trio_as_aio`) before it allows the trio-asyncio loop + to close. This should resolve some cases of deadlocks and "RuntimeError: Event loop + is closed" when an ``async with open_loop():`` block is cancelled. (`#89 <https://github.com/python-trio/trio-asyncio/issues/89>`__) +- :func:`asyncio.get_running_loop` will now return the trio-asyncio event loop + (if running), instead of failing with :exc:`RuntimeError`. (`#99 <https://github.com/python-trio/trio-asyncio/issues/99>`__) +- On Python versions with native contextvars support (3.7+), a Trio task + started from asyncio context (using :func:`trio_as_aio`, + :meth:`~BaseTrioEventLoop.trio_as_future`, etc) will now properly + inherit the contextvars of its caller. Also, if the entire + trio-asyncio loop is cancelled, such tasks will no longer let + `trio.Cancelled` exceptions leak into their asyncio caller. (`#76 <https://github.com/python-trio/trio-asyncio/issues/76>`__) +- Previously, cancelling the context surrounding an :func:`open_loop` + block might cause a deadlock in some cases. The ordering of operations + during loop teardown has been improved, so this shouldn't happen + anymore. (`#81 <https://github.com/python-trio/trio-asyncio/issues/81>`__) + +Deprecations and Removals +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A number of functions deprecated since 0.10.0 are now removed: + +================================================= ============================================= + Removed Replacement +================================================= ============================================= +``wrap_generator(proc, *args)`` :func:`aio_as_trio(proc(*args))<aio_as_trio>` +``run_iterator(aiter)`` :func:`aio_as_trio(aiter)<aio_as_trio>` +``trio2aio`` :func:`aio_as_trio` +``aio2trio`` :func:`trio_as_aio` +``run_future`` ``TrioEventLoop.run_future`` :func:`run_aio_future` +``run_coroutine`` ``TrioEventLoop.run_coroutine`` :func:`run_aio_coroutine` +``wrap_trio_context(ctx)`` :func:`trio_as_aio(ctx)<trio_as_aio>` +``TrioEventLoop.run_trio(proc, *args)`` :func:`trio_as_aio(proc)(*args)<trio_as_aio>` +``run_asyncio(proc, *args)`` :func:`aio_as_trio(proc)(*args)<aio_as_trio>` +================================================= ============================================= + +Miscellaneous +~~~~~~~~~~~~~ + +- ``trio-asyncio`` now requires Trio 0.15. Support for Python < 3.6 has been removed. (`#82 <https://github.com/python-trio/trio-asyncio/issues/82>`__) + +- No more ``TrioDeprecationWarning`` about ``trio.hazmat``. (`#82 <https://github.com/python-trio/trio-asyncio/issues/82>`__) + + trio-asyncio 0.11.0 (2020-03-09) -------------------------------- diff --git a/newsfragments/76.bugfix.rst b/newsfragments/76.bugfix.rst deleted file mode 100644 index 7494fdc4..00000000 --- a/newsfragments/76.bugfix.rst +++ /dev/null @@ -1,6 +0,0 @@ -On Python versions with native contextvars support (3.7+), a Trio task -started from asyncio context (using :func:`trio_as_aio`, -:meth:`~BaseTrioEventLoop.trio_as_future`, etc) will now properly -inherit the contextvars of its caller. Also, if the entire -trio-asyncio loop is cancelled, such tasks will no longer let -`trio.Cancelled` exceptions leak into their asyncio caller. diff --git a/newsfragments/80.bugfix.rst b/newsfragments/80.bugfix.rst deleted file mode 100644 index d51c7d34..00000000 --- a/newsfragments/80.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -Previously, cancelling the context surrounding an :func:`open_loop` -block might cause a deadlock in some cases. The ordering of operations -during loop teardown has been improved, so this shouldn't happen -anymore. diff --git a/newsfragments/82.misc.rst b/newsfragments/82.misc.rst deleted file mode 100644 index bc9a04dc..00000000 --- a/newsfragments/82.misc.rst +++ /dev/null @@ -1,3 +0,0 @@ -``trio-asyncio`` now requires Trio 0.15. - -Support for Python < 3.6 has been removed. diff --git a/newsfragments/89.bugfix.rst b/newsfragments/89.bugfix.rst deleted file mode 100644 index 29932b7b..00000000 --- a/newsfragments/89.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -trio-asyncio now cancels any Trio tasks that were started inside a trio-asyncio -loop (using e.g. :func:`trio_as_aio`) before it allows the trio-asyncio loop -to close. This should resolve some cases of deadlocks and "RuntimeError: Event loop -is closed" when an ``async with open_loop():`` block is cancelled. diff --git a/newsfragments/99.bugfix.rst b/newsfragments/99.bugfix.rst deleted file mode 100644 index 4a2267c2..00000000 --- a/newsfragments/99.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`asyncio.get_running_loop()` will now return the trio-asyncio event loop -(if running), instead of failing with :exc:`RuntimeError`. diff --git a/pyproject.toml b/pyproject.toml index b7f95256..37bbc996 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,32 @@ [tool.towncrier] package = "trio_asyncio" +title_format = "trio-asyncio {version} ({project_date})" filename = "docs/source/history.rst" directory = "newsfragments" underlines = ["-", "~", "^"] issue_format = "`#{issue} <https://github.com/python-trio/trio-asyncio/issues/{issue}>`__" + +[[tool.towncrier.type]] +directory = "feature" +name = "Features" +showcontent = true + +[[tool.towncrier.type]] +directory = "bugfix" +name = "Bugfixes" +showcontent = true + +[[tool.towncrier.type]] +directory = "doc" +name = "Improved documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "removal" +name = "Deprecations and removals" +showcontent = true + +[[tool.towncrier.type]] +directory = "misc" +name = "Miscellaneous" +showcontent = true diff --git a/tests/aiotest/test_callback.py b/tests/aiotest/test_callback.py index d9419fa6..b70f4209 100644 --- a/tests/aiotest/test_callback.py +++ b/tests/aiotest/test_callback.py @@ -1,7 +1,6 @@ from tests import aiotest import signal import pytest -from .. import utils as test_utils class TestCallback(aiotest.TestCase): @@ -51,10 +50,6 @@ async def test(): func = lambda: False coro = test() try: - # no longer depends on the loop - # with pytest.raises(RuntimeError): - # fut = config.asyncio.Future(loop=loop) - # await loop.run_future(fut) with pytest.raises(RuntimeError, match='not a sync loop'): loop.run_until_complete(None) with pytest.raises(RuntimeError): @@ -71,9 +66,6 @@ async def test(): loop.run_in_executor(None, func) with pytest.raises(RuntimeError, match='Event loop is closed'): await loop.run_aio_coroutine(coro) - with test_utils.deprecate(self): - with pytest.raises(RuntimeError, match='Event loop is closed'): - await loop.run_coroutine(coro) with pytest.raises(RuntimeError, match='Event loop is closed'): loop.add_signal_handler(signal.SIGTERM, func) finally: diff --git a/tests/aiotest/test_coroutine.py b/tests/aiotest/test_coroutine.py index 0ab30549..dd73fb99 100644 --- a/tests/aiotest/test_coroutine.py +++ b/tests/aiotest/test_coroutine.py @@ -1,13 +1,12 @@ from tests import aiotest import trio_asyncio import pytest -from .. import utils as test_utils async def hello_world(asyncio, result, delay, loop): result.append("Hello") # retrieve the event loop from the policy - await asyncio.sleep(delay, loop=loop) + await asyncio.sleep(delay) result.append('World') return "." @@ -17,27 +16,13 @@ class TestCoroutine(aiotest.TestCase): async def test_hello_world(self, loop, config): result = [] coro = hello_world(config.asyncio, result, 0.001, loop) - await loop.run_aio_coroutine(config.asyncio.ensure_future(coro, loop=loop)) - assert result == ['Hello', 'World'] - - @pytest.mark.trio - async def test_hello_world_depr(self, loop, config): - result = [] - coro = hello_world(config.asyncio, result, 0.001, loop) - with test_utils.deprecate(self): - await loop.run_coroutine(config.asyncio.ensure_future(coro, loop=loop)) - assert result == ['Hello', 'World'] - - @pytest.mark.trio - async def run_hello_world(self, loop, config): - result = [] - await loop.run_asyncio(hello_world, config.asyncio, result, 0.001, loop) + await loop.run_aio_coroutine(config.asyncio.ensure_future(coro)) assert result == ['Hello', 'World'] @pytest.mark.trio async def test_waiter(self, loop, config): async def waiter(asyncio, hello_world, result): - fut = asyncio.Future(loop=loop) + fut = asyncio.Future() loop.call_soon(fut.set_result, "Future") value = await fut @@ -49,20 +34,3 @@ async def waiter(asyncio, hello_world, result): result = [] await trio_asyncio.aio_as_trio(waiter)(config.asyncio, hello_world, result) assert result == ['Future', 'Hello', 'World', '.'] - - @pytest.mark.trio - async def test_waiter_depr(self, loop, config): - async def waiter(asyncio, hello_world, result): - fut = asyncio.Future(loop=loop) - loop.call_soon(fut.set_result, "Future") - - value = await fut - result.append(value) - - value = await hello_world(asyncio, result, 0.001, loop) - result.append(value) - - result = [] - with test_utils.deprecate(self): - await loop.run_asyncio(waiter, config.asyncio, hello_world, result) - assert result == ['Future', 'Hello', 'World', '.'] diff --git a/tests/aiotest/test_network.py b/tests/aiotest/test_network.py index cfb87f1b..c9cfd052 100644 --- a/tests/aiotest/test_network.py +++ b/tests/aiotest/test_network.py @@ -79,7 +79,7 @@ async def test_tcp_hello(self, loop, config): proto = TcpEchoClientProtocol(message, loop) coro = loop.create_connection(lambda: proto, host, port) - await loop.run_coroutine(coro) + await loop.run_aio_coroutine(coro) assert proto.state != 'new' await loop.stop().wait()() diff --git a/tests/aiotest/test_thread.py b/tests/aiotest/test_thread.py index 7baf1e70..ef914284 100644 --- a/tests/aiotest/test_thread.py +++ b/tests/aiotest/test_thread.py @@ -2,7 +2,6 @@ import pytest import trio import trio_asyncio -from .. import utils as test_utils class TestThread(aiotest.TestCase): @@ -27,28 +26,6 @@ def work(): assert work_ident is not None assert work_ident != get_ident() - @pytest.mark.trio - async def test_ident_depr(self, loop, config): - threading = config.threading - try: - get_ident = threading.get_ident # Python 3 - except AttributeError: - get_ident = threading._get_ident # Python 2 - - result = {'ident': None} - - def work(): - result['ident'] = get_ident() - - fut = loop.run_in_executor(None, work) - with test_utils.deprecate(self): - await loop.run_coroutine(fut) - - # ensure that work() was executed in a different thread - work_ident = result['ident'] - assert work_ident is not None - assert work_ident != get_ident() - @pytest.mark.trio async def test_run_twice(self, loop): result = [] @@ -65,24 +42,6 @@ def work(): await loop.run_aio_future(fut) assert result == ["run", "run"] - @pytest.mark.trio - async def test_run_twice_depr(self, loop): - result = [] - - def work(): - result.append("run") - - fut = loop.run_in_executor(None, work) - with test_utils.deprecate(self): - await loop.run_future(fut) - assert result == ["run"] - - # ensure that run_in_executor() can be called twice - fut = loop.run_in_executor(None, work) - with test_utils.deprecate(self): - await loop.run_future(fut) - assert result == ["run", "run"] - @pytest.mark.trio async def test_policy(self, loop, config): asyncio = config.asyncio @@ -99,23 +58,6 @@ def work(): await loop.run_aio_future(fut) assert isinstance(result['loop'], (AssertionError, RuntimeError)) - @pytest.mark.trio - async def test_policy_depr(self, loop, config): - asyncio = config.asyncio - result = {'loop': 'not set'} # sentinel, different than None - - def work(): - try: - result['loop'] = asyncio.get_event_loop() - except Exception as exc: - result['loop'] = exc - - # get_event_loop() must return None in a different thread - fut = loop.run_in_executor(None, work) - with test_utils.deprecate(self): - await loop.run_future(fut) - assert isinstance(result['loop'], (AssertionError, RuntimeError)) - @pytest.mark.trio async def test_run_in_thread(self, config): threading = config.threading diff --git a/tests/interop/test_adapter.py b/tests/interop/test_adapter.py index 0c8bf48b..ff10cb5f 100644 --- a/tests/interop/test_adapter.py +++ b/tests/interop/test_adapter.py @@ -1,6 +1,5 @@ import pytest from trio_asyncio import aio_as_trio, trio_as_aio, allow_asyncio -from trio_asyncio import aio2trio, trio2aio import asyncio import trio import sniffio @@ -11,7 +10,6 @@ from contextlib import asynccontextmanager except ImportError: from async_generator import asynccontextmanager -from .. import utils as test_utils from trio_asyncio import TrioAsyncioDeprecationWarning @@ -45,45 +43,29 @@ async def dly_trio_adapted(self): self.flag |= 2 return 8 - @de_deprecate_converter(aio2trio) - async def dly_trio_depr(self): - if sys.version_info >= (3, 7): - assert sniffio.current_async_library() == "trio" - await trio.sleep(0.01) - self.flag |= 2 - return 8 - - @de_deprecate_converter(trio2aio) - async def dly_asyncio_depr(self): - if sys.version_info >= (3, 7): - assert sniffio.current_async_library() == "asyncio" - await asyncio.sleep(0.01, loop=self.loop) - self.flag |= 1 - return 4 - @aio_as_trio async def dly_asyncio_adapted(self): if sys.version_info >= (3, 7): assert sniffio.current_async_library() == "asyncio" - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.flag |= 1 return 4 async def dly_asyncio(self, do_test=True): if do_test and sys.version_info >= (3, 7): assert sniffio.current_async_library() == "asyncio" - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.flag |= 1 return 4 async def iter_asyncio(self, do_test=True): if do_test and sys.version_info >= (3, 7): assert sniffio.current_async_library() == "asyncio" - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) yield 1 - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) yield 2 - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.flag |= 1 async def iter_trio(self): @@ -98,10 +80,10 @@ async def iter_trio(self): @asynccontextmanager async def ctx_asyncio(self): - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.flag |= 1 yield self - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.flag |= 2 @asynccontextmanager @@ -114,15 +96,6 @@ async def ctx_trio(self): class TestAdapt(aiotest.TestCase): - @pytest.mark.trio - async def test_asyncio_trio_depr(self, loop): - """Call asyncio from trio""" - - sth = SomeThing(loop) - res = await aio_as_trio(sth.dly_trio_depr, loop=loop)() - assert res == 8 - assert sth.flag == 2 - @pytest.mark.trio async def test_asyncio_trio_adapted(self, loop): """Call asyncio from trio""" @@ -133,12 +106,11 @@ async def test_asyncio_trio_adapted(self, loop): assert sth.flag == 2 @pytest.mark.trio - async def test_asyncio_trio_depr2(self, loop): + async def test_asyncio_trio_adapted_no_call(self, loop): """Call asyncio from trio""" sth = SomeThing(loop) - with test_utils.deprecate(self): - res = await loop.run_asyncio(sth.dly_trio_adapted) + res = await aio_as_trio(sth.dly_trio_adapted) assert res == 8 assert sth.flag == 2 @@ -172,13 +144,6 @@ async def test_trio_asyncio_future(self, loop): assert res == 4 assert sth.flag == 1 - @pytest.mark.trio - async def test_trio_asyncio_depr(self, loop): - sth = SomeThing(loop) - res = await sth.dly_asyncio_depr() - assert res == 4 - assert sth.flag == 1 - @pytest.mark.trio async def test_trio_asyncio_iter(self, loop): sth = SomeThing(loop) @@ -232,20 +197,6 @@ async def run_asyncio_trio(self, loop): assert res == 8 assert sth.flag == 2 - async def run_asyncio_trio_adapted(self, loop): - """Call asyncio from trio""" - sth = SomeThing(loop) - res = await sth.dly_trio_adapted() - assert res == 8 - assert sth.flag == 2 - - async def run_asyncio_trio_depr(self, loop): - """Call asyncio from trio""" - sth = SomeThing(loop) - res = await sth.dly_trio_depr() - assert res == 8 - assert sth.flag == 2 - @pytest.mark.trio async def test_asyncio_trio(self, loop): await allow_asyncio(self.run_asyncio_trio, loop) @@ -272,15 +223,32 @@ async def run_trio_asyncio_future(self, loop): async def test_trio_asyncio_future(self, loop): await allow_asyncio(self.run_trio_asyncio_future, loop) - async def run_trio_asyncio_depr(self, loop): + def get_asyncio_future(self, loop, sth): + async def set_result(future, sth): + await asyncio.sleep(0.01) + sth.flag |= 1 + future.set_result(4) + + f = loop.create_future() + loop.create_task(set_result(f, sth)) + return f + + @pytest.mark.trio + async def test_trio_asyncio_future_getter(self, loop): + sth = SomeThing(loop) + res = await allow_asyncio(self.get_asyncio_future, loop, sth) + assert res == 4 + assert sth.flag == 1 + + async def run_trio_asyncio_adapted(self, loop): sth = SomeThing(loop) - res = await sth.dly_asyncio_depr() + res = await sth.dly_asyncio_adapted() assert res == 4 assert sth.flag == 1 @pytest.mark.trio - async def test_trio_asyncio_depr(self, loop): - await allow_asyncio(self.run_trio_asyncio_depr, loop) + async def test_trio_asyncio_adapted(self, loop): + await allow_asyncio(self.run_trio_asyncio_adapted, loop) async def run_trio_asyncio_iter(self, loop): sth = SomeThing(loop) diff --git a/tests/interop/test_calls.py b/tests/interop/test_calls.py index ef8dbfac..0e40a9f8 100644 --- a/tests/interop/test_calls.py +++ b/tests/interop/test_calls.py @@ -2,7 +2,7 @@ import asyncio import trio import sniffio -from trio_asyncio import aio_as_trio, trio_as_aio +from trio_asyncio import aio_as_trio, trio_as_aio, run_aio_generator from tests import aiotest from functools import partial import sys @@ -48,7 +48,7 @@ async def __aenter__(self): self.parent.did_it = 1 if sys.version_info >= (3, 7): assert sniffio.current_async_library() == "asyncio" - await asyncio.sleep(0.01, loop=self.loop) + await asyncio.sleep(0.01) self.parent.did_it = 2 return self @@ -62,20 +62,10 @@ async def call_t_a(self, proc, *args, loop=None): """called from Trio""" return await aio_as_trio(proc, loop=loop)(*args) - async def call_t_a_depr(self, proc, *args, loop=None): - """called from Trio""" - with test_utils.deprecate(self): - return await loop.run_asyncio(proc, *args) - async def call_a_t(self, proc, *args, loop=None): """call from asyncio to an async trio function""" return await trio_as_aio(proc, loop=loop)(*args) - async def call_a_t_depr(self, proc, *args, loop=None): - """call from asyncio to an async trio function""" - with test_utils.deprecate(self): - return await loop.run_trio(proc, *args) - async def call_a_ts(self, proc, *args, loop=None): """called from asyncio to a sync trio function""" return proc(*args) @@ -83,24 +73,13 @@ async def call_a_ts(self, proc, *args, loop=None): @pytest.mark.trio async def test_call_at(self, loop): async def delay(t): - done = asyncio.Event(loop=loop) + done = asyncio.Event() loop.call_at(t, done.set) await done.wait() t = loop.time() + 0.1 await aio_as_trio(delay, loop=loop)(t) - @pytest.mark.trio - async def test_call_at_depr(self, loop): - async def delay(t): - done = asyncio.Event(loop=loop) - loop.call_at(t, done.set) - await done.wait() - - t = loop.time() + 0.1 - with test_utils.deprecate(self): - await loop.run_asyncio(delay, t) - @pytest.mark.trio async def test_asyncio_trio(self, loop): """Call asyncio from trio""" @@ -115,20 +94,6 @@ async def dly_trio(seen): assert res == 8 assert seen.flag == 2 - @pytest.mark.trio - async def test_asyncio_trio_depr(self, loop): - """Call asyncio from trio""" - - async def dly_trio(seen): - await trio.sleep(0.01) - seen.flag |= 2 - return 8 - - seen = Seen() - res = await aio_as_trio(partial(self.call_a_t_depr, loop=loop), loop=loop)(dly_trio, seen) - assert res == 8 - assert seen.flag == 2 - @pytest.mark.trio async def test_call_asyncio_ctx(self, loop): self.did_it = 0 @@ -150,19 +115,6 @@ async def _call_trio_ctx(): await aio_as_trio(_call_trio_ctx, loop=loop)() - @pytest.mark.trio - async def test_call_trio_ctx_depr(self, loop): - async def _call_trio_ctx(): - self.did_it = 0 - async with loop.wrap_trio_context(TrioContext(self)) as ctx: - assert ctx.parent is self - assert self.did_it == 2 - self.did_it = 3 - assert self.did_it == 4 - - with test_utils.deprecate(self): - await loop.run_asyncio(_call_trio_ctx) - @pytest.mark.trio async def test_asyncio_trio_sync(self, loop): """Call asyncio from trio""" @@ -176,24 +128,10 @@ def dly_trio(seen): assert res == 8 assert seen.flag == 2 - @pytest.mark.trio - async def test_asyncio_trio_sync_depr(self, loop): - """Call asyncio from trio""" - - def dly_trio(seen): - seen.flag |= 2 - return 8 - - seen = Seen() - with test_utils.deprecate(self): - res = await loop.run_asyncio(partial(self.call_a_ts, loop=loop), dly_trio, seen) - assert res == 8 - assert seen.flag == 2 - @pytest.mark.trio async def test_trio_asyncio(self, loop): async def dly_asyncio(seen): - await asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01) seen.flag |= 1 return 4 @@ -202,18 +140,6 @@ async def dly_asyncio(seen): assert res == 4 assert seen.flag == 1 - @pytest.mark.trio - async def test_trio_asyncio_depr(self, loop): - async def dly_asyncio(seen): - await asyncio.sleep(0.01, loop=loop) - seen.flag |= 1 - return 4 - - seen = Seen() - res = await self.call_t_a_depr(dly_asyncio, seen, loop=loop) - assert res == 4 - assert seen.flag == 1 - @pytest.mark.trio async def test_asyncio_trio_error(self, loop): async def err_trio(): @@ -224,38 +150,6 @@ async def err_trio(): await aio_as_trio(partial(self.call_a_t, loop=loop), loop=loop)(err_trio) assert err.value.args[0] == "I has another owie" - @pytest.mark.trio - async def test_asyncio_trio_error_depr1(self, loop): - async def err_trio(): - await trio.sleep(0.01) - raise RuntimeError("I has another owie") - - with pytest.raises(RuntimeError) as err: - await aio_as_trio(partial(self.call_a_t_depr, loop=loop), loop=loop)(err_trio) - assert err.value.args[0] == "I has another owie" - - @pytest.mark.trio - async def test_asyncio_trio_error_depr2(self, loop): - async def err_trio(): - await trio.sleep(0.01) - raise RuntimeError("I has another owie") - - with pytest.raises(RuntimeError) as err: - with test_utils.deprecate(self): - await loop.run_asyncio(partial(self.call_a_t, loop=loop), err_trio) - assert err.value.args[0] == "I has another owie" - - @pytest.mark.trio - async def test_asyncio_trio_error_depr3(self, loop): - async def err_trio(): - await trio.sleep(0.01) - raise RuntimeError("I has another owie") - - with pytest.raises(RuntimeError) as err: - with test_utils.deprecate(self): - await loop.run_asyncio(partial(self.call_a_t_depr, loop=loop), err_trio) - assert err.value.args[0] == "I has another owie" - @pytest.mark.trio async def test_asyncio_trio_sync_error(self, loop): def err_trio_sync(): @@ -266,37 +160,16 @@ def err_trio_sync(): await aio_as_trio(partial(self.call_a_ts, loop=loop), loop=loop)(err_trio_sync) assert err.value.args[0] == "I has more owie" - @pytest.mark.trio - async def test_asyncio_trio_sync_error_depr(self, loop): - def err_trio_sync(): - loop.time() # verify that the loop is running - raise RuntimeError("I has more owie") - - with pytest.raises(RuntimeError) as err: - with test_utils.deprecate(self): - await loop.run_asyncio(partial(self.call_a_ts, loop=loop), err_trio_sync) - assert err.value.args[0] == "I has more owie" - @pytest.mark.trio async def test_trio_asyncio_error(self, loop): async def err_asyncio(): - await asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01) raise RuntimeError("I has an owie") with pytest.raises(RuntimeError) as err: await self.call_t_a(err_asyncio, loop=loop) assert err.value.args[0] == "I has an owie" - @pytest.mark.trio - async def test_trio_asyncio_error_depr(self, loop): - async def err_asyncio(): - await asyncio.sleep(0.01, loop=loop) - raise RuntimeError("I has an owie") - - with pytest.raises(RuntimeError) as err: - await self.call_t_a_depr(err_asyncio, loop=loop) - assert err.value.args[0] == "I has an owie" - @pytest.mark.trio async def test_asyncio_trio_cancel_out(self, loop): async def cancelled_trio(seen): @@ -317,14 +190,14 @@ async def cancelled_trio(seen): async def test_trio_asyncio_cancel_out(self, loop): async def cancelled_asyncio(seen): seen.flag |= 1 - await asyncio.sleep(0.01, loop=loop) - f = asyncio.Future(loop=loop) + await asyncio.sleep(0.01) + f = asyncio.Future() f.cancel() return f.result() # raises error def cancelled_future(seen): seen.flag |= 1 - f = asyncio.Future(loop=loop) + f = asyncio.Future() f.cancel() return f # contains error @@ -343,36 +216,6 @@ async def check_cancel(proc, seen): await check_cancel(cancelled_asyncio, seen) assert seen.flag == 1 | 4 - @pytest.mark.trio - async def test_trio_asyncio_cancel_out_depr(self, loop): - async def cancelled_asyncio(seen): - seen.flag |= 1 - await asyncio.sleep(0.01, loop=loop) - f = asyncio.Future(loop=loop) - f.cancel() - return f.result() # raises error - - def cancelled_future(seen): - seen.flag |= 1 - f = asyncio.Future(loop=loop) - f.cancel() - return f # contains error - - async def check_cancel(proc, seen): - with trio.CancelScope() as scope: - with pytest.raises(asyncio.CancelledError): - await self.call_t_a_depr(proc, seen, loop=loop) - assert not scope.cancel_called - seen.flag |= 4 - - seen = Seen() - await check_cancel(cancelled_future, seen) - assert seen.flag == 1 | 4 - - seen = Seen() - await check_cancel(cancelled_asyncio, seen) - assert seen.flag == 1 | 4 - @pytest.mark.trio async def test_asyncio_trio_cancel_in(self, loop): async def in_trio(started, seen): @@ -387,7 +230,7 @@ async def in_trio(started, seen): seen.flag |= 2 async def cancel_asyncio(seen): - started = asyncio.Event(loop=loop) + started = asyncio.Event() f = asyncio.ensure_future(self.call_a_t(in_trio, started, seen, loop=loop)) await started.wait() f.cancel() @@ -404,7 +247,7 @@ async def test_trio_asyncio_cancel_in(self, loop): async def in_asyncio(started, seen): started.set() try: - await asyncio.sleep(9999, loop=loop) + await asyncio.sleep(9999) except asyncio.CancelledError: seen.flag |= 1 except trio.Cancelled: @@ -426,35 +269,6 @@ async def cancel_trio(seen): await cancel_trio(seen) assert seen.flag == 1 | 2 | 8 - @pytest.mark.trio - async def test_trio_asyncio_cancel_in_depr(self, loop): - async def in_asyncio(started, seen): - started.set() - try: - await asyncio.sleep(9999, loop=loop) - except asyncio.CancelledError: - seen.flag |= 1 - except trio.Cancelled: - seen.flag |= 16 - else: - seen.flag |= 4 - finally: - seen.flag |= 2 - - async def cancel_trio(seen): - started = trio.Event() - async with trio.open_nursery() as nursery: - nursery.start_soon( - partial(self.call_t_a_depr, loop=loop), in_asyncio, started, seen - ) - await started.wait() - nursery.cancel_scope.cancel() - seen.flag |= 8 - - seen = Seen() - await cancel_trio(seen) - assert seen.flag == 1 | 2 | 8 - @pytest.mark.trio async def test_trio_asyncio_cancel_direct(self, loop): def in_asyncio(started, seen): @@ -479,30 +293,6 @@ async def cancel_trio(seen): await cancel_trio(seen) assert seen.flag == 1 | 8 - @pytest.mark.trio - async def test_trio_asyncio_cancel_direct_depr(self, loop): - def in_asyncio(started, seen): - # This is intentionally not async - seen.flag |= 1 - raise asyncio.CancelledError() - - async def cancel_trio(seen): - started = trio.Event() - try: - async with trio.open_nursery() as nursery: - nursery.start_soon( - partial(self.call_t_a_depr, loop=loop), in_asyncio, started, seen - ) - await started.wait() - nursery.cancel_scope.cancel() - finally: - seen.flag |= 8 - - seen = Seen() - with pytest.raises(asyncio.CancelledError): - await cancel_trio(seen) - assert seen.flag == 1 | 8 - @pytest.mark.trio async def test_trio_asyncio_error_direct(self, loop): def err_asyncio(): @@ -513,25 +303,14 @@ def err_asyncio(): await self.call_t_a(err_asyncio, loop=loop) assert err.value.args[0] == "I has an owie" - @pytest.mark.trio - async def test_trio_asyncio_error_direct_depr(self, loop): - def err_asyncio(): - # This is intentionally not async - raise RuntimeError("I has an owie") - - with pytest.raises(RuntimeError) as err: - await self.call_t_a_depr(err_asyncio, loop=loop) - assert err.value.args[0] == "I has an owie" - @pytest.mark.trio async def test_trio_asyncio_generator(self, loop): async def dly_asyncio(): yield 1 - await asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01) yield 2 - with test_utils.deprecate(self): - res = await async_gen_to_list(loop.wrap_generator(dly_asyncio)) + res = await async_gen_to_list(run_aio_generator(loop, dly_asyncio())) assert res == [1, 2] @pytest.mark.trio @@ -541,9 +320,8 @@ async def dly_asyncio(): raise RuntimeError("I has an owie") yield 2 - with test_utils.deprecate(self): - with pytest.raises(RuntimeError) as err: - await async_gen_to_list(loop.wrap_generator(dly_asyncio)) + with pytest.raises(RuntimeError) as err: + await async_gen_to_list(run_aio_generator(loop, dly_asyncio())) assert err.value.args[0] == "I has an owie" @pytest.mark.trio @@ -557,13 +335,12 @@ async def cancel_soon(nursery): await trio.sleep(0.01) nursery.cancel_scope.cancel() - hold = asyncio.Event(loop=loop) + hold = asyncio.Event() seen = Seen() - with test_utils.deprecate(self): - async with trio.open_nursery() as nursery: - nursery.start_soon(async_gen_to_list, loop.wrap_generator(dly_asyncio, hold, seen)) - nursery.start_soon(cancel_soon, nursery) + async with trio.open_nursery() as nursery: + nursery.start_soon(async_gen_to_list, run_aio_generator(loop, dly_asyncio(hold, seen))) + nursery.start_soon(cancel_soon, nursery) assert nursery.cancel_scope.cancel_called assert seen.flag == 1 @@ -571,7 +348,7 @@ async def cancel_soon(nursery): async def test_trio_asyncio_iterator(self, loop): async def slow_nums(): for n in range(1, 6): - await asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01) yield n sum = 0 @@ -583,7 +360,7 @@ async def slow_nums(): async def test_trio_asyncio_iterator_depr(self, loop): async def slow_nums(): for n in range(1, 6): - await asyncio.sleep(0.01, loop=loop) + await asyncio.sleep(0.01) yield n sum = 0 diff --git a/tests/module_with_deprecations.py b/tests/module_with_deprecations.py new file mode 100644 index 00000000..24de2588 --- /dev/null +++ b/tests/module_with_deprecations.py @@ -0,0 +1,21 @@ +regular = "hi" + +from trio_asyncio import _deprecate + +_deprecate.enable_attribute_deprecations(__name__) + +# Make sure that we don't trigger infinite recursion when accessing module +# attributes in between calling enable_attribute_deprecations and defining +# __deprecated_attributes__: +import sys + +this_mod = sys.modules[__name__] +assert this_mod.regular == "hi" +assert not hasattr(this_mod, "dep1") + +__deprecated_attributes__ = { + "dep1": _deprecate.DeprecatedAttribute("value1", "1.1", issue=1), + "dep2": _deprecate.DeprecatedAttribute( + "value2", "1.2", issue=1, instead="instead-string" + ), +} diff --git a/tests/test_aio_subprocess.py b/tests/test_aio_subprocess.py index 55ec0dfc..218d7399 100644 --- a/tests/test_aio_subprocess.py +++ b/tests/test_aio_subprocess.py @@ -20,12 +20,12 @@ class MySubprocessProtocol(asyncio.SubprocessProtocol): def __init__(self, loop): self.state = 'INITIAL' self.transport = None - self.connected = asyncio.Future(loop=loop) - self.completed = asyncio.Future(loop=loop) - self.disconnects = {fd: asyncio.Future(loop=loop) for fd in range(3)} + self.connected = asyncio.Future() + self.completed = asyncio.Future() + self.disconnects = {fd: asyncio.Future() for fd in range(3)} self.data = {1: b'', 2: b''} self.returncode = None - self.got_data = {1: asyncio.Event(loop=loop), 2: asyncio.Event(loop=loop)} + self.got_data = {1: asyncio.Event(), 2: asyncio.Event()} def connection_made(self, transport): self.transport = transport diff --git a/tests/test_deprecate.py b/tests/test_deprecate.py new file mode 100644 index 00000000..749c5901 --- /dev/null +++ b/tests/test_deprecate.py @@ -0,0 +1,245 @@ +# Mostly copied from trio.tests.test_deprecate. + +import pytest + +import inspect +import warnings + +from trio_asyncio._deprecate import ( + TrioAsyncioDeprecationWarning, + warn_deprecated, + deprecated, + deprecated_alias, +) + +from . import module_with_deprecations + + +@pytest.fixture +def recwarn_always(recwarn): + warnings.simplefilter("always") + # ResourceWarnings about unclosed sockets can occur nondeterministically + # (during GC) which throws off the tests in this file + warnings.simplefilter("ignore", ResourceWarning) + return recwarn + + +def _here(): + info = inspect.getframeinfo(inspect.currentframe().f_back) + return (info.filename, info.lineno) + + +def test_warn_deprecated(recwarn_always): + def deprecated_thing(): + warn_deprecated("ice", "1.2", issue=1, instead="water") + + deprecated_thing() + filename, lineno = _here() + assert len(recwarn_always) == 1 + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "ice is deprecated" in got.message.args[0] + assert "trio-asyncio 1.2" in got.message.args[0] + assert "water instead" in got.message.args[0] + assert "/issues/1" in got.message.args[0] + assert got.filename == filename + assert got.lineno == lineno - 1 + + +def test_warn_deprecated_no_instead_or_issue(recwarn_always): + # Explicitly no instead or issue + warn_deprecated("water", "1.3", issue=None, instead=None) + assert len(recwarn_always) == 1 + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "water is deprecated" in got.message.args[0] + assert "no replacement" in got.message.args[0] + assert "trio-asyncio 1.3" in got.message.args[0] + + +def test_warn_deprecated_stacklevel(recwarn_always): + def nested1(): + nested2() + + def nested2(): + warn_deprecated("x", "1.3", issue=7, instead="y", stacklevel=3) + + filename, lineno = _here() + nested1() + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert got.filename == filename + assert got.lineno == lineno + 1 + + +def old(): # pragma: no cover + pass + + +def new(): # pragma: no cover + pass + + +def test_warn_deprecated_formatting(recwarn_always): + warn_deprecated(old, "1.0", issue=1, instead=new) + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "test_deprecate.old is deprecated" in got.message.args[0] + assert "test_deprecate.new instead" in got.message.args[0] + + +@deprecated("1.5", issue=123, instead=new) +def deprecated_old(): + return 3 + + +def test_deprecated_decorator(recwarn_always): + assert deprecated_old() == 3 + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "test_deprecate.deprecated_old is deprecated" in got.message.args[0] + assert "1.5" in got.message.args[0] + assert "test_deprecate.new" in got.message.args[0] + assert "issues/123" in got.message.args[0] + + +class Foo: + @deprecated("1.0", issue=123, instead="crying") + def method(self): + return 7 + + +def test_deprecated_decorator_method(recwarn_always): + f = Foo() + assert f.method() == 7 + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "test_deprecate.Foo.method is deprecated" in got.message.args[0] + + +@deprecated("1.2", thing="the thing", issue=None, instead=None) +def deprecated_with_thing(): + return 72 + + +def test_deprecated_decorator_with_explicit_thing(recwarn_always): + assert deprecated_with_thing() == 72 + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "the thing is deprecated" in got.message.args[0] + + +def new_hotness(): + return "new hotness" + + +old_hotness = deprecated_alias("old_hotness", new_hotness, "1.23", issue=1) + + +def test_deprecated_alias(recwarn_always): + assert old_hotness() == "new hotness" + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "test_deprecate.old_hotness is deprecated" in got.message.args[0] + assert "1.23" in got.message.args[0] + assert "test_deprecate.new_hotness instead" in got.message.args[0] + assert "issues/1" in got.message.args[0] + + assert ".. deprecated:: 1.23" in old_hotness.__doc__ + assert "test_deprecate.new_hotness instead" in old_hotness.__doc__ + assert "issues/1>`__" in old_hotness.__doc__ + + +class Alias: + def new_hotness_method(self): + return "new hotness method" + + old_hotness_method = deprecated_alias( + "Alias.old_hotness_method", new_hotness_method, "3.21", issue=1 + ) + + +def test_deprecated_alias_method(recwarn_always): + obj = Alias() + assert obj.old_hotness_method() == "new hotness method" + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + msg = got.message.args[0] + assert "test_deprecate.Alias.old_hotness_method is deprecated" in msg + assert "test_deprecate.Alias.new_hotness_method instead" in msg + + +@deprecated("2.1", issue=1, instead="hi") +def docstring_test1(): # pragma: no cover + """Hello!""" + + +@deprecated("2.1", issue=None, instead="hi") +def docstring_test2(): # pragma: no cover + """Hello!""" + + +@deprecated("2.1", issue=1, instead=None) +def docstring_test3(): # pragma: no cover + """Hello!""" + + +@deprecated("2.1", issue=None, instead=None) +def docstring_test4(): # pragma: no cover + """Hello!""" + + +def test_deprecated_docstring_munging(): + assert ( + docstring_test1.__doc__ + == """Hello! + +.. deprecated:: 2.1 + Use hi instead. + For details, see `issue #1 <https://github.com/python-trio/trio-asyncio/issues/1>`__. + +""" + ) + + assert ( + docstring_test2.__doc__ + == """Hello! + +.. deprecated:: 2.1 + Use hi instead. + +""" + ) + + assert ( + docstring_test3.__doc__ + == """Hello! + +.. deprecated:: 2.1 + For details, see `issue #1 <https://github.com/python-trio/trio-asyncio/issues/1>`__. + +""" + ) + + assert ( + docstring_test4.__doc__ + == """Hello! + +.. deprecated:: 2.1 + +""" + ) + + +def test_module_with_deprecations(recwarn_always): + assert module_with_deprecations.regular == "hi" + assert len(recwarn_always) == 0 + + filename, lineno = _here() + assert module_with_deprecations.dep1 == "value1" + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert got.filename == filename + assert got.lineno == lineno + 1 + + assert "module_with_deprecations.dep1" in got.message.args[0] + assert "trio-asyncio 1.1" in got.message.args[0] + assert "/issues/1" in got.message.args[0] + assert "value1 instead" in got.message.args[0] + + assert module_with_deprecations.dep2 == "value2" + got = recwarn_always.pop(TrioAsyncioDeprecationWarning) + assert "instead-string instead" in got.message.args[0] + + with pytest.raises(AttributeError): + module_with_deprecations.asdf diff --git a/tests/test_misc.py b/tests/test_misc.py index 7ff0c6c3..dd97f08f 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -3,9 +3,6 @@ import asyncio import trio import sys -from . import utils as test_utils - -# from tests import aiotest class Seen: @@ -44,16 +41,6 @@ async def raise_err(): await trio_asyncio.aio_as_trio(raise_err, loop=loop)() assert err.value.args[0] == "Foo" - @pytest.mark.trio - async def test_err1_depr(self, loop): - async def raise_err(): - raise RuntimeError("Foo") - - with test_utils.deprecate(self): - with pytest.raises(RuntimeError) as err: - await loop.run_asyncio(raise_err) - assert err.value.args[0] == "Foo" - @pytest.mark.trio async def test_err3(self, loop): owch = 0 @@ -71,24 +58,6 @@ async def call_nested(): await trio_asyncio.aio_as_trio(call_nested, loop=loop)() assert owch - @pytest.mark.trio - async def test_err3_depr(self, loop): - owch = 0 - - async def nest(): - nonlocal owch - owch = 1 - raise RuntimeError("Hello") - - async def call_nested(): - with pytest.raises(RuntimeError) as err: - await loop.run_trio(nest) - assert err.value.args[0] == "Hello" - - with test_utils.deprecate(self): - await loop.run_asyncio(call_nested) - assert owch - @pytest.mark.trio async def test_run(self, loop): owch = 0 @@ -104,23 +73,6 @@ async def call_nested(): await trio_asyncio.aio_as_trio(call_nested, loop=loop)() assert owch - @pytest.mark.trio - async def test_run_depr(self, loop): - owch = 0 - - async def nest(): - await trio.sleep(0.01) - nonlocal owch - owch = 1 - - async def call_nested(): - with test_utils.deprecate(self): - await loop.run_trio(nest) - - with test_utils.deprecate(self): - await loop.run_asyncio(call_nested) - assert owch - async def _test_run(self): owch = 0 @@ -138,24 +90,6 @@ async def call_nested(): def test_run2(self): trio_asyncio.run(self._test_run) - async def _test_run_depr(self): - owch = 0 - - async def nest(): - await trio.sleep(0.01) - nonlocal owch - owch = 1 - - async def call_nested(): - await trio_asyncio.run_trio(nest) - - with test_utils.deprecate(self): - await trio_asyncio.run_asyncio(call_nested) - assert owch - - def test_run2_depr(self): - trio_asyncio.run(self._test_run_depr) - @pytest.mark.trio async def test_run_task(self): owch = 0 @@ -196,27 +130,6 @@ async def call_more_nested(): await trio_asyncio.aio_as_trio(call_more_nested, loop=loop)() assert owch - @pytest.mark.trio - async def test_err2_depr(self, loop): - owch = 0 - - async def nest(): - nonlocal owch - owch = 1 - raise RuntimeError("Hello") - - async def call_nested(): - await loop.run_asyncio(nest) - - async def call_more_nested(): - with pytest.raises(RuntimeError) as err: - await loop.run_trio(call_nested) - assert err.value.args[0] == "Hello" - - with test_utils.deprecate(self): - await loop.run_asyncio(call_more_nested) - assert owch - @pytest.mark.trio async def test_run3(self, loop): owch = 0 @@ -234,24 +147,6 @@ async def call_more_nested(): await trio_asyncio.aio_as_trio(call_more_nested, loop=loop)() assert owch - @pytest.mark.trio - async def test_run3_depr(self, loop): - owch = 0 - - async def nest(): - nonlocal owch - owch = 1 - - async def call_nested(): - await loop.run_asyncio(nest) - - async def call_more_nested(): - await loop.run_trio(call_nested) - - with test_utils.deprecate(self): - await loop.run_asyncio(call_more_nested) - assert owch - @pytest.mark.trio async def test_cancel_sleep(self, loop): owch = 0 @@ -259,36 +154,16 @@ async def test_cancel_sleep(self, loop): def do_not_run(): nonlocal owch owch = 1 - raise Exception("should not run") async def cancel_sleep(): h = loop.call_later(0.2, do_not_run) - await asyncio.sleep(0.1, loop=loop) + await asyncio.sleep(0.01) h.cancel() - await asyncio.sleep(0.3, loop=loop) + await asyncio.sleep(0.3) await trio_asyncio.aio_as_trio(cancel_sleep, loop=loop)() assert owch == 0 - @pytest.mark.trio - async def test_cancel_sleep_depr(self, loop): - owch = 0 - - def do_not_run(): - nonlocal owch - owch = 1 - raise Exception("should not run") - - async def cancel_sleep(): - h = loop.call_later(0.2, do_not_run) - await asyncio.sleep(0.1, loop=loop) - h.cancel() - await asyncio.sleep(0.3, loop=loop) - - with test_utils.deprecate(self): - await loop.run_asyncio(cancel_sleep) - assert owch == 0 - @pytest.mark.trio async def test_wrong_context_manager_order(): @@ -352,7 +227,6 @@ async def run_asyncio_loop(nursery, *, task_status=trio.TASK_STATUS_IGNORED): # Trigger KeyboardInterrupt that should propagate accross the coroutines signal.pthread_kill(threading.get_ident(), signal.SIGINT) - @pytest.mark.trio @pytest.mark.parametrize("throw_another", [False, True]) async def test_cancel_loop(throw_another): diff --git a/trio_asyncio/__init__.py b/trio_asyncio/__init__.py index e37e8819..50526feb 100644 --- a/trio_asyncio/__init__.py +++ b/trio_asyncio/__init__.py @@ -27,12 +27,6 @@ run_trio_task, run_trio, run_aio_coroutine, - # forwarders to deprecated event loop methods: - run_future, - run_coroutine, - run_asyncio, - wrap_generator, - run_iterator, ) from ._adapter import ( aio_as_trio, @@ -40,9 +34,6 @@ # aliases for the above: asyncio_as_trio, trio_as_asyncio, - # deprecated aliases for the above: - trio2aio, - aio2trio, # additional experimental goodie: allow_asyncio, ) diff --git a/trio_asyncio/_adapter.py b/trio_asyncio/_adapter.py index a1145a9e..88be8349 100644 --- a/trio_asyncio/_adapter.py +++ b/trio_asyncio/_adapter.py @@ -2,17 +2,15 @@ # Trio. import types -import warnings import asyncio import trio_asyncio from contextvars import ContextVar -from ._deprecate import deprecated_alias from ._util import run_aio_generator, run_aio_future, run_trio_generator -from ._loop import current_loop, current_policy +from ._loop import current_loop -from functools import wraps, partial +from functools import partial async def _call_defer(proc, *args, **kwargs): @@ -56,7 +54,7 @@ async def __call__(self, *args, **kwargs): return await self.loop.run_aio_coroutine(f) def __await__(self): - """Compatibility code for "await loop.run_asyncio(coro)" + """Support for commonly used (but not recommended) "await aio_as_trio(proc(*args))" """ f = self.proc if not hasattr(f, "__await__"): @@ -236,7 +234,7 @@ def _allow_asyncio(fn, *args): coro = fn(*args) # start the coroutine if isinstance(coro, asyncio.Future): - return (yield from trio_asyncio.run_future(coro)) + return (yield from trio_asyncio.run_aio_future(coro)) p, a = coro.send, None while True: @@ -271,7 +269,7 @@ async def allow_asyncio(fn, *args): import trio_asyncio async def hello(loop): - await asyncio.sleep(1, loop=loop) + await asyncio.sleep(1) print("Hello") await trio.sleep(1) print("World") @@ -293,7 +291,3 @@ async def main(): return await _allow_asyncio(fn, *args) finally: shim.reset(token) - - -trio2aio = deprecated_alias("trio_asyncio.trio2aio", aio_as_trio, "0.10.0", issue=38) -aio2trio = deprecated_alias("trio_asyncio.aio2trio", trio_as_aio, "0.10.0", issue=38) diff --git a/trio_asyncio/_base.py b/trio_asyncio/_base.py index 4329d1f8..3b64b462 100644 --- a/trio_asyncio/_base.py +++ b/trio_asyncio/_base.py @@ -10,9 +10,7 @@ import concurrent.futures from ._handles import ScopedHandle, AsyncHandle -from ._util import run_aio_future, run_aio_generator -from ._deprecate import deprecated, deprecated_alias -from . import _util +from ._util import run_aio_future from selectors import _BaseSelectorImpl, EVENT_READ, EVENT_WRITE @@ -415,7 +413,7 @@ async def synchronize(self): This is a Trio-flavored async function. - From asyncio, call ``await loop.run_trio(loop.synchronize)`` + From asyncio, call ``await trio_as_aio(loop.synchronize)()`` instead of ``await asyncio.sleep(0)`` if you need to process all queued callbacks. @@ -788,43 +786,3 @@ def __enter__(self): def __exit__(self, *tb): raise RuntimeError("You need to use a sync loop, or 'async with open_loop()'.") - - # Deprecated aliases # - - run_future = staticmethod( - deprecated_alias( - "trio_asyncio.BaseTrioEventLoop.run_future", - _util.run_aio_future, - "0.10.0", - issue=38, - ) - ) - - run_coroutine = deprecated_alias( - "trio_asyncio.BaseTrioEventLoop.run_coroutine", - run_aio_coroutine, - "0.10.0", - issue=38, - ) - - @deprecated("0.10.0", issue=38, instead="aio_as_trio(gen(*args))") - def wrap_generator(self, gen, *args): - return run_aio_generator(self, gen(*args)) - - @deprecated("0.10.0", issue=38, instead="aio_as_trio(aiter)") - def run_iterator(self, aiter): - return run_aio_generator(self, aiter) - - @deprecated("0.10.0", issue=38, instead="aio_as_trio(proc)(*args)") - def run_asyncio(self, proc, *args): - from ._adapter import Asyncio_Trio_Wrapper - return Asyncio_Trio_Wrapper(proc, args=args, loop=self) - - @deprecated("0.10.0", issue=38, instead="trio_as_aio(ctx)") - def wrap_trio_context(self, ctx): - from ._adapter import Trio_Asyncio_Wrapper - return Trio_Asyncio_Wrapper(ctx, loop=self) - - @deprecated("0.10.0", issue=38, instead="trio_as_aio(proc)(*args)") - def run_trio(self, proc, *args): - return self.trio_as_future(proc, *args) diff --git a/trio_asyncio/_loop.py b/trio_asyncio/_loop.py index 617de191..da0019f8 100644 --- a/trio_asyncio/_loop.py +++ b/trio_asyncio/_loop.py @@ -4,7 +4,6 @@ import sys import trio import asyncio -import warnings import threading from contextvars import ContextVar @@ -13,9 +12,8 @@ except ImportError: from async_generator import asynccontextmanager -from ._util import run_aio_future, run_aio_generator from ._async import TrioEventLoop -from ._deprecate import deprecated, warn_deprecated +from ._deprecate import warn_deprecated try: from trio.lowlevel import wait_for_child @@ -346,7 +344,7 @@ async def _waitpid(self, pid, callback, *args): def add_child_handler(self, pid, callback, *args): """Add a callback to run when a child process terminates.""" - h = self._loop.run_trio(self._waitpid, pid, callback, *args) + h = self._loop.trio_as_future(self._waitpid, pid, callback, *args) self._callbacks[pid] = h def remove_child_handler(self, pid): @@ -488,43 +486,3 @@ def run_trio_task(proc, *args): will propagate to, and terminate, the trio-asyncio loop. """ _running_loop().run_trio_task(proc, *args) - - -# These are aliases for methods in BaseTrioEventLoop which are -# themselves deprecated. If we deprecate these and call the deprecated -# loop method, the user gets two warnings. If we just call the -# deprecated loop method, the warning points here instead of to user -# code. Therefore, we "chase the pointer" and inline the body of the -# deprecated loop method into each of these functions. - - -@deprecated("0.10.0", issue=38, instead="aio_as_trio(proc(*args))") -def wrap_generator(proc, *args): - return run_aio_generator(_running_loop(), proc(*args)) - - -@deprecated("0.10.0", issue=38, instead="aio_as_trio(aiter)") -def run_iterator(aiter): - return run_aio_generator(_running_loop(), aiter) - - -@deprecated("0.10.0", issue=38, instead="trio_as_aio(ctx)") -def wrap_trio_context(ctx): - from ._adapter import Trio_Asyncio_Wrapper - return Trio_Asyncio_Wrapper(ctx, loop=_running_loop()) - - -@deprecated("0.10.0", issue=38, instead="aio_as_trio(proc)(*args)") -def run_asyncio(proc, *args): - from ._adapter import Asyncio_Trio_Wrapper - return Asyncio_Trio_Wrapper(proc, args=args, loop=_running_loop()) - - -@deprecated("0.10.0", issue=38, instead="run_aio_coroutine") -async def run_coroutine(fut): - return await _running_loop().run_aio_coroutine(fut) - - -@deprecated("0.10.0", issue=38, instead="run_aio_future") -async def run_future(fut): - return await run_aio_future(fut) diff --git a/trio_asyncio/_util.py b/trio_asyncio/_util.py index cfadf56b..e27a0178 100644 --- a/trio_asyncio/_util.py +++ b/trio_asyncio/_util.py @@ -108,7 +108,7 @@ def abort_cb(raise_cancel_arg): try: while True: # Schedule in asyncio that we read the next item from the iterator - current_read = asyncio.ensure_future(consume_next(), loop=loop) + current_read = asyncio.ensure_future(consume_next()) item = await trio.lowlevel.wait_task_rescheduled(abort_cb) diff --git a/trio_asyncio/_version.py b/trio_asyncio/_version.py index a65a5498..75fa6d0e 100644 --- a/trio_asyncio/_version.py +++ b/trio_asyncio/_version.py @@ -1,3 +1,3 @@ # This file is imported from __init__.py and exec'd from setup.py -__version__ = "0.11.0+dev" +__version__ = "0.12.0+dev"