Skip to content

Commit afd090f

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython 3.15 branch from GitHub (2026-07-28)
Summary: Imported python/cpython `3.15.0b4+dev` from upstream rev [`5cc8361`](https://www.github.com/python/cpython/commit/5cc8361e4baa3df705f8a811eeaeaa03e4f15b83) (committed 2026-07-28 02:30:04+00:00). # Commit Info - Base: (`3.15.0b4+dev`) - [`df66175`](https://www.github.com/python/cpython/commit/df66175cb819882828bb2583fb58e56ab23dc01d) (commit date: 2026-07-27 00:03:23+00:00) - Imported: (`3.15.0b4+dev`) - [`5cc8361`](https://www.github.com/python/cpython/commit/5cc8361e4baa3df705f8a811eeaeaa03e4f15b83) (commit date: 2026-07-28 02:30:04+00:00) # Noteworthy file changes - Low-signal files (3 added, 1 removed) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GJ-ghSCGxUcJPLEDAHQmMA3TwMI9br0LAAAz Reviewed By: itamaro Differential Revision: D113872247 fbshipit-source-id: cbf5873566dd8a4c0bf9553877fbe7c4e5a52449
1 parent 92cda99 commit afd090f

15 files changed

Lines changed: 108 additions & 71 deletions

Include/internal/pycore_interp_structs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -988,7 +988,6 @@ struct _is {
988988
struct _obmalloc_state *obmalloc;
989989

990990
PyObject *audit_hooks;
991-
PyMutex audit_hooks_mutex;
992991
PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];
993992
PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];
994993
PyContext_WatchCallback context_watchers[CONTEXT_MAX_WATCHERS];

Lib/asyncio/__main__.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,14 @@ def interrupt(self) -> None:
212212
loop = asyncio.new_event_loop()
213213
asyncio.set_event_loop(loop)
214214

215-
repl_locals = {'asyncio': asyncio}
216-
for key in {'__name__', '__package__',
217-
'__loader__', '__spec__',
218-
'__builtins__', '__file__'}:
219-
repl_locals[key] = locals()[key]
215+
repl_locals = {
216+
'asyncio': asyncio,
217+
'__name__': __name__,
218+
'__package__': None,
219+
'__loader__': __loader__,
220+
'__spec__': None,
221+
'__builtins__': __builtins__,
222+
}
220223

221224
console = AsyncIOInteractiveConsole(repl_locals, loop)
222225

Lib/collections/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,9 @@ class Counter(dict):
553553
or multiset. Elements are stored as dictionary keys and their counts
554554
are stored as dictionary values.
555555
556+
When constructed from a Mapping or Counter, the original object's
557+
values will be used as the initial counts.
558+
556559
>>> c = Counter('abcdeabcdabcaba') # count elements from a string
557560
558561
>>> c.most_common(3) # three most common elements

Lib/sysconfig/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ def parse_config_h(fp, vars=None):
437437
import re
438438
define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n")
439439
undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n")
440+
quoted_re = re.compile('^"(.*)"$')
440441

441442
while True:
442443
line = fp.readline()
@@ -445,6 +446,8 @@ def parse_config_h(fp, vars=None):
445446
m = define_rx.match(line)
446447
if m:
447448
n, v = m.group(1, 2)
449+
if mq := quoted_re.match(v):
450+
v = mq.group(1)
448451
try:
449452
if n in _ALWAYS_STR:
450453
raise ValueError

Lib/test/test_free_threading/test_sys.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,6 @@ def worker(worker_id):
4444
workers = [lambda: worker(i) for i in range(5)]
4545
threading_helper.run_concurrently(workers)
4646

47-
def test_sys_audit_hooks(self):
48-
def _hook(*args):
49-
return None
50-
51-
def adder():
52-
for _ in range(100):
53-
sys.addaudithook(_hook)
54-
55-
def auditor():
56-
for _ in range(2000):
57-
sys.audit("fusil.tsan.test")
58-
59-
threading_helper.run_concurrently([adder, auditor])
60-
6147

6248
if __name__ == "__main__":
6349
unittest.main()

Lib/test/test_functools.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,40 @@ def f(**kwargs):
579579
with self.assertRaises(RuntimeError):
580580
result = p(**{BadStr("poison"): "new_value"})
581581

582+
def test_call_safety_against_reentrant_mutation(self):
583+
def old_function(*args, **kwargs):
584+
return "old_function", args, kwargs
585+
586+
def new_function(*args, **kwargs):
587+
return "new_function", args, kwargs
588+
589+
g_partial = None
590+
591+
class EvilKey(str):
592+
armed = False
593+
def __hash__(self):
594+
if EvilKey.armed and g_partial is not None:
595+
EvilKey.armed = False
596+
new_args_tuple = ("new_arg",)
597+
new_keywords_dict = {"new_keyword": None}
598+
new_tuple_state = (new_function, new_args_tuple, new_keywords_dict, None)
599+
g_partial.__setstate__(new_tuple_state)
600+
gc.collect()
601+
return str.__hash__(self)
602+
603+
g_partial = functools.partial(old_function, "old_arg", old_keyword=None)
604+
605+
kwargs = {EvilKey("evil_key"): None}
606+
EvilKey.armed = True
607+
608+
result = g_partial(**kwargs)
609+
expected = ("old_function", ("old_arg",), {"old_keyword": None, "evil_key": None})
610+
self.assertEqual(result, expected)
611+
612+
result = g_partial()
613+
expected = ("new_function", ("new_arg",), {"new_keyword": None})
614+
self.assertEqual(result, expected)
615+
582616
@unittest.skipUnless(c_functools, 'requires the C _functools module')
583617
class TestPartialC(TestPartial, unittest.TestCase):
584618
if c_functools:

Lib/test/test_sysconfig.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,12 @@ def test_linux_ext_suffix(self):
576576
expected_suffixes = 'x86_64-linux-gnu.so', 'x86_64-linux-musl.so'
577577
self.assertEndsWith(suffix, expected_suffixes)
578578

579+
@unittest.skipIf(sysconfig.get_config_var('PY_BUILTIN_HASHLIB_HASHES') is None,
580+
'PY_BUILTIN_HASHLIB_HASHES required for this test')
581+
def test_PY_BUILTIN_HASHLIB_HASHES_in_vars(self):
582+
vars = sysconfig.get_config_vars()
583+
self.assertFalse(vars['PY_BUILTIN_HASHLIB_HASHES'].startswith('"'))
584+
579585
@unittest.skipUnless(sys.platform == 'android', 'Android-specific test')
580586
def test_android_ext_suffix(self):
581587
machine = platform.machine()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid double-quoting string values from ``pyconfig.h`` in ``sysconfigdata``
2+
variables.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix the :mod:`asyncio` REPL namespace so that relative imports no longer
2+
resolve against the :mod:`asyncio` package and ``__file__`` is no longer
3+
set.

Misc/NEWS.d/next/Library/2026-07-22-12-42-53.gh-issue-154431.U2kXXZ.rst

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)