Skip to content

Commit 08d92db

Browse files
authored
Merge branch 'main' into windows-add-sysconfig-abiflags
2 parents 8fa952b + fccf9ab commit 08d92db

File tree

12 files changed

+125
-62
lines changed

12 files changed

+125
-62
lines changed

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/test_ssl.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2782,6 +2782,14 @@ def try_protocol_combo(server_protocol, client_protocol, expect_success,
27822782
% (expect_success, stats['version']))
27832783

27842784

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+
27852793
class ThreadedTests(unittest.TestCase):
27862794

27872795
@support.requires_resource('walltime')
@@ -4042,8 +4050,13 @@ def test_no_legacy_server_connect(self):
40424050
sni_name=hostname)
40434051

40444052
def test_dh_params(self):
4045-
# 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).
40464055
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")
40474060
# test scenario needs TLS <= 1.2
40484061
client_context.maximum_version = ssl.TLSVersion.TLSv1_2
40494062
try:
@@ -4059,7 +4072,7 @@ def test_dh_params(self):
40594072
sni_name=hostname)
40604073
cipher = stats["cipher"][0]
40614074
parts = cipher.split("-")
4062-
if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
4075+
if not dhe_aliases.intersection(parts):
40634076
self.fail("Non-DH key exchange: " + cipher[0])
40644077

40654078
def test_ecdh_curve(self):

Lib/test/test_tools/test_msgfmt.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Tests for the Tools/i18n/msgfmt.py tool."""
22

33
import json
4+
import struct
45
import sys
56
import unittest
67
from gettext import GNUTranslations
@@ -40,6 +41,28 @@ def test_compilation(self):
4041

4142
self.assertDictEqual(actual._catalog, expected._catalog)
4243

44+
def test_binary_header(self):
45+
with open(data_dir / "general.mo", "rb") as f:
46+
mo_data = f.read()
47+
48+
(
49+
magic,
50+
version,
51+
num_strings,
52+
orig_table_offset,
53+
trans_table_offset,
54+
hash_table_size,
55+
hash_table_offset,
56+
) = struct.unpack("=Iiiiiii", mo_data[:28])
57+
58+
self.assertEqual(magic, 0x950412de)
59+
self.assertEqual(version, 0)
60+
self.assertEqual(num_strings, 9)
61+
self.assertEqual(orig_table_offset, 28)
62+
self.assertEqual(trans_table_offset, 100)
63+
self.assertEqual(hash_table_size, 0)
64+
self.assertEqual(hash_table_offset, 0)
65+
4366
def test_translations(self):
4467
with open(data_dir / 'general.mo', 'rb') as f:
4568
t = GNUTranslations(f)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``test_ssl.test_dh_params`` is skipped if the underlying TLS library does not support finite-field ephemeral Diffie-Hellman.

Objects/dictobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,12 @@ ensure_shared_on_read(PyDictObject *mp)
13261326
Py_END_CRITICAL_SECTION();
13271327
}
13281328
}
1329+
1330+
void
1331+
_PyDict_EnsureSharedOnRead(PyDictObject *mp)
1332+
{
1333+
ensure_shared_on_read(mp);
1334+
}
13291335
#endif
13301336

13311337
static inline void

Python/bytecodes.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,34 +2283,36 @@ dummy_func(
22832283
assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
22842284
PyDictObject *dict = _PyObject_GetManagedDict(owner_o);
22852285
DEOPT_IF(dict == NULL);
2286+
PyDictKeysObject *dk = FT_ATOMIC_LOAD_PTR(dict->ma_keys);
22862287
assert(PyDict_CheckExact((PyObject *)dict));
2288+
#ifdef Py_GIL_DISABLED
2289+
DEOPT_IF(!_Py_IsOwnedByCurrentThread((PyObject *)dict) && !_PyObject_GC_IS_SHARED(dict));
2290+
#endif
22872291
PyObject *attr_o;
2288-
if (!LOCK_OBJECT(dict)) {
2292+
if (hint >= (size_t)FT_ATOMIC_LOAD_SSIZE_RELAXED(dk->dk_nentries)) {
22892293
DEOPT_IF(true);
22902294
}
22912295

2292-
if (hint >= (size_t)dict->ma_keys->dk_nentries) {
2293-
UNLOCK_OBJECT(dict);
2294-
DEOPT_IF(true);
2295-
}
22962296
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
2297-
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
2298-
UNLOCK_OBJECT(dict);
2297+
if (dk->dk_kind != DICT_KEYS_UNICODE) {
22992298
DEOPT_IF(true);
23002299
}
2301-
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
2302-
if (ep->me_key != name) {
2303-
UNLOCK_OBJECT(dict);
2300+
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dk) + hint;
2301+
if (FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key) != name) {
23042302
DEOPT_IF(true);
23052303
}
2306-
attr_o = ep->me_value;
2304+
attr_o = FT_ATOMIC_LOAD_PTR(ep->me_value);
23072305
if (attr_o == NULL) {
2308-
UNLOCK_OBJECT(dict);
23092306
DEOPT_IF(true);
23102307
}
23112308
STAT_INC(LOAD_ATTR, hit);
2309+
#ifdef Py_GIL_DISABLED
2310+
if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) {
2311+
DEOPT_IF(true);
2312+
}
2313+
#else
23122314
attr = PyStackRef_FromPyObjectNew(attr_o);
2313-
UNLOCK_OBJECT(dict);
2315+
#endif
23142316
PyStackRef_CLOSE(owner);
23152317
}
23162318

Python/executor_cases.c.h

Lines changed: 19 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/gc.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,20 +2407,20 @@ void
24072407
PyUnstable_GC_VisitObjects(gcvisitobjects_t callback, void *arg)
24082408
{
24092409
GCState *gcstate = get_gc_state();
2410-
int origenstate = gcstate->enabled;
2410+
int original_state = gcstate->enabled;
24112411
gcstate->enabled = 0;
2412-
if (visit_generation(callback, arg, &gcstate->young)) {
2412+
if (visit_generation(callback, arg, &gcstate->young) < 0) {
24132413
goto done;
24142414
}
2415-
if (visit_generation(callback, arg, &gcstate->old[0])) {
2415+
if (visit_generation(callback, arg, &gcstate->old[0]) < 0) {
24162416
goto done;
24172417
}
2418-
if (visit_generation(callback, arg, &gcstate->old[1])) {
2418+
if (visit_generation(callback, arg, &gcstate->old[1]) < 0) {
24192419
goto done;
24202420
}
24212421
visit_generation(callback, arg, &gcstate->permanent_generation);
24222422
done:
2423-
gcstate->enabled = origenstate;
2423+
gcstate->enabled = original_state;
24242424
}
24252425

24262426
#endif // Py_GIL_DISABLED

0 commit comments

Comments
 (0)