Skip to content

Commit 1099b09

Browse files
authored
Bring trio-asyncio into the next decade (#66)
A collection of changes to make CI pass, including on 3.8. Fix use of deprecated Trio features: * Don't refer to trio.hazmat.Task._cancel_stack in interop tests * Don't use deprecated trio.Event.clear * Launch threads with trio.to_thread.run_sync Collect Python stdlib asyncio tests from the installed stdlib, rather than trying to vendor them. This lets us run the tests on far more platforms. Ignore some asyncio deprecation warnings on 3.8 for now. Clean up the monkeypatching of asyncio event loop and event loop policy accessors. The primary functional changes are: * Make TrioPolicy a singleton * Patch new_event_loop and set_event_loop to go through TrioPolicy like get_event_loop does * Improve SyncTrioEventLoop to not leak threads so much.
1 parent 42dd575 commit 1099b09

38 files changed

+405
-16319
lines changed

.travis.yml

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,22 @@
11
language: python
2-
python:
3-
- 3.6
4-
- 3.6-dev
5-
sudo: false
6-
dist: trusty
2+
dist: xenial
73

84
matrix:
95
include:
10-
# As of 2018-07-05, Travis's 3.7 and 3.8 builds only work if you
11-
# use dist: xenial AND sudo: required
12-
# See: https://github.com/python-trio/trio/pull/556#issuecomment-402879391
6+
- python: 3.5
7+
- python: 3.6
138
- python: 3.7
14-
dist: xenial
15-
sudo: required
169
- python: 3.7-dev
17-
dist: xenial
18-
sudo: required
10+
- python: 3.8
1911
- python: 3.8-dev
20-
dist: xenial
21-
sudo: required
22-
# - os: linux
23-
# language: generic
24-
# env: USE_PYPY_RELEASE_VERSION=5.9-beta
25-
# Uncomment if you want to test on pypy nightly
26-
# - os: linux
27-
# language: generic
28-
# env: USE_PYPY_NIGHTLY=1
12+
- python: nightly
2913
- os: osx
3014
language: generic
3115
env: MACPYTHON=3.6.3
3216
- python: 3.6
3317
env: CHECK_DOCS=1
3418
- python: 3.6
3519
env: CHECK_FORMATTING=1
36-
allow_failures:
37-
- python: 3.8-dev
3820

3921
script:
4022
- ci/travis.sh

README.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,18 @@
2626
**Trio-Asyncio** is a re-implementation of the ``asyncio`` mainloop on top of
2727
Trio.
2828

29-
Trio-Asyncio requires Python 3.6 or 3.7. It should work on Python 3.5.3, but
30-
that's not tested, as the test suite requires 3.6.
29+
Trio-Asyncio requires at least Python 3.5.3. It is tested on recent versions of
30+
3.5, 3.6, 3.7, 3.8, and nightly.
3131

3232
+++++++++++
3333
Rationale
3434
+++++++++++
3535

3636
Trio has native concepts of tasks and task cancellation. Asyncio is based
3737
on callbacks and chaining Futures, albeit with nicer syntax, which make
38-
handling of failures and timeouts fundamentally less reliable, esp. in
38+
handling of failures and timeouts fundamentally less reliable, especially in
3939
larger programs. Thus, you *really* want to base your async project on Trio.
40-
40+
4141
On the other hand, there are quite a few asyncio-enhanced libraries. You
4242
*really* don't want to re-invent any wheels in your project.
4343

ci/travis.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ else
9292
mkdir empty
9393
cd empty
9494

95-
pytest -W error -ra -v --cov=trio_asyncio --cov-config=../.coveragerc --verbose ../tests
95+
pytest -ra -v --cov=trio_asyncio --cov-config=../.coveragerc --verbose ../tests
9696

9797
bash <(curl -s https://codecov.io/bash)
9898
fi

newsfragments/66.feature.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Substantially reorganize monkeypatching for asyncio event loop and
2+
event loop policy accessors, fixing support for Python 3.8. Also, stop
3+
using features deprecated in Trio 0.12.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"""
5454

5555
install_requires = [
56-
"trio >= 0.11.0",
56+
"trio >= 0.12.0",
5757
"async_generator >= 1.6",
5858
"outcome",
5959
]

tests/__init__.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,3 @@
1111
aRepr.maxother = 9999
1212
aRepr.maxlong = 9999
1313
del aRepr
14-
15-
# Find the test SSL keys.
16-
from . import utils as test_utils
17-
18-
19-
def finish_request(self, request, client_address):
20-
import os
21-
import ssl
22-
here = os.path.join(os.path.dirname(__file__), 'python')
23-
keyfile = os.path.join(here, 'ssl_key.pem')
24-
certfile = os.path.join(here, 'ssl_cert.pem')
25-
context = ssl.SSLContext()
26-
context.load_cert_chain(certfile, keyfile)
27-
28-
ssock = context.wrap_socket(request, server_side=True)
29-
try:
30-
self.RequestHandlerClass(ssock, client_address, self)
31-
ssock.close()
32-
except OSError:
33-
# maybe socket has been closed by peer
34-
pass
35-
36-
37-
test_utils.SSLWSGIServerMixin.finish_request = finish_request
38-
del test_utils
39-
del finish_request

tests/interop/test_adapter.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pytest
2+
from async_generator import async_generator, yield_
23
from trio_asyncio import aio_as_trio, trio_as_aio, allow_asyncio
34
from trio_asyncio import aio2trio, trio2aio
45
import asyncio
@@ -72,39 +73,43 @@ async def dly_asyncio(self, do_test=True):
7273
self.flag |= 1
7374
return 4
7475

76+
@async_generator
7577
async def iter_asyncio(self, do_test=True):
7678
if do_test and sys.version_info >= (3, 7):
7779
assert sniffio.current_async_library() == "asyncio"
7880
await asyncio.sleep(0.01, loop=self.loop)
79-
yield 1
81+
await yield_(1)
8082
await asyncio.sleep(0.01, loop=self.loop)
81-
yield 2
83+
await yield_(2)
8284
await asyncio.sleep(0.01, loop=self.loop)
8385
self.flag |= 1
8486

87+
@async_generator
8588
async def iter_trio(self):
8689
if sys.version_info >= (3, 7):
8790
assert sniffio.current_async_library() == "trio"
8891
await trio.sleep(0.01)
89-
yield 1
92+
await yield_(1)
9093
await trio.sleep(0.01)
91-
yield 2
94+
await yield_(2)
9295
await trio.sleep(0.01)
9396
self.flag |= 1
9497

9598
@asynccontextmanager
99+
@async_generator
96100
async def ctx_asyncio(self):
97101
await asyncio.sleep(0.01, loop=self.loop)
98102
self.flag |= 1
99-
yield self
103+
await yield_(self)
100104
await asyncio.sleep(0.01, loop=self.loop)
101105
self.flag |= 2
102106

103107
@asynccontextmanager
108+
@async_generator
104109
async def ctx_trio(self):
105110
await trio.sleep(0.01)
106111
self.flag |= 1
107-
yield self
112+
await yield_(self)
108113
await trio.sleep(0.01)
109114
self.flag |= 2
110115

tests/interop/test_calls.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import asyncio
33
import trio
44
import sniffio
5+
from async_generator import async_generator, yield_
56
from trio_asyncio import aio_as_trio, trio_as_aio
67
from tests import aiotest
78
from functools import partial
@@ -302,7 +303,7 @@ async def test_asyncio_trio_cancel_out(self, loop):
302303
async def cancelled_trio(seen):
303304
seen.flag |= 1
304305
await trio.sleep(0.01)
305-
scope = trio.hazmat.current_task()._cancel_stack[-1]
306+
scope = trio.hazmat.current_task()._cancel_status._scope
306307
scope.cancel()
307308
seen.flag |= 2
308309
await trio.sleep(0.01)
@@ -525,21 +526,23 @@ def err_asyncio():
525526

526527
@pytest.mark.trio
527528
async def test_trio_asyncio_generator(self, loop):
529+
@async_generator
528530
async def dly_asyncio():
529-
yield 1
531+
await yield_(1)
530532
await asyncio.sleep(0.01, loop=loop)
531-
yield 2
533+
await yield_(2)
532534

533535
with test_utils.deprecate(self):
534536
res = await async_gen_to_list(loop.wrap_generator(dly_asyncio))
535537
assert res == [1, 2]
536538

537539
@pytest.mark.trio
538540
async def test_trio_asyncio_generator_with_error(self, loop):
541+
@async_generator
539542
async def dly_asyncio():
540-
yield 1
543+
await yield_(1)
541544
raise RuntimeError("I has an owie")
542-
yield 2
545+
await yield_(2)
543546

544547
with test_utils.deprecate(self):
545548
with pytest.raises(RuntimeError) as err:
@@ -548,8 +551,9 @@ async def dly_asyncio():
548551

549552
@pytest.mark.trio
550553
async def test_trio_asyncio_generator_with_cancellation(self, loop):
554+
@async_generator
551555
async def dly_asyncio(hold, seen):
552-
yield 1
556+
await yield_(1)
553557
seen.flag |= 1
554558
await hold.wait()
555559

@@ -569,10 +573,11 @@ async def cancel_soon(nursery):
569573

570574
@pytest.mark.trio
571575
async def test_trio_asyncio_iterator(self, loop):
576+
@async_generator
572577
async def slow_nums():
573578
for n in range(1, 6):
574-
asyncio.sleep(0.01, loop=loop)
575-
yield n
579+
await asyncio.sleep(0.01, loop=loop)
580+
await yield_(n)
576581

577582
sum = 0
578583
async for n in aio_as_trio(slow_nums()):
@@ -581,10 +586,11 @@ async def slow_nums():
581586

582587
@pytest.mark.trio
583588
async def test_trio_asyncio_iterator_depr(self, loop):
589+
@async_generator
584590
async def slow_nums():
585591
for n in range(1, 6):
586-
asyncio.sleep(0.01, loop=loop)
587-
yield n
592+
await asyncio.sleep(0.01, loop=loop)
593+
await yield_(n)
588594

589595
sum = 0
590596
# with test_utils.deprecate(self): ## not yet

tests/pytest.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[pytest]
2+
filterwarnings =
3+
error
4+
ignore:The loop argument is deprecated since Python 3.8:DeprecationWarning
5+
ignore:"@coroutine" decorator is deprecated since Python 3.8:DeprecationWarning
6+
default:Tried to add marker .* but that test doesn't exist.:RuntimeWarning

tests/python/__init__.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +0,0 @@
1-
import os
2-
from test.support import load_package_tests, import_module
3-
4-
# Skip tests if we don't have concurrent.futures.
5-
import_module('concurrent.futures')
6-
7-
8-
def load_tests(*args):
9-
return load_package_tests(os.path.dirname(__file__), *args)
10-
11-
12-
# this code is from
13-
# git@github.com:python/cpython.git
14-
# Revision d48ecebad
15-
# Python 3.6.4
16-
#

0 commit comments

Comments
 (0)