Skip to content

Commit f924661

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython 3.15 branch from GitHub (2026-06-16)
Summary: Imported python/cpython `3.15.0b2+dev` from upstream rev [`ff6e973`](https://www.github.com/python/cpython/commit/ff6e973c3bbe419ff8aef16b05a1c77749c073c2) (committed 2026-06-16 16:48:56+00:00). # Commit Info - Base: (`3.15.0b2+dev`) - [`e2c7fa7`](https://www.github.com/python/cpython/commit/e2c7fa7ff65dce05b857a3bbac275894dad967ad) (commit date: 2026-06-15 22:45:45+00:00) - Imported: (`3.15.0b2+dev`) - [`ff6e973`](https://www.github.com/python/cpython/commit/ff6e973c3bbe419ff8aef16b05a1c77749c073c2) (commit date: 2026-06-16 16:48:56+00:00) # Noteworthy file changes - Test files (1 added) - Low-signal files (2 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GKREQSuWsy43tWsFAH7VkD3Rxc8Sbr0LAAAz Reviewed By: itamaro Differential Revision: D108841492 fbshipit-source-id: 2ef85136c87396b057344a9d53513240b23418eb
1 parent 2d57d0e commit f924661

15 files changed

Lines changed: 180 additions & 25 deletions

File tree

Doc/c-api/init_config.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,10 @@ Some options are read from the :mod:`sys` attributes. For example, the option
623623
624624
.. versionadded:: 3.14
625625
626+
.. versionchanged:: next
627+
The function now replaces :data:`sys.flags` (create a new object),
628+
instead of modifying :data:`sys.flags` in-place.
629+
626630
627631
.. _pyconfig_api:
628632

Doc/c-api/module.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,15 @@ Feature slots
247247
If ``Py_mod_multiple_interpreters`` is not specified, the import
248248
machinery defaults to ``Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED``.
249249
250+
For historical reasons, the values are declared as pointers (``void *``).
251+
When using :c:type:`PySlot` arrays, use :c:macro:`PySlot_DATA` for
252+
:c:macro:`!Py_mod_multiple_interpreters`:
253+
254+
.. code-block:: c
255+
256+
PySlot_DATA(Py_mod_multiple_interpreters,
257+
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED)
258+
250259
.. versionadded:: 3.12
251260
252261
.. c:macro:: Py_mod_gil
@@ -272,6 +281,14 @@ Feature slots
272281
If ``Py_mod_gil`` is not specified, the import machinery defaults to
273282
``Py_MOD_GIL_USED``.
274283
284+
For historical reasons, the values are declared as pointers (``void *``).
285+
When using :c:type:`PySlot` arrays, use :c:macro:`PySlot_DATA` for
286+
:c:macro:`!Py_mod_gil`:
287+
288+
.. code-block:: c
289+
290+
PySlot_DATA(Py_mod_gil, Py_MOD_GIL_NOT_USED)
291+
275292
.. versionadded:: 3.13
276293
277294

Lib/email/contentmanager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ def set_text_content(msg, string, subtype="plain", charset='utf-8', cte=None,
174174
params=None, headers=None):
175175
_prepare_set(msg, 'text', subtype, headers)
176176

177-
charset = email.charset.Charset(charset).input_charset
177+
cs = email.charset.Charset(charset)
178+
charset = cs.output_charset
178179
cte, payload = _encode_text(string, charset, cte, msg.policy)
179180
msg.set_payload(payload)
180181
msg.set_param('charset', charset, replace=True)

Lib/test/test_asyncio/test_ssl.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,6 +1544,9 @@ async def client(addr):
15441544
# This triggers bug gh-115514, also tested using mocks in
15451545
# test.test_asyncio.test_selector_events.SelectorSocketTransportTests.test_write_buffer_after_close
15461546
socket_transport = writer.transport._ssl_protocol._transport
1547+
# connection_lost may have already cleared _transport.
1548+
if socket_transport is None:
1549+
return
15471550

15481551
class SocketWrapper:
15491552
def __init__(self, sock) -> None:

Lib/test/test_capi/test_config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,11 @@ def expect_bool_not(value):
356356
for value in new_values:
357357
expected, expect_flag = expect_func(value)
358358

359+
old_flags = sys.flags
359360
config_set(name, value)
360361
self.assertEqual(config_get(name), expected)
361362
self.assertEqual(getattr(sys.flags, sys_flag), expect_flag)
363+
self.assertIsNot(sys.flags, old_flags)
362364
if name == "write_bytecode":
363365
self.assertEqual(getattr(sys, "dont_write_bytecode"),
364366
expect_flag)

Lib/test/test_email/test_contentmanager.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,46 @@ def test_set_text_charset_cp949(self):
362362
self.assertEqual(m.get_payload(decode=True), content.encode('ks_c_5601-1987'))
363363
self.assertEqual(m.get_content(), content)
364364

365+
def test_set_text_charset_shift_jis(self):
366+
m = self._make_message()
367+
content = "\u65e5\u672c\u8a9e\n"
368+
raw_data_manager.set_content(m, content, charset='shift_jis')
369+
self.assertEqual(m['Content-Type'], 'text/plain; charset="iso-2022-jp"')
370+
self.assertEqual(m.get_payload(decode=True), content.encode('iso-2022-jp'))
371+
self.assertEqual(m.get_content(), content)
372+
self.assertEqual(str(m), textwrap.dedent("""\
373+
Content-Type: text/plain; charset="iso-2022-jp"
374+
Content-Transfer-Encoding: 7bit
375+
376+
\x1b$BF|K\\8l\x1b(B
377+
"""))
378+
self.assertEqual(bytes(m), textwrap.dedent("""\
379+
Content-Type: text/plain; charset="iso-2022-jp"
380+
Content-Transfer-Encoding: 7bit
381+
382+
\u65e5\u672c\u8a9e
383+
""").encode('iso-2022-jp'))
384+
385+
def test_set_text_charset_euc_jp(self):
386+
m = self._make_message()
387+
content = "\u65e5\u672c\u8a9e\n"
388+
raw_data_manager.set_content(m, content, charset='euc-jp')
389+
self.assertEqual(m['Content-Type'], 'text/plain; charset="iso-2022-jp"')
390+
self.assertEqual(m.get_payload(decode=True), content.encode('iso-2022-jp'))
391+
self.assertEqual(m.get_content(), content)
392+
self.assertEqual(str(m), textwrap.dedent("""\
393+
Content-Type: text/plain; charset="iso-2022-jp"
394+
Content-Transfer-Encoding: 7bit
395+
396+
\x1b$BF|K\\8l\x1b(B
397+
"""))
398+
self.assertEqual(bytes(m), textwrap.dedent("""\
399+
Content-Type: text/plain; charset="iso-2022-jp"
400+
Content-Transfer-Encoding: 7bit
401+
402+
\u65e5\u672c\u8a9e
403+
""").encode('iso-2022-jp'))
404+
365405
def test_set_text_plain_long_line_heuristics(self):
366406
m = self._make_message()
367407
content = ("Simple but long message that is over 78 characters"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import sys
2+
import unittest
3+
from test.support import threading_helper
4+
5+
6+
class SysModuleTest(unittest.TestCase):
7+
def test_int_max_str_digits_thread(self):
8+
# gh-151218: Check that it's safe to call get_int_max_str_digits() and
9+
# set_int_max_str_digits() in parallel. Previously, this test triggered
10+
# warnings in TSan on a free threaded build.
11+
12+
old_limit = sys.get_int_max_str_digits()
13+
self.addCleanup(sys.set_int_max_str_digits, old_limit)
14+
15+
def worker(worker_id):
16+
if not worker_id:
17+
for i in range (20_000):
18+
sys.get_int_max_str_digits()
19+
else:
20+
for i in range (20_000):
21+
sys.set_int_max_str_digits(4300 + (i & 7))
22+
23+
workers = [lambda: worker(i) for i in range(5)]
24+
threading_helper.run_concurrently(workers)
25+
26+
27+
if __name__ == "__main__":
28+
unittest.main()

Lib/test/test_os/test_posix.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,9 @@ def check_stat(uid, gid):
899899
self.assertRaises(OSError, chown_func, first_param, 0, -1)
900900
check_stat(uid, gid)
901901
if hasattr(os, 'getgroups'):
902-
if 0 not in os.getgroups():
902+
# Also check the effective gid, which the kernel
903+
# accepts for chown even if not in getgroups().
904+
if 0 not in os.getgroups() and os.getegid() != 0:
903905
self.assertRaises(OSError, chown_func, first_param, -1, 0)
904906
check_stat(uid, gid)
905907
# test illegal types

Lib/test/test_sys.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,26 @@ def test_pystats(self):
13591359
def test_disable_gil_abi(self):
13601360
self.assertEqual('t' in sys.abiflags, support.Py_GIL_DISABLED)
13611361

1362+
def test_int_max_str_digits(self):
1363+
old_limit = sys.get_int_max_str_digits()
1364+
self.assertIsInstance(old_limit, int)
1365+
self.assertGreaterEqual(old_limit, 0)
1366+
self.addCleanup(sys.set_int_max_str_digits, old_limit)
1367+
1368+
sys.set_int_max_str_digits(0)
1369+
self.assertEqual(sys.get_int_max_str_digits(), 0)
1370+
1371+
sys.set_int_max_str_digits(2_048)
1372+
self.assertEqual(sys.get_int_max_str_digits(), 2_048)
1373+
1374+
with self.assertRaises(ValueError):
1375+
# the minimum is 640 digits
1376+
sys.set_int_max_str_digits(5)
1377+
with self.assertRaises(ValueError):
1378+
sys.set_int_max_str_digits(-2)
1379+
with self.assertRaises(TypeError):
1380+
sys.set_int_max_str_digits(2_048.0)
1381+
13621382

13631383
@test.support.cpython_only
13641384
@test.support.force_not_colorized_test_class
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:c:func:`PyConfig_Set` and :func:`sys.set_int_max_str_digits` now replace
2+
:data:`sys.flags` (create a new object), instead of modifying :data:`sys.flags`
3+
in-place. Patch by Victor Stinner.

0 commit comments

Comments
 (0)