Skip to content

Commit 8e35cc9

Browse files
authored
Update asyncio to 3.14.5 (RustPython#8012)
1 parent 5b2f6bc commit 8e35cc9

12 files changed

Lines changed: 257 additions & 51 deletions

Lib/asyncio/__main__.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -86,22 +86,27 @@ def run(self):
8686
global return_code
8787

8888
try:
89-
banner = (
90-
f'asyncio REPL {sys.version} on {sys.platform}\n'
91-
f'Use "await" directly instead of "asyncio.run()".\n'
92-
f'Type "help", "copyright", "credits" or "license" '
93-
f'for more information.\n'
94-
)
89+
if not sys.flags.quiet:
90+
banner = (
91+
f'asyncio REPL {sys.version} on {sys.platform}\n'
92+
f'Use "await" directly instead of "asyncio.run()".\n'
93+
f'Type "help", "copyright", "credits" or "license" '
94+
f'for more information.\n'
95+
)
9596

96-
console.write(banner)
97+
console.write(banner)
9798

98-
if startup_path := os.getenv("PYTHONSTARTUP"):
99+
if not sys.flags.isolated and (startup_path := os.getenv("PYTHONSTARTUP")):
99100
sys.audit("cpython.run_startup", startup_path)
100-
101-
import tokenize
102-
with tokenize.open(startup_path) as f:
103-
startup_code = compile(f.read(), startup_path, "exec")
101+
try:
102+
import tokenize
103+
with tokenize.open(startup_path) as f:
104+
startup_code = compile(f.read(), startup_path, "exec")
104105
exec(startup_code, console.locals)
106+
except SystemExit:
107+
raise
108+
except BaseException:
109+
console.showtraceback()
105110

106111
ps1 = getattr(sys, "ps1", ">>> ")
107112
if CAN_USE_PYREPL:
@@ -236,4 +241,5 @@ def interrupt(self) -> None:
236241
break
237242

238243
console.write('exiting asyncio REPL...\n')
244+
loop.close()
239245
sys.exit(return_code)

Lib/asyncio/base_events.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,17 @@ async def start_tls(self, transport, protocol, sslcontext, *,
13451345
# have a chance to get called before "ssl_protocol.connection_made()".
13461346
transport.pause_reading()
13471347

1348+
# gh-142352: move buffered StreamReader data to SSLProtocol
1349+
if server_side:
1350+
from .streams import StreamReaderProtocol
1351+
if isinstance(protocol, StreamReaderProtocol):
1352+
stream_reader = getattr(protocol, '_stream_reader', None)
1353+
if stream_reader is not None:
1354+
buffer = stream_reader._buffer
1355+
if buffer:
1356+
ssl_protocol._incoming.write(buffer)
1357+
buffer.clear()
1358+
13481359
transport.set_protocol(ssl_protocol)
13491360
conmade_cb = self.call_soon(ssl_protocol.connection_made, transport)
13501361
resume_cb = self.call_soon(transport.resume_reading)

Lib/asyncio/base_subprocess.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ def _try_finish(self):
265265
# to avoid hanging forever in self._wait as otherwise _exit_waiters
266266
# would never be woken up, we wake them up here.
267267
for waiter in self._exit_waiters:
268-
if not waiter.cancelled():
268+
if not waiter.done():
269269
waiter.set_result(self._returncode)
270270
if all(p is not None and p.disconnected
271271
for p in self._pipes.values()):
@@ -278,7 +278,7 @@ def _call_connection_lost(self, exc):
278278
finally:
279279
# wake up futures waiting for wait()
280280
for waiter in self._exit_waiters:
281-
if not waiter.cancelled():
281+
if not waiter.done():
282282
waiter.set_result(self._returncode)
283283
self._exit_waiters = None
284284
self._loop = None

Lib/asyncio/futures.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ def _set_state(future, other):
392392

393393
def _call_check_cancel(destination):
394394
if destination.cancelled():
395-
if source_loop is None or source_loop is dest_loop:
395+
if source_loop is None or source_loop is events._get_running_loop():
396396
source.cancel()
397397
else:
398398
source_loop.call_soon_threadsafe(source.cancel)
@@ -401,7 +401,7 @@ def _call_set_state(source):
401401
if (destination.cancelled() and
402402
dest_loop is not None and dest_loop.is_closed()):
403403
return
404-
if dest_loop is None or dest_loop is source_loop:
404+
if dest_loop is None or dest_loop is events._get_running_loop():
405405
_set_state(destination, source)
406406
else:
407407
if dest_loop.is_closed():

Lib/asyncio/queues.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class Queue(mixins._LoopBoundMixin):
3737
is an integer greater than 0, then "await put()" will block when the
3838
queue reaches maxsize, until an item is removed by get().
3939
40-
Unlike the standard library Queue, you can reliably know this Queue's size
40+
Unlike queue.Queue, you can reliably know this Queue's size
4141
with qsize(), since your single-threaded asyncio application won't be
4242
interrupted between calling qsize() and doing an operation on the Queue.
4343
"""

Lib/asyncio/windows_utils.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import msvcrt
1111
import os
1212
import subprocess
13-
import tempfile
1413
import warnings
1514

1615

@@ -24,17 +23,14 @@
2423
PIPE = subprocess.PIPE
2524
STDOUT = subprocess.STDOUT
2625
_mmap_counter = itertools.count()
26+
_MAX_PIPE_ATTEMPTS = 20
2727

2828

2929
# Replacement for os.pipe() using handles instead of fds
3030

3131

3232
def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
3333
"""Like os.pipe() but with overlapped support and using handles not fds."""
34-
address = tempfile.mktemp(
35-
prefix=r'\\.\pipe\python-pipe-{:d}-{:d}-'.format(
36-
os.getpid(), next(_mmap_counter)))
37-
3834
if duplex:
3935
openmode = _winapi.PIPE_ACCESS_DUPLEX
4036
access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
@@ -56,9 +52,20 @@ def pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
5652

5753
h1 = h2 = None
5854
try:
59-
h1 = _winapi.CreateNamedPipe(
60-
address, openmode, _winapi.PIPE_WAIT,
61-
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
55+
for attempts in itertools.count():
56+
address = r'\\.\pipe\python-pipe-{:d}-{:d}-{}'.format(
57+
os.getpid(), next(_mmap_counter), os.urandom(8).hex())
58+
try:
59+
h1 = _winapi.CreateNamedPipe(
60+
address, openmode, _winapi.PIPE_WAIT,
61+
1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
62+
break
63+
except OSError as e:
64+
if attempts >= _MAX_PIPE_ATTEMPTS:
65+
raise
66+
if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
67+
_winapi.ERROR_ACCESS_DENIED):
68+
raise
6269

6370
h2 = _winapi.CreateFile(
6471
address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,
@@ -104,8 +111,9 @@ def fileno(self):
104111

105112
def close(self, *, CloseHandle=_winapi.CloseHandle):
106113
if self._handle is not None:
107-
CloseHandle(self._handle)
114+
handle = self._handle
108115
self._handle = None
116+
CloseHandle(handle)
109117

110118
def __del__(self, _warn=warnings.warn):
111119
if self._handle is not None:

Lib/test/test_asyncio/test_sock_lowlevel.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,27 @@ def test_recvfrom_into(self):
427427
self.loop.run_until_complete(
428428
self._basetest_datagram_recvfrom_into(server_address))
429429

430+
async def _basetest_datagram_recvfrom_into_wrong_size(self, server_address):
431+
# Call sock_sendto() with a size larger than the buffer
432+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
433+
sock.setblocking(False)
434+
435+
buf = bytearray(5000)
436+
data = b'\x01' * 4096
437+
wrong_size = len(buf) + 1
438+
await self.loop.sock_sendto(sock, data, server_address)
439+
with self.assertRaises(ValueError):
440+
await self.loop.sock_recvfrom_into(
441+
sock, buf, wrong_size)
442+
443+
size, addr = await self.loop.sock_recvfrom_into(sock, buf)
444+
self.assertEqual(buf[:size], data)
445+
446+
def test_recvfrom_into_wrong_size(self):
447+
with test_utils.run_udp_echo_server() as server_address:
448+
self.loop.run_until_complete(
449+
self._basetest_datagram_recvfrom_into_wrong_size(server_address))
450+
430451
async def _basetest_datagram_sendto_blocking(self, server_address):
431452
# Sad path, sock.sendto() raises BlockingIOError
432453
# This involves patching sock.sendto() to raise BlockingIOError but
@@ -642,6 +663,10 @@ async def recvfrom_into(socket):
642663
self._basetest_datagram_send_to_non_listening_address(
643664
recvfrom_into))
644665

666+
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON; AssertionError: ValueError not raised")
667+
def test_recvfrom_into_wrong_size(self):
668+
return super().test_recvfrom_into_wrong_size()
669+
645670
else:
646671
import selectors
647672

Lib/test/test_asyncio/test_ssl.py

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
MACOS = (sys.platform == 'darwin')
2929
BUF_MULTIPLIER = 1024 if not MACOS else 64
30+
HANDSHAKE_TIMEOUT = support.LONG_TIMEOUT
3031

3132

3233
def tearDownModule():
@@ -257,15 +258,12 @@ def prog(sock):
257258
await fut
258259

259260
async def start_server():
260-
extras = {}
261-
extras = dict(ssl_handshake_timeout=support.SHORT_TIMEOUT)
262-
263261
srv = await asyncio.start_server(
264262
handle_client,
265263
'127.0.0.1', 0,
266264
family=socket.AF_INET,
267265
ssl=sslctx,
268-
**extras)
266+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
269267

270268
try:
271269
srv_socks = srv.sockets
@@ -322,14 +320,11 @@ def server(sock):
322320
sock.close()
323321

324322
async def client(addr):
325-
extras = {}
326-
extras = dict(ssl_handshake_timeout=support.SHORT_TIMEOUT)
327-
328323
reader, writer = await asyncio.open_connection(
329324
*addr,
330325
ssl=client_sslctx,
331326
server_hostname='',
332-
**extras)
327+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
333328

334329
writer.write(A_DATA)
335330
self.assertEqual(await reader.readexactly(2), b'OK')
@@ -349,7 +344,8 @@ async def client_sock(addr):
349344
reader, writer = await asyncio.open_connection(
350345
sock=sock,
351346
ssl=client_sslctx,
352-
server_hostname='')
347+
server_hostname='',
348+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
353349

354350
writer.write(A_DATA)
355351
self.assertEqual(await reader.readexactly(2), b'OK')
@@ -448,7 +444,7 @@ async def client(addr):
448444
*addr,
449445
ssl=client_sslctx,
450446
server_hostname='',
451-
ssl_handshake_timeout=support.SHORT_TIMEOUT)
447+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
452448
writer.close()
453449
await self.wait_closed(writer)
454450

@@ -610,7 +606,7 @@ def client():
610606

611607
extras = {}
612608
if server_ssl:
613-
extras = dict(ssl_handshake_timeout=support.SHORT_TIMEOUT)
609+
extras = dict(ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
614610

615611
f = loop.create_task(
616612
loop.connect_accepted_socket(
@@ -659,7 +655,8 @@ async def client(addr):
659655
reader, writer = await asyncio.open_connection(
660656
*addr,
661657
ssl=client_sslctx,
662-
server_hostname='')
658+
server_hostname='',
659+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
663660

664661
self.assertEqual(await reader.readline(), b'A\n')
665662
writer.write(b'B')
@@ -1153,14 +1150,11 @@ def do(func, *args):
11531150
await fut
11541151

11551152
async def start_server():
1156-
extras = {}
1157-
11581153
srv = await self.loop.create_server(
11591154
server_protocol_factory,
11601155
'127.0.0.1', 0,
11611156
family=socket.AF_INET,
1162-
ssl=sslctx_1,
1163-
**extras)
1157+
ssl=sslctx_1)
11641158

11651159
try:
11661160
srv_socks = srv.sockets
@@ -1210,14 +1204,11 @@ def server(sock):
12101204
sock.close()
12111205

12121206
async def client(addr):
1213-
extras = {}
1214-
extras = dict(ssl_handshake_timeout=support.SHORT_TIMEOUT)
1215-
12161207
reader, writer = await asyncio.open_connection(
12171208
*addr,
12181209
ssl=client_sslctx,
12191210
server_hostname='',
1220-
**extras)
1211+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
12211212

12221213
writer.write(A_DATA)
12231214
self.assertEqual(await reader.readexactly(2), b'OK')
@@ -1287,7 +1278,8 @@ async def client(addr):
12871278
reader, writer = await asyncio.open_connection(
12881279
*addr,
12891280
ssl=client_sslctx,
1290-
server_hostname='')
1281+
server_hostname='',
1282+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
12911283
sslprotocol = writer.transport._ssl_protocol
12921284
writer.write(b'ping')
12931285
data = await reader.readexactly(4)
@@ -1399,7 +1391,8 @@ async def client(addr):
13991391
reader, writer = await asyncio.open_connection(
14001392
*addr,
14011393
ssl=client_sslctx,
1402-
server_hostname='')
1394+
server_hostname='',
1395+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
14031396
writer.write(b'ping')
14041397
data = await reader.readexactly(4)
14051398
self.assertEqual(data, b'pong')
@@ -1530,7 +1523,8 @@ async def client(addr):
15301523
reader, writer = await asyncio.open_connection(
15311524
*addr,
15321525
ssl=client_sslctx,
1533-
server_hostname='')
1526+
server_hostname='',
1527+
ssl_handshake_timeout=HANDSHAKE_TIMEOUT)
15341528
writer.write(b'ping')
15351529
data = await reader.readexactly(4)
15361530
self.assertEqual(data, b'pong')

Lib/test/test_asyncio/test_streams.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,48 @@ async def client(addr):
819819
self.assertEqual(msg1, b"hello world 1!\n")
820820
self.assertEqual(msg2, b"hello world 2!\n")
821821

822+
@unittest.skipIf(ssl is None, 'No ssl module')
823+
def test_start_tls_buffered_data(self):
824+
# gh-142352: test start_tls() with buffered data
825+
826+
async def server_handler(client_reader, client_writer):
827+
# Wait for TLS ClientHello to be buffered before start_tls().
828+
await client_reader._wait_for_data('test_start_tls_buffered_data'),
829+
self.assertTrue(client_reader._buffer)
830+
await client_writer.start_tls(test_utils.simple_server_sslcontext())
831+
832+
line = await client_reader.readline()
833+
self.assertEqual(line, b"ping\n")
834+
client_writer.write(b"pong\n")
835+
await client_writer.drain()
836+
client_writer.close()
837+
await client_writer.wait_closed()
838+
839+
async def client(addr):
840+
reader, writer = await asyncio.open_connection(*addr)
841+
await writer.start_tls(test_utils.simple_client_sslcontext())
842+
843+
writer.write(b"ping\n")
844+
await writer.drain()
845+
line = await reader.readline()
846+
self.assertEqual(line, b"pong\n")
847+
writer.close()
848+
await writer.wait_closed()
849+
850+
async def run_test():
851+
server = await asyncio.start_server(
852+
server_handler, socket_helper.HOSTv4, 0)
853+
server_addr = server.sockets[0].getsockname()
854+
855+
await client(server_addr)
856+
server.close()
857+
await server.wait_closed()
858+
859+
messages = []
860+
self.loop.set_exception_handler(lambda loop, ctx: messages.append(ctx))
861+
self.loop.run_until_complete(run_test())
862+
self.assertEqual(messages, [])
863+
822864
def test_streamreader_constructor_without_loop(self):
823865
with self.assertRaisesRegex(RuntimeError, 'no current event loop'):
824866
asyncio.StreamReader()

0 commit comments

Comments
 (0)