Skip to content

Commit de32f84

Browse files
author
Muse Code
committed
Fix CI: news entry, lint fixes, and test updates (gh-109051)
- Remove unused imports flagged by ruff (asyncio.base_events, asyncio.sslproto). - Add Misc/NEWS.d entry for gh-109051 (bedevere/news). - test_ssl: rewrite test_remote_shutdown_receives_trailing_data_on_slow_socket to fill the transport buffer instead of the removed _test__append_write_backlog helper, mirroring the sibling test rewrite already in this PR. - test_sslproto: stop mocking sslobj.write() failures; without an outgoing write buffer those errors propagate instead of being buffered and retried. Co-authored-by: Muse Code (Meta Muse Spark)
1 parent 08eb83c commit de32f84

5 files changed

Lines changed: 47 additions & 15 deletions

File tree

‎Lib/asyncio/base_events.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
from . import staggered
4949
from . import tasks
5050
from . import timeouts
51-
from . import transports
5251
from . import trsock
5352
from .log import logger
5453

‎Lib/asyncio/sslproto.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# SPDX-License-Identifier: PSF-2.0 AND (MIT OR Apache-2.0)
33
# SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io
44

5-
import collections
65
import enum
76
import warnings
87
try:

‎Lib/test/test_asyncio/test_ssl.py‎

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,6 @@ def test_remote_shutdown_receives_trailing_data_on_slow_socket(self):
14651465
# The slow path is triggered here by setting SO_SNDBUF, see code and comment below.
14661466

14671467
CHUNK = 1024 * 128
1468-
SIZE = 32
14691468

14701469
sslctx = self._create_server_ssl_context(
14711470
test_utils.ONLYCERT,
@@ -1503,25 +1502,38 @@ def server(sock):
15031502
sslobj.write(b'pong')
15041503
sock.send(outgoing.read())
15051504

1506-
time.sleep(0.2) # wait for the peer to fill its backlog
1505+
data_len = 0
1506+
filled.wait()
1507+
# trigger peer's resume_writing()
1508+
incoming.write(sock.recv(65536 * 4))
1509+
while True:
1510+
try:
1511+
chunk = len(sslobj.read(16384))
1512+
data_len += chunk
1513+
except ssl.SSLWantReadError:
1514+
break
15071515

15081516
# send close_notify but don't wait for response
15091517
with self.assertRaises(ssl.SSLWantReadError):
15101518
sslobj.unwrap()
15111519
sock.send(outgoing.read())
15121520

1521+
eof_received.wait()
15131522
# should receive all data
1514-
data_len = 0
15151523
while True:
15161524
try:
15171525
chunk = len(sslobj.read(16384))
15181526
data_len += chunk
15191527
except ssl.SSLWantReadError:
15201528
incoming.write(sock.recv(16384))
1529+
if not incoming.pending:
1530+
# EOF received
1531+
break
15211532
except ssl.SSLZeroReturnError:
15221533
break
15231534

1524-
self.assertEqual(data_len, CHUNK * SIZE*2)
1535+
assert count > 0
1536+
self.assertEqual(data_len, CHUNK * count)
15251537

15261538
# verify that close_notify is received
15271539
sslobj.unwrap()
@@ -1533,19 +1545,20 @@ def eof_server(sock):
15331545
self.assertEqual(sock.recv_all(4), b'ping')
15341546
sock.send(b'pong')
15351547

1536-
time.sleep(0.2) # wait for the peer to fill its backlog
1548+
filled.wait()
15371549

15381550
# send EOF
15391551
sock.shutdown(socket.SHUT_WR)
15401552

15411553
# should receive all data
1542-
data = sock.recv_all(CHUNK * SIZE)
1543-
self.assertEqual(len(data), CHUNK * SIZE)
1554+
assert count > 0
1555+
data = sock.recv_all(CHUNK * count)
1556+
self.assertEqual(len(data), CHUNK * count)
15441557

15451558
sock.close()
15461559

15471560
async def client(addr):
1548-
nonlocal future
1561+
nonlocal future, count
15491562
future = self.loop.create_future()
15501563

15511564
reader, writer = await asyncio.open_connection(
@@ -1557,15 +1570,21 @@ async def client(addr):
15571570
data = await reader.readexactly(4)
15581571
self.assertEqual(data, b'pong')
15591572

1560-
# fill write backlog in a hacky way - renegotiation won't help
1561-
for _ in range(SIZE*2):
1562-
writer.transport._test__append_write_backlog(b'x' * CHUNK)
1573+
count = 0
1574+
# Fill the buffer - with a hack to ensure the protocol is
1575+
# paused without actually waiting on drain
1576+
while not writer._protocol._paused:
1577+
writer.write(b'x' * CHUNK)
1578+
count += 1
1579+
await asyncio.sleep(0)
1580+
filled.set()
15631581

15641582
try:
15651583
data = await reader.read()
15661584
self.assertEqual(data, b'')
15671585
except (BrokenPipeError, ConnectionResetError):
15681586
pass
1587+
eof_received.set()
15691588

15701589
# Make sure _SelectorSocketTransport enters the delayed write
15711590
# path in its `write` method by wrapping socket in a fake class
@@ -1614,9 +1633,15 @@ def wrapper(sock):
16141633
self.loop.call_soon_threadsafe(future.set_result, None)
16151634
return wrapper
16161635

1636+
filled = threading.Event()
1637+
eof_received = threading.Event()
1638+
count = 0
16171639
with self.tcp_server(run(server)) as srv:
16181640
self.loop.run_until_complete(client(srv.addr))
16191641

1642+
filled = threading.Event()
1643+
eof_received = threading.Event()
1644+
count = 0
16201645
with self.tcp_server(run(eof_server)) as srv:
16211646
self.loop.run_until_complete(client(srv.addr))
16221647

‎Lib/test/test_asyncio/test_sslproto.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ def connection_made(self, ssl_proto, *, do_handshake=None):
4747
sslobj = mock.Mock()
4848
# emulate reading decompressed data
4949
sslobj.read.side_effect = ssl.SSLWantReadError
50-
sslobj.write.side_effect = ssl.SSLWantReadError
50+
# NOTE: sslobj.write is left as a plain Mock (writes succeed).
51+
# There is no outgoing write buffer anymore, so an SSLWantReadError
52+
# from write() would propagate to the caller instead of being
53+
# buffered and retried.
5154
if do_handshake is not None:
5255
sslobj.do_handshake = do_handshake
5356
ssl_proto._sslobj = sslobj
@@ -169,7 +172,9 @@ def test_connection_lost_when_busy(self):
169172
# emulate reading decompressed data
170173
sslobj = mock.Mock()
171174
sslobj.read.side_effect = ssl.SSLWantReadError
172-
sslobj.write.side_effect = ssl.SSLWantReadError
175+
# NOTE: writes succeed (plain Mock). There is no outgoing write
176+
# buffer anymore, so an SSLWantReadError from write() would
177+
# propagate to the caller instead of being buffered and retried.
173178
ssl_proto._sslobj = sslobj
174179

175180
# emulate outgoing data
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Remove the redundant outgoing write buffer from :mod:`asyncio`
2+
TLS transports. Encrypted data is now written directly to the underlying
3+
transport, and write flow control is delegated to it. This also fixes an
4+
:exc:`AssertionError` when the buffer size was checked inconsistently.

0 commit comments

Comments
 (0)