Skip to content

Commit fa19e74

Browse files
Merge branch 'main' into local-annos
2 parents 989b47f + fccf9ab commit fa19e74

28 files changed

+275
-168
lines changed

.github/workflows/tail-call.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ jobs:
8787
set PlatformToolset=clangcl
8888
set LLVMToolsVersion=${{ matrix.llvm }}.1.5
8989
set LLVMInstallDir=C:\Program Files\LLVM
90-
./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }}
91-
./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
90+
call ./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture }}
91+
call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3
9292
9393
# No tests (yet):
9494
- name: Emulated Windows (release)

Doc/library/os.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3693,16 +3693,16 @@ features:
36933693

36943694
This example displays the number of bytes taken by non-directory files in each
36953695
directory under the starting directory, except that it doesn't look under any
3696-
CVS subdirectory::
3696+
``__pycache__`` subdirectory::
36973697

36983698
import os
36993699
from os.path import join, getsize
3700-
for root, dirs, files in os.walk('python/Lib/email'):
3700+
for root, dirs, files in os.walk('python/Lib/xml'):
37013701
print(root, "consumes", end=" ")
37023702
print(sum(getsize(join(root, name)) for name in files), end=" ")
37033703
print("bytes in", len(files), "non-directory files")
3704-
if 'CVS' in dirs:
3705-
dirs.remove('CVS') # don't visit CVS directories
3704+
if '__pycache__' in dirs:
3705+
dirs.remove('__pycache__') # don't visit __pycache__ directories
37063706

37073707
In the next example (simple implementation of :func:`shutil.rmtree`),
37083708
walking the tree bottom-up is essential, :func:`rmdir` doesn't allow
@@ -3755,16 +3755,16 @@ features:
37553755

37563756
This example displays the number of bytes taken by non-directory files in each
37573757
directory under the starting directory, except that it doesn't look under any
3758-
CVS subdirectory::
3758+
``__pycache__`` subdirectory::
37593759

37603760
import os
3761-
for root, dirs, files, rootfd in os.fwalk('python/Lib/email'):
3761+
for root, dirs, files, rootfd in os.fwalk('python/Lib/xml'):
37623762
print(root, "consumes", end="")
37633763
print(sum([os.stat(name, dir_fd=rootfd).st_size for name in files]),
37643764
end="")
37653765
print("bytes in", len(files), "non-directory files")
3766-
if 'CVS' in dirs:
3767-
dirs.remove('CVS') # don't visit CVS directories
3766+
if '__pycache__' in dirs:
3767+
dirs.remove('__pycache__') # don't visit __pycache__ directories
37683768

37693769
In the next example, walking the tree bottom-up is essential:
37703770
:func:`rmdir` doesn't allow deleting a directory before the directory is

Include/internal/pycore_dict.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,10 @@ extern int _PyDict_Pop_KnownHash(
150150
Py_hash_t hash,
151151
PyObject **result);
152152

153+
#ifdef Py_GIL_DISABLED
154+
PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp);
155+
#endif
156+
153157
#define DKIX_EMPTY (-1)
154158
#define DKIX_DUMMY (-2) /* Used internally */
155159
#define DKIX_ERROR (-3)

Lib/os.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,12 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
345345
346346
import os
347347
from os.path import join, getsize
348-
for root, dirs, files in os.walk('python/Lib/email'):
348+
for root, dirs, files in os.walk('python/Lib/xml'):
349349
print(root, "consumes ")
350350
print(sum(getsize(join(root, name)) for name in files), end=" ")
351351
print("bytes in", len(files), "non-directory files")
352-
if 'CVS' in dirs:
353-
dirs.remove('CVS') # don't visit CVS directories
352+
if '__pycache__' in dirs:
353+
dirs.remove('__pycache__') # don't visit __pycache__ directories
354354
355355
"""
356356
sys.audit("os.walk", top, topdown, onerror, followlinks)
@@ -460,13 +460,13 @@ def fwalk(top=".", topdown=True, onerror=None, *, follow_symlinks=False, dir_fd=
460460
Example:
461461
462462
import os
463-
for root, dirs, files, rootfd in os.fwalk('python/Lib/email'):
463+
for root, dirs, files, rootfd in os.fwalk('python/Lib/xml'):
464464
print(root, "consumes", end="")
465465
print(sum(os.stat(name, dir_fd=rootfd).st_size for name in files),
466466
end="")
467467
print("bytes in", len(files), "non-directory files")
468-
if 'CVS' in dirs:
469-
dirs.remove('CVS') # don't visit CVS directories
468+
if '__pycache__' in dirs:
469+
dirs.remove('__pycache__') # don't visit __pycache__ directories
470470
"""
471471
sys.audit("os.fwalk", top, topdown, onerror, follow_symlinks, dir_fd)
472472
top = fspath(top)

