Skip to content

Commit fe01773

Browse files
authored
Merge pull request #94 from shamrin/release-0.12.0
Release 0.12.0
2 parents b93c320 + a18c2b4 commit fe01773

23 files changed

+413
-668
lines changed

Diff for: docs/source/history.rst

+50
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,56 @@ Release history
55

66
.. towncrier release notes start
77
8+
trio-asyncio 0.12.0 (2021-01-07)
9+
--------------------------------
10+
11+
Bugfixes
12+
~~~~~~~~
13+
14+
- trio-asyncio now cancels any Trio tasks that were started inside a trio-asyncio
15+
loop (using e.g. :func:`trio_as_aio`) before it allows the trio-asyncio loop
16+
to close. This should resolve some cases of deadlocks and "RuntimeError: Event loop
17+
is closed" when an ``async with open_loop():`` block is cancelled. (`#89 <https://github.com/python-trio/trio-asyncio/issues/89>`__)
18+
- :func:`asyncio.get_running_loop` will now return the trio-asyncio event loop
19+
(if running), instead of failing with :exc:`RuntimeError`. (`#99 <https://github.com/python-trio/trio-asyncio/issues/99>`__)
20+
- On Python versions with native contextvars support (3.7+), a Trio task
21+
started from asyncio context (using :func:`trio_as_aio`,
22+
:meth:`~BaseTrioEventLoop.trio_as_future`, etc) will now properly
23+
inherit the contextvars of its caller. Also, if the entire
24+
trio-asyncio loop is cancelled, such tasks will no longer let
25+
`trio.Cancelled` exceptions leak into their asyncio caller. (`#76 <https://github.com/python-trio/trio-asyncio/issues/76>`__)
26+
- Previously, cancelling the context surrounding an :func:`open_loop`
27+
block might cause a deadlock in some cases. The ordering of operations
28+
during loop teardown has been improved, so this shouldn't happen
29+
anymore. (`#81 <https://github.com/python-trio/trio-asyncio/issues/81>`__)
30+
31+
Deprecations and Removals
32+
~~~~~~~~~~~~~~~~~~~~~~~~~
33+
34+
A number of functions deprecated since 0.10.0 are now removed:
35+
36+
================================================= =============================================
37+
Removed Replacement
38+
================================================= =============================================
39+
``wrap_generator(proc, *args)`` :func:`aio_as_trio(proc(*args))<aio_as_trio>`
40+
``run_iterator(aiter)`` :func:`aio_as_trio(aiter)<aio_as_trio>`
41+
``trio2aio`` :func:`aio_as_trio`
42+
``aio2trio`` :func:`trio_as_aio`
43+
``run_future`` ``TrioEventLoop.run_future`` :func:`run_aio_future`
44+
``run_coroutine`` ``TrioEventLoop.run_coroutine`` :func:`run_aio_coroutine`
45+
``wrap_trio_context(ctx)`` :func:`trio_as_aio(ctx)<trio_as_aio>`
46+
``TrioEventLoop.run_trio(proc, *args)`` :func:`trio_as_aio(proc)(*args)<trio_as_aio>`
47+
``run_asyncio(proc, *args)`` :func:`aio_as_trio(proc)(*args)<aio_as_trio>`
48+
================================================= =============================================
49+
50+
Miscellaneous
51+
~~~~~~~~~~~~~
52+
53+
- ``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>`__)
54+
55+
- No more ``TrioDeprecationWarning`` about ``trio.hazmat``. (`#82 <https://github.com/python-trio/trio-asyncio/issues/82>`__)
56+
57+
858
trio-asyncio 0.11.0 (2020-03-09)
959
--------------------------------
1060

Diff for: newsfragments/76.bugfix.rst

-6
This file was deleted.

Diff for: newsfragments/80.bugfix.rst

-4
This file was deleted.

Diff for: newsfragments/82.misc.rst

-3
This file was deleted.

Diff for: newsfragments/89.bugfix.rst

-4
This file was deleted.

Diff for: newsfragments/99.bugfix.rst

-2
This file was deleted.

Diff for: pyproject.toml

