Drop Python 3.5/3.6 support (#383)

Fixes #381
This commit is contained in:
Fantix King 2021-01-24 19:59:20 -06:00 committed by GitHub
parent e21ceea0f0
commit cdd2218fa3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 120 additions and 487 deletions

View File

@ -72,7 +72,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
python-version: [3.7, 3.8, 3.9]
os: [ubuntu-20.04, macos-latest]
arch: [x86_64, aarch64]
exclude:

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
python-version: [3.7, 3.8, 3.9]
os: [ubuntu-latest, macos-latest]
steps:

View File

@ -39,7 +39,7 @@ about it.
Installation
------------
uvloop requires Python 3.5 or greater and is available on PyPI.
uvloop requires Python 3.7 or greater and is available on PyPI.
Use pip to install it::
$ pip install uvloop
@ -72,7 +72,7 @@ manually creating an asyncio event loop:
Building From Source
--------------------
To build uvloop, you'll need Python 3.5 or greater:
To build uvloop, you'll need Python 3.7 or greater:
1. Clone the repository:

View File

@ -28,7 +28,7 @@ from the `libuv` Github repository.
Build
-----
To build `uvloop`, you'll need ``Cython`` and Python 3.5.
To build `uvloop`, you'll need ``Cython`` and Python 3.7.
.. note::

View File

@ -14,7 +14,7 @@ uvloop
`uvloop` is a fast, drop-in replacement of the built-in asyncio event loop.
`uvloop` is released under the MIT license.
`uvloop` and asyncio, combined with the power of async/await in Python 3.5,
`uvloop` and asyncio, combined with the power of async/await in Python 3.7,
makes it easier than ever to write high-performance networking code in Python.
`uvloop` makes asyncio fast. In fact, it is at least 2x faster than nodejs,

View File

@ -8,7 +8,7 @@ uvloop.
Installation
------------
`uvloop` is available from PyPI. It requires Python 3.5.
`uvloop` is available from PyPI. It requires Python 3.7.
Use pip to install it.

View File

@ -1,11 +1,8 @@
import sys
vi = sys.version_info
if vi < (3, 5):
raise RuntimeError('uvloop requires Python 3.5 or greater')
if vi[:2] == (3, 6):
if vi.releaselevel == 'beta' and vi.serial < 3:
raise RuntimeError('uvloop requires Python 3.5 or 3.6b3 or greater')
if vi < (3, 7):
raise RuntimeError('uvloop requires Python 3.7 or greater')
if sys.platform in ('win32', 'cygwin', 'cli'):
raise RuntimeError('uvloop does not support Windows at the moment')
@ -310,8 +307,6 @@ setup(
'Development Status :: 5 - Production/Stable',
'Framework :: AsyncIO',
'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',
'Programming Language :: Python :: 3.9',

View File

@ -345,9 +345,6 @@ class _TestBase:
self.loop.run_until_complete(foo())
def test_run_until_complete_loop_orphan_future_close_loop(self):
if self.implementation == 'asyncio' and sys.version_info < (3, 6, 2):
raise unittest.SkipTest('unfixed asyncio')
async def foo(delay):
await asyncio.sleep(delay)
@ -463,9 +460,7 @@ class _TestBase:
self.loop.set_debug(True)
if hasattr(self.loop, 'get_exception_handler'):
# Available since Python 3.5.2
self.assertIsNone(self.loop.get_exception_handler())
self.assertIsNone(self.loop.get_exception_handler())
self.loop.set_exception_handler(handler)
if hasattr(self.loop, 'get_exception_handler'):
self.assertIs(self.loop.get_exception_handler(), handler)
@ -582,31 +577,19 @@ class _TestBase:
self.loop.set_task_factory(None)
self.assertIsNone(self.loop.get_task_factory())
def _compile_agen(self, src):
try:
g = {}
exec(src, globals(), g)
except SyntaxError:
# Python < 3.6
raise unittest.SkipTest()
else:
return g['waiter']
def test_shutdown_asyncgens_01(self):
finalized = list()
if not hasattr(self.loop, 'shutdown_asyncgens'):
raise unittest.SkipTest()
waiter = self._compile_agen(
'''async def waiter(timeout, finalized):
try:
await asyncio.sleep(timeout)
yield 1
finally:
await asyncio.sleep(0)
finalized.append(1)
''')
async def waiter(timeout, finalized):
try:
await asyncio.sleep(timeout)
yield 1
finally:
await asyncio.sleep(0)
finalized.append(1)
async def wait():
async for _ in waiter(1, finalized):
@ -641,13 +624,12 @@ class _TestBase:
self.assertIn('asyncgen', context)
logged += 1
waiter = self._compile_agen('''async def waiter(timeout):
async def waiter(timeout):
try:
await asyncio.sleep(timeout)
yield 1
finally:
1 / 0
''')
async def wait():
async for _ in waiter(1):
@ -669,10 +651,9 @@ class _TestBase:
if not hasattr(self.loop, 'shutdown_asyncgens'):
raise unittest.SkipTest()
waiter = self._compile_agen('''async def waiter():
async def waiter():
yield 1
yield 2
''')
async def foo():
# We specifically want to hit _asyncgen_finalizer_hook

View File

@ -1,19 +1,14 @@
import asyncio
import contextvars
import decimal
import random
import sys
import unittest
import weakref
from uvloop import _testbase as tb
PY37 = sys.version_info >= (3, 7, 0)
class _ContextBaseTests:
@unittest.skipUnless(PY37, 'requires Python 3.7')
def test_task_decimal_context(self):
async def fractions(t, precision, x, y):
with decimal.localcontext() as ctx:
@ -37,9 +32,7 @@ class _ContextBaseTests:
self.assertEqual(str(r2[0]), '0.333333')
self.assertEqual(str(r2[1]), '0.111111')
@unittest.skipUnless(PY37, 'requires Python 3.7')
def test_task_context_1(self):
import contextvars
cvar = contextvars.ContextVar('cvar', default='nope')
async def sub():
@ -58,9 +51,7 @@ class _ContextBaseTests:
task = self.loop.create_task(main())
self.loop.run_until_complete(task)
@unittest.skipUnless(PY37, 'requires Python 3.7')
def test_task_context_2(self):
import contextvars
cvar = contextvars.ContextVar('cvar', default='nope')
async def main():
@ -90,9 +81,7 @@ class _ContextBaseTests:
self.assertEqual(cvar.get(), 'nope')
@unittest.skipUnless(PY37, 'requires Python 3.7')
def test_task_context_3(self):
import contextvars
cvar = contextvars.ContextVar('cvar', default=-1)
# Run 100 Tasks in parallel, each modifying cvar.
@ -115,9 +104,7 @@ class _ContextBaseTests:
self.assertEqual(cvar.get(), -1)
@unittest.skipUnless(PY37, 'requires Python 3.7')
def test_task_context_4(self):
import contextvars
cvar = contextvars.ContextVar('cvar', default='nope')
class TrackMe:
@ -141,23 +128,7 @@ class _ContextBaseTests:
class Test_UV_Context(_ContextBaseTests, tb.UVTestCase):
@unittest.skipIf(PY37, 'requires Python <3.6')
def test_context_arg(self):
def cb():
pass
with self.assertRaisesRegex(NotImplementedError,
'requires Python 3.7'):
self.loop.call_soon(cb, context=1)
with self.assertRaisesRegex(NotImplementedError,
'requires Python 3.7'):
self.loop.call_soon_threadsafe(cb, context=1)
with self.assertRaisesRegex(NotImplementedError,
'requires Python 3.7'):
self.loop.call_later(0.1, cb, context=1)
pass
class Test_AIO_Context(_ContextBaseTests, tb.AIOTestCase):

View File

@ -21,10 +21,6 @@ class _TestSockets:
return buf
def test_socket_connect_recv_send(self):
if self.is_asyncio_loop() and sys.version_info[:3] == (3, 5, 2):
# See https://github.com/python/asyncio/pull/366 for details.
raise unittest.SkipTest()
if sys.version_info[:3] >= (3, 8, 0):
# @asyncio.coroutine is deprecated in 3.8
raise unittest.SkipTest()

View File

@ -10,8 +10,6 @@ def find_uvloop_root():
class TestFlake8(unittest.TestCase):
@unittest.skipIf(sys.version_info < (3, 6, 0),
"flake8 under 3.5 does not recognize f-strings in *.pyx")
def test_flake8(self):
edgepath = find_uvloop_root()
config_path = os.path.join(edgepath, '.flake8')

View File

@ -5,7 +5,6 @@ import os
import select
import socket
import unittest.mock
import uvloop
import ssl
import sys
import threading
@ -55,10 +54,6 @@ class MyBaseProto(asyncio.Protocol):
class _TestTCP:
def test_create_server_1(self):
if self.is_asyncio_loop() and sys.version_info[:3] == (3, 5, 2):
# See https://github.com/python/asyncio/pull/366 for details.
raise unittest.SkipTest()
CNT = 0 # number of clients that were successful
TOTAL_CNT = 25 # total number of clients that test will create
TIMEOUT = 5.0 # timeout for this test
@ -118,21 +113,14 @@ class _TestTCP:
nonlocal CNT
CNT = 0
addrs = ('127.0.0.1', 'localhost')
if not isinstance(self.loop, uvloop.Loop):
# Hack to let tests run on Python 3.5.0
# (asyncio doesn't support multiple hosts in 3.5.0)
addrs = '127.0.0.1'
srv = await asyncio.start_server(
handle_client,
addrs, 0,
('127.0.0.1', 'localhost'), 0,
family=socket.AF_INET)
srv_socks = srv.sockets
self.assertTrue(srv_socks)
if self.has_start_serving():
self.assertTrue(srv.is_serving())
self.assertTrue(srv.is_serving())
addr = srv_socks[0].getsockname()
@ -149,8 +137,7 @@ class _TestTCP:
for srv_sock in srv_socks:
self.assertEqual(srv_sock.fileno(), -1)
if self.has_start_serving():
self.assertFalse(srv.is_serving())
self.assertFalse(srv.is_serving())
async def start_server_sock():
nonlocal CNT
@ -166,13 +153,11 @@ class _TestTCP:
family=socket.AF_INET,
sock=sock)
if self.PY37:
self.assertIs(srv.get_loop(), self.loop)
self.assertIs(srv.get_loop(), self.loop)
srv_socks = srv.sockets
self.assertTrue(srv_socks)
if self.has_start_serving():
self.assertTrue(srv.is_serving())
self.assertTrue(srv.is_serving())
tasks = []
for _ in range(TOTAL_CNT):
@ -187,8 +172,7 @@ class _TestTCP:
for srv_sock in srv_socks:
self.assertEqual(srv_sock.fileno(), -1)
if self.has_start_serving():
self.assertFalse(srv.is_serving())
self.assertFalse(srv.is_serving())
self.loop.run_until_complete(start_server())
self.assertEqual(CNT, TOTAL_CNT)
@ -213,8 +197,7 @@ class _TestTCP:
srv_socks = srv.sockets
self.assertTrue(srv_socks)
if self.has_start_serving():
self.assertTrue(srv.is_serving())
self.assertTrue(srv.is_serving())
host, port = srv_socks[0].getsockname()
self.assertNotEqual(0, port)
@ -226,8 +209,7 @@ class _TestTCP:
for srv_sock in srv_socks:
self.assertEqual(srv_sock.fileno(), -1)
if self.has_start_serving():
self.assertFalse(srv.is_serving())
self.assertFalse(srv.is_serving())
self.loop.run_until_complete(start_server_ephemeral_ports())
@ -267,11 +249,6 @@ class _TestTCP:
raise unittest.SkipTest(
'The system does not support SO_REUSEPORT')
if sys.version_info[:3] < (3, 5, 1):
raise unittest.SkipTest(
'asyncio in CPython 3.5.0 does not have the '
'reuse_port argument')
port = tb.find_free_port()
async def runner():
@ -338,9 +315,6 @@ class _TestTCP:
self.loop.run_until_complete(test())
def test_create_server_8(self):
if self.implementation == 'asyncio' and not self.PY37:
raise unittest.SkipTest()
with self.assertRaisesRegex(
ValueError, 'ssl_handshake_timeout is only meaningful'):
self.loop.run_until_complete(
@ -348,9 +322,6 @@ class _TestTCP:
lambda: None, host='::', port=0, ssl_handshake_timeout=10))
def test_create_server_9(self):
if not self.has_start_serving():
raise unittest.SkipTest()
async def handle_client(reader, writer):
pass
@ -375,9 +346,6 @@ class _TestTCP:
self.loop.run_until_complete(start_server())
def test_create_server_10(self):
if not self.has_start_serving():
raise unittest.SkipTest()
async def handle_client(reader, writer):
pass
@ -578,9 +546,6 @@ class _TestTCP:
self.loop.run_until_complete(client(srv.addr))
def test_create_connection_6(self):
if self.implementation == 'asyncio' and not self.PY37:
raise unittest.SkipTest()
with self.assertRaisesRegex(
ValueError, 'ssl_handshake_timeout is only meaningful'):
self.loop.run_until_complete(
@ -1093,9 +1058,6 @@ class Test_UV_TCP(_TestTCP, tb.UVTestCase):
self.loop.run_until_complete(srv.wait_closed())
def test_connect_accepted_socket_ssl_args(self):
if self.implementation == 'asyncio' and not self.PY37:
raise unittest.SkipTest()
with self.assertRaisesRegex(
ValueError, 'ssl_handshake_timeout is only meaningful'):
with socket.socket() as s:
@ -1152,7 +1114,7 @@ class Test_UV_TCP(_TestTCP, tb.UVTestCase):
proto.loop = loop
extras = {}
if server_ssl and (self.implementation != 'asyncio' or self.PY37):
if server_ssl:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
f = loop.create_task(
@ -1318,9 +1280,7 @@ class _TestSSL(tb.SSLTestCase):
await fut
async def start_server():
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
srv = await asyncio.start_server(
handle_client,
@ -1383,9 +1343,7 @@ class _TestSSL(tb.SSLTestCase):
sock.close()
async def client(addr):
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
reader, writer = await asyncio.open_connection(
*addr,
@ -1517,10 +1475,7 @@ class _TestSSL(tb.SSLTestCase):
max_clients=1,
backlog=1) as srv:
exc_type = ssl.SSLError
if self.PY37:
exc_type = ssl.SSLCertVerificationError
with self.assertRaises(exc_type):
with self.assertRaises(ssl.SSLCertVerificationError):
self.loop.run_until_complete(client(srv.addr))
def test_start_tls_wrong_args(self):
@ -2190,9 +2145,7 @@ class _TestSSL(tb.SSLTestCase):
await fut
async def start_server():
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
srv = await self.loop.create_server(
server_protocol_factory,
@ -2282,9 +2235,7 @@ class _TestSSL(tb.SSLTestCase):
conn.shutdown()
async def client(addr):
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
reader, writer = await asyncio.open_connection(
*addr,
@ -2408,9 +2359,7 @@ class _TestSSL(tb.SSLTestCase):
await fut
async def start_server():
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras['ssl_handshake_timeout'] = SSL_HANDSHAKE_TIMEOUT
extras = {'ssl_handshake_timeout': SSL_HANDSHAKE_TIMEOUT}
if self.implementation != 'asyncio': # or self.PY38
extras['ssl_shutdown_timeout'] = 0.5
@ -2473,9 +2422,7 @@ class _TestSSL(tb.SSLTestCase):
sock.close()
async def client(addr):
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
extras = dict(ssl_handshake_timeout=SSL_HANDSHAKE_TIMEOUT)
reader, writer = await asyncio.open_connection(
*addr,

View File

@ -64,8 +64,7 @@ class _TestUDP:
self.assertIs(server.transport, s_transport)
extra = {}
if hasattr(socket, 'SO_REUSEPORT') and \
sys.version_info[:3] >= (3, 5, 1):
if hasattr(socket, 'SO_REUSEPORT'):
extra['reuse_port'] = True
coro = self.loop.create_datagram_endpoint(
@ -179,21 +178,13 @@ class _TestUDP:
assert False, 'Can not create socket.'
with sock:
try:
f = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop), sock=sock)
except TypeError as ex:
# asyncio in 3.5.0 doesn't have the 'sock' argument
if 'got an unexpected keyword argument' not in ex.args[0]:
raise
else:
tr, pr = self.loop.run_until_complete(f)
self.assertIsInstance(pr, MyDatagramProto)
tr.close()
self.loop.run_until_complete(pr.done)
f = self.loop.create_datagram_endpoint(
lambda: MyDatagramProto(loop=self.loop), sock=sock)
tr, pr = self.loop.run_until_complete(f)
self.assertIsInstance(pr, MyDatagramProto)
tr.close()
self.loop.run_until_complete(pr.done)
@unittest.skipIf(sys.version_info < (3, 5, 1),
"asyncio in 3.5.0 doesn't have the 'sock' argument")
def test_create_datagram_endpoint_sock_unix_domain(self):
class Proto(asyncio.DatagramProtocol):
@ -295,38 +286,32 @@ class _TestUDP:
s1, s2 = socket.socketpair(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
with s1, s2:
try:
f = self.loop.create_datagram_endpoint(
lambda: Proto(loop=self.loop), sock=s1)
except TypeError as ex:
# asyncio in 3.5.0 doesn't have the 'sock' argument
if 'got an unexpected keyword argument' not in ex.args[0]:
raise
f = self.loop.create_datagram_endpoint(
lambda: Proto(loop=self.loop), sock=s1)
tr, pr = self.loop.run_until_complete(f)
self.assertIsInstance(pr, Proto)
s2.send(b'hello, socketpair')
addr = self.loop.run_until_complete(
asyncio.wait_for(peername, 1))
if sys.platform.startswith('linux'):
self.assertEqual(addr, None)
else:
tr, pr = self.loop.run_until_complete(f)
self.assertIsInstance(pr, Proto)
self.assertEqual(addr, '')
self.assertEqual(pr.nbytes, 17)
s2.send(b'hello, socketpair')
addr = self.loop.run_until_complete(
asyncio.wait_for(peername, 1))
if sys.platform.startswith('linux'):
self.assertEqual(addr, None)
else:
self.assertEqual(addr, '')
self.assertEqual(pr.nbytes, 17)
if not self.is_asyncio_loop():
# asyncio doesn't support sendto(xx) on UDP sockets
# https://git.io/Jfqbw
data = b'from uvloop'
tr.sendto(data)
result = self.loop.run_until_complete(asyncio.wait_for(
self.loop.run_in_executor(None, s2.recv, 1024),
1))
self.assertEqual(data, result)
if not self.is_asyncio_loop():
# asyncio doesn't support sendto(xx) on UDP sockets
# https://git.io/Jfqbw
data = b'from uvloop'
tr.sendto(data)
result = self.loop.run_until_complete(asyncio.wait_for(
self.loop.run_in_executor(None, s2.recv, 1024),
1))
self.assertEqual(data, result)
tr.close()
self.loop.run_until_complete(pr.done)
tr.close()
self.loop.run_until_complete(pr.done)
def _skip_create_datagram_endpoint_reuse_addr(self):
if self.implementation == 'asyncio':
@ -336,8 +321,6 @@ class _TestUDP:
raise unittest.SkipTest()
if (3, 7, 0) <= sys.version_info < (3, 7, 6):
raise unittest.SkipTest()
if sys.version_info < (3, 6, 10):
raise unittest.SkipTest()
def test_create_datagram_endpoint_reuse_address_error(self):
# bpo-37228: Ensure that explicit passing of `reuse_address=True`
@ -418,8 +401,8 @@ class Test_UV_UDP(_TestUDP, tb.UVTestCase):
class Test_AIO_UDP(_TestUDP, tb.AIOTestCase):
@unittest.skipUnless(tb.has_IPv6, 'no IPv6')
@unittest.skipIf(
sys.version_info[:3] < (3, 6, 7) or sys.version_info[:3] == (3, 7, 0),
'bpo-27500: bug fixed in Python 3.6.7, 3.7.1 and above.',
sys.version_info[:3] == (3, 7, 0),
'bpo-27500: bug fixed in Python 3.7.1 and above.',
)
def test_create_datagram_endpoint_addrs_ipv6(self):
self._test_create_datagram_endpoint_addrs_ipv6()

View File

@ -66,8 +66,7 @@ class _TestUnix:
try:
srv_socks = srv.sockets
self.assertTrue(srv_socks)
if self.has_start_serving():
self.assertTrue(srv.is_serving())
self.assertTrue(srv.is_serving())
tasks = []
for _ in range(TOTAL_CNT):
@ -83,8 +82,7 @@ class _TestUnix:
for srv_sock in srv_socks:
self.assertEqual(srv_sock.fileno(), -1)
if self.has_start_serving():
self.assertFalse(srv.is_serving())
self.assertFalse(srv.is_serving())
# asyncio doesn't cleanup the sock file
self.assertTrue(os.path.exists(sock_name))
@ -103,8 +101,7 @@ class _TestUnix:
try:
srv_socks = srv.sockets
self.assertTrue(srv_socks)
if self.has_start_serving():
self.assertTrue(srv.is_serving())
self.assertTrue(srv.is_serving())
tasks = []
for _ in range(TOTAL_CNT):
@ -120,8 +117,7 @@ class _TestUnix:
for srv_sock in srv_socks:
self.assertEqual(srv_sock.fileno(), -1)
if self.has_start_serving():
self.assertFalse(srv.is_serving())
self.assertFalse(srv.is_serving())
# asyncio doesn't cleanup the sock file
self.assertTrue(os.path.exists(sock_name))
@ -160,9 +156,6 @@ class _TestUnix:
self.loop.create_unix_server(object, sock_name))
def test_create_unix_server_3(self):
if self.implementation == 'asyncio' and not self.PY37:
raise unittest.SkipTest()
with self.assertRaisesRegex(
ValueError, 'ssl_handshake_timeout is only meaningful'):
self.loop.run_until_complete(
@ -371,30 +364,12 @@ class _TestUnix:
(BrokenPipeError, ConnectionResetError))
def test_create_unix_connection_6(self):
if self.implementation == 'asyncio' and not self.PY37:
raise unittest.SkipTest()
with self.assertRaisesRegex(
ValueError, 'ssl_handshake_timeout is only meaningful'):
self.loop.run_until_complete(
self.loop.create_unix_connection(
lambda: None, path='/tmp/a', ssl_handshake_timeout=10))
@unittest.skipUnless(sys.version_info < (3, 7),
'Python version must be < 3.7')
def test_transport_unclosed_warning(self):
async def test(sock):
return await self.loop.create_unix_connection(
asyncio.Protocol,
None,
sock=sock)
with self.assertWarnsRegex(ResourceWarning, 'unclosed'):
s1, s2 = socket.socketpair(socket.AF_UNIX)
with s1, s2:
self.loop.run_until_complete(test(s1))
self.loop.close()
class Test_UV_Unix(_TestUnix, tb.UVTestCase):
@ -592,9 +567,7 @@ class _TestSSL(tb.SSLTestCase):
await fut
async def start_server():
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=10.0)
extras = dict(ssl_handshake_timeout=10.0)
with tempfile.TemporaryDirectory() as td:
sock_name = os.path.join(td, 'sock')
@ -655,9 +628,7 @@ class _TestSSL(tb.SSLTestCase):
sock.close()
async def client(addr):
extras = {}
if self.implementation != 'asyncio' or self.PY37:
extras = dict(ssl_handshake_timeout=10.0)
extras = dict(ssl_handshake_timeout=10.0)
reader, writer = await asyncio.open_unix_connection(
addr,

View File

@ -3,7 +3,6 @@ import asyncio as __asyncio
from asyncio.events import BaseDefaultEventLoopPolicy as __BasePolicy
from . import includes as __includes # NOQA
from . import _patch # NOQA
from .loop import Loop as __BaseLoop # NOQA
from ._version import __version__ # NOQA

View File

@ -1,70 +0,0 @@
import asyncio
import sys
def _format_coroutine(coro):
if asyncio.iscoroutine(coro) \
and not hasattr(coro, 'cr_code') \
and not hasattr(coro, 'gi_code'):
# Most likely a Cython coroutine
coro_name = '{}()'.format(coro.__qualname__ or coro.__name__)
running = False
try:
running = coro.cr_running
except AttributeError:
try:
running = coro.gi_running
except AttributeError:
pass
if running:
return '{} running'.format(coro_name)
else:
return coro_name
return _old_format_coroutine(coro)
async def _wait_for_data(self, func_name):
"""Wait until feed_data() or feed_eof() is called.
If stream was paused, automatically resume it.
"""
if self._waiter is not None:
raise RuntimeError('%s() called while another coroutine is '
'already waiting for incoming data' % func_name)
assert not self._eof, '_wait_for_data after EOF'
# Waiting for data while paused will make deadlock, so prevent it.
if self._paused:
self._paused = False
self._transport.resume_reading()
try:
create_future = self._loop.create_future
except AttributeError:
self._waiter = asyncio.Future(loop=self._loop)
else:
self._waiter = create_future()
try:
await self._waiter
finally:
self._waiter = None
if sys.version_info < (3, 5, 3):
# This is needed to support Cython 'async def' coroutines.
from asyncio import coroutines
_old_format_coroutine = coroutines._format_coroutine
coroutines._format_coroutine = _format_coroutine
if sys.version_info < (3, 5, 2):
# Fix a possible deadlock, improve performance.
from asyncio import streams
_old_wait_for_data = streams.StreamReader._wait_for_data
_wait_for_data.__module__ = _old_wait_for_data.__module__
streams.StreamReader._wait_for_data = _wait_for_data

View File

@ -13,7 +13,6 @@ import re
import select
import socket
import ssl
import sys
import tempfile
import threading
import time
@ -73,15 +72,10 @@ class BaseTestCase(unittest.TestCase, metaclass=BaseTestCaseMeta):
async def wait_closed(self, obj):
if not isinstance(obj, asyncio.StreamWriter):
return
if sys.version_info >= (3, 7, 0):
try:
await obj.wait_closed()
except (BrokenPipeError, ConnectionError):
pass
def has_start_serving(self):
return not (self.is_asyncio_loop() and
sys.version_info[:2] in [(3, 5), (3, 6)])
try:
await obj.wait_closed()
except (BrokenPipeError, ConnectionError):
pass
def is_asyncio_loop(self):
return type(self.loop).__module__.startswith('asyncio.')
@ -102,9 +96,6 @@ class BaseTestCase(unittest.TestCase, metaclass=BaseTestCaseMeta):
self.loop.set_exception_handler(self.loop_exception_handler)
self.__unhandled_exceptions = []
self.PY37 = sys.version_info[:2] >= (3, 7)
self.PY36 = sys.version_info[:2] >= (3, 6)
def tearDown(self):
self.loop.close()

View File

@ -15,15 +15,9 @@ cdef class Handle:
self._source_traceback = extract_stack()
cdef inline _set_context(self, object context):
if PY37:
if context is None:
context = Context_CopyCurrent()
self.context = context
else:
if context is not None:
raise NotImplementedError(
'"context" argument requires Python 3.7')
self.context = None
if context is None:
context = Context_CopyCurrent()
self.context = context
def __dealloc__(self):
if UVLOOP_DEBUG and self.loop is not None:
@ -52,9 +46,8 @@ cdef class Handle:
Py_INCREF(self)
try:
if PY37:
assert self.context is not None
Context_Enter(self.context)
assert self.context is not None
Context_Enter(self.context)
if cb_type == 1:
callback = self.arg1
@ -108,8 +101,7 @@ cdef class Handle:
finally:
context = self.context
Py_DECREF(self)
if PY37:
Context_Exit(context)
Context_Exit(context)
cdef _cancel(self):
self._cancelled = 1
@ -185,15 +177,9 @@ cdef class TimerHandle:
self.loop._debug_cb_timer_handles_total += 1
self.loop._debug_cb_timer_handles_count += 1
if PY37:
if context is None:
context = Context_CopyCurrent()
self.context = context
else:
if context is not None:
raise NotImplementedError(
'"context" argument requires Python 3.7')
self.context = None
if context is None:
context = Context_CopyCurrent()
self.context = context
if loop._debug:
self._debug_info = (
@ -257,9 +243,8 @@ cdef class TimerHandle:
if self.loop._debug:
started = time_monotonic()
try:
if PY37:
assert self.context is not None
Context_Enter(self.context)
assert self.context is not None
Context_Enter(self.context)
if args is not None:
callback(*args)
@ -288,8 +273,7 @@ cdef class TimerHandle:
finally:
context = self.context
Py_DECREF(self)
if PY37:
Context_Exit(context)
Context_Exit(context)
self._clear()
# Public API

View File

@ -252,14 +252,7 @@ cdef class UVProcess(UVHandle):
self.options.flags |= uv.UV_PROCESS_DETACHED
if cwd is not None:
try:
# Lookup __fspath__ manually, as os.fspath() isn't
# available on Python 3.5.
fspath = type(cwd).__fspath__
except AttributeError:
pass
else:
cwd = fspath(cwd)
cwd = os_fspath(cwd)
if isinstance(cwd, str):
cwd = PyUnicode_EncodeFSDefault(cwd)
@ -283,14 +276,7 @@ cdef class UVProcess(UVHandle):
self.__args = args.copy()
for i in range(an):
arg = args[i]
try:
fspath = type(arg).__fspath__
except AttributeError:
pass
else:
arg = fspath(arg)
arg = os_fspath(args[i])
if isinstance(arg, str):
self.__args[i] = PyUnicode_EncodeFSDefault(arg)
elif not isinstance(arg, bytes):

View File

@ -54,27 +54,7 @@ MakeUnixSockPyAddr(struct sockaddr_un *addr)
}
#if PY_VERSION_HEX < 0x03070000
PyObject * Context_CopyCurrent(void) {
PyErr_SetString(PyExc_NotImplementedError,
"\"contextvars\" support requires Python 3.7+");
return NULL;
};
int Context_Enter(PyObject *ctx) {
PyErr_SetString(PyExc_NotImplementedError,
"\"contextvars\" support requires Python 3.7+");
return -1;
}
int Context_Exit(PyObject *ctx) {
PyErr_SetString(PyExc_NotImplementedError,
"\"contextvars\" support requires Python 3.7+");
return -1;
}
#elif PY_VERSION_HEX < 0x03070100
#if PY_VERSION_HEX < 0x03070100
PyObject * Context_CopyCurrent(void) {
return (PyObject *)PyContext_CopyCurrent();
@ -103,26 +83,3 @@ int Context_Exit(PyObject *ctx) {
}
#endif
#if PY_VERSION_HEX < 0x03070000
void PyOS_BeforeFork(void)
{
_PyImport_AcquireLock();
}
void PyOS_AfterFork_Parent(void)
{
if (_PyImport_ReleaseLock() <= 0) {
Py_FatalError("failed releasing import lock after fork");
}
}
void PyOS_AfterFork_Child(void)
{
PyOS_AfterFork();
}
#endif

View File

@ -111,6 +111,7 @@ cdef os_pipe = os.pipe
cdef os_read = os.read
cdef os_remove = os.remove
cdef os_stat = os.stat
cdef os_fspath = os.fspath
cdef stat_S_ISSOCK = stat.S_ISSOCK

View File

@ -49,8 +49,6 @@ include "errors.pyx"
cdef:
int PY39 = PY_VERSION_HEX >= 0x03090000
int PY37 = PY_VERSION_HEX >= 0x03070000
int PY36 = PY_VERSION_HEX >= 0x03060000
uint64_t MAX_SLEEP = 3600 * 24 * 365 * 100
@ -177,13 +175,9 @@ cdef class Loop:
self._coroutine_debug_set = False
if hasattr(sys, 'get_asyncgen_hooks'):
# Python >= 3.6
# A weak set of all asynchronous generators that are
# being iterated by the loop.
self._asyncgens = weakref_WeakSet()
else:
self._asyncgens = None
# A weak set of all asynchronous generators that are
# being iterated by the loop.
self._asyncgens = weakref_WeakSet()
# Set to True when `loop.shutdown_asyncgens` is called.
self._asyncgens_shutdown_called = False
@ -1100,39 +1094,16 @@ cdef class Loop:
if self._coroutine_debug_set == enabled:
return
if PY37:
if enabled:
self._coroutine_origin_tracking_saved_depth = (
sys.get_coroutine_origin_tracking_depth())
sys.set_coroutine_origin_tracking_depth(
DEBUG_STACK_DEPTH)
else:
sys.set_coroutine_origin_tracking_depth(
self._coroutine_origin_tracking_saved_depth)
self._coroutine_debug_set = enabled
if enabled:
self._coroutine_origin_tracking_saved_depth = (
sys.get_coroutine_origin_tracking_depth())
sys.set_coroutine_origin_tracking_depth(
DEBUG_STACK_DEPTH)
else:
wrapper = aio_debug_wrapper
current_wrapper = sys_get_coroutine_wrapper()
sys.set_coroutine_origin_tracking_depth(
self._coroutine_origin_tracking_saved_depth)
if enabled:
if current_wrapper not in (None, wrapper):
_warn_with_source(
"loop.set_debug(True): cannot set debug coroutine "
"wrapper; another wrapper is already set %r" %
current_wrapper, RuntimeWarning, self)
else:
sys_set_coroutine_wrapper(wrapper)
self._coroutine_debug_set = True
else:
if current_wrapper not in (None, wrapper):
_warn_with_source(
"loop.set_debug(False): cannot unset debug coroutine "
"wrapper; another wrapper was set %r" %
current_wrapper, RuntimeWarning, self)
else:
sys_set_coroutine_wrapper(None)
self._coroutine_debug_set = False
self._coroutine_debug_set = enabled
def _get_backend_id(self):
"""This method is used by uvloop tests and is not part of the API."""
@ -1352,16 +1323,14 @@ cdef class Loop:
# This is how asyncio loop behaves.
mode = uv.UV_RUN_NOWAIT
self._set_coroutine_debug(self._debug)
if self._asyncgens is not None:
old_agen_hooks = sys.get_asyncgen_hooks()
sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
finalizer=self._asyncgen_finalizer_hook)
old_agen_hooks = sys.get_asyncgen_hooks()
sys.set_asyncgen_hooks(firstiter=self._asyncgen_firstiter_hook,
finalizer=self._asyncgen_finalizer_hook)
try:
self._run(mode)
finally:
self._set_coroutine_debug(False)
if self._asyncgens is not None:
sys.set_asyncgen_hooks(*old_agen_hooks)
sys.set_asyncgen_hooks(*old_agen_hooks)
def close(self):
"""Close the event loop.
@ -1509,11 +1478,8 @@ cdef class Loop:
if sl > 2:
flowinfo = sockaddr[2]
if flowinfo < 0 or flowinfo > 0xfffff:
if PY37:
msg = 'getnameinfo(): flowinfo must be 0-1048575.'
else:
msg = 'getsockaddrarg: flowinfo must be 0-1048575.'
raise OverflowError(msg)
raise OverflowError(
'getnameinfo(): flowinfo must be 0-1048575.')
else:
flowinfo = 0
@ -2095,14 +2061,7 @@ cdef class Loop:
'path and sock can not be specified at the same time')
orig_path = path
try:
# Lookup __fspath__ manually, as os.fspath() isn't
# available on Python 3.5.
fspath = type(path).__fspath__
except AttributeError:
pass
else:
path = fspath(path)
path = os_fspath(path)
if isinstance(path, str):
path = PyUnicode_EncodeFSDefault(path)
@ -2221,14 +2180,7 @@ cdef class Loop:
raise ValueError(
'path and sock can not be specified at the same time')
try:
# Lookup __fspath__ manually, as os.fspath() isn't
# available on Python 3.5.
fspath = type(path).__fspath__
except AttributeError:
pass
else:
path = fspath(path)
path = os_fspath(path)
if isinstance(path, str):
path = PyUnicode_EncodeFSDefault(path)
@ -2850,13 +2802,13 @@ cdef class Loop:
if (hasattr(callback, '__self__') and
isinstance(callback.__self__, aio_AbstractChildWatcher)):
_warn_with_source(
warnings_warn(
"!!! asyncio is trying to install its ChildWatcher for "
"SIGCHLD signal !!!\n\nThis is probably because a uvloop "
"instance is used with asyncio.set_event_loop(). "
"The correct way to use uvloop is to install its policy: "
"`asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())`"
"\n\n", RuntimeWarning, self)
"\n\n", RuntimeWarning, source=self)
# TODO: ideally we should always raise an error here,
# but that would be a backwards incompatible change,
@ -3107,10 +3059,10 @@ cdef class Loop:
def _asyncgen_firstiter_hook(self, agen):
if self._asyncgens_shutdown_called:
_warn_with_source(
warnings_warn(
"asynchronous generator {!r} was scheduled after "
"loop.shutdown_asyncgens() call".format(agen),
ResourceWarning, self)
ResourceWarning, source=self)
self._asyncgens.add(agen)
@ -3119,9 +3071,7 @@ cdef class Loop:
"""Shutdown all active asynchronous generators."""
self._asyncgens_shutdown_called = True
if self._asyncgens is None or not len(self._asyncgens):
# If Python version is <3.6 or we don't have any asynchronous
# generators alive.
if not len(self._asyncgens):
return
closing_agens = list(self._asyncgens)
@ -3304,19 +3254,12 @@ cdef __install_pymem():
cdef _set_signal_wakeup_fd(fd):
if PY37 and fd >= 0:
if fd >= 0:
return signal_set_wakeup_fd(fd, warn_on_full_buffer=False)
else:
return signal_set_wakeup_fd(fd)
cdef _warn_with_source(msg, cls, source):
if PY36:
warnings_warn(msg, cls, source=source)
else:
warnings_warn(msg, cls)
# Helpers for tests
@cython.iterable_coroutine