From c67e39dc35ba1992e1938bf8d8044074aae9b73f Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 10:29:23 +0400 Subject: [PATCH 01/25] Drop support for Python 3.5 --- .travis.yml | 7 ------- README.rst | 2 +- azure-pipelines.yml | 10 ---------- docs/source/index.rst | 2 +- docs/source/tutorial.rst | 4 ++-- setup.py | 7 ++++--- 6 files changed, 8 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index 685b4a8e93..756d472eb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,13 +21,6 @@ jobs: env: - "JOB_NAME='Ubuntu 19.10, full VM'" - "VM_IMAGE=https://cloud-images.ubuntu.com/eoan/current/eoan-server-cloudimg-amd64.img" - # 3.5.0 and 3.5.1 have different __aiter__ semantics than all - # other versions, so we need to test them specially. Travis's - # newer images only provide 3.5.2+, so we have to request the old - # 'trusty' images. - - python: 3.5.0 - dist: trusty - - python: 3.5-dev - python: 3.6-dev - python: 3.7-dev - python: 3.8-dev diff --git a/README.rst b/README.rst index 4fe3ee5ebe..b1dae85404 100644 --- a/README.rst +++ b/README.rst @@ -102,7 +102,7 @@ demonstration of implementing the "Happy Eyeballs" algorithm in an older library versus Trio. **Cool, but will it work on my system?** Probably! As long as you have -some kind of Python 3.5-or-better (CPython or the latest PyPy3 are +some kind of Python 3.6-or-better (CPython or the latest PyPy3 are both fine), and are using Linux, macOS, or Windows, then Trio should absolutely work. *BSD and illumos likely work too, but we don't have testing infrastructure for them. And all of our dependencies are pure diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a6c84408c1..c56eb0650c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,12 +27,6 @@ jobs: python.version: '3.7.5' python.pkg: 'python' lsp: 'http://download.pctools.com/mirror/updates/9.0.0.2308-SDavfree-lite_en.exe' - "Python 3.5, 32 bit": - python.version: '3.5.4' - python.pkg: 'pythonx86' - "Python 3.5, 64 bit": - python.version: '3.5.4' - python.pkg: 'python' "Python 3.6, 32 bit": python.version: '3.6.8' python.pkg: 'pythonx86' @@ -76,8 +70,6 @@ jobs: "Formatting and linting": python.version: '3.8' CHECK_FORMATTING: 1 - "Python 3.5": - python.version: '3.5' "Python 3.6": python.version: '3.6' "Python 3.7": @@ -104,8 +96,6 @@ jobs: timeoutInMinutes: 10 strategy: matrix: - "Python 3.5": - python.version: '3.5' "Python 3.6": python.version: '3.6' "Python 3.7": diff --git a/docs/source/index.rst b/docs/source/index.rst index 4f20067785..6e4f2f78e1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -44,7 +44,7 @@ chance to give feedback about any compatibility-breaking changes. Vital statistics: * Supported environments: Linux, macOS, or Windows running some kind of Python - 3.5-or-better (either CPython or PyPy3 is fine). \*BSD and + 3.6-or-better (either CPython or PyPy3 is fine). \*BSD and illumos likely work too, but are untested. * Install: ``python3 -m pip install -U trio`` (or on Windows, maybe diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst index 3b9255b236..e435966f3b 100644 --- a/docs/source/tutorial.rst +++ b/docs/source/tutorial.rst @@ -94,7 +94,7 @@ Okay, ready? Let's get started. Before you begin ---------------- -1. Make sure you're using Python 3.5 or newer. +1. Make sure you're using Python 3.6 or newer. 2. ``python3 -m pip install --upgrade trio`` (or on Windows, maybe ``py -3 -m pip install --upgrade trio`` – `details @@ -312,7 +312,7 @@ runs: >>>> # but forcing a garbage collection gives us a warning: >>>> import gc >>>> gc.collect() - /home/njs/pypy-3.5-nightly/lib-python/3/importlib/_bootstrap.py:191: RuntimeWarning: coroutine 'sleep' was never awaited + /home/njs/pypy-3.8-nightly/lib-python/3/importlib/_bootstrap.py:191: RuntimeWarning: coroutine 'sleep' was never awaited if _module_locks.get(name) is wr: # XXX PyPy fix? 0 >>>> diff --git a/setup.py b/setup.py index 45964b34b2..714bdc78fd 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ Vital statistics: * Supported environments: Linux, macOS, or Windows running some kind of Python - 3.5-or-better (either CPython or PyPy3 is fine). \\*BSD and illumos likely + 3.6-or-better (either CPython or PyPy3 is fine). \\*BSD and illumos likely work too, but are not tested. * Install: ``python3 -m pip install -U trio`` (or on Windows, maybe @@ -101,7 +101,7 @@ ":os_name == 'nt'": ["cffi >= 1.12"], # "cffi is required on windows", ":python_version < '3.7'": ["contextvars>=2.1"] }, - python_requires=">=3.5", + python_requires=">=3.6", keywords=["async", "io", "networking", "trio"], classifiers=[ "Development Status :: 3 - Alpha", @@ -115,8 +115,9 @@ "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: System :: Networking", "Framework :: Trio", ], From 66a4678383ccff7c5907009c6c5d262aaf651cb1 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 10:42:46 +0400 Subject: [PATCH 02/25] Stop referencing Python 3.5 in comments --- trio/_core/_entry_queue.py | 4 ++-- trio/_core/_run.py | 9 +++------ trio/_core/tests/test_ki.py | 4 +--- trio/_core/tests/test_run.py | 4 +--- trio/_highlevel_ssl_helpers.py | 8 ++------ trio/tests/test_path.py | 2 +- trio/tests/test_ssl.py | 7 +++---- 7 files changed, 13 insertions(+), 25 deletions(-) diff --git a/trio/_core/_entry_queue.py b/trio/_core/_entry_queue.py index 97b1c56fa4..ee20b6e562 100644 --- a/trio/_core/_entry_queue.py +++ b/trio/_core/_entry_queue.py @@ -179,8 +179,8 @@ def run_sync_soon(self, sync_fn, *args, idempotent=False): hashable, and Trio will make a best-effort attempt to discard any call submission which is equal to an already-pending call. Trio will make an attempt to process these in first-in first-out order, - but no guarantees. (Currently processing is FIFO on CPython 3.6 and - PyPy, but not CPython 3.5.) + but no guarantees. (Currently processing is FIFO on CPython and + PyPy.) Any ordering guarantees apply separately to ``idempotent=False`` and ``idempotent=True`` calls; there's no rule for how calls in the diff --git a/trio/_core/_run.py b/trio/_core/_run.py index faf4c1371b..b5aae49a5b 100644 --- a/trio/_core/_run.py +++ b/trio/_core/_run.py @@ -1262,12 +1262,9 @@ def _return_value_looks_like_wrong_library(value): # The protocol for detecting an asyncio Future-like object if getattr(value, "_asyncio_future_blocking", None) is not None: return True - # asyncio.Future doesn't have _asyncio_future_blocking until - # 3.5.3. We don't want to import asyncio, but this janky check - # should work well enough for our purposes. And it also catches - # tornado Futures and twisted Deferreds. By the time we're calling - # this function, we already know something has gone wrong, so a - # heuristic is pretty safe. + # This janky check catches tornado Futures and twisted Deferreds. + # By the time we're calling this function, we already know + # something has gone wrong, so a heuristic is pretty safe. if value.__class__.__name__ in ("Future", "Deferred"): return True return False diff --git a/trio/_core/tests/test_ki.py b/trio/_core/tests/test_ki.py index e0d3b97c50..b64057c496 100644 --- a/trio/_core/tests/test_ki.py +++ b/trio/_core/tests/test_ki.py @@ -504,9 +504,7 @@ def test_ki_wakes_us_up(): # # which contains the desired sequence. # - # Affected version of CPython include: - # - all versions of 3.5 (fix will not be backported) - # - 3.6.1 and earlier + # Affected version of CPython include 3.6.1 and earlier. # It's fixed in 3.6.2 and 3.7+ # # PyPy was never affected. diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index fc03197133..e887bfff6b 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -38,9 +38,7 @@ async def sleep_forever(): # Some of our tests need to leak coroutines, and thus trigger the # "RuntimeWarning: coroutine '...' was never awaited" message. This context # manager should be used anywhere this happens to hide those messages, because -# (a) when expected they're clutter, (b) on CPython 3.5.x where x < 3, this -# warning can trigger a segfault if we run with warnings turned into errors: -# https://bugs.python.org/issue27811 +# when expected they're clutter. @contextmanager def ignore_coroutine_never_awaited_warnings(): with warnings.catch_warnings(): diff --git a/trio/_highlevel_ssl_helpers.py b/trio/_highlevel_ssl_helpers.py index ce78832087..fc8e59b75a 100644 --- a/trio/_highlevel_ssl_helpers.py +++ b/trio/_highlevel_ssl_helpers.py @@ -14,12 +14,8 @@ # if it's one we created, but not OK if it's one that was passed in... and # the one major protocol using NPN/ALPN is HTTP/2, which mandates that you use # a specially configured SSLContext anyway! I also thought maybe we could copy -# the given SSLContext and then mutate the copy, but it's no good: -# copy.copy(SSLContext) seems to succeed, but the state is not transferred! -# For example, with CPython 3.5, we have: -# ctx = ssl.create_default_context() -# assert ctx.check_hostname == True -# assert copy.copy(ctx).check_hostname == False +# the given SSLContext and then mutate the copy, but it's no good as SSLContext +# objects can't be copied: https://bugs.python.org/issue33023. # So... let's punt on that for now. Hopefully we'll be getting a new Python # TLS API soon and can revisit this then. async def open_ssl_over_tcp_stream( diff --git a/trio/tests/test_path.py b/trio/tests/test_path.py index 67d7c2957e..e6045a0a26 100644 --- a/trio/tests/test_path.py +++ b/trio/tests/test_path.py @@ -57,7 +57,7 @@ async def test_cmp_magic(cls_a, cls_b): assert not b == None # noqa -# upstream python3.5 bug: we should also test (pathlib.Path, trio.Path), but +# upstream python3.8 bug: we should also test (pathlib.Path, trio.Path), but # __*div__ does not properly raise NotImplementedError like the other comparison # magic, so trio.Path's implementation does not get dispatched cls_pairs = [ diff --git a/trio/tests/test_ssl.py b/trio/tests/test_ssl.py index 0ac217bb4c..184b5b5c2a 100644 --- a/trio/tests/test_ssl.py +++ b/trio/tests/test_ssl.py @@ -175,13 +175,12 @@ def __init__(self, sleeper=None): ctx = SSL.Context(SSL.SSLv23_METHOD) # TLS 1.3 removes renegotiation support. Which is great for them, but # we still have to support versions before that, and that means we - # need to test renegotation support, which means we need to force this + # need to test renegotiation support, which means we need to force this # to use a lower version where this test server can trigger # renegotiations. Of course TLS 1.3 support isn't released yet, but # I'm told that this will work once it is. (And once it is we can - # remove the pragma: no cover too.) Alternatively, once we drop - # support for CPython 3.5 on macOS, then we could switch to using - # TLSv1_2_METHOD. + # remove the pragma: no cover too.) Alternatively, we could switch to + # using TLSv1_2_METHOD. # # Discussion: https://github.com/pyca/pyopenssl/issues/624 From 80e408b88bf68d148d2551142bbf0437d063d30b Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 10:43:47 +0400 Subject: [PATCH 03/25] Remove nuget Python 3.5 fix --- ci.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ci.sh b/ci.sh index 6a202cb3be..2a0724a8c9 100755 --- a/ci.sh +++ b/ci.sh @@ -55,10 +55,6 @@ if [ "$AGENT_OS" = "Windows_NT" ]; then pydir="$PWD/pyinstall/${PYTHON_PKG}" export PATH="${pydir}/tools:${pydir}/tools/scripts:$PATH" - - # Fix an issue with the nuget python 3.5 packages - # https://github.com/python-trio/trio/pull/827#issuecomment-457433940 - rm -f "${pydir}/tools/pyvenv.cfg" || true fi ### Travis + macOS ### From d6e7a0cf01c8d76544ed9caa55c99caad09f7c01 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:03:58 +0400 Subject: [PATCH 04/25] Stop unwrapping paths now that Python 3.5 is gone --- trio/_path.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/trio/_path.py b/trio/_path.py index bbadf9d874..fbe9db26f6 100644 --- a/trio/_path.py +++ b/trio/_path.py @@ -9,17 +9,6 @@ __all__ = ['Path'] -# python3.5 compat: __fspath__ does not exist in 3.5, so unwrap any trio.Path -# being passed to any wrapped method -def unwrap_paths(args): - new_args = [] - for arg in args: - if isinstance(arg, Path): - arg = arg._wrapped - new_args.append(arg) - return new_args - - # re-wrap return value from methods that return new instances of pathlib.Path def rewrap_path(value): if isinstance(value, pathlib.Path): @@ -30,7 +19,6 @@ def rewrap_path(value): def _forward_factory(cls, attr_name, attr): @wraps(attr) def wrapper(self, *args, **kwargs): - args = unwrap_paths(args) attr = getattr(self._wrapped, attr_name) value = attr(*args, **kwargs) return rewrap_path(value) @@ -69,7 +57,6 @@ async def wrapper(self, *args, **kwargs): def thread_wrapper_factory(cls, meth_name): @async_wraps(cls, cls._wraps, meth_name) async def wrapper(self, *args, **kwargs): - args = unwrap_paths(args) meth = getattr(self._wrapped, meth_name) func = partial(meth, *args, **kwargs) value = await trio.to_thread.run_sync(func) @@ -82,7 +69,6 @@ def classmethod_wrapper_factory(cls, meth_name): @classmethod @async_wraps(cls, cls._wraps, meth_name) async def wrapper(cls, *args, **kwargs): - args = unwrap_paths(args) meth = getattr(cls._wraps, meth_name) func = partial(meth, *args, **kwargs) value = await trio.to_thread.run_sync(func) @@ -168,8 +154,6 @@ class Path(metaclass=AsyncAutoWrapperType): _wrap_iter = ['glob', 'rglob', 'iterdir'] def __init__(self, *args): - args = unwrap_paths(args) - self._wrapped = pathlib.Path(*args) def __getattr__(self, name): From dcc70ddfade6bbc99c8de78b98c6718dc4d3b718 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:05:22 +0400 Subject: [PATCH 05/25] Remove fspath backport now that Python 3.5 is gone --- trio/_file_io.py | 6 +--- trio/_path.py | 4 +-- trio/_socket.py | 3 +- trio/_util.py | 60 ---------------------------------- trio/tests/test_file_io.py | 4 +-- trio/tests/test_path.py | 3 +- trio/tests/test_util.py | 67 +------------------------------------- 7 files changed, 8 insertions(+), 139 deletions(-) diff --git a/trio/_file_io.py b/trio/_file_io.py index 32468af46b..ca1f003741 100644 --- a/trio/_file_io.py +++ b/trio/_file_io.py @@ -2,7 +2,7 @@ import io from .abc import AsyncResource -from ._util import aiter_compat, async_wraps, fspath +from ._util import aiter_compat, async_wraps import trio @@ -159,10 +159,6 @@ async def open_file( :func:`trio.Path.open` """ - # python3.5 compat - if isinstance(file, trio.Path): - file = fspath(file) - _file = wrap_file( await trio.to_thread.run_sync( io.open, file, mode, buffering, encoding, errors, newline, closefd, diff --git a/trio/_path.py b/trio/_path.py index fbe9db26f6..89a285ed39 100644 --- a/trio/_path.py +++ b/trio/_path.py @@ -4,7 +4,7 @@ import pathlib import trio -from trio._util import async_wraps, fspath +from trio._util import async_wraps __all__ = ['Path'] @@ -169,7 +169,7 @@ def __repr__(self): return 'trio.Path({})'.format(repr(str(self))) def __fspath__(self): - return fspath(self._wrapped) + return os.fspath(self._wrapped) @wraps(pathlib.Path.open) async def open(self, *args, **kwargs): diff --git a/trio/_socket.py b/trio/_socket.py index 18403962d2..fe9ca242c1 100644 --- a/trio/_socket.py +++ b/trio/_socket.py @@ -7,7 +7,6 @@ import idna as _idna import trio -from ._util import fspath from . import _core @@ -512,7 +511,7 @@ async def _resolve_address(self, address, flags): elif self._sock.family == _stdlib_socket.AF_UNIX: await trio.hazmat.checkpoint() # unwrap path-likes - return fspath(address) + return _os.fspath(address) else: await trio.hazmat.checkpoint() diff --git a/trio/_util.py b/trio/_util.py index 9204b83349..d21669c855 100644 --- a/trio/_util.py +++ b/trio/_util.py @@ -177,66 +177,6 @@ def fix_one(qualname, name, obj): fix_one(objname, objname, obj) -# os.fspath is defined on Python 3.6+ but we need to support Python 3.5 too -# This is why we provide our own implementation. On Python 3.6+ we use the -# StdLib's version and on Python 3.5 our own version. -# Our own implementation implementation is based on PEP 519 while it has also -# been adapted to work with pathlib objects on python 3.5 -# The input typehint is removed as there is no os.PathLike on 3.5. -# See: https://www.python.org/dev/peps/pep-0519/#os - - -def fspath(path) -> t.Union[str, bytes]: - """Return the path representation of a path-like object. - - Returns - ------- - - If str or bytes is passed in, it is returned unchanged. - - If the os.PathLike interface is implemented it is used to get the path - representation. - - If the python version is 3.5 or earlier and a pathlib object is passed, - the object's string representation is returned. - - Raises - ------ - - Regardless of the input, if the path representation (e.g. the value - returned from __fspath__) is not str or bytes, TypeError is raised. - - If the provided path is not str, bytes, pathlib.PurePath or os.PathLike, - TypeError is raised. - """ - if isinstance(path, (str, bytes)): - return path - # Work from the object's type to match method resolution of other magic - # methods. - path_type = type(path) - # On python 3.5, pathlib objects don't have the __fspath__ method, - # but we still want to get their string representation. - if issubclass(path_type, pathlib.PurePath): - return str(path) - try: - path_repr = path_type.__fspath__(path) - except AttributeError: - if hasattr(path_type, '__fspath__'): - raise - else: - raise TypeError( - "expected str, bytes or os.PathLike object, " - "not " + path_type.__name__ - ) - if isinstance(path_repr, (str, bytes)): - return path_repr - else: - raise TypeError( - "expected {}.__fspath__() to return str or bytes, " - "not {}".format(path_type.__name__, - type(path_repr).__name__) - ) - - -if hasattr(os, "fspath"): - fspath = os.fspath # noqa - - class generic_function: """Decorator that makes a function indexable, to communicate non-inferrable generic type parameters to a static type checker. diff --git a/trio/tests/test_file_io.py b/trio/tests/test_file_io.py index 8f96e75aac..fd4fa648b4 100644 --- a/trio/tests/test_file_io.py +++ b/trio/tests/test_file_io.py @@ -1,4 +1,5 @@ import io +import os import pytest from unittest import mock @@ -6,13 +7,12 @@ import trio from trio import _core -from trio._util import fspath from trio._file_io import AsyncIOWrapper, _FILE_SYNC_ATTRS, _FILE_ASYNC_METHODS @pytest.fixture def path(tmpdir): - return fspath(tmpdir.join('test')) + return os.fspath(tmpdir.join('test')) @pytest.fixture diff --git a/trio/tests/test_path.py b/trio/tests/test_path.py index e6045a0a26..9bbbfd4df2 100644 --- a/trio/tests/test_path.py +++ b/trio/tests/test_path.py @@ -5,7 +5,6 @@ import trio from trio._path import AsyncAutoWrapperType as Type -from trio._util import fspath from trio._file_io import AsyncIOWrapper @@ -203,7 +202,7 @@ async def test_path_nonpath(): async def test_open_file_can_open_path(path): async with await trio.open_file(path, 'w') as f: - assert f.name == fspath(path) + assert f.name == os.fspath(path) async def test_globmethods(path): diff --git a/trio/tests/test_util.py b/trio/tests/test_util.py index 5815ae3e42..ae83327a23 100644 --- a/trio/tests/test_util.py +++ b/trio/tests/test_util.py @@ -8,7 +8,7 @@ import trio from .. import _core from .._util import ( - signal_raise, ConflictDetector, fspath, is_main_thread, generic_function, + signal_raise, ConflictDetector, is_main_thread, generic_function, Final, NoPublicConstructor ) from ..testing import wait_all_tasks_blocked, assert_checkpoints @@ -97,71 +97,6 @@ def __fspath__(self): return self.path -class TestFspath: - - # based on: - # https://github.com/python/cpython/blob/da6c3da6c33c6bf794f741e348b9c6d86cc43ec5/Lib/test/test_os.py#L3527-L3571 - - @pytest.mark.parametrize( - "path", (b'hello', b'goodbye', b'some/path/and/file') - ) - def test_return_bytes(self, path): - assert path == fspath(path) - - @pytest.mark.parametrize( - "path", ('hello', 'goodbye', 'some/path/and/file') - ) - def test_return_string(self, path): - assert path == fspath(path) - - @pytest.mark.parametrize( - "path", (pathlib.Path("/home"), pathlib.Path("C:\\windows")) - ) - def test_handle_pathlib(self, path): - assert str(path) == fspath(path) - - @pytest.mark.parametrize("path", ("path/like/object", b"path/like/object")) - def test_handle_pathlike_protocol(self, path): - pathlike = ConcretePathLike(path) - assert path == fspath(pathlike) - if sys.version_info > (3, 6): - assert issubclass(ConcretePathLike, os.PathLike) - assert isinstance(pathlike, os.PathLike) - - def test_argument_required(self): - with pytest.raises(TypeError): - fspath() - - def test_throw_error_at_multiple_arguments(self): - with pytest.raises(TypeError): - fspath(1, 2) - - @pytest.mark.parametrize( - "klass", (23, object(), int, type, os, type("blah", (), {})()) - ) - def test_throw_error_at_non_pathlike(self, klass): - with pytest.raises(TypeError): - fspath(klass) - - @pytest.mark.parametrize( - "exception, method", - [ - (TypeError, 1), # __fspath__ is not callable - (TypeError, lambda x: 23 - ), # __fspath__ returns a value other than str or bytes - (Exception, lambda x: raise_(Exception) - ), # __fspath__raises a random exception - (AttributeError, lambda x: raise_(AttributeError) - ), # __fspath__ raises AttributeError - ] - ) - def test_bad_pathlike_implementation(self, exception, method): - klass = type('foo', (), {}) - klass.__fspath__ = method - with pytest.raises(exception): - fspath(klass()) - - async def test_is_main_thread(): assert is_main_thread() From deb9f879737e7f3e63c219e8f29fb3f97a37ca73 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:06:32 +0400 Subject: [PATCH 06/25] Assume os.PathLike exists now that Python 3.5 is gone --- trio/_path.py | 4 +--- trio/tests/test_util.py | 8 +------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/trio/_path.py b/trio/_path.py index 89a285ed39..2f34a38972 100644 --- a/trio/_path.py +++ b/trio/_path.py @@ -203,6 +203,4 @@ async def open(self, *args, **kwargs): # sense than inventing our own special docstring for this. del Path.absolute.__doc__ -# python3.5 compat -if hasattr(os, 'PathLike'): - os.PathLike.register(Path) +os.PathLike.register(Path) diff --git a/trio/tests/test_util.py b/trio/tests/test_util.py index ae83327a23..5a5b189091 100644 --- a/trio/tests/test_util.py +++ b/trio/tests/test_util.py @@ -82,13 +82,7 @@ def test_module_metadata_is_fixed_up(): assert trio.to_thread.run_sync.__qualname__ == "run_sync" -# define a concrete class implementing the PathLike protocol -# Since we want to have compatibility with Python 3.5 we need -# to define the base class on runtime. -BaseKlass = os.PathLike if hasattr(os, "PathLike") else object - - -class ConcretePathLike(BaseKlass): +class ConcretePathLike(os.PathLike): """ Class implementing the file system path protocol.""" def __init__(self, path=""): self.path = path From 215b8d57d1d4a4639816153ea0f6a951d1ab8e38 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:08:21 +0400 Subject: [PATCH 07/25] Remove aiter_compat now that Python 3.5 is gone --- trio/_abc.py | 3 --- trio/_core/_unbounded_queue.py | 2 -- trio/_core/tests/test_run.py | 2 -- trio/_file_io.py | 3 +-- trio/_signals.py | 5 +---- trio/_sync.py | 1 - trio/_util.py | 18 ------------------ 7 files changed, 2 insertions(+), 32 deletions(-) diff --git a/trio/_abc.py b/trio/_abc.py index 675eb5dd9e..663b1089ce 100644 --- a/trio/_abc.py +++ b/trio/_abc.py @@ -1,6 +1,5 @@ from abc import ABCMeta, abstractmethod from typing import Generic, TypeVar -from ._util import aiter_compat import trio @@ -414,7 +413,6 @@ async def receive_some(self, max_bytes=None): """ - @aiter_compat def __aiter__(self): return self @@ -629,7 +627,6 @@ async def receive(self) -> ReceiveType: """ - @aiter_compat def __aiter__(self): return self diff --git a/trio/_core/_unbounded_queue.py b/trio/_core/_unbounded_queue.py index f5e2dda5c3..abe4d60c56 100644 --- a/trio/_core/_unbounded_queue.py +++ b/trio/_core/_unbounded_queue.py @@ -1,7 +1,6 @@ import attr from .. import _core -from .._util import aiter_compat from .._deprecate import deprecated __all__ = ["UnboundedQueue"] @@ -146,7 +145,6 @@ def statistics(self): tasks_waiting=self._lot.statistics().tasks_waiting ) - @aiter_compat def __aiter__(self): return self diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index e887bfff6b..e248139343 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -20,7 +20,6 @@ from ... import _core from ..._threads import to_thread_run_sync from ..._timeouts import sleep, fail_after -from ..._util import aiter_compat from ...testing import ( wait_all_tasks_blocked, Sequencer, @@ -2054,7 +2053,6 @@ def __init__(self, *largs): async def _accumulate(self, f, items, i): items[i] = await f() - @aiter_compat def __aiter__(self): return self diff --git a/trio/_file_io.py b/trio/_file_io.py index ca1f003741..10464589a9 100644 --- a/trio/_file_io.py +++ b/trio/_file_io.py @@ -2,7 +2,7 @@ import io from .abc import AsyncResource -from ._util import aiter_compat, async_wraps +from ._util import async_wraps import trio @@ -95,7 +95,6 @@ def __dir__(self): ) return attrs - @aiter_compat def __aiter__(self): return self diff --git a/trio/_signals.py b/trio/_signals.py index 2ebb4a0a5a..2f2793c43e 100644 --- a/trio/_signals.py +++ b/trio/_signals.py @@ -3,9 +3,7 @@ from collections import OrderedDict import trio -from ._util import ( - signal_raise, aiter_compat, is_main_thread, ConflictDetector -) +from ._util import signal_raise, is_main_thread, ConflictDetector __all__ = ["open_signal_receiver"] @@ -96,7 +94,6 @@ def deliver_next(): def _pending_signal_count(self): return len(self._pending) - @aiter_compat def __aiter__(self): return self diff --git a/trio/_sync.py b/trio/_sync.py index 58f01c1970..ea9fcbc51e 100644 --- a/trio/_sync.py +++ b/trio/_sync.py @@ -5,7 +5,6 @@ import trio -from ._util import aiter_compat from ._core import enable_ki_protection, ParkingLot from ._deprecate import deprecated diff --git a/trio/_util.py b/trio/_util.py index d21669c855..135dc10465 100644 --- a/trio/_util.py +++ b/trio/_util.py @@ -68,24 +68,6 @@ def signal_raise(signum): signal.pthread_kill(threading.get_ident(), signum) -# Decorator to handle the change to __aiter__ in 3.5.2 -if sys.version_info < (3, 5, 2): - - def aiter_compat(aiter_impl): - # de-sugar decorator to fix Python 3.8 coverage issue - # https://github.com/python-trio/trio/pull/784#issuecomment-446438407 - async def __aiter__(*args, **kwargs): - return aiter_impl(*args, **kwargs) - - __aiter__ = wraps(aiter_impl)(__aiter__) - - return __aiter__ -else: - - def aiter_compat(aiter_impl): - return aiter_impl - - # See: #461 as to why this is needed. # The gist is that threading.main_thread() has the capability to lie to us # if somebody else edits the threading ident cache to replace the main From 4d8d173face5428a432802275f31fcee1f3c23ca Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:09:27 +0400 Subject: [PATCH 08/25] Assume enum.IntFlag exists now that Python 3.5 is gone --- trio/_core/_windows_cffi.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/trio/_core/_windows_cffi.py b/trio/_core/_windows_cffi.py index e2b95a9113..58845b86f4 100644 --- a/trio/_core/_windows_cffi.py +++ b/trio/_core/_windows_cffi.py @@ -1,10 +1,6 @@ import cffi import re import enum -try: - from enum import IntFlag -except ImportError: # python 3.5 - from enum import IntEnum as IntFlag ################################################################ # Functions and types @@ -264,7 +260,7 @@ class FileFlags(enum.IntEnum): TRUNCATE_EXISTING = 5 -class AFDPollFlags(IntFlag): +class AFDPollFlags(enum.IntFlag): # These are drawn from a combination of: # https://github.com/piscisaureus/wepoll/blob/master/src/afd.h # https://github.com/reactos/reactos/blob/master/sdk/include/reactos/drivers/afd/shared.h @@ -289,7 +285,7 @@ class WSAIoctls(enum.IntEnum): SIO_BSP_HANDLE_SELECT = 0x4800001C -class CompletionModes(IntFlag): +class CompletionModes(enum.IntFlag): FILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 0x1 FILE_SKIP_SET_EVENT_ON_HANDLE = 0x2 From 125d70d99cfc0bd04df666f372cee1871f119681 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:11:46 +0400 Subject: [PATCH 09/25] Remove unneeded filterwarnings now that Python 3.5 is gone --- trio/tests/test_exports.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/trio/tests/test_exports.py b/trio/tests/test_exports.py index a9b7179f5f..8257e4137d 100644 --- a/trio/tests/test_exports.py +++ b/trio/tests/test_exports.py @@ -59,10 +59,6 @@ def public_namespaces(module): # https://github.com/PyCQA/astroid/issues/681 "ignore:the imp module is deprecated.*:DeprecationWarning" ) -@pytest.mark.filterwarnings( - # Same as above, but on Python 3.5 - "ignore:the imp module is deprecated.*:PendingDeprecationWarning" -) @pytest.mark.parametrize("modname", NAMESPACES) @pytest.mark.parametrize("tool", ["pylint", "jedi"]) def test_static_tool_sees_all_symbols(tool, modname): From c54b70c1f5d3bb06b5aedf1111ca723391dace4b Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:32:35 +0400 Subject: [PATCH 10/25] Guarantee run_sync_soon ordering now that Python 3.5 is gone --- trio/_core/_entry_queue.py | 4 +--- trio/_core/tests/test_run.py | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/trio/_core/_entry_queue.py b/trio/_core/_entry_queue.py index ee20b6e562..6833cc886f 100644 --- a/trio/_core/_entry_queue.py +++ b/trio/_core/_entry_queue.py @@ -178,9 +178,7 @@ def run_sync_soon(self, sync_fn, *args, idempotent=False): If ``idempotent=True``, then ``sync_fn`` and ``args`` must be hashable, and Trio will make a best-effort attempt to discard any call submission which is equal to an already-pending call. Trio - will make an attempt to process these in first-in first-out order, - but no guarantees. (Currently processing is FIFO on CPython and - PyPy.) + will process these in first-in first-out order. Any ordering guarantees apply separately to ``idempotent=False`` and ``idempotent=True`` calls; there's no rule for how calls in the diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index e248139343..f7026081a5 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -1384,12 +1384,6 @@ def cb(x): for i in range(100): token.run_sync_soon(cb, i, idempotent=True) await wait_all_tasks_blocked() - if ( - sys.version_info < (3, 6) - and platform.python_implementation() == "CPython" - ): - # no order guarantees - record.sort() # Otherwise, we guarantee FIFO assert record == list(range(100)) From fac7da6d7ad896729578e3ba036db1870c88a306 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 11:50:32 +0400 Subject: [PATCH 11/25] Run yapf --- trio/tests/test_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trio/tests/test_util.py b/trio/tests/test_util.py index 5a5b189091..771c1c960e 100644 --- a/trio/tests/test_util.py +++ b/trio/tests/test_util.py @@ -8,8 +8,8 @@ import trio from .. import _core from .._util import ( - signal_raise, ConflictDetector, is_main_thread, generic_function, - Final, NoPublicConstructor + signal_raise, ConflictDetector, is_main_thread, generic_function, Final, + NoPublicConstructor ) from ..testing import wait_all_tasks_blocked, assert_checkpoints From c0a698829e70ea6c716cca6673eb106a45213383 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 13:56:56 +0400 Subject: [PATCH 12/25] Test an early Python 3.6 version in CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 756d472eb5..576f0b9ae5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ jobs: env: - "JOB_NAME='Ubuntu 19.10, full VM'" - "VM_IMAGE=https://cloud-images.ubuntu.com/eoan/current/eoan-server-cloudimg-amd64.img" + - python: 3.6.1 # earliest 3.6 version available on Travis - python: 3.6-dev - python: 3.7-dev - python: 3.8-dev From 3b319e6bf7163a1bc4532785f524bfc839f82003 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 14:41:08 +0400 Subject: [PATCH 13/25] Assume Python 3.6 socket/ssl constants exist Since we no longer support Python 3.5. --- trio/_deprecated_ssl_reexports.py | 9 ++------- trio/socket.py | 21 +++------------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/trio/_deprecated_ssl_reexports.py b/trio/_deprecated_ssl_reexports.py index f86077e3fe..35d22f49f4 100644 --- a/trio/_deprecated_ssl_reexports.py +++ b/trio/_deprecated_ssl_reexports.py @@ -15,15 +15,10 @@ cert_time_to_seconds, CertificateError, create_default_context, DER_cert_to_PEM_cert, get_default_verify_paths, match_hostname, PEM_cert_to_DER_cert, Purpose, SSLEOFError, SSLError, SSLSyscallError, - SSLZeroReturnError + SSLZeroReturnError, AlertDescription, SSLErrorNumber, SSLSession, + VerifyFlags, VerifyMode, Options ) -# Added in python 3.6 -try: - from ssl import AlertDescription, SSLErrorNumber, SSLSession, VerifyFlags, VerifyMode, Options # noqa -except ImportError: - pass - # Added in python 3.7 try: from ssl import SSLCertVerificationError, TLSVersion # noqa diff --git a/trio/socket.py b/trio/socket.py index 266fc0dbda..b5f6a4fdfe 100644 --- a/trio/socket.py +++ b/trio/socket.py @@ -137,26 +137,11 @@ # expose these functions to trio.socket from socket import ( - gaierror, - herror, - gethostname, - ntohs, - htonl, - htons, - inet_aton, - inet_ntoa, - inet_pton, - inet_ntop, + gaierror, herror, gethostname, ntohs, htonl, htons, inet_aton, inet_ntoa, + inet_pton, inet_ntop, sethostname, if_nameindex, if_nametoindex, + if_indextoname ) -# not always available so expose only if -try: - from socket import ( - sethostname, if_nameindex, if_nametoindex, if_indextoname - ) -except ImportError: - pass - if _sys.platform == 'win32': # See https://github.com/python-trio/trio/issues/39 # Do not import for windows platform From 60b812aba624cbfa337588fea71f68b8ce06101f Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 14:41:30 +0400 Subject: [PATCH 14/25] Silence pytest junit_family warning --- setup.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 0e814ba376..e692055f3e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,4 @@ [tool:pytest] xfail_strict = true -faulthandler_timeout=60 +faulthandler_timeout = 60 +junit_family = xunit2 From 4f3030f77ff908b412f81e17c04165dfa7a1620d Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:12:37 +0400 Subject: [PATCH 15/25] Assume SO_PROTOCOL and SO_DOMAIN exist on Linux Since we no longer support Python 3.5. --- trio/_socket.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/trio/_socket.py b/trio/_socket.py index fe9ca242c1..a3ffe0315f 100644 --- a/trio/_socket.py +++ b/trio/_socket.py @@ -295,13 +295,7 @@ def _sniff_sockopts_for_fileno(family, type, proto, fileno): # and then we'll throw it away and construct a new one with the correct metadata. if not _sys.platform == "linux": return family, type, proto - try: - from socket import SO_DOMAIN, SO_PROTOCOL - except ImportError: - # Only available on 3.6 and above: - SO_PROTOCOL = 38 - SO_DOMAIN = 39 - from socket import SOL_SOCKET, SO_TYPE + from socket import SO_DOMAIN, SO_PROTOCOL, SOL_SOCKET, SO_TYPE sockobj = _stdlib_socket.socket(family, type, proto, fileno=fileno) try: family = sockobj.getsockopt(SOL_SOCKET, SO_DOMAIN) From aef43c60c46cc721313b7196ede7b2ddcd3bfe3c Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:33:16 +0400 Subject: [PATCH 16/25] Replace "3.6 or earlier" with "3.6" Since we no longer support Python 3.5. --- trio/_core/_run.py | 4 ++-- trio/_util.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/trio/_core/_run.py b/trio/_core/_run.py index b5aae49a5b..9feb540d53 100644 --- a/trio/_core/_run.py +++ b/trio/_core/_run.py @@ -60,7 +60,7 @@ def _public(fn): # On 3.7+, Context.run() is implemented in C and doesn't show up in -# tracebacks. On 3.6 and earlier, we use the contextvars backport, which is +# tracebacks. On 3.6, we use the contextvars backport, which is # currently implemented in Python and adds 1 frame to tracebacks. So this # function is a super-overkill version of "0 if sys.version_info >= (3, 7) # else 1". But if Context.run ever changes, we'll be ready! @@ -1912,7 +1912,7 @@ def run_impl(runner, async_fn, args): try: # We used to unwrap the Outcome object here and send/throw its # contents in directly, but it turns out that .throw() is - # buggy, at least on CPython 3.6 and earlier: + # buggy, at least on CPython 3.6: # https://bugs.python.org/issue29587 # https://bugs.python.org/issue29590 # So now we send in the Outcome object and unwrap it on the diff --git a/trio/_util.py b/trio/_util.py index 135dc10465..088c4f8b37 100644 --- a/trio/_util.py +++ b/trio/_util.py @@ -188,7 +188,7 @@ def __getitem__(self, _): # If a new class inherits from any ABC, then the new class's metaclass has to # inherit from ABCMeta. If a new class inherits from typing.Generic, and -# you're using Python 3.6 or earlier, then the new class's metaclass has to +# you're using Python 3.6, then the new class's metaclass has to # inherit from typing.GenericMeta. Some of the classes that want to use Final # or NoPublicConstructor inherit from ABCs and generics, so Final has to # inherit from these metaclasses. Fortunately, GenericMeta inherits from From f56eca0a6af4c522198141e21ac419bbe694f4a7 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:34:00 +0400 Subject: [PATCH 17/25] Stop considering Python 3.5 SyntaxError --- trio/_core/tests/test_run.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index f7026081a5..f7e60c8264 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -2387,22 +2387,18 @@ def test_async_function_implemented_in_C(): # cr_frame, but C functions don't have Python frames. ns = {"_core": _core} - try: - exec( - dedent( - """ - async def agen_fn(record): - assert not _core.currently_ki_protected() - record.append("the generator ran") - yield - """ - ), - ns, - ) - except SyntaxError: - pytest.skip("Requires Python 3.6+") - else: - agen_fn = ns["agen_fn"] + exec( + dedent( + """ + async def agen_fn(record): + assert not _core.currently_ki_protected() + record.append("the generator ran") + yield + """ + ), + ns, + ) + agen_fn = ns["agen_fn"] run_record = [] agen = agen_fn(run_record) From bd8d1a0de6d77081abe7802845e6a90565a04c0e Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:43:28 +0400 Subject: [PATCH 18/25] Use native async generators now that Python 3.5 is gone --- trio/_core/tests/test_ki.py | 16 +++++----------- trio/_core/tests/test_run.py | 4 +--- trio/_util.py | 2 -- trio/testing/_sequencer.py | 5 ++--- trio/tests/test_ssl.py | 12 ++++-------- 5 files changed, 12 insertions(+), 27 deletions(-) diff --git a/trio/_core/tests/test_ki.py b/trio/_core/tests/test_ki.py index b64057c496..906ac3ab9a 100644 --- a/trio/_core/tests/test_ki.py +++ b/trio/_core/tests/test_ki.py @@ -7,9 +7,7 @@ import contextlib import time -from async_generator import ( - async_generator, yield_, isasyncgenfunction, asynccontextmanager -) +from async_generator import isasyncgenfunction, asynccontextmanager from ... import _core from ...testing import wait_all_tasks_blocked @@ -140,39 +138,35 @@ def protected_manager(): async def test_agen_protection(): @_core.enable_ki_protection - @async_generator async def agen_protected1(): assert _core.currently_ki_protected() try: - await yield_() + yield finally: assert _core.currently_ki_protected() @_core.disable_ki_protection - @async_generator async def agen_unprotected1(): assert not _core.currently_ki_protected() try: - await yield_() + yield finally: assert not _core.currently_ki_protected() # Swap the order of the decorators: - @async_generator @_core.enable_ki_protection async def agen_protected2(): assert _core.currently_ki_protected() try: - await yield_() + yield finally: assert _core.currently_ki_protected() - @async_generator @_core.disable_ki_protection async def agen_unprotected2(): assert not _core.currently_ki_protected() try: - await yield_() + yield finally: assert not _core.currently_ki_protected() diff --git a/trio/_core/tests/test_run.py b/trio/_core/tests/test_run.py index f7e60c8264..cc246cbdd7 100644 --- a/trio/_core/tests/test_run.py +++ b/trio/_core/tests/test_run.py @@ -14,7 +14,6 @@ import outcome import sniffio import pytest -from async_generator import async_generator from .tutil import slow, check_sequence_matches, gc_collect_harder from ... import _core @@ -1760,9 +1759,8 @@ def generator_based_coro(): # pragma: no cover bad_call(len, [1, 2, 3]) assert "appears to be synchronous" in str(excinfo.value) - @async_generator async def async_gen(arg): # pragma: no cover - pass + yield with pytest.raises(TypeError) as excinfo: bad_call(async_gen, 0) diff --git a/trio/_util.py b/trio/_util.py index 088c4f8b37..b50a58036e 100644 --- a/trio/_util.py +++ b/trio/_util.py @@ -9,8 +9,6 @@ import typing as t import threading -import async_generator - # There's a dependency loop here... _core is allowed to use this file (in fact # it's the *only* file in the main trio/ package it's allowed to use), but # ConflictDetector needs checkpoint so it also has to import diff --git a/trio/testing/_sequencer.py b/trio/testing/_sequencer.py index 118969f83d..05b7560eec 100644 --- a/trio/testing/_sequencer.py +++ b/trio/testing/_sequencer.py @@ -1,7 +1,7 @@ from collections import defaultdict import attr -from async_generator import async_generator, yield_, asynccontextmanager +from async_generator import asynccontextmanager from .. import _core from .. import _util @@ -61,7 +61,6 @@ async def main(): _broken = attr.ib(default=False, init=False) @asynccontextmanager - @async_generator async def __call__(self, position: int): if position in self._claimed: raise RuntimeError( @@ -84,6 +83,6 @@ async def __call__(self, position: int): if self._broken: raise RuntimeError("sequence broken!") try: - await yield_() + yield finally: self._sequence_points[position + 1].set() diff --git a/trio/tests/test_ssl.py b/trio/tests/test_ssl.py index 184b5b5c2a..2115e81702 100644 --- a/trio/tests/test_ssl.py +++ b/trio/tests/test_ssl.py @@ -8,7 +8,7 @@ from OpenSSL import SSL import trustme -from async_generator import async_generator, yield_, asynccontextmanager +from async_generator import asynccontextmanager import trio from .. import _core @@ -138,7 +138,6 @@ def ssl_echo_serve_sync(sock, *, expect_fail=False): # (running in a thread). Useful for testing making connections with different # SSLContexts. @asynccontextmanager -@async_generator async def ssl_echo_server_raw(**kwargs): a, b = stdlib_socket.socketpair() async with trio.open_nursery() as nursery: @@ -151,19 +150,16 @@ async def ssl_echo_server_raw(**kwargs): partial(ssl_echo_serve_sync, b, **kwargs) ) - await yield_(SocketStream(tsocket.from_stdlib_socket(a))) + yield SocketStream(tsocket.from_stdlib_socket(a)) # Fixture that gives a properly set up SSLStream connected to a trio-test-1 # echo server (running in a thread) @asynccontextmanager -@async_generator async def ssl_echo_server(client_ctx, **kwargs): async with ssl_echo_server_raw(**kwargs) as sock: - await yield_( - SSLStream( - sock, client_ctx, server_hostname="trio-test-1.example.org" - ) + yield SSLStream( + sock, client_ctx, server_hostname="trio-test-1.example.org" ) From dd185ab7d9c6a2886eb8934e64a0f5b57eb2c1c2 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:47:27 +0400 Subject: [PATCH 19/25] Remove unused test code --- trio/tests/test_util.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/trio/tests/test_util.py b/trio/tests/test_util.py index 771c1c960e..b45bfed425 100644 --- a/trio/tests/test_util.py +++ b/trio/tests/test_util.py @@ -1,7 +1,4 @@ -import os -import pathlib import signal -import sys import pytest @@ -11,7 +8,7 @@ signal_raise, ConflictDetector, is_main_thread, generic_function, Final, NoPublicConstructor ) -from ..testing import wait_all_tasks_blocked, assert_checkpoints +from ..testing import wait_all_tasks_blocked def raise_(exc): @@ -82,15 +79,6 @@ def test_module_metadata_is_fixed_up(): assert trio.to_thread.run_sync.__qualname__ == "run_sync" -class ConcretePathLike(os.PathLike): - """ Class implementing the file system path protocol.""" - def __init__(self, path=""): - self.path = path - - def __fspath__(self): - return self.path - - async def test_is_main_thread(): assert is_main_thread() From 1240e16fb8dc899d8412a7a609dd15de87d9b26f Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Wed, 5 Feb 2020 15:48:10 +0400 Subject: [PATCH 20/25] Fix socket imports to work on Windows --- trio/socket.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/trio/socket.py b/trio/socket.py index b5f6a4fdfe..266fc0dbda 100644 --- a/trio/socket.py +++ b/trio/socket.py @@ -137,11 +137,26 @@ # expose these functions to trio.socket from socket import ( - gaierror, herror, gethostname, ntohs, htonl, htons, inet_aton, inet_ntoa, - inet_pton, inet_ntop, sethostname, if_nameindex, if_nametoindex, - if_indextoname + gaierror, + herror, + gethostname, + ntohs, + htonl, + htons, + inet_aton, + inet_ntoa, + inet_pton, + inet_ntop, ) +# not always available so expose only if +try: + from socket import ( + sethostname, if_nameindex, if_nametoindex, if_indextoname + ) +except ImportError: + pass + if _sys.platform == 'win32': # See https://github.com/python-trio/trio/issues/39 # Do not import for windows platform From ec3f30dfb0008a8f640dc15f0fcee59a227c5b85 Mon Sep 17 00:00:00 2001 From: Kyle Lawlor Date: Sat, 15 Feb 2020 17:50:37 -0500 Subject: [PATCH 21/25] switch from 3.5 compatible fspath helper to os.fspath --- trio/_highlevel_open_unix_stream.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trio/_highlevel_open_unix_stream.py b/trio/_highlevel_open_unix_stream.py index 59141ebc38..08eef0c135 100644 --- a/trio/_highlevel_open_unix_stream.py +++ b/trio/_highlevel_open_unix_stream.py @@ -1,3 +1,4 @@ +import os from contextlib import contextmanager import trio @@ -44,6 +45,6 @@ async def open_unix_socket(filename,): # possible location to connect to sock = socket(AF_UNIX, SOCK_STREAM) with close_on_error(sock): - await sock.connect(trio._util.fspath(filename)) + await sock.connect(os.fspath(filename)) return trio.SocketStream(sock) From 435f2fb5b0a9f77b04ccfce51d523adc5b4be0c6 Mon Sep 17 00:00:00 2001 From: Kyle Lawlor Date: Sat, 15 Feb 2020 18:37:09 -0500 Subject: [PATCH 22/25] add a deprecation warning for python3.5 --- trio/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/trio/__init__.py b/trio/__init__.py index 6e9035d8fd..019323f53c 100644 --- a/trio/__init__.py +++ b/trio/__init__.py @@ -64,7 +64,7 @@ open_ssl_over_tcp_stream, open_ssl_over_tcp_listeners, serve_ssl_over_tcp ) -from ._deprecate import TrioDeprecationWarning +from ._deprecate import TrioDeprecationWarning, warn_deprecated # Submodules imported by default from . import hazmat @@ -170,3 +170,8 @@ __name__ + ".subprocess", _deprecated_subprocess_reexports.__dict__ ) del fixup_module_metadata + +import sys +if sys.version_info < (3, 6): + _deprecate.warn_deprecated("Support for Python 3.5", "0.14", issue=75, instead="Python 3.6+") +del sys From ee5f2c09cffb79bdcc6214fcd157d4d786b5f35d Mon Sep 17 00:00:00 2001 From: Kyle Lawlor Date: Wed, 19 Feb 2020 10:48:20 -0500 Subject: [PATCH 23/25] Revert "add a deprecation warning for python3.5" This reverts commit 435f2fb5b0a9f77b04ccfce51d523adc5b4be0c6. --- trio/__init__.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/trio/__init__.py b/trio/__init__.py index 019323f53c..6e9035d8fd 100644 --- a/trio/__init__.py +++ b/trio/__init__.py @@ -64,7 +64,7 @@ open_ssl_over_tcp_stream, open_ssl_over_tcp_listeners, serve_ssl_over_tcp ) -from ._deprecate import TrioDeprecationWarning, warn_deprecated +from ._deprecate import TrioDeprecationWarning # Submodules imported by default from . import hazmat @@ -170,8 +170,3 @@ __name__ + ".subprocess", _deprecated_subprocess_reexports.__dict__ ) del fixup_module_metadata - -import sys -if sys.version_info < (3, 6): - _deprecate.warn_deprecated("Support for Python 3.5", "0.14", issue=75, instead="Python 3.6+") -del sys From 542025ab435a4a1ffcace171df669a90b39ba2cb Mon Sep 17 00:00:00 2001 From: Kyle Lawlor Date: Wed, 19 Feb 2020 10:50:18 -0500 Subject: [PATCH 24/25] Revert "Assume SO_PROTOCOL and SO_DOMAIN exist on Linux" This reverts commit 4f3030f77ff908b412f81e17c04165dfa7a1620d. --- trio/_socket.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/trio/_socket.py b/trio/_socket.py index a3ffe0315f..fe9ca242c1 100644 --- a/trio/_socket.py +++ b/trio/_socket.py @@ -295,7 +295,13 @@ def _sniff_sockopts_for_fileno(family, type, proto, fileno): # and then we'll throw it away and construct a new one with the correct metadata. if not _sys.platform == "linux": return family, type, proto - from socket import SO_DOMAIN, SO_PROTOCOL, SOL_SOCKET, SO_TYPE + try: + from socket import SO_DOMAIN, SO_PROTOCOL + except ImportError: + # Only available on 3.6 and above: + SO_PROTOCOL = 38 + SO_DOMAIN = 39 + from socket import SOL_SOCKET, SO_TYPE sockobj = _stdlib_socket.socket(family, type, proto, fileno=fileno) try: family = sockobj.getsockopt(SOL_SOCKET, SO_DOMAIN) From 137673b65bc7a22f94dd56f77a8a0aba27bd3545 Mon Sep 17 00:00:00 2001 From: Kyle Lawlor Date: Wed, 19 Feb 2020 11:28:11 -0500 Subject: [PATCH 25/25] add comment to explain manual setting of SO_* constants --- trio/_socket.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/trio/_socket.py b/trio/_socket.py index fe9ca242c1..9e7a37abca 100644 --- a/trio/_socket.py +++ b/trio/_socket.py @@ -298,7 +298,9 @@ def _sniff_sockopts_for_fileno(family, type, proto, fileno): try: from socket import SO_DOMAIN, SO_PROTOCOL except ImportError: - # Only available on 3.6 and above: + # pypy does not expose these constants so we need to set these manually. + # when the following upstream issue is resolved we can remove these: + # https://foss.heptapod.net/pypy/pypy/issues/3171 SO_PROTOCOL = 38 SO_DOMAIN = 39 from socket import SOL_SOCKET, SO_TYPE