+26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
[tool.towncrier]
22
package = "trio_asyncio"
3+
title_format = "trio-asyncio {version} ({project_date})"
34
filename = "docs/source/history.rst"
45
directory = "newsfragments"
56
underlines = ["-", "~", "^"]
67
issue_format = "`#{issue} <https://github.com/python-trio/trio-asyncio/issues/{issue}>`__"
8+
9+
[[tool.towncrier.type]]
10+
directory = "feature"
11+
name = "Features"
12+
showcontent = true
13+
14+
[[tool.towncrier.type]]
15+
directory = "bugfix"
16+
name = "Bugfixes"
17+
showcontent = true
18+
19+
[[tool.towncrier.type]]
20+
directory = "doc"
21+
name = "Improved documentation"
22+
showcontent = true
23+
24+
[[tool.towncrier.type]]
25+
directory = "removal"
26+
name = "Deprecations and removals"
27+
showcontent = true
28+
29+
[[tool.towncrier.type]]
30+
directory = "misc"
31+
name = "Miscellaneous"
32+
showcontent = true

Diff for: tests/aiotest/test_callback.py

-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from tests import aiotest
22
import signal
33
import pytest
4-
from .. import utils as test_utils
54

65

76
class TestCallback(aiotest.TestCase):
@@ -51,10 +50,6 @@ async def test():
5150
func = lambda: False
5251
coro = test()
5352
try:
54-
# no longer depends on the loop
55-
# with pytest.raises(RuntimeError):
56-
# fut = config.asyncio.Future(loop=loop)
57-
# await loop.run_future(fut)
5853
with pytest.raises(RuntimeError, match='not a sync loop'):
5954
loop.run_until_complete(None)
6055
with pytest.raises(RuntimeError):
@@ -71,9 +66,6 @@ async def test():
7166
loop.run_in_executor(None, func)
7267
with pytest.raises(RuntimeError, match='Event loop is closed'):
7368
await loop.run_aio_coroutine(coro)
74-
with test_utils.deprecate(self):
75-
with pytest.raises(RuntimeError, match='Event loop is closed'):
76-
await loop.run_coroutine(coro)
7769
with pytest.raises(RuntimeError, match='Event loop is closed'):
7870
loop.add_signal_handler(signal.SIGTERM, func)
7971
finally:

Diff for: tests/aiotest/test_coroutine.py

+3-35
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
from tests import aiotest
22
import trio_asyncio
33
import pytest
4-
from .. import utils as test_utils
54

65

76
async def hello_world(asyncio, result, delay, loop):
87
result.append("Hello")
98
# retrieve the event loop from the policy
10-
await asyncio.sleep(delay, loop=loop)
9+
await asyncio.sleep(delay)
1110
result.append('World')
1211
return "."
1312

@@ -17,27 +16,13 @@ class TestCoroutine(aiotest.TestCase):
1716
async def test_hello_world(self, loop, config):
1817
result = []
1918
coro = hello_world(config.asyncio, result, 0.001, loop)
20-
await loop.run_aio_coroutine(config.asyncio.ensure_future(coro, loop=loop))
21-
assert result == ['Hello', 'World']
22-
23-
@pytest.mark.trio
24-
async def test_hello_world_depr(self, loop, config):
25-
result = []
26-
coro = hello_world(config.asyncio, result, 0.001, loop)
27-
with test_utils.deprecate(self):
28-
await loop.run_coroutine(config.asyncio.ensure_future(coro, loop=loop))
29-
assert result == ['Hello', 'World']
30-
31-
@pytest.mark.trio
32-
async def run_hello_world(self, loop, config):
33-
result = []
34-
await loop.run_asyncio(hello_world, config.asyncio, result, 0.001, loop)
19+
await loop.run_aio_coroutine(config.asyncio.ensure_future(coro))
3520
assert result == ['Hello', 'World']
3621

3722
@pytest.mark.trio
3823
async def test_waiter(self, loop, config):
3924
async def waiter(asyncio, hello_world, result):
40-
fut = asyncio.Future(loop=loop)
25+
fut = asyncio.Future()
4126
loop.call_soon(fut.set_result, "Future")
4227

