Skip to content

Commit 9fcd45c

Browse files
authored
Merge branch 'main' into fix-proactor-error-hang
2 parents 9eda8d0 + 8b2433a commit 9fcd45c

41 files changed

Lines changed: 759 additions & 272 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Lib/asyncio/proactor_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,8 @@ async def _sock_sendfile_native(self, sock, file, offset, count):
778778
async def _sendfile_native(self, transp, file, offset, count):
779779
resume_reading = transp.is_reading()
780780
transp.pause_reading()
781-
await transp._make_empty_waiter()
782781
try:
782+
await transp._make_empty_waiter()
783783
return await self.sock_sendfile(transp._sock, file, offset, count,
784784
fallback=False)
785785
finally:

Lib/asyncio/selector_events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,8 @@ async def _sendfile_native(self, transp, file, offset, count):
739739
del self._transports[transp._sock_fd]
740740
resume_reading = transp.is_reading()
741741
transp.pause_reading()
742-
await transp._make_empty_waiter()
743742
try:
743+
await transp._make_empty_waiter()
744744
return await self.sock_sendfile(transp._sock, file, offset, count,
745745
fallback=False)
746746
finally:

Lib/difflib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match']
3232

3333
from heapq import nlargest as _nlargest
34-
from collections import namedtuple as _namedtuple
34+
from collections import deque as _deque, namedtuple as _namedtuple
3535
from types import GenericAlias
3636
lazy from _colorize import can_colorize, get_theme
3737

@@ -1571,7 +1571,7 @@ def _line_pair_iterator():
15711571
is defined) does not need to be of module scope.
15721572
"""
15731573
line_iterator = _line_iterator()
1574-
fromlines,tolines=[],[]
1574+
fromlines, tolines = _deque(), _deque()
15751575
while True:
15761576
# Collecting lines of text until we have a from/to pair
15771577
while (len(fromlines)==0 or len(tolines)==0):
@@ -1584,8 +1584,8 @@ def _line_pair_iterator():
15841584
if to_line is not None:
15851585
tolines.append((to_line,found_diff))
15861586
# Once we have a pair, remove them from the collection and yield it
1587-
from_line, fromDiff = fromlines.pop(0)
1588-
to_line, to_diff = tolines.pop(0)
1587+
from_line, fromDiff = fromlines.popleft()
1588+
to_line, to_diff = tolines.popleft()
15891589
yield (from_line,to_line,fromDiff or to_diff)
15901590

15911591
# Handle case where user does not want context differencing, just yield

Lib/idlelib/idle_test/test_configdialog.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ def test_fontlist_key(self):
150150
font = d.fontlist.get('active')
151151

152152
# Test Down key.
153-
fontlist.focus_force()
154153
fontlist.update()
154+
fontlist.focus_force()
155155
fontlist.event_generate('<Key-Down>')
156156
fontlist.event_generate('<KeyRelease-Down>')
157157

@@ -160,8 +160,8 @@ def test_fontlist_key(self):
160160
self.assertIn(d.font_name.get(), down_font.lower())
161161

162162
# Test Up key.
163-
fontlist.focus_force()
164163
fontlist.update()
164+
fontlist.focus_force()
165165
fontlist.event_generate('<Key-Up>')
166166
fontlist.event_generate('<KeyRelease-Up>')
167167

Lib/test/test_asyncio/test_sendfile.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,47 @@ def test_sendfile(self):
376376
self.assertEqual(srv_proto.data, self.DATA)
377377
self.assertEqual(self.file.tell(), len(self.DATA))
378378

379+
def test_sendfile_cancel_empty_waiter(self):
380+
for reading in (True, False):
381+
with self.subTest(reading=reading):
382+
srv_proto, cli_proto = self.prepare_sendfile()
383+
transport = cli_proto.transport
384+
if not reading:
385+
transport.pause_reading()
386+
waiter = self.loop.create_future()
387+
388+
def make_empty_waiter():
389+
transport._empty_waiter = waiter
390+
return waiter
391+
392+
with mock.patch.object(transport, '_make_empty_waiter',
393+
side_effect=make_empty_waiter):
394+
task = self.loop.create_task(
395+
self.loop.sendfile(transport, self.file))
396+
test_utils.run_briefly(self.loop)
397+
self.assertIs(transport._empty_waiter, waiter)
398+
self.assertFalse(waiter.done())
399+
self.assertFalse(transport.is_reading())
400+
task.cancel()
401+
with self.assertRaises(asyncio.CancelledError):
402+
self.run_loop(task)
403+
404+
try:
405+
self.assertIsNone(transport._empty_waiter)
406+
self.assertEqual(transport.is_reading(), reading)
407+
if isinstance(self.loop, asyncio.SelectorEventLoop):
408+
self.assertIs(
409+
self.loop._transports[transport._sock_fd],
410+
transport)
411+
finally:
412+
transport._reset_empty_waiter()
413+
414+
ret = self.run_loop(self.loop.sendfile(transport, self.file))
415+
transport.close()
416+
self.run_loop(srv_proto.done)
417+
self.assertEqual(ret, len(self.DATA))
418+
self.assertEqual(srv_proto.data, self.DATA)
419+
379420
def test_sendfile_force_fallback(self):
380421
srv_proto, cli_proto = self.prepare_sendfile()
381422

Lib/test/test_capi/test_tokenizer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ class TokenizerTests(unittest.TestCase):
99
def test_source(self):
1010
_testinternalcapi.test_tokenizer_source()
1111

12+
def test_source_discard(self):
13+
_testinternalcapi.test_tokenizer_source_discard()
14+
1215
def test_cursor(self):
1316
_testinternalcapi.test_tokenizer_cursor()
1417

Lib/test/test_difflib.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,26 @@ def test_mdiff_catch_stop_iteration(self):
200200
[((1, '\x00-2\x01'), (1, '\x00+3\x01'), True)],
201201
)
202202

203+
def test_mdiff_lopsided_replace(self):
204+
self.assertEqual(
205+
list(difflib._mdiff(["a\n"] * 4, ["b\n"])),
206+
[
207+
((1, '\x00-a\n\x01'), (1, '\x00+b\n\x01'), True),
208+
((2, '\x00-a\n\x01'), ('', '\n'), True),
209+
((3, '\x00-a\n\x01'), ('', '\n'), True),
210+
((4, '\x00-a\n\x01'), ('', '\n'), True),
211+
],
212+
)
213+
self.assertEqual(
214+
list(difflib._mdiff(["a\n"], ["b\n"] * 4)),
215+
[
216+
((1, '\x00-a\n\x01'), (1, '\x00+b\n\x01'), True),
217+
(('', '\n'), (2, '\x00+b\n\x01'), True),
218+
(('', '\n'), (3, '\x00+b\n\x01'), True),
219+
(('', '\n'), (4, '\x00+b\n\x01'), True),
220+
],
221+
)
222+
203223

204224
patch914575_from1 = """
205225
1. Beautiful is beTTer than ugly.

