Skip to content

Commit edcc666

Browse files
itamarometa-codesync[bot]
authored andcommitted
Import CPython 3.14.5+ stable branch (2026-05-30)
Summary: Imported python/cpython `3.14.5+` from upstream rev [`088c8ea`](https://www.github.com/python/cpython/commit/088c8ea18829c219d36441a8cb86da6da75fe755) (committed 2026-05-30 17:15:29+00:00). # Commit Info - Base: (`3.14.5+`) - [`8053ead`](https://www.github.com/python/cpython/commit/8053ead86b8ca5f97472366a3623c53ee3a15350) (commit date: 2026-05-26 19:46:42+00:00) - Imported: (`3.14.5+`) - [`088c8ea`](https://www.github.com/python/cpython/commit/088c8ea18829c219d36441a8cb86da6da75fe755) (commit date: 2026-05-30 17:15:29+00:00) # Noteworthy file changes - Low-signal files (6 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GF9SHiJ0PKWbhKYEAOn94a1ZUUkHbr0LAAAz Reviewed By: yoney Differential Revision: D106947358 fbshipit-source-id: 3c13b9cf0c7057638eb8008565ab85a5b42cae0d
1 parent 272f32a commit edcc666

108 files changed

Lines changed: 1191 additions & 762 deletions

File tree

Some content is hidden

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

Doc/howto/free-threading-python.rst

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,132 @@ to false. If the flag is true then the :class:`warnings.catch_warnings`
165165
context manager uses a context variable for warning filters. If the flag is
166166
false then :class:`~warnings.catch_warnings` modifies the global filters list,
167167
which is not thread-safe. See the :mod:`warnings` module for more details.
168+
169+
170+
Increased memory usage
171+
----------------------
172+
173+
The free-threaded build will typically use more memory compared to the default
174+
build. There are multiple reasons for this, mostly due to design decisions.
175+
176+
177+
All interned strings are immortal
178+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
179+
180+
For modern Python versions (since version 2.3), interning a string (e.g. with
181+
:func:`sys.intern`) does not cause it to become immortal. Instead, if the last
182+
reference to that string disappears, it will be removed from the interned
183+
string table. This is not the case for the free-threaded build and any interned
184+
string will become immortal, surviving until interpreter shutdown.
185+
186+
187+
Non-GC objects have a larger object header
188+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
189+
190+
The free-threaded build uses a different :c:type:`PyObject` structure. Instead
191+
of having the GC related information allocated before the :c:type:`PyObject`
192+
structure, like in the default build, the GC related info is part of the normal
193+
object header. For example, on the AMD64 platform, ``None`` uses 32 bytes on
194+
the free-threaded build vs 16 bytes for the default build. GC objects (such as
195+
dicts and lists) are the same size for both builds since the free-threaded
196+
build does not use additional space for the GC info.
197+
198+
199+
QSBR can delay freeing of memory
200+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
201+
202+
In order to safely implement lock-free data structures, a safe memory
203+
reclamation (SMR) scheme is used, known as quiescent state-based reclamation
204+
(QSBR). This means that the memory backing data structures allowing lock-free
205+
access will use QSBR, which defers the free operation, rather than immediately
206+
freeing the memory. Two examples of these data structures are the list object
207+
and the dictionary keys object. See ``InternalDocs/qsbr.md`` in the CPython
208+
source tree for more details on how QSBR is implemented. Running
209+
:func:`gc.collect` should cause all memory being held by QSBR to be actually
210+
freed. Note that even when QSBR frees the memory, the underlying memory
211+
allocator may not immediately return that memory to the OS and so the resident
212+
set size (RSS) of the process might not decrease.
213+
214+
215+
mimalloc allocator vs pymalloc
216+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
217+
218+
The default build will normally use the "pymalloc" memory allocator for small
219+
allocations (512 bytes or smaller). The free-threaded build does not use
220+
pymalloc and allocates all Python objects using the "mimalloc" allocator. The
221+
pymalloc allocator has the following properties that help keep memory usage
222+
low: small per-allocated-block overhead, effective memory fragmentation
223+
prevention, and quick return of free memory to the operating system. The
224+
mimalloc allocator does quite well in these respects as well but can have some
225+
more overhead.
226+
227+
In the free-threaded build, mimalloc manages memory in a number of separate
228+
heaps (currently four). For example, all GC supporting objects are allocated
229+
from their own heap. Using separate heaps means that free memory in one heap
230+
cannot be used for an allocation that uses another heap. Also, some heaps are
231+
configured to use QSBR (quiescent-state based reclamation) when freeing the
232+
memory that backs up the heap (known as "pages" in mimalloc terminology). The
233+
use of QSBR creates a delay between all memory blocks for a page being freed
234+
and the memory page being released, either for new allocations or back to the
235+
OS.
236+
237+
The mimalloc allocator also defers returning freed memory back to the OS. You
238+
can reduce that delay by setting the environment variable
239+
:envvar:`!MIMALLOC_PURGE_DELAY` to ``0``. Note that this will likely reduce
240+
the performance of the allocator.
241+
242+
243+
Free-threaded reference counting can cause objects to live longer
244+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
245+
246+
In the default build, when an object's reference count reaches zero, it is
247+
normally deallocated. The free-threaded build uses "biased reference
248+
counting", with a fast-path for objects "owned" by the current thread and a
249+
slow path for other objects. See :pep:`703` for additional details. Any time
250+
an object's reference count ends up in a "queued" state, deallocation can be
251+
deferred. The queued state is cleared from the "eval breaker" section of the
252+
bytecode evaluator.
253+
254+
The free-threaded build also allows a different mode of reference counting,
255+
known as "deferred reference counting". This mode is enabled by setting a flag
256+
on a per-object basis. Deferred reference counting is enabled for the
257+
following types:
258+
259+
* module objects
260+
* module top-level functions
261+
* class methods defined in the class scope
262+
* descriptor objects
263+
* thread-local objects, created by :class:`threading.local`
264+
265+
When deferred reference counting is enabled, references from Python function
266+
stacks are not added to the reference count. This scheme reduces the overhead
267+
of reference counting, especially for objects used from multiple threads.
268+
Because the stack references are not counted, objects with deferred reference
269+
counting are not immediately freed when their internal reference count goes to
270+
zero. Instead, they are examined by the next GC run and, if no stack
271+
references to them are found, they are freed. This means these objects are
272+
freed by the GC and not when their reference count goes to zero, as is typical.
273+
274+
275+
Per-thread reference counting can delay freeing objects
276+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
277+
278+
To avoid contention on the reference count fields of frequently shared
279+
objects, the free-threaded build also uses "per-thread reference counting"
280+
for a few selected object types. Rather than updating a single shared
281+
reference count, each thread maintains its own local reference count array,
282+
indexed by a unique id assigned to the object. The true reference count is
283+
only computed by summing the per-thread counts when the object's local
284+
count drops to zero. Per-thread reference counting is currently used for:
285+
286+
* heap type objects (classes created in Python)
287+
* code objects
288+
* the ``__dict__`` of module objects
289+
290+
Because the per-thread counts must be merged back to the object before it
291+
can be deallocated, objects using per-thread reference counting are
292+
typically freed later than they would be in the default build. In
293+
particular, such an object is usually not freed until the thread that
294+
referenced it reaches a safe point (for example, in the "eval breaker"
295+
section of the bytecode evaluator) or exits. Running :func:`gc.collect`
296+
will merge the per-thread counts and allow these objects to be freed.

Doc/library/ctypes.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ used to wrap these libraries in pure Python.
1616

1717
.. include:: ../includes/optional-module.rst
1818

19+
.. warning::
20+
21+
:mod:`!ctypes` provides low-level access to native libraries and the
22+
process's memory, bypassing Python's safety mechanisms and allowing
23+
execution of arbitrary native code.
24+
Incorrect use can corrupt data and objects, reveal sensitive information,
25+
cause crashes, or otherwise compromise the running process.
26+
1927

2028
.. _ctypes-ctypes-tutorial:
2129

@@ -200,10 +208,8 @@ argument values::
200208
OSError: exception: access violation reading 0x00000020
201209
>>>
202210

203-
There are, however, enough ways to crash Python with :mod:`!ctypes`, so you
204-
should be careful anyway. The :mod:`faulthandler` module can be helpful in
205-
debugging crashes (e.g. from segmentation faults produced by erroneous C library
206-
calls).
211+
The :mod:`faulthandler` module can help debug crashes,
212+
such as segmentation faults produced by erroneous C library calls.
207213

208214
``None``, integers, bytes objects and (unicode) strings are the only native
209215
Python objects that can directly be used as parameters in these function calls.

Doc/library/inspect.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,10 +1574,11 @@ properties, will be invoked and :meth:`~object.__getattr__` and
15741574
may be called.
15751575

15761576
For cases where you want passive introspection, like documentation tools, this
1577-
can be inconvenient. :func:`getattr_static` has the same signature as :func:`getattr`
1577+
can be inconvenient. :func:`getattr_static` has a similar signature as :func:`getattr`
15781578
but avoids executing code when it fetches attributes.
15791579

1580-
.. function:: getattr_static(obj, attr, default=None)
1580+
.. function:: getattr_static(obj, attr)
1581+
getattr_static(obj, attr, default)
15811582

15821583
Retrieve attributes without triggering dynamic lookup via the
15831584
descriptor protocol, :meth:`~object.__getattr__`

Doc/library/pydoc.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ will start a HTTP server on port 1234, allowing you to browse the
7171
documentation at ``http://localhost:1234/`` in your preferred web browser.
7272
Specifying ``0`` as the port number will select an arbitrary unused port.
7373

74+
.. warning::
75+
76+
The :mod:`!pydoc` HTTP server is intended for local use during
77+
development and is not suitable for production use.
78+
7479
:program:`python -m pydoc -n <hostname>` will start the server listening at the given
7580
hostname. By default the hostname is 'localhost' but if you want the server to
7681
be reached from other machines, you may want to change the host name that the

Doc/reference/compound_stmts.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ The match statement is used for pattern matching. Syntax:
620620
match_stmt: 'match' `subject_expr` ":" NEWLINE INDENT `case_block`+ DEDENT
621621
subject_expr: `flexible_expression` "," [`flexible_expression_list` [',']]
622622
: | `assignment_expression`
623-
case_block: 'case' `patterns` [`guard`] ":" `!block`
623+
case_block: 'case' `patterns` [`guard`] ":" `suite`
624624

625625
.. note::
626626
This section uses single quotes to denote

Doc/using/cmdline.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ additional methods of invocation:
5050
* When called with ``-c command``, it executes the Python statement(s) given as
5151
*command*. Here *command* may contain multiple statements separated by
5252
newlines. Leading whitespace is significant in Python statements!
53-
* When called with ``-m module-name``, the given module is located on the
54-
Python module path and executed as a script.
53+
* When called with ``-m module-name``, the given module is located using the standard
54+
import mechanism and executed as a script.
5555

5656
In non-interactive mode, the entire input is parsed before it is executed.
5757

@@ -78,8 +78,8 @@ source.
7878

7979
.. option:: -m <module-name>
8080

81-
Search :data:`sys.path` for the named module and execute its contents as
82-
the :mod:`__main__` module.
81+
Locate the module using the standard import mechanism and execute its contents
82+
as the :mod:`__main__` module.
8383

8484
Since the argument is a *module* name, you must not give a file extension
8585
(``.py``). The module name should be a valid absolute Python module name, but

Lib/_collections_abc.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,8 @@ def __subclasshook__(cls, C):
461461
class _CallableGenericAlias(GenericAlias):
462462
""" Represent `Callable[argtypes, resulttype]`.
463463
464-
This sets ``__args__`` to a tuple containing the flattened ``argtypes``
465-
followed by ``resulttype``.
464+
This sets ``__args__`` to a tuple containing the flattened
465+
``argtypes`` followed by ``resulttype``.
466466
467467
Example: ``Callable[[int, str], float]`` sets ``__args__`` to
468468
``(int, str, float)``.
@@ -927,8 +927,9 @@ def __delitem__(self, key):
927927
__marker = object()
928928

929929
def pop(self, key, default=__marker):
930-
'''D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
931-
If key is not found, d is returned if given, otherwise KeyError is raised.
930+
'''D.pop(k[,d]) -> v, remove specified key and return the corresponding
931+
value. If key is not found, d is returned if given, otherwise
932+
KeyError is raised.
932933
'''
933934
try:
934935
value = self[key]
@@ -962,9 +963,12 @@ def clear(self):
962963

963964
def update(self, other=(), /, **kwds):
964965
''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F.
965-
If E present and has a .keys() method, does: for k in E.keys(): D[k] = E[k]
966-
If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v
967-
In either case, this is followed by: for k, v in F.items(): D[k] = v
966+
If E present and has a .keys() method, does:
967+
for k in E.keys(): D[k] = E[k]
968+
If E present and lacks .keys() method, does:
969+
for (k, v) in E: D[k] = v
970+
In either case, this is followed by:
971+
for k, v in F.items(): D[k] = v
968972
'''
969973
if isinstance(other, Mapping):
970974
for key in other:
@@ -1029,8 +1033,8 @@ def __reversed__(self):
10291033
yield self[i]
10301034

10311035
def index(self, value, start=0, stop=None):
1032-
'''S.index(value, [start, [stop]]) -> integer -- return first index of value.
1033-
Raises ValueError if the value is not present.
1036+
'''S.index(value, [start, [stop]]) -> integer -- return first index of
1037+
value. Raises ValueError if the value is not present.
10341038
10351039
Supporting start and stop arguments is optional, but
10361040
recommended.
@@ -1138,15 +1142,16 @@ def reverse(self):
11381142
self[i], self[n-i-1] = self[n-i-1], self[i]
11391143

11401144
def extend(self, values):
1141-
'S.extend(iterable) -- extend sequence by appending elements from the iterable'
1145+
"""S.extend(iterable) -- extend sequence by appending elements from the
1146+
iterable"""
11421147
if values is self:
11431148
values = list(values)
11441149
for v in values:
11451150
self.append(v)
11461151

11471152
def pop(self, index=-1):
1148-
'''S.pop([index]) -> item -- remove and return item at index (default last).
1149-
Raise IndexError if list is empty or index is out of range.
1153+
'''S.pop([index]) -> item -- remove and return item at index (default
1154+
last). Raise IndexError if list is empty or index is out of range.
11501155
'''
11511156
v = self[index]
11521157
del self[index]

Lib/asyncio/base_events.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ async def _sock_sendfile_native(self, sock, file, offset, count):
963963
f"and file {file!r} combination")
964964

965965
async def _sock_sendfile_fallback(self, sock, file, offset, count):
966-
if offset:
966+
if hasattr(file, 'seek'):
967967
file.seek(offset)
968968
blocksize = (
969969
min(count, constants.SENDFILE_FALLBACK_READBUFFER_SIZE)
@@ -1278,7 +1278,6 @@ async def sendfile(self, transport, file, offset=0, count=None,
12781278
raise RuntimeError(
12791279
f"fallback is disabled and native sendfile is not "
12801280
f"supported for transport {transport!r}")
1281-
12821281
return await self._sendfile_fallback(transport, file,
12831282
offset, count)
12841283

@@ -1287,7 +1286,7 @@ async def _sendfile_native(self, transp, file, offset, count):
12871286
"sendfile syscall is not supported")
12881287

12891288
async def _sendfile_fallback(self, transp, file, offset, count):
1290-
if offset:
1289+
if hasattr(file, 'seek'):
12911290
file.seek(offset)
12921291
blocksize = min(count, 16384) if count else 16384
12931292
buf = bytearray(blocksize)

Lib/asyncio/proactor_events.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,7 @@ async def _sock_sendfile_native(self, sock, file, offset, count):
756756
offset += blocksize
757757
total_sent += blocksize
758758
finally:
759-
if total_sent > 0:
760-
file.seek(offset)
759+
file.seek(offset)
761760

762761
async def _sendfile_native(self, transp, file, offset, count):
763762
resume_reading = transp.is_reading()

Lib/asyncio/unix_events.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,12 @@ def _sock_sendfile_native_impl(self, fut, registered_fd, sock, fileno,
384384
# order to simplify the common case.
385385
self.remove_writer(registered_fd)
386386
if fut.cancelled():
387-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
387+
self._sock_sendfile_update_filepos(fileno, offset)
388388
return
389389
if count:
390390
blocksize = count - total_sent
391391
if blocksize <= 0:
392-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
392+
self._sock_sendfile_update_filepos(fileno, offset)
393393
fut.set_result(total_sent)
394394
return
395395

@@ -423,20 +423,20 @@ def _sock_sendfile_native_impl(self, fut, registered_fd, sock, fileno,
423423
# plain send().
424424
err = exceptions.SendfileNotAvailableError(
425425
"os.sendfile call failed")
426-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
426+
self._sock_sendfile_update_filepos(fileno, offset)
427427
fut.set_exception(err)
428428
else:
429-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
429+
self._sock_sendfile_update_filepos(fileno, offset)
430430
fut.set_exception(exc)
431431
except (SystemExit, KeyboardInterrupt):
432432
raise
433433
except BaseException as exc:
434-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
434+
self._sock_sendfile_update_filepos(fileno, offset)
435435
fut.set_exception(exc)
436436
else:
437437
if sent == 0:
438438
# EOF
439-
self._sock_sendfile_update_filepos(fileno, offset, total_sent)
439+
self._sock_sendfile_update_filepos(fileno, offset)
440440
fut.set_result(total_sent)
441441
else:
442442
offset += sent
@@ -447,9 +447,9 @@ def _sock_sendfile_native_impl(self, fut, registered_fd, sock, fileno,
447447
fd, sock, fileno,
448448
offset, count, blocksize, total_sent)
449449

450-
def _sock_sendfile_update_filepos(self, fileno, offset, total_sent):
451-
if total_sent > 0:
452-
os.lseek(fileno, offset, os.SEEK_SET)
450+
def _sock_sendfile_update_filepos(self, fileno, offset):
451+
# After this helper runs, the source fd's lseek pointer is at offset."
452+
os.lseek(fileno, offset, os.SEEK_SET)
453453

454454
def _sock_add_cancellation_callback(self, fut, sock):
455455
def cb(fut):

0 commit comments

Comments
 (0)