Lib/test/audit-tests.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,15 @@ def test_open(testfn):
208208
if not fn:
209209
continue
210210
with assertRaises(RuntimeError):
211-
fn(*args)
211+
try:
212+
fn(*args)
213+
except NotImplementedError:
214+
if fn == load_dh_params:
215+
# Not callable in some builds
216+
load_dh_params = None
217+
raise RuntimeError
218+
else:
219+
raise
212220

213221
actual_mode = [(a[0], a[1]) for e, a in hook.seen if e == "open" and a[1]]
214222
actual_flag = [(a[0], a[2]) for e, a in hook.seen if e == "open" and not a[1]]

Lib/test/libregrtest/tsan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# chosen because they use threads and run in a reasonable amount of time.
33

44
TSAN_TESTS = [
5-
'test_asyncio.test_free_threading',
5+
'test_asyncio',
66
# TODO: enable more of test_capi once bugs are fixed (GH-116908, GH-116909).
77
'test_capi.test_mem',
88
'test_capi.test_pyatomic',

Lib/test/test_asyncio/test_events.py

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2652,33 +2652,46 @@ def callback(*args):
26522652

26532653
h1 = asyncio.TimerHandle(when, callback, (), self.loop)
26542654
h2 = asyncio.TimerHandle(when, callback, (), self.loop)
2655-
# TODO: Use assertLess etc.
2656-
self.assertFalse(h1 < h2)
2657-
self.assertFalse(h2 < h1)
2658-
self.assertTrue(h1 <= h2)
2659-
self.assertTrue(h2 <= h1)
2660-
self.assertFalse(h1 > h2)
2661-
self.assertFalse(h2 > h1)
2662-
self.assertTrue(h1 >= h2)
2663-
self.assertTrue(h2 >= h1)
2664-
self.assertTrue(h1 == h2)
2665-
self.assertFalse(h1 != h2)
2655+
with self.assertRaises(AssertionError):
2656+
self.assertLess(h1, h2)
2657+
with self.assertRaises(AssertionError):
2658+
self.assertLess(h2, h1)
2659+
with self.assertRaises(AssertionError):
2660+
self.assertGreater(h1, h2)
2661+
with self.assertRaises(AssertionError):
2662+
self.assertGreater(h2, h1)
2663+
with self.assertRaises(AssertionError):
2664+
self.assertNotEqual(h1, h2)
2665+
2666+
self.assertLessEqual(h1, h2)
2667+
self.assertLessEqual(h2, h1)
2668+
self.assertGreaterEqual(h1, h2)
2669+
self.assertGreaterEqual(h2, h1)
2670+
self.assertEqual(h1, h2)
26662671

26672672
h2.cancel()
2668-
self.assertFalse(h1 == h2)
2673+
with self.assertRaises(AssertionError):
2674+
self.assertEqual(h1, h2)
2675+
self.assertNotEqual(h1, h2)
26692676

26702677
h1 = asyncio.TimerHandle(when, callback, (), self.loop)
26712678
h2 = asyncio.TimerHandle(when + 10.0, callback, (), self.loop)
2672-
self.assertTrue(h1 < h2)
2673-
self.assertFalse(h2 < h1)
2674-
self.assertTrue(h1 <= h2)
2675-
self.assertFalse(h2 <= h1)
2676-
self.assertFalse(h1 > h2)
2677-
self.assertTrue(h2 > h1)
2678-
self.assertFalse(h1 >= h2)
2679-
self.assertTrue(h2 >= h1)
2680-
self.assertFalse(h1 == h2)
2681-
self.assertTrue(h1 != h2)
2679+
with self.assertRaises(AssertionError):
2680+
self.assertLess(h2, h1)
2681+
with self.assertRaises(AssertionError):
2682+
self.assertLessEqual(h2, h1)
2683+
with self.assertRaises(AssertionError):
2684+
self.assertGreater(h1, h2)
2685+
with self.assertRaises(AssertionError):
2686+
self.assertGreaterEqual(h1, h2)
2687+
with self.assertRaises(AssertionError):
2688+
self.assertEqual(h1, h2)
2689+
2690+
self.assertLess(h1, h2)
2691+
self.assertGreater(h2, h1)
2692+
self.assertLessEqual(h1, h2)
2693+
self.assertGreaterEqual(h2, h1)
2694+
self.assertNotEqual(h1, h2)
26822695

26832696
h3 = asyncio.Handle(callback, (), self.loop)
26842697
self.assertIs(NotImplemented, h1.__eq__(h3))
@@ -2692,19 +2705,25 @@ def callback(*args):
26922705
h1 <= ()
26932706
with self.assertRaises(TypeError):
26942707
h1 >= ()
2695-
self.assertFalse(h1 == ())
2696-
self.assertTrue(h1 != ())
2697-
2698-
self.assertTrue(h1 == ALWAYS_EQ)
2699-
self.assertFalse(h1 != ALWAYS_EQ)
2700-
self.assertTrue(h1 < LARGEST)
2701-
self.assertFalse(h1 > LARGEST)
2702-
self.assertTrue(h1 <= LARGEST)
2703-
self.assertFalse(h1 >= LARGEST)
2704-
self.assertFalse(h1 < SMALLEST)
2705-
self.assertTrue(h1 > SMALLEST)
2706-
self.assertFalse(h1 <= SMALLEST)
2707-
self.assertTrue(h1 >= SMALLEST)
2708+
with self.assertRaises(AssertionError):
2709+
self.assertEqual(h1, ())
2710+
with self.assertRaises(AssertionError):
2711+
self.assertNotEqual(h1, ALWAYS_EQ)
2712+
with self.assertRaises(AssertionError):
2713+
self.assertGreater(h1, LARGEST)
2714+
with self.assertRaises(AssertionError):
2715+
self.assertGreaterEqual(h1, LARGEST)
2716+
with self.assertRaises(AssertionError):
2717+
self.assertLess(h1, SMALLEST)
2718+
with self.assertRaises(AssertionError):
2719+
self.assertLessEqual(h1, SMALLEST)
2720+
2721+
self.assertNotEqual(h1, ())
2722+
self.assertEqual(h1, ALWAYS_EQ)
2723+
self.assertLess(h1, LARGEST)
2724+
self.assertLessEqual(h1, LARGEST)
2725+
self.assertGreaterEqual(h1, SMALLEST)
2726+
self.assertGreater(h1, SMALLEST)
27082727

27092728

27102729
class AbstractEventLoopTests(unittest.TestCase):

Lib/test/test_audit.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def run_test_in_subprocess(self, *args):
2323
with subprocess.Popen(
2424
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
2525
encoding="utf-8",
26+
errors="backslashreplace",
2627
stdout=subprocess.PIPE,
2728
stderr=subprocess.PIPE,
2829
) as p:

Lib/test/test_pyrepl/test_interact.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def test_multiple_statements_fail_early(self):
5858
console = InteractiveColoredConsole()
5959
code = dedent("""\
6060
raise Exception('foobar')
61-
print('spam&eggs')
61+
print('spam', 'eggs', sep='&')
6262
""")
6363
f = io.StringIO()
6464
with contextlib.redirect_stderr(f):

Lib/test/test_ssl.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,10 +1321,14 @@ def test_load_verify_cadata(self):
13211321
with self.assertRaises(ssl.SSLError):
13221322
ctx.load_verify_locations(cadata=cacert_der + b"A")
13231323

1324-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
13251324
def test_load_dh_params(self):
13261325
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
1327-
ctx.load_dh_params(DHFILE)
1326+
try:
1327+
ctx.load_dh_params(DHFILE)
1328+
except RuntimeError:
1329+
if Py_DEBUG_WIN32:
1330+
self.skipTest("not supported on Win32 debug build")
1331+
raise
13281332
ctx.load_dh_params(BYTES_DHFILE)
13291333
self.assertRaises(TypeError, ctx.load_dh_params)
13301334
self.assertRaises(TypeError, ctx.load_dh_params, None)
@@ -1648,12 +1652,17 @@ def test_str(self):
16481652
self.assertEqual(str(e), "foo")
16491653
self.assertEqual(e.errno, 1)
16501654

1651-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
16521655
def test_lib_reason(self):
16531656
# Test the library and reason attributes
16541657
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
1655-
with self.assertRaises(ssl.SSLError) as cm:
1656-
ctx.load_dh_params(CERTFILE)
1658+
try:
1659+
with self.assertRaises(ssl.SSLError) as cm:
1660+
ctx.load_dh_params(CERTFILE)
1661+
except RuntimeError:
1662+
if Py_DEBUG_WIN32:
1663+
self.skipTest("not supported on Win32 debug build")
1664+
raise
1665+
16571666
self.assertEqual(cm.exception.library, 'PEM')
16581667
regex = "(NO_START_LINE|UNSUPPORTED_PUBLIC_KEY_TYPE)"
16591668
self.assertRegex(cm.exception.reason, regex)
@@ -2773,6 +2782,14 @@ def try_protocol_combo(server_protocol, client_protocol, expect_success,
27732782
% (expect_success, stats['version']))
27742783

27752784

2785+
def supports_kx_alias(ctx, aliases):
2786+
for cipher in ctx.get_ciphers():
2787+
for alias in aliases:
2788+
if f"Kx={alias}" in cipher['description']:
2789+
return True
2790+
return False
2791+
2792+
27762793
class ThreadedTests(unittest.TestCase):
27772794

27782795
@support.requires_resource('walltime')
@@ -4032,21 +4049,30 @@ def test_no_legacy_server_connect(self):
40324049
chatty=True, connectionchatty=True,
40334050
sni_name=hostname)
40344051