Lib/test/test_hashlib.py

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import tempfile
1919
import threading
2020
import unittest
21+
from functools import partial
22+
from operator import attrgetter
2123
from test import support
2224
from test.support import _4G, bigmemtest
2325
from test.support import hashlib_helper
@@ -52,18 +54,39 @@
5254
def get_fips_mode():
5355
return 0
5456

57+
58+
try:
59+
import _md5
60+
except ImportError:
61+
_md5 = None
62+
requires_md5 = unittest.skipUnless(_md5, 'requires _md5')
63+
64+
5565
try:
5666
import _blake2
5767
except ImportError:
5868
_blake2 = None
59-
6069
requires_blake2 = unittest.skipUnless(_blake2, 'requires _blake2')
6170

71+
72+
try:
73+
import _sha1
74+
except ImportError:
75+
_sha1 = None
76+
requires_sha1 = unittest.skipUnless(_sha1, 'requires _sha1')
77+
78+
79+
try:
80+
import _sha2
81+
except ImportError:
82+
_sha2 = None
83+
requires_sha2 = unittest.skipUnless(_sha2, 'requires _sha2')
84+
85+
6286
try:
6387
import _sha3
6488
except ImportError:
6589
_sha3 = None
66-
6790
requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
6891

6992

@@ -1418,5 +1441,76 @@ def scrypt(password=b"password", /, **kwargs):
14181441
self.assertRaises(numeric_exc_types, scrypt, dklen=MAX_DKLEN + 1)
14191442

14201443

