Skip to content

Commit 046604d

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython 3.15 branch from GitHub (2026-06-30)
Summary: Imported python/cpython `3.15.0b3+dev` from upstream rev [`ac20726`](https://www.github.com/python/cpython/commit/ac207265bdbcf7d507d2c9831aa54eda0fe9bb61) (committed 2026-06-30 00:12:59+00:00). # Commit Info - Base: (`3.15.0b3+dev`) - [`404113b`](https://www.github.com/python/cpython/commit/404113bd37625215d03545e51f8caa9fb7f1eea8) (commit date: 2026-06-29 02:34:20+00:00) - Imported: (`3.15.0b3+dev`) - [`ac20726`](https://www.github.com/python/cpython/commit/ac207265bdbcf7d507d2c9831aa54eda0fe9bb61) (commit date: 2026-06-30 00:12:59+00:00) # Noteworthy file changes - Test files (1 added) - Low-signal files (11 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GKdteiby1XD7FW4FAInh9vmdz64xbr0LAAAz Differential Revision: D110143556 fbshipit-source-id: 94822308fe873d67f8beafe50a51a7b5a4d9baf0
1 parent 612c628 commit 046604d

45 files changed

Lines changed: 882 additions & 128 deletions

Some content is hidden

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

Doc/c-api/threads.rst

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,61 @@ a thread state that was previously attached for the current thread.
242242
.. seealso::
243243
:pep:`788`
244244

245+
.. _c-api-reuse-thread-state:
246+
247+
Reusing a thread state across repeated calls
248+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
249+
250+
Creating and destroying a :c:type:`PyThreadState` is not free, and is more
251+
expensive on a :term:`free-threaded build`. A foreign thread that calls into
252+
the interpreter many times -- for example, a worker thread in a native thread
253+
pool -- should avoid creating a fresh thread state on every entry and
254+
destroying it on every exit. Instead, set up one thread state when the thread
255+
starts (or lazily on its first call into Python), attach and detach it around
256+
each call, and tear it down once when the thread exits.
257+
258+
Manage the thread state explicitly with :c:func:`PyThreadState_New`, attaching
259+
and detaching it with :c:func:`PyEval_RestoreThread` and
260+
:c:func:`PyEval_SaveThread`. This happens in three distinct phases, at
261+
different points in the thread's life.
262+
263+
When the thread starts, create one thread state for it. ``interp`` is the
264+
target interpreter, captured by the code that created this thread while it held
265+
an attached thread state (for example via :c:func:`PyInterpreterState_Get`)::
266+
267+
PyThreadState *tstate = PyThreadState_New(interp);
268+
269+
Then, on each call into Python -- which may happen many times over the thread's
270+
life -- attach the thread state, make the Python C API calls that require it,
271+
and detach again so the thread does not hold the GIL while off doing non-Python
272+
work::
273+
274+
PyEval_RestoreThread(tstate);
275+
result = CallSomeFunction(); /* your Python C API calls go here */
276+
PyEval_SaveThread();
277+
278+
When the thread is finished calling into Python, destroy the thread state once::
279+
280+
PyEval_RestoreThread(tstate);
281+
PyThreadState_Clear(tstate);
282+
PyThreadState_DeleteCurrent();
283+
284+
The general-purpose entry points for calling in from a foreign thread --
285+
:c:func:`PyThreadState_Ensure` and the older :c:func:`PyGILState_Ensure` -- do
286+
*not* guarantee a persistent thread state: their thread-state lifetime is
287+
deliberately implementation-defined, so a matched acquire/release pair may
288+
create and destroy a thread state each time. Use :c:func:`PyThreadState_New`,
289+
as shown here, whenever you specifically want to reuse one thread state across
290+
calls.
291+
292+
The code that created the foreign thread must arrange for the shutdown sequence
293+
to run before the thread exits, and before :c:func:`Py_FinalizeEx` is called.
294+
If interpreter finalization begins first, the shutdown
295+
:c:func:`PyEval_RestoreThread` call will hang the thread rather than return (see
296+
:ref:`cautions-regarding-runtime-finalization`). If the thread exits without
297+
running the shutdown sequence, the thread state is leaked for the remainder of
298+
the process.
299+
245300
.. _c-api-attach-detach:
246301

247302
Attaching/detaching thread states

Doc/howto/mro.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The Python 2.3 Method Resolution Order
1010
The Method Resolution Order discussed here was *introduced* in Python 2.3,
1111
but it is still used in later versions -- including Python 3.
1212

13-
By `Michele Simionato <https://www.phyast.pitt.edu/~micheles/>`__.
13+
By `Michele Simionato <https://github.com/micheles>`__.
1414

1515
:Abstract:
1616

Doc/library/dialog.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ listed below:
131131
The below functions when called create a modal, native look-and-feel dialog,
132132
wait for the user's selection, and return it.
133133
The exact return value depends on the function (see below); when the dialog is
134-
cancelled it is an empty string, an empty tuple, an empty list or ``None``.
134+
cancelled it is an empty string, an empty tuple or ``None``.
135+
The precise type of this empty value may vary between platforms and Tk
136+
versions, so test the result for truth rather than comparing it with a
137+
specific value.
135138

136139
.. function:: askopenfile(mode="r", **options)
137140
askopenfiles(mode="r", **options)
@@ -140,7 +143,7 @@ cancelled it is an empty string, an empty tuple, an empty list or ``None``.
140143
:func:`askopenfile` returns the opened file object, or ``None`` if the
141144
dialog is cancelled.
142145
:func:`askopenfiles` returns a list of the opened file objects, or an empty
143-
list if cancelled.
146+
tuple if cancelled.
144147
The files are opened in mode *mode* (read-only ``'r'`` by default).
145148

146149
.. function:: asksaveasfile(mode="w", **options)

Doc/library/hashlib.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,15 @@ hash supplied more than 2047 bytes of data at once in its constructor or
5050
.. index:: single: OpenSSL; (use in module hashlib)
5151

5252
Constructors for hash algorithms that are always present in this module are
53-
:func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`, :func:`sha512`,
54-
:func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, :func:`sha3_512`,
55-
:func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and :func:`blake2s`.
56-
:func:`md5` is normally available as well, though it may be missing or blocked
57-
if you are using a rare "FIPS compliant" build of Python.
58-
These correspond to :data:`algorithms_guaranteed`.
53+
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
54+
:func:`sha512`, :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`,
55+
:func:`sha3_512`, :func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and
56+
:func:`blake2s`. These correspond to :data:`algorithms_guaranteed`.
57+
58+
Any of these may nonetheless be missing or blocked in unusual environments,
59+
such as a rare "FIPS compliant" build of Python or when OpenSSL's "FIPS mode"
60+
is configured to exclude some algorithms from its default provider. Calling
61+
the constructor of an algorithm that is unavailable raises :exc:`ValueError`.
5962

6063
Additional algorithms may also be available if your Python distribution's
6164
:mod:`!hashlib` was linked against a build of OpenSSL that provides others.

Doc/library/numbers.rst

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,7 @@ Notes for type implementers
9090

9191
Implementers should be careful to make equal numbers equal and hash
9292
them to the same values. This may be subtle if there are two different
93-
extensions of the real numbers. For example, :class:`fractions.Fraction`
94-
implements :func:`hash` as follows::
95-
96-
def __hash__(self):
97-
if self.denominator == 1:
98-
# Get integers right.
99-
return hash(self.numerator)
100-
# Expensive check, but definitely correct.
101-
if self == float(self):
102-
return hash(float(self))
103-
else:
104-
# Use tuple's hash to avoid a high collision rate on
105-
# simple fractions.
106-
return hash((self.numerator, self.denominator))
93+
extensions of the real numbers. See also :ref:`numeric-hash`.
10794

10895

10996
Adding More Numeric ABCs

Doc/library/tkinter.rst

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,11 +1056,11 @@ Base and mixin classes
10561056
:class:`int`.
10571057
Raise :exc:`ValueError` if *s* is not a valid integer.
10581058

1059-
.. method:: getvar(name='PY_VAR')
1059+
.. method:: getvar(name)
10601060

10611061
Return the value of the Tcl global variable named *name*.
10621062

1063-
.. method:: setvar(name='PY_VAR', value='1')
1063+
.. method:: setvar(name, value)
10641064

10651065
Set the Tcl global variable named *name* to *value*.
10661066

@@ -1523,10 +1523,10 @@ Base and mixin classes
15231523
This updates the display of windows, for example after geometry changes,
15241524
but does not process events caused by the user.
15251525

1526-
.. method:: waitvar(name='PY_VAR')
1526+
.. method:: waitvar(name)
15271527
:no-typesetting:
15281528

1529-
.. method:: wait_variable(name='PY_VAR')
1529+
.. method:: wait_variable(name)
15301530

15311531
Wait until the Tcl variable *name* is modified, continuing to process
15321532
events in the meantime so that the application stays responsive.
@@ -2620,7 +2620,8 @@ Base and mixin classes
26202620
Make *widget* a stand-alone top-level window, decorated by the window
26212621
manager with a title bar and so on.
26222622
Only :class:`Frame`, :class:`LabelFrame` and :class:`Toplevel` widgets
2623-
may be used; passing any other widget type raises an error.
2623+
may be used (the :mod:`tkinter.ttk` versions are **not** accepted);
2624+
passing any other widget type raises an error.
26242625
:meth:`wm_manage` is an alias of :meth:`!manage`.
26252626

26262627
.. versionadded:: 3.3
@@ -3297,6 +3298,14 @@ Toplevel widgets
32973298
profile files is the :envvar:`HOME` environment variable or, if that
32983299
isn't defined, then :data:`os.curdir`.
32993300

3301+
.. note::
3302+
3303+
On Windows, creating a Tcl interpreter (by instantiating :class:`Tk` or
3304+
calling :func:`Tcl`) sets the :envvar:`HOME` environment variable for
3305+
the process, if it is not already set, to ``%HOMEDRIVE%%HOMEPATH%`` (or
3306+
:envvar:`USERPROFILE`, or ``c:\``). This is done by Tcl and can affect
3307+
other code that reads :envvar:`HOME`.
3308+
33003309
.. attribute:: tk
33013310

33023311
The Tk application object created by instantiating :class:`Tk`. This

Lib/curses/textpad.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,42 @@ def _update_max_yx(self):
5656
self.maxy = maxy - 1
5757
self.maxx = maxx - 1
5858

59+
def _decode(self, ch):
60+
# The text of a chtype cell or input byte, decoded with the window's
61+
# encoding. A_CHARTEXT keeps the character byte, dropping the attributes.
62+
return bytes([ch & curses.A_CHARTEXT]).decode(self.win.encoding, 'replace')
63+
64+
def _char_at(self, *yx):
65+
# The text of the cell at the given position (default: the cursor).
66+
# instr() re-encodes it to the window's encoding; inch() cannot
67+
# represent a non-ASCII 8-bit-locale character on a wide build.
68+
return self.win.instr(*yx, 1).decode(self.win.encoding, 'replace')
69+
70+
def _cell_at(self, *yx):
71+
# The cell at the given position (default: the cursor) as a chtype
72+
# addch() can write back with its rendition. inch() mangles a non-ASCII
73+
# character on a wide build, so take the byte from instr() and the
74+
# attributes from inch().
75+
return self.win.instr(*yx, 1)[0] | self.win.inch(*yx) & curses.A_ATTRIBUTES
76+
77+
def _isprint(self, cell):
78+
# Whether a chtype cell holds a printable character; _decode() drops the
79+
# attribute bits.
80+
return self._decode(cell).isprintable()
81+
82+
def _printable_key(self, ch):
83+
# Whether the integer keystroke is a printable character, not a key
84+
# code. 0..255 are character bytes (decoded with the window's encoding);
85+
# larger values are function and navigation keys.
86+
return ch <= 0xff and self._decode(ch).isprintable()
87+
5988
def _end_of_line(self, y):
6089
"""Go to the location of the first blank on the given line,
6190
returning the index of the last non-blank character."""
6291
self._update_max_yx()
6392
last = self.maxx
6493
while True:
65-
if curses.ascii.ascii(self.win.inch(y, last)) != curses.ascii.SP:
94+
if self._char_at(y, last) != ' ':
6695
last = min(self.maxx, last+1)
6796
break
6897
elif last == 0:
@@ -76,15 +105,16 @@ def _insert_printable_char(self, ch):
76105
backyx = None
77106
while True:
78107
if self.insert_mode:
79-
oldch = self.win.inch()
108+
oldch = self._cell_at()
80109
if y >= self.maxy and x >= self.maxx:
81110
# Use insch() in the lower-right cell: addch() there would move
82111
# the cursor out of the window, raising an error and scrolling
83-
# a scrollable window.
84-
self.win.insch(ch)
112+
# a scrollable window. Pass it as text: insch() does not decode
113+
# an int byte through the locale on a wide build.
114+
self.win.insch(self._decode(ch), ch & curses.A_ATTRIBUTES)
85115
break
86116
self.win.addch(ch)
87-
if not self.insert_mode or not curses.ascii.isprint(oldch):
117+
if not self.insert_mode or not self._isprint(oldch):
88118
break
89119
ch = oldch
90120
(y, x) = self.win.getyx()
@@ -100,7 +130,7 @@ def do_command(self, ch):
100130
self._update_max_yx()
101131
(y, x) = self.win.getyx()
102132
self.lastcmd = ch
103-
if curses.ascii.isprint(ch):
133+
if self._printable_key(ch):
104134
self._insert_printable_char(ch)
105135
elif ch == curses.ascii.SOH: # ^a
106136
self.win.move(y, 0)
@@ -174,7 +204,7 @@ def gather(self):
174204
for x in range(self.maxx+1):
175205
if self.stripspaces and x > stop:
176206
break
177-
result = result + chr(curses.ascii.ascii(self.win.inch(y, x)))
207+
result = result + self._char_at(y, x)
178208
if self.maxy > 0:
179209
result = result + "\n"
180210
return result

Lib/hashlib.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -261,16 +261,15 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
261261
return digestobj
262262

263263

264-
__logging = None
265264
for __func_name in __always_supported:
266265
# try them all, some may not work due to the OpenSSL
267266
# version not supporting that algorithm.
268267
try:
269268
globals()[__func_name] = __get_hash(__func_name)
270-
except ValueError as __exc:
271-
import logging as __logging
272-
__logging.error('hash algorithm %s will not be supported at runtime '
273-
'[reason: %s]', __func_name, __exc)
269+
except ValueError:
270+
# Don't log here: logging at import time has global side effects and
271+
# would tell the wrong audience; code that uses a missing algorithm
272+
# gets a ValueError from the stub installed below.
274273
# The following code can be simplified in Python 3.19
275274
# once "string" is removed from the signature.
276275
__code = f'''\
@@ -291,9 +290,8 @@ def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
291290
'''
292291
exec(__code, {"__UNSET": object()}, __locals := {})
293292
globals()[__func_name] = __locals[__func_name]
294-
del __exc, __code, __locals
293+
del __code, __locals
295294

296295
# Cleanup locals()
297296
del __always_supported, __func_name, __get_hash
298297
del __py_new, __hash_new, __get_openssl_constructor
299-
del __logging

Lib/idlelib/News3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Released on 2026-10-01
44
=========================
55

66

7+
gh-85320: IDLE now reads and writes its configuration files and the
8+
breakpoints file using UTF-8 instead of the locale encoding.
9+
Files with non-ASCII characters and non-UTF-8 encoding may need
10+
to be opened in an editor and resaved with UTF-8 encoding.
11+
712
gh-143774: Better explain the operation of Format / Format Paragraph.
813
Patch by Terry J. Reedy.
914

Lib/idlelib/config.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ def GetOptionList(self, section):
7373

7474
def Load(self):
7575
"Load the configuration file from disk."
76-
if self.file:
77-
self.read(self.file)
76+
if self.file and os.path.exists(self.file):
77+
with open(self.file, encoding='utf-8', errors='replace') as f:
78+
self.read_file(f)
7879

7980
class IdleUserConfParser(IdleConfParser):
8081
"""
@@ -133,10 +134,10 @@ def Save(self):
133134
if fname and fname[0] != '#':
134135
if not self.IsEmpty():
135136
try:
136-
cfgFile = open(fname, 'w')
137+
cfgFile = open(fname, 'w', encoding='utf-8')
137138
except OSError:
138139
os.unlink(fname)
139-
cfgFile = open(fname, 'w')
140+
cfgFile = open(fname, 'w', encoding='utf-8')
140141
with cfgFile:
141142
self.write(cfgFile)
142143
elif os.path.exists(self.file):

0 commit comments

Comments
 (0)