Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring trio-asyncio into the next decade #66

Merged
merged 22 commits into from
Jan 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ecb8181
[WIP] Attempt to fix CI
oremanj Jan 4, 2020
20f08e2
Run asyncio tests using the installed Python
oremanj Jan 5, 2020
43e8d68
Add missing files
oremanj Jan 6, 2020
41a3397
Use greenlet instead of threading for sync loop; document and update …
oremanj Jan 6, 2020
2798541
Add dependency on greenlet
oremanj Jan 6, 2020
e371720
Revert greenlet change; make sync loop close() actually terminate the…
oremanj Jan 6, 2020
a46f566
Put warning args in the right order
oremanj Jan 6, 2020
4ef8e3e
Ignore DeprecationWarnings about loop= arg on 3.8
oremanj Jan 6, 2020
0e35011
Reorganize CI matrix
oremanj Jan 6, 2020
1df6bba
Nerf threading_cleanup so tests (esp on 3.8) don't take so long
oremanj Jan 6, 2020
005ac02
xfail two run_coroutine_threadsafe tests on 3.8
oremanj Jan 6, 2020
d721247
yapfify
oremanj Jan 6, 2020
32e156a
Add a few more skips; move -Werror into pytest.ini so the particular …
oremanj Jan 6, 2020
79870ec
Don't skip tests that don't exist
oremanj Jan 6, 2020
3ef2f52
Import selectors; don't leak threads
oremanj Jan 6, 2020
b609b6b
Don't crash if a test we're trying to skip doesn't exist
oremanj Jan 6, 2020
4a838aa
Prevent crashes in __del__
oremanj Jan 6, 2020
580ac8a
capitalize EPollEventLoop correctly; 3.5 backcompat for async generators
oremanj Jan 6, 2020
39e7eb1
Hopefully-final pass of xfail tweaking
oremanj Jan 6, 2020
18c6429
Clarify versions that encounter SSL errors
oremanj Jan 6, 2020
1a81e4f
Mention new test matrix in the README
oremanj Jan 6, 2020
ecffc85
Mention fixing the deprecation errors
oremanj Jan 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 5 additions & 23 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,22 @@
language: python
python:
- 3.6
- 3.6-dev
sudo: false
dist: trusty
dist: xenial

matrix:
include:
# As of 2018-07-05, Travis's 3.7 and 3.8 builds only work if you
# use dist: xenial AND sudo: required
# See: https://github.com/python-trio/trio/pull/556#issuecomment-402879391
- python: 3.5
- python: 3.6
- python: 3.7
dist: xenial
sudo: required
- python: 3.7-dev
dist: xenial
sudo: required
- python: 3.8
- python: 3.8-dev
dist: xenial
sudo: required
# - os: linux
# language: generic
# env: USE_PYPY_RELEASE_VERSION=5.9-beta
# Uncomment if you want to test on pypy nightly
# - os: linux
# language: generic
# env: USE_PYPY_NIGHTLY=1
- python: nightly
- os: osx
language: generic
env: MACPYTHON=3.6.3
- python: 3.6
env: CHECK_DOCS=1
- python: 3.6
env: CHECK_FORMATTING=1
allow_failures:
- python: 3.8-dev

script:
- ci/travis.sh
8 changes: 4 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@
**Trio-Asyncio** is a re-implementation of the ``asyncio`` mainloop on top of
Trio.

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

+++++++++++
Rationale
+++++++++++

Trio has native concepts of tasks and task cancellation. Asyncio is based
on callbacks and chaining Futures, albeit with nicer syntax, which make
handling of failures and timeouts fundamentally less reliable, esp. in
handling of failures and timeouts fundamentally less reliable, especially in
larger programs. Thus, you *really* want to base your async project on Trio.

On the other hand, there are quite a few asyncio-enhanced libraries. You
*really* don't want to re-invent any wheels in your project.

Expand Down
2 changes: 1 addition & 1 deletion ci/travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ else
mkdir empty
cd empty