1444+
@threading_helper.requires_working_threading()
1445+
class TestTSAN(unittest.TestCase):
1446+
1447+
@threading_helper.reap_threads
1448+
def check_attribute(self, write, read, expected, nthreads=8):
1449+
ready = threading.Event()
1450+
barrier = threading.Barrier(nthreads)
1451+
1452+
def writer():
1453+
barrier.wait()
1454+
while not ready.is_set():
1455+
write()
1456+
1457+
def reader():
1458+
barrier.wait()
1459+
while not ready.is_set():
1460+
self.assertEqual(read(), expected)
1461+
1462+
targets = [writer if i % 2 else reader for i in range(nthreads)]
1463+
workers = [threading.Thread(target=target) for target in targets]
1464+
with threading_helper.start_threads(workers, unlock=ready.set):
1465+
pass
1466+
1467+
def check_HACL_attribute(self, module, version, attrname):
1468+
blob = b"A" * 65536
1469+
obj = getattr(module, version)()
1470+
update = partial(obj.update, blob)
1471+
read = attrgetter(attrname)
1472+
self.check_attribute(update, partial(read, obj), read(obj))
1473+
1474+
@requires_md5
1475+
@support.subTests("attrname", ["block_size", "digest_size"])
1476+
def test_HACL_md5_attributes(self, attrname):
1477+
self.check_HACL_attribute(_md5, "md5", attrname)
1478+
1479+
@requires_sha1
1480+
@support.subTests("attrname", ["block_size", "digest_size"])
1481+
def test_HACL_sha1_attributes(self, attrname):
1482+
self.check_HACL_attribute(_sha1, "sha1", attrname)
1483+
1484+
@requires_sha2
1485+
@support.subTests("size", [224, 256, 384, 512])
1486+
@support.subTests("attrname", ["block_size", "digest_size"])
1487+
def test_HACL_sha2_attributes(self, size, attrname):
1488+
self.check_HACL_attribute(_sha2, f"sha{size}", attrname)
1489+
1490+
@requires_sha3
1491+
@support.subTests("size", [224, 256, 384, 512])
1492+
@support.subTests(
1493+
"attrname",
1494+
["block_size", "digest_size", "_capacity_bits", "_rate_bits"],
1495+
)
1496+
def test_HACL_sha3_attributes(self, size, attrname):
1497+
self.check_HACL_attribute(_sha3, f"sha3_{size}", attrname)
1498+
1499+
@requires_sha3
1500+
@support.subTests("size", [128, 256])
1501+
@support.subTests(
1502+
"attrname",
1503+
["block_size", "digest_size", "_capacity_bits", "_rate_bits"],
1504+
)
1505+
def test_HACL_shake_attributes(self, size, attrname):
1506+
self.check_HACL_attribute(_sha3, f"shake_{size}", attrname)
1507+
1508+
@requires_blake2
1509+
@support.subTests("version", ["blake2s", "blake2b"])
1510+
@support.subTests("attrname", ["block_size", "digest_size"])
1511+
def test_HACL_blake2_attributes(self, version, attrname):
1512+
self.check_HACL_attribute(_blake2, version, attrname)
1513+
1514+
14211515
if __name__ == "__main__":
14221516
unittest.main()

Lib/test/test_io/test_memoryio.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,18 @@ def test_cow_mutable(self):
10251025
memio = self.ioclass(ba)
10261026
self.assertEqual(sys.getrefcount(ba), old_rc)
10271027

1028+
def test_write_with_export(self):
1029+
memio = self.ioclass(b"abcd")
1030+
memio.seek(2)
1031+
with memio.getbuffer() as view:
1032+
self.assertRaises(BufferError, memio.__init__, b"replacement")
1033+
self.assertEqual(memio.tell(), 2)
1034+
self.assertEqual(memio.getvalue(), b"abcd")
1035+
self.assertEqual(bytes(view), b"abcd")
1036+
memio.write(b"X")
1037+
self.assertEqual(memio.getvalue(), b"abXd")
1038+
1039+
10281040
class CStringIOTest(PyStringIOTest):
10291041
ioclass = io.StringIO
10301042
UnsupportedOperation = io.UnsupportedOperation

Lib/test/test_repl.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@ def test_lexer_buffer_realloc_with_null_start(self):
198198
self.assertEqual(p.returncode, 0)
199199
self.assertIn(long_value, output)
200200

201+
@cpython_only
202+
def test_multiline_fstring_source_reallocation(self):
203+
long_line = " " * 9000 + "+ 2"
204+
user_input = (
205+
'value = f"""{(\n'
206+
'1\n'
207+
f'{long_line}\n'
208+
')}"""\n'
209+
'print(value)\n'
210+
)
211+
p = spawn_repl()
212+
p.stdin.write(user_input)
213+
output = kill_python(p)
214+
self.assertEqual(p.returncode, 0)
215+
self.assertIn(">>> 3\n>>> ", output)
216+
201217
def test_close_stdin(self):
202218
user_input = dedent('''
203219
import os

0 commit comments

Comments
 (0)