Skip to content

Commit 4fc352a

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Import CPython 3.14.7+ stable branch (2026-08-21)
Summary: Imported python/cpython `3.14.7+` from upstream rev [`197fdd7`](https://www.github.com/python/cpython/commit/197fdd787a117686fa78a4e7ceefedf2f06038d6) (committed 2026-08-21 01:41:26+00:00). # Commit Info - Base: (`3.14.7+`) - [`cb76caa`](https://www.github.com/python/cpython/commit/cb76caaa6467f0ae8f9d58b5956211ed855a8905) (commit date: 2026-08-20 01:52:17+00:00) - Imported: (`3.14.7+`) - [`197fdd7`](https://www.github.com/python/cpython/commit/197fdd787a117686fa78a4e7ceefedf2f06038d6) (commit date: 2026-08-21 01:41:26+00:00) # Noteworthy file changes - Test files (1 added) - Low-signal files (3 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GJQ5fS6b8Zc9qqsDAFa8jWWszxVVbr0LAAAz Reviewed By: itamaro Differential Revision: D116929264 fbshipit-source-id: dd14681ab159dbb3864e6fb1eebac0cf7065fd40
1 parent 38a337e commit 4fc352a

11 files changed

Lines changed: 188 additions & 32 deletions

File tree

Doc/about.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and now maintained as an independent project.
1010
.. _reStructuredText: https://docutils.sourceforge.io/rst.html
1111
.. _Sphinx: https://www.sphinx-doc.org/
1212

13-
.. In the online version of these documents, you can submit comments and suggest
13+
.. In the online version of this documentation, you can submit comments and suggest
1414
changes directly on the documentation pages.
1515
1616
Development of the documentation and its toolchain is an entirely volunteer

Doc/tools/templates/indexsidebar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<h3>{% trans %}Download{% endtrans %}</h3>
2-
<p><a href="{{ pathto('download') }}">{% trans %}Download these documents{% endtrans %}</a></p>
2+
<p><a href="{{ pathto('download') }}">{% trans %}Download the documentation{% endtrans %}</a></p>
33
<h3>{% trans %}Docs by version{% endtrans %}</h3>
44
<ul>
55
{# _docs_by_version.html is overwritten by build_docs.py for non-EOL versions #}

Doc/tutorial/stdlib.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ aids for working with large modules like :mod:`os`::
3636
<returns an extensive manual page created from the module's docstrings>
3737

3838
For daily file and directory management tasks, the :mod:`shutil` module provides
39-
a higher level interface that is easier to use::
39+
a higher-level interface that is easier to use::
4040

4141
>>> import shutil
4242
>>> shutil.copyfile('data.db', 'archive.db')
@@ -63,7 +63,7 @@ wildcard searches::
6363
Command-line arguments
6464
======================
6565

66-
Common utility scripts often need to process command line arguments. These
66+
Common utility scripts often need to process command-line arguments. These
6767
arguments are stored in the :mod:`sys` module's *argv* attribute as a list. For
6868
instance, let's take the following :file:`demo.py` file::
6969

@@ -77,7 +77,7 @@ line::
7777
['demo.py', 'one', 'two', 'three']
7878

7979
The :mod:`argparse` module provides a more sophisticated mechanism to process
80-
command line arguments. The following script extracts one or more filenames
80+
command-line arguments. The following script extracts one or more filenames
8181
and an optional number of lines to be displayed::
8282

8383
import argparse

Lib/concurrent/interpreters/_queues.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,12 @@ def put(self, obj, block=True, timeout=None, *,
221221
timeout = int(timeout)
222222
if timeout < 0:
223223
raise ValueError(f'timeout value must be non-negative')
224-
end = time.time() + timeout
224+
end = time.monotonic() + timeout
225225
while True:
226226
try:
227227
_queues.put(self._id, obj, unboundop)
228228
except QueueFull as exc:
229-
if timeout is not None and time.time() >= end:
229+
if timeout is not None and time.monotonic() >= end:
230230
raise # re-raise
231231
time.sleep(_delay)
232232
else:
@@ -256,12 +256,12 @@ def get(self, block=True, timeout=None, *,
256256
timeout = int(timeout)
257257
if timeout < 0:
258258
raise ValueError(f'timeout value must be non-negative')
259-
end = time.time() + timeout
259+
end = time.monotonic() + timeout
260260
while True:
261261
try:
262262
obj, unboundop = _queues.get(self._id)
263263
except QueueEmpty as exc:
264-
if timeout is not None and time.time() >= end:
264+
if timeout is not None and time.monotonic() >= end:
265265
raise # re-raise
266266
time.sleep(_delay)
267267
else:
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import contextvars
2+
import unittest
3+
from threading import Event, Thread
4+
5+
from test.support import threading_helper
6+
7+
8+
@threading_helper.requires_working_threading()
9+
class TestContext(unittest.TestCase):
10+
def test_racing_read_write(self):
11+
# gh-154535: reading a Context object from one thread while another
12+
# thread sets variables in it used to crash. The readers looked at
13+
# Context.ctx_vars without owning a reference to it, so the writer
14+
# could deallocate the mapping while a reader was walking it.
15+
ctx = contextvars.Context()
16+
cvars = [contextvars.ContextVar(f"cvar{i}") for i in range(64)]
17+
done = Event()
18+
errors = []
19+
20+
def writer():
21+
def body():
22+
i = 0
23+
while not done.is_set():
24+
cvars[i % len(cvars)].set(i)
25+
i += 1
26+
try:
27+
ctx.run(body)
28+
except BaseException as e:
29+
errors.append(e)
30+
31+
def reader():
32+
try:
33+
for _ in range(200):
34+
ctx.copy()
35+
len(ctx)
36+
list(ctx)
37+
list(ctx.items())
38+
list(ctx.keys())
39+
list(ctx.values())
40+
cvars[0] in ctx
41+
ctx.get(cvars[0])
42+
ctx == ctx
43+
except BaseException as e:
44+
errors.append(e)
45+
finally:
46+
done.set()
47+
48+
threads = [Thread(target=writer)]
49+
threads += [Thread(target=reader) for _ in range(4)]
50+
with threading_helper.start_threads(threads, done.set):
51+
pass
52+
53+
self.assertEqual(errors, [], msg=f"unexpected errors: {errors}")
54+
55+
56+
if __name__ == "__main__":
57+
unittest.main()

Lib/test/test_interpreters/test_queues.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import pickle
33
import threading
44
from textwrap import dedent
5+
import time
56
import unittest
7+
from unittest import mock
68

79
from test.support import import_helper, Py_DEBUG
810
# Raise SkipTest if subinterpreters not supported.
@@ -355,6 +357,19 @@ def test_get_timeout(self):
355357
with self.assertRaises(queues.QueueEmpty):
356358
queue.get(HUGE_TIMEOUT, 0.1)
357359

360+
def test_timeout_uses_monotonic_clock(self):
361+
# gh-153005: the deadline must be computed from the monotonic clock,
362+
# since the wall clock can be adjusted while the call is blocked.
363+
queue = queues.create(1)
364+
with mock.patch.object(queues, 'time', wraps=time) as fake_time:
365+
with self.assertRaises(queues.QueueEmpty):
366+
queue.get(timeout=0)
367+
queue.put(None)
368+
with self.assertRaises(queues.QueueFull):
369+
queue.put(None, timeout=0)
370+
fake_time.monotonic.assert_called()
371+
fake_time.time.assert_not_called()
372+
358373
def test_get_nowait(self):
359374
queue = queues.create()
360375
with self.assertRaises(queues.QueueEmpty):
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:meth:`!concurrent.interpreters.Queue.get` and
2+
:meth:`!concurrent.interpreters.Queue.put` now compute their ``timeout``
3+
deadline from :func:`time.monotonic` instead of the wall clock, so adjusting
4+
the system clock during the call no longer makes them over- or under-wait.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid a data-race in free-threaded builds when reading and writing context
2+
variables from different threads.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix error handling in the :mod:`zoneinfo` accelerator module when a
2+
transition index is ``-1`` or a TZ string's ``__bool__`` raises.

Modules/_zoneinfo.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
10671067
}
10681068

10691069
Py_ssize_t cur_trans_idx = PyLong_AsSsize_t(num);
1070-
if (cur_trans_idx == -1) {
1070+
if (cur_trans_idx == -1 && PyErr_Occurred()) {
10711071
goto error;
10721072
}
10731073

@@ -1178,7 +1178,12 @@ load_data(zoneinfo_state *state, PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
11781178
self->ttinfo_before = &(self->_ttinfos[0]);
11791179
}
11801180

1181-
if (tz_str != Py_None && PyObject_IsTrue(tz_str)) {
1181+
int has_tz_str = PyObject_IsTrue(tz_str);
1182+
if (has_tz_str < 0) {
1183+
goto error;
1184+
}
1185+
1186+
if (has_tz_str) {
11821187
if (parse_tz_str(state, tz_str, &(self->tzrule_after))) {
11831188
goto error;
11841189
}

0 commit comments

Comments
 (0)