4035-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
40364052
def test_dh_params(self):
4037-
# Check we can get a connection with ephemeral Diffie-Hellman
4053+
# Check we can get a connection with ephemeral finite-field
4054+
# Diffie-Hellman (if supported).
40384055
client_context, server_context, hostname = testing_context()
4056+
dhe_aliases = {"ADH", "EDH", "DHE"}
4057+
if not (supports_kx_alias(client_context, dhe_aliases)
4058+
and supports_kx_alias(server_context, dhe_aliases)):
4059+
self.skipTest("libssl doesn't support ephemeral DH")
40394060
# test scenario needs TLS <= 1.2
40404061
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
4041-
server_context.load_dh_params(DHFILE)
4062+
try:
4063+
server_context.load_dh_params(DHFILE)
4064+
except RuntimeError:
4065+
if Py_DEBUG_WIN32:
4066+
self.skipTest("not supported on Win32 debug build")
4067+
raise
40424068
server_context.set_ciphers("kEDH")
40434069
server_context.maximum_version = ssl.TLSVersion.TLSv1_2
40444070
stats = server_params_test(client_context, server_context,
40454071
chatty=True, connectionchatty=True,
40464072
sni_name=hostname)
40474073
cipher = stats["cipher"][0]
40484074
parts = cipher.split("-")
4049-
if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4075+
if not dhe_aliases.intersection(parts):
40504076
self.fail("Non-DH key exchange: " + cipher[0])
40514077