4328
value = await fut
@@ -49,20 +34,3 @@ async def waiter(asyncio, hello_world, result):
4934
result = []
5035
await trio_asyncio.aio_as_trio(waiter)(config.asyncio, hello_world, result)
5136
assert result == ['Future', 'Hello', 'World', '.']
52-
53-
@pytest.mark.trio
54-
async def test_waiter_depr(self, loop, config):
55-
async def waiter(asyncio, hello_world, result):
56-
fut = asyncio.Future(loop=loop)
57-
loop.call_soon(fut.set_result, "Future")
58-
59-
value = await fut
60-
result.append(value)
61-
62-
value = await hello_world(asyncio, result, 0.001, loop)
63-
result.append(value)
64-
65-
result = []
66-
with test_utils.deprecate(self):
67-
await loop.run_asyncio(waiter, config.asyncio, hello_world, result)
68-
assert result == ['Future', 'Hello', 'World', '.']

Diff for: tests/aiotest/test_network.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ async def test_tcp_hello(self, loop, config):
7979

8080
proto = TcpEchoClientProtocol(message, loop)
8181
coro = loop.create_connection(lambda: proto, host, port)
82-
await loop.run_coroutine(coro)
82+
await loop.run_aio_coroutine(coro)
8383
assert proto.state != 'new'
8484

8585
await loop.stop().wait()()

Diff for: tests/aiotest/test_thread.py

-58
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import pytest
33
import trio
44
import trio_asyncio
5-
from .. import utils as test_utils
65

76

87
class TestThread(aiotest.TestCase):
@@ -27,28 +26,6 @@ def work():
2726
assert work_ident is not None
2827
assert work_ident != get_ident()
2928

30-
@pytest.mark.trio
31-
async def test_ident_depr(self, loop, config):
32-
threading = config.threading
33-
try:
34-
get_ident = threading.get_ident # Python 3
35-
except AttributeError:
36-
get_ident = threading._get_ident # Python 2
37-
38-
result = {'ident': None}
39-
40-
def work():
41-
result['ident'] = get_ident()
42-
43-
fut = loop.run_in_executor(None, work)
44-
with test_utils.deprecate(self):
45-
await loop.run_coroutine(fut)
46-
47-
# ensure that work() was executed in a different thread
48-
work_ident = result['ident']
49-
assert work_ident is not None
50-
assert work_ident != get_ident()
51-
5229
@pytest.mark.trio
5330
async def test_run_twice(self, loop):
5431
result = []
@@ -65,24 +42,6 @@ def work():
6542
await loop.run_aio_future(fut)
6643
assert result == ["run", "run"]
6744

68-
@pytest.mark.trio
69-
async def test_run_twice_depr(self, loop):
70-
result = []
71-
72-
def work():
73-
result.append("run")
74-
75-
fut = loop.run_in_executor(None, work)
76-
with test_utils.deprecate(self):
77-
await loop.run_future(fut)
78-
assert result == ["run"]
79-
80-
# ensure that run_in_executor() can be called twice
81-
fut = loop.run_in_executor(None, work)
82-
with test_utils.deprecate(self):
83-
await loop.run_future(fut)
84-
assert result == ["run", "run"]
85-
8645
@pytest.mark.trio
8746
async def test_policy(self, loop, config):
8847
asyncio = config.asyncio
@@ -99,23 +58,6 @@ def work():
9958
await loop.run_aio_future(fut)
10059
assert isinstance(result['loop'], (AssertionError, RuntimeError))
10160

102-
@pytest.mark.trio
103-
async def test_policy_depr(self, loop, config):
104-
asyncio = config.asyncio
105-
result = {'loop': 'not set'} # sentinel, different than None
106-
107-
def work():
108-
try:
109-
result['loop'] = asyncio.get_event_loop()
110-
except Exception as exc:
111-
result['loop'] = exc
112-
113-
# get_event_loop() must return None in a different thread
114-
fut = loop.run_in_executor(None, work)
115-
with test_utils.deprecate(self):
116-
await loop.run_future(fut)
117-
assert isinstance(result['loop'], (AssertionError, RuntimeError))
118-
11961
@pytest.mark.trio
12062
async def test_run_in_thread(self, config):
12163
threading = config.threading

0 commit comments

Comments
 (0)