Skip to content

Commit 8e42921

Browse files
zeroday0619fantixelprans
authored
Support python 3.11+ (#473)
* chore: Cython version update * add 3.11-dev pipeline * Test and build on Python 3.11 * Drop test_context_run_segfault * Support context in loop.create_task() * Consistent PseudoSocket repr * Add stubs for new 3.11 loop.sock_*() methods * Skip test_create_ssl_server_manual_connection_lost on 3.11 for now Co-authored-by: Fantix King <[email protected]> Co-authored-by: Elvis Pranskevichus <[email protected]>
1 parent e04637e commit 8e42921

File tree

9 files changed

+55
-49
lines changed

9 files changed

+55
-49
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
strategy:
7676
matrix:
7777
os: [ubuntu-latest, macos-latest]
78-
cibw_python: ["cp37-*", "cp38-*", "cp39-*", "cp310-*"]
78+
cibw_python: ["cp37-*", "cp38-*", "cp39-*", "cp310-*", "cp311-*"]
7979
cibw_arch: ["x86_64", "aarch64", "universal2"]
8080
exclude:
8181
- os: ubuntu-latest

.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.7", "3.8", "3.9", "3.10"]
17+
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11.0-rc.1"]
1818
os: [ubuntu-latest, macos-latest]
1919

2020
env:

setup.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@
2121
from setuptools.command.sdist import sdist
2222

2323

24-
CYTHON_DEPENDENCY = 'Cython(>=0.29.24,<0.30.0)'
24+
CYTHON_DEPENDENCY = 'Cython(>=0.29.32,<0.30.0)'
2525

2626
# Minimal dependencies required to test uvloop.
2727
TEST_DEPENDENCIES = [
2828
# pycodestyle is a dependency of flake8, but it must be frozen because
2929
# their combination breaks too often
3030
# (example breakage: https://gitlab.com/pycqa/flake8/issues/427)
31-
'aiohttp',
31+
# aiohttp doesn't support 3.11 yet,
32+
# see https://github.com/aio-libs/aiohttp/issues/6600
33+
'aiohttp ; python_version < "3.11"',
3234
'flake8~=3.9.2',
3335
'psutil',
3436
'pycodestyle~=2.7.0',

tests/test_base.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,9 @@ class MyTask(asyncio.Task):
540540
async def coro():
541541
pass
542542

543-
factory = lambda loop, coro: MyTask(coro, loop=loop)
543+
factory = lambda loop, coro, **kwargs: MyTask(
544+
coro, loop=loop, **kwargs
545+
)
544546

545547
self.assertIsNone(self.loop.get_task_factory())
546548
self.loop.set_task_factory(factory)
@@ -577,7 +579,9 @@ def get_name(self):
577579
async def coro():
578580
pass
579581

580-
factory = lambda loop, coro: MyTask(coro, loop=loop)
582+
factory = lambda loop, coro, **kwargs: MyTask(
583+
coro, loop=loop, **kwargs
584+
)
581585

582586
self.assertIsNone(self.loop.get_task_factory())
583587
task = self.loop.create_task(coro(), name="mytask")

tests/test_context.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ def close():
452452
self._run_server_test(test, async_sock=True)
453453

454454
def test_create_ssl_server_manual_connection_lost(self):
455+
if self.implementation == 'asyncio' and sys.version_info >= (3, 11, 0):
456+
# TODO(fantix): fix for 3.11
457+
raise unittest.SkipTest('should pass on 3.11')
458+
455459
async def test(proto, cvar, ssl_sock, **_):
456460
def close():
457461
cvar.set('closing')

tests/test_tcp.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -652,43 +652,6 @@ async def runner():
652652
self.assertIsNone(
653653
self.loop.run_until_complete(connection_lost_called))
654654

655-
def test_context_run_segfault(self):
656-
is_new = False
657-
done = self.loop.create_future()
658-
659-
def server(sock):
660-
sock.sendall(b'hello')
661-
662-
class Protocol(asyncio.Protocol):
663-
def __init__(self):
664-
self.transport = None
665-
666-
def connection_made(self, transport):
667-
self.transport = transport
668-
669-
def data_received(self, data):
670-
try:
671-
self = weakref.ref(self)
672-
nonlocal is_new
673-
if is_new:
674-
done.set_result(data)
675-
else:
676-
is_new = True
677-
new_proto = Protocol()
678-
self().transport.set_protocol(new_proto)
679-
new_proto.connection_made(self().transport)
680-
new_proto.data_received(data)
681-
except Exception as e:
682-
done.set_exception(e)
683-
684-
async def test(addr):
685-
await self.loop.create_connection(Protocol, *addr)
686-
data = await done
687-
self.assertEqual(data, b'hello')
688-
689-
with self.tcp_server(server) as srv:
690-
self.loop.run_until_complete(test(srv.addr))
691-
692655

693656
class Test_UV_TCP(_TestTCP, tb.UVTestCase):
694657

uvloop/loop.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import ssl
3+
import sys
34
from socket import AddressFamily, SocketKind, _Address, _RetAddress, socket
45
from typing import (
56
IO,
@@ -210,6 +211,9 @@ class Loop:
210211
async def sock_sendall(self, sock: socket, data: bytes) -> None: ...
211212
async def sock_accept(self, sock: socket) -> Tuple[socket, _RetAddress]: ...
212213
async def sock_connect(self, sock: socket, address: _Address) -> None: ...
214+
async def sock_recvfrom(self, sock: socket, bufsize: int) -> bytes: ...
215+
async def sock_recvfrom_into(self, sock: socket, buf: bytearray, nbytes: int = ...) -> int: ...
216+
async def sock_sendto(self, sock: socket, data: bytes, address: _Address) -> None: ...
213217
async def connect_accepted_socket(
214218
self,
215219
protocol_factory: Callable[[], _ProtocolT],

uvloop/loop.pyx

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ include "errors.pyx"
5050

5151
cdef:
5252
int PY39 = PY_VERSION_HEX >= 0x03090000
53+
int PY311 = PY_VERSION_HEX >= 0x030b0000
5354
uint64_t MAX_SLEEP = 3600 * 24 * 365 * 100
5455

5556

@@ -1413,19 +1414,35 @@ cdef class Loop:
14131414
"""Create a Future object attached to the loop."""
14141415
return self._new_future()
14151416

1416-
def create_task(self, coro, *, name=None):
1417+
def create_task(self, coro, *, name=None, context=None):
14171418
"""Schedule a coroutine object.
14181419
14191420
Return a task object.
14201421
14211422
If name is not None, task.set_name(name) will be called if the task
14221423
object has the set_name attribute, true for default Task in Python 3.8.
1424+
1425+
An optional keyword-only context argument allows specifying a custom
1426+
contextvars.Context for the coro to run in. The current context copy is
1427+
created when no context is provided.
14231428
"""
14241429
self._check_closed()
1425-
if self._task_factory is None:
1426-
task = aio_Task(coro, loop=self)
1430+
if PY311:
1431+
if self._task_factory is None:
1432+
task = aio_Task(coro, loop=self, context=context)
1433+
else:
1434+
task = self._task_factory(self, coro, context=context)
14271435
else:
1428-
task = self._task_factory(self, coro)
1436+
if context is None:
1437+
if self._task_factory is None:
1438+
task = aio_Task(coro, loop=self)
1439+
else:
1440+
task = self._task_factory(self, coro)
1441+
else:
1442+
if self._task_factory is None:
1443+
task = context.run(aio_Task, coro, self)
1444+
else:
1445+
task = context.run(self._task_factory, self, coro)
14291446

14301447
# copied from asyncio.tasks._set_task_name (bpo-34270)
14311448
if name is not None:
@@ -2604,6 +2621,18 @@ cdef class Loop:
26042621
finally:
26052622
socket_dec_io_ref(sock)
26062623

2624+
@cython.iterable_coroutine
2625+
async def sock_recvfrom(self, sock, bufsize):
2626+
raise NotImplementedError
2627+
2628+
@cython.iterable_coroutine
2629+
async def sock_recvfrom_into(self, sock, buf, nbytes=0):
2630+
raise NotImplementedError
2631+
2632+
@cython.iterable_coroutine
2633+
async def sock_sendto(self, sock, data, address):
2634+
raise NotImplementedError
2635+
26072636
@cython.iterable_coroutine
26082637
async def connect_accepted_socket(self, protocol_factory, sock, *,
26092638
ssl=None,

uvloop/pseudosock.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ cdef class PseudoSocket:
4141

4242
def __repr__(self):
4343
s = ("<uvloop.PseudoSocket fd={}, family={!s}, "
44-
"type={!s}, proto={}").format(self.fileno(), self.family,
45-
self.type, self.proto)
44+
"type={!s}, proto={}").format(self.fileno(), self.family.name,
45+
self.type.name, self.proto)
4646

4747
if self._fd != -1:
4848
try:

0 commit comments

Comments
 (0)