40524078
def test_ecdh_curve(self):
@@ -4819,14 +4845,18 @@ def keylog_lines(self, fname=os_helper.TESTFN):
48194845
return len(list(f))
48204846

48214847
@requires_keylog
4822-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
48234848
def test_keylog_defaults(self):
48244849
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
48254850
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
48264851
self.assertEqual(ctx.keylog_filename, None)
48274852

48284853
self.assertFalse(os.path.isfile(os_helper.TESTFN))
4829-
ctx.keylog_filename = os_helper.TESTFN
4854+
try:
4855+
ctx.keylog_filename = os_helper.TESTFN
4856+
except RuntimeError:
4857+
if Py_DEBUG_WIN32:
4858+
self.skipTest("not supported on Win32 debug build")
4859+
raise
48304860
self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
48314861
self.assertTrue(os.path.isfile(os_helper.TESTFN))
48324862
self.assertEqual(self.keylog_lines(), 1)
@@ -4843,12 +4873,17 @@ def test_keylog_defaults(self):
48434873
ctx.keylog_filename = 1
48444874

48454875
@requires_keylog
4846-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
48474876
def test_keylog_filename(self):
48484877
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
48494878
client_context, server_context, hostname = testing_context()
48504879

4851-
client_context.keylog_filename = os_helper.TESTFN
4880+
try:
4881+
client_context.keylog_filename = os_helper.TESTFN
4882+
except RuntimeError:
4883+
if Py_DEBUG_WIN32:
4884+
self.skipTest("not supported on Win32 debug build")
4885+
raise
4886+
48524887
server = ThreadedEchoServer(context=server_context, chatty=False)
48534888
with server:
48544889
with client_context.wrap_socket(socket.socket(),
@@ -4881,7 +4916,6 @@ def test_keylog_filename(self):
48814916
@requires_keylog
48824917
@unittest.skipIf(sys.flags.ignore_environment,
48834918
"test is not compatible with ignore_environment")
4884-
@unittest.skipIf(Py_DEBUG_WIN32, "Avoid mixing debug/release CRT on Windows")
48854919
def test_keylog_env(self):
48864920
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
48874921
with unittest.mock.patch.dict(os.environ):
@@ -4891,7 +4925,12 @@ def test_keylog_env(self):
48914925
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
48924926
self.assertEqual(ctx.keylog_filename, None)
48934927

4894-
ctx = ssl.create_default_context()
4928+
try:
4929+
ctx = ssl.create_default_context()
4930+
except RuntimeError:
4931+
if Py_DEBUG_WIN32:
4932+
self.skipTest("not supported on Win32 debug build")
4933+
raise
48954934
self.assertEqual(ctx.keylog_filename, os_helper.TESTFN)
48964935

48974936
ctx = ssl._create_stdlib_context()

0 commit comments

Comments
 (0)