Skip to content

Commit cdd2218

Browse files
authored
Drop Python 3.5/3.6 support (#383)
Fixes #381
1 parent e21ceea commit cdd2218

22 files changed

+123
-490
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
runs-on: ${{ matrix.os }}
7373
strategy:
7474
matrix:
75-
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
75+
python-version: [3.7, 3.8, 3.9]
7676
os: [ubuntu-20.04, macos-latest]
7777
arch: [x86_64, aarch64]
7878
exclude:

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ${{ matrix.os }}
1515
strategy:
1616
matrix:
17-
python-version: [3.5, 3.6, 3.7, 3.8, 3.9]
17+
python-version: [3.7, 3.8, 3.9]
1818
os: [ubuntu-latest, macos-latest]
1919

2020
steps:

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ about it.
3939
Installation
4040
------------
4141

42-
uvloop requires Python 3.5 or greater and is available on PyPI.
42+
uvloop requires Python 3.7 or greater and is available on PyPI.
4343
Use pip to install it::
4444

4545
$ pip install uvloop
@@ -72,7 +72,7 @@ manually creating an asyncio event loop:
7272
Building From Source
7373
--------------------
7474

75-
To build uvloop, you'll need Python 3.5 or greater:
75+
To build uvloop, you'll need Python 3.7 or greater:
7676

7777
1. Clone the repository:
7878

docs/dev/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ from the `libuv` Github repository.
2828
Build
2929
-----
3030

31-
To build `uvloop`, you'll need ``Cython`` and Python 3.5.
31+
To build `uvloop`, you'll need ``Cython`` and Python 3.7.
3232

3333
.. note::
3434

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ uvloop
1414
`uvloop` is a fast, drop-in replacement of the built-in asyncio event loop.
1515
`uvloop` is released under the MIT license.
1616

17-
`uvloop` and asyncio, combined with the power of async/await in Python 3.5,
17+
`uvloop` and asyncio, combined with the power of async/await in Python 3.7,
1818
makes it easier than ever to write high-performance networking code in Python.
1919

2020
`uvloop` makes asyncio fast. In fact, it is at least 2x faster than nodejs,

docs/user/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ uvloop.
88
Installation
99
------------
1010

11-
`uvloop` is available from PyPI. It requires Python 3.5.
11+
`uvloop` is available from PyPI. It requires Python 3.7.
1212

1313
Use pip to install it.
1414

setup.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import sys
22

33
vi = sys.version_info
4-
if vi < (3, 5):
5-
raise RuntimeError('uvloop requires Python 3.5 or greater')
6-
if vi[:2] == (3, 6):
7-
if vi.releaselevel == 'beta' and vi.serial < 3:
8-
raise RuntimeError('uvloop requires Python 3.5 or 3.6b3 or greater')
4+
if vi < (3, 7):
5+
raise RuntimeError('uvloop requires Python 3.7 or greater')
96

107
if sys.platform in ('win32', 'cygwin', 'cli'):
118
raise RuntimeError('uvloop does not support Windows at the moment')
@@ -310,8 +307,6 @@ def build_extensions(self):
310307
'Development Status :: 5 - Production/Stable',
311308
'Framework :: AsyncIO',
312309
'Programming Language :: Python :: 3 :: Only',
313-
'Programming Language :: Python :: 3.5',
314-
'Programming Language :: Python :: 3.6',
315310
'Programming Language :: Python :: 3.7',
316311
'Programming Language :: Python :: 3.8',
317312
'Programming Language :: Python :: 3.9',

tests/test_base.py

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -345,9 +345,6 @@ async def foo():
345345
self.loop.run_until_complete(foo())
346346

347347
def test_run_until_complete_loop_orphan_future_close_loop(self):
348-
if self.implementation == 'asyncio' and sys.version_info < (3, 6, 2):
349-
raise unittest.SkipTest('unfixed asyncio')
350-
351348
async def foo(delay):
352349
await asyncio.sleep(delay)
353350

@@ -463,9 +460,7 @@ def handler(loop, exc):
463460

464461
self.loop.set_debug(True)
465462

466-
if hasattr(self.loop, 'get_exception_handler'):
467-
# Available since Python 3.5.2
468-
self.assertIsNone(self.loop.get_exception_handler())
463+
self.assertIsNone(self.loop.get_exception_handler())
469464
self.loop.set_exception_handler(handler)
470465
if hasattr(self.loop, 'get_exception_handler'):
471466
self.assertIs(self.loop.get_exception_handler(), handler)
@@ -582,31 +577,19 @@ async def coro():
582577
self.loop.set_task_factory(None)
583578
self.assertIsNone(self.loop.get_task_factory())
584579

585-
def _compile_agen(self, src):
586-
try:
587-
g = {}
588-
exec(src, globals(), g)
589-
except SyntaxError:
590-
# Python < 3.6
591-
raise unittest.SkipTest()
592-
else:
593-
return g['waiter']
594-
595580
def test_shutdown_asyncgens_01(self):
596581
finalized = list()
597582

598583
if not hasattr(self.loop, 'shutdown_asyncgens'):
599584
raise unittest.SkipTest()
600585

601-
waiter = self._compile_agen(
602-
'''async def waiter(timeout, finalized):
603-
try:
604-
await asyncio.sleep(timeout)
605-
yield 1
606-
finally:
607-
await asyncio.sleep(0)
608-
finalized.append(1)
609-
''')
586+
async def waiter(timeout, finalized):
587+
try:
588+
await asyncio.sleep(timeout)
589+
yield 1
590+
finally:
591+
await asyncio.sleep(0)
592+
finalized.append(1)
610593

611594
async def wait():
612595
async for _ in waiter(1, finalized):
@@ -641,13 +624,12 @@ def logger(loop, context):
641624
self.assertIn('asyncgen', context)
642625
logged += 1
643626

644-
waiter = self._compile_agen('''async def waiter(timeout):
627+
async def waiter(timeout):
645628
try:
646629
await asyncio.sleep(timeout)
647630
yield 1
648631
finally:
649632
1 / 0
650-
''')
651633

652634
async def wait():
653635
async for _ in waiter(1):
@@ -669,10 +651,9 @@ def test_shutdown_asyncgens_03(self):
669651
if not hasattr(self.loop, 'shutdown_asyncgens'):
670652
raise unittest.SkipTest()
671653

672-
waiter = self._compile_agen('''async def waiter():
654+
async def waiter():
673655
yield 1
674656
yield 2
675-
''')
676657

677658
async def foo():
678659
# We specifically want to hit _asyncgen_finalizer_hook

tests/test_context.py

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
import asyncio
2+
import contextvars
23
import decimal
34
import random
4-
import sys
5-
import unittest
65
import weakref
76

87
from uvloop import _testbase as tb
98

109

11-
PY37 = sys.version_info >= (3, 7, 0)
12-
13-
1410
class _ContextBaseTests:
1511

16-
@unittest.skipUnless(PY37, 'requires Python 3.7')
1712
def test_task_decimal_context(self):
1813
async def fractions(t, precision, x, y):
1914
with decimal.localcontext() as ctx:
@@ -37,9 +32,7 @@ async def main():
3732
self.assertEqual(str(r2[0]), '0.333333')
3833
self.assertEqual(str(r2[1]), '0.111111')
3934

40-
@unittest.skipUnless(PY37, 'requires Python 3.7')
4135
def test_task_context_1(self):
42-
import contextvars
4336
cvar = contextvars.ContextVar('cvar', default='nope')
4437

4538
async def sub():
@@ -58,9 +51,7 @@ async def main():
5851
task = self.loop.create_task(main())
5952
self.loop.run_until_complete(task)
6053

61-
@unittest.skipUnless(PY37, 'requires Python 3.7')
6254
def test_task_context_2(self):
63-
import contextvars
6455
cvar = contextvars.ContextVar('cvar', default='nope')
6556

6657
async def main():
@@ -90,9 +81,7 @@ def fut_on_done(fut):
9081

9182
self.assertEqual(cvar.get(), 'nope')
9283

93-
@unittest.skipUnless(PY37, 'requires Python 3.7')
9484
def test_task_context_3(self):
95-
import contextvars
9685
cvar = contextvars.ContextVar('cvar', default=-1)
9786

9887
# Run 100 Tasks in parallel, each modifying cvar.
@@ -115,9 +104,7 @@ async def main():
115104

116105
self.assertEqual(cvar.get(), -1)
117106

118-
@unittest.skipUnless(PY37, 'requires Python 3.7')
119107
def test_task_context_4(self):
120-
import contextvars
121108
cvar = contextvars.ContextVar('cvar', default='nope')
122109

123110
class TrackMe:
@@ -141,23 +128,7 @@ async def main():
141128

142129

143130
class Test_UV_Context(_ContextBaseTests, tb.UVTestCase):
144-
145-
@unittest.skipIf(PY37, 'requires Python <3.6')
146-
def test_context_arg(self):
147-
def cb():
148-
pass
149-
150-
with self.assertRaisesRegex(NotImplementedError,
151-
'requires Python 3.7'):
152-
self.loop.call_soon(cb, context=1)
153-
154-
with self.assertRaisesRegex(NotImplementedError,
155-
'requires Python 3.7'):
156-
self.loop.call_soon_threadsafe(cb, context=1)
157-
158-
with self.assertRaisesRegex(NotImplementedError,
159-
'requires Python 3.7'):
160-
self.loop.call_later(0.1, cb, context=1)
131+
pass
161132

162133

163134
class Test_AIO_Context(_ContextBaseTests, tb.AIOTestCase):

tests/test_sockets.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ async def recv_all(self, sock, nbytes):
2121
return buf
2222

2323
def test_socket_connect_recv_send(self):
24-
if self.is_asyncio_loop() and sys.version_info[:3] == (3, 5, 2):
25-
# See https://github.com/python/asyncio/pull/366 for details.
26-
raise unittest.SkipTest()
27-
2824
if sys.version_info[:3] >= (3, 8, 0):
2925
# @asyncio.coroutine is deprecated in 3.8
3026
raise unittest.SkipTest()

tests/test_sourcecode.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ def find_uvloop_root():
1010

1111
class TestFlake8(unittest.TestCase):
1212

13-
@unittest.skipIf(sys.version_info < (3, 6, 0),
14-
"flake8 under 3.5 does not recognize f-strings in *.pyx")
1513
def test_flake8(self):
1614
edgepath = find_uvloop_root()
1715
config_path = os.path.join(edgepath, '.flake8')

0 commit comments

Comments
 (0)