pytest -W error -ra -v --cov=trio_asyncio --cov-config=../.coveragerc --verbose ../tests
pytest -ra -v --cov=trio_asyncio --cov-config=../.coveragerc --verbose ../tests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change intentional?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes -- I created a pytest.ini with a more detailed warnings filter. (The loop= argument is deprecated in several asyncio methods on 3.8+. I didn't think it advisable to remove support for passing the loop just yet.)


bash <(curl -s https://codecov.io/bash)
fi
3 changes: 3 additions & 0 deletions newsfragments/66.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Substantially reorganize monkeypatching for asyncio event loop and
event loop policy accessors, fixing support for Python 3.8. Also, stop
using features deprecated in Trio 0.12.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"""

install_requires = [
"trio >= 0.11.0",
"trio >= 0.12.0",
"async_generator >= 1.6",
"outcome",
]
Expand Down
26 changes: 0 additions & 26 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,3 @@
aRepr.maxother = 9999
aRepr.maxlong = 9999
del aRepr

# Find the test SSL keys.
from . import utils as test_utils


def finish_request(self, request, client_address):
import os
import ssl
here = os.path.join(os.path.dirname(__file__), 'python')
keyfile = os.path.join(here, 'ssl_key.pem')
certfile = os.path.join(here, 'ssl_cert.pem')
context = ssl.SSLContext()
context.load_cert_chain(certfile, keyfile)

ssock = context.wrap_socket(request, server_side=True)
try:
self.RequestHandlerClass(ssock, client_address, self)
ssock.close()
except OSError:
# maybe socket has been closed by peer
pass


test_utils.SSLWSGIServerMixin.finish_request = finish_request
del test_utils
del finish_request
17 changes: 11 additions & 6 deletions tests/interop/test_adapter.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from async_generator import async_generator, yield_
from trio_asyncio import aio_as_trio, trio_as_aio, allow_asyncio
from trio_asyncio import aio2trio, trio2aio
import asyncio
Expand Down Expand Up @@ -72,39 +73,43 @@ async def dly_asyncio(self, do_test=True):
self.flag |= 1
return 4

@async_generator
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)
yield 1
await yield_(1)
await asyncio.sleep(0.01, loop=self.loop)
yield 2
await yield_(2)
await asyncio.sleep(0.01, loop=self.loop)
self.flag |= 1

@async_generator
async def iter_trio(self):
if sys.version_info >= (3, 7):
assert sniffio.current_async_library() == "trio"
await trio.sleep(0.01)
yield 1
await yield_(1)
await trio.sleep(0.01)
yield 2
await yield_(2)
await trio.sleep(0.01)
self.flag |= 1

@asynccontextmanager
@async_generator
async def ctx_asyncio(self):
await asyncio.sleep(0.01, loop=self.loop)
self.flag |= 1
yield self
await yield_(self)
await asyncio.sleep(0.01, loop=self.loop)
self.flag |= 2

@asynccontextmanager
@async_generator
async def ctx_trio(self):
await trio.sleep(0.01)
self.flag |= 1
yield self
await yield_(self)
await trio.sleep(0.01)
self.flag |= 2

Expand Down
26 changes: 16 additions & 10 deletions tests/interop/test_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import asyncio
import trio
import sniffio
from async_generator import async_generator, yield_
from trio_asyncio import aio_as_trio, trio_as_aio
from tests import aiotest
from functools import partial
Expand Down Expand Up @@ -302,7 +303,7 @@ async def test_asyncio_trio_cancel_out(self, loop):
async def cancelled_trio(seen):
seen.flag |= 1
await trio.sleep(0.01)
scope = trio.hazmat.current_task()._cancel_stack[-1]
scope = trio.hazmat.current_task()._cancel_status._scope
scope.cancel()
seen.flag |= 2
await trio.sleep(0.01)
Expand Down Expand Up @@ -525,21 +526,23 @@ def err_asyncio():

@pytest.mark.trio
async def test_trio_asyncio_generator(self, loop):
@async_generator
async def dly_asyncio():
yield 1
await yield_(1)
await asyncio.sleep(0.01, loop=loop)
yield 2
await yield_(2)

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

@pytest.mark.trio
async def test_trio_asyncio_generator_with_error(self, loop):
@async_generator
async def dly_asyncio():
yield 1
await yield_(1)
raise RuntimeError("I has an owie")
yield 2
await yield_(2)

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

@pytest.mark.trio
async def test_trio_asyncio_generator_with_cancellation(self, loop):
@async_generator
async def dly_asyncio(hold, seen):
yield 1
await yield_(1)
seen.flag |= 1
await hold.wait()

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

@pytest.mark.trio
async def test_trio_asyncio_iterator(self, loop):
@async_generator
async def slow_nums():
for n in range(1, 6):
asyncio.sleep(0.01, loop=loop)
yield n
await asyncio.sleep(0.01, loop=loop)
await yield_(n)

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

@pytest.mark.trio
async def test_trio_asyncio_iterator_depr(self, loop):
@async_generator
async def slow_nums():
for n in range(1, 6):
asyncio.sleep(0.01, loop=loop)
yield n
await asyncio.sleep(0.01, loop=loop)
await yield_(n)

sum = 0
# with test_utils.deprecate(self): ## not yet
Expand Down
6 changes: 6 additions & 0 deletions tests/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[pytest]
filterwarnings =
error
ignore:The loop argument is deprecated since Python 3.8:DeprecationWarning
ignore:"@coroutine" decorator is deprecated since Python 3.8:DeprecationWarning
default:Tried to add marker .* but that test doesn't exist.:RuntimeWarning
16 changes: 0 additions & 16 deletions tests/python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +0,0 @@
import os
from test.support import load_package_tests, import_module

# Skip tests if we don't have concurrent.futures.
import_module('concurrent.futures')


def load_tests(*args):
return load_package_tests(os.path.dirname(__file__), *args)


# this code is from
# git@github.com:python/cpython.git
# Revision d48ecebad
# Python 3.6.4
#
4 changes: 0 additions & 4 deletions tests/python/__main__.py

This file was deleted.

Loading