Skip to content

Commit 5c6735c

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Sync pre-release CPython main branch from GitHub (2026-08-31)
Summary: Imported python/cpython `3.16.0a0` from upstream rev [`b38e073`](https://www.github.com/python/cpython/commit/b38e073f1be8fe40af991c044a791cefff098f0d) (committed 2026-08-31 21:54:35+00:00). # Commit Info - Base: (`3.16.0a0`) - [`03503dc`](https://www.github.com/python/cpython/commit/03503dccd0aa6d8895614e80ae9c78c03c813d45) (commit date: 2026-08-30 21:43:38+00:00) - Imported: (`3.16.0a0`) - [`b38e073`](https://www.github.com/python/cpython/commit/b38e073f1be8fe40af991c044a791cefff098f0d) (commit date: 2026-08-31 21:54:35+00:00) # Noteworthy file changes - Low-signal files (7 added, 1 removed) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GMDh2RyY_BolHpaIAJBFADyfsL5kbr0LAAAz Differential Revision: D118237701 fbshipit-source-id: 87533c616a6224c5d45ee04948d79d4c06ee0258
1 parent 94acb6f commit 5c6735c

35 files changed

Lines changed: 482 additions & 151 deletions

Doc/library/ast.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2254,7 +2254,7 @@ and classes for traversing abstract syntax trees:
22542254

22552255
In addition, if ``mode`` is ``'func_type'``, the input syntax is
22562256
modified to correspond to :pep:`484` "signature type comments",
2257-
e.g. ``(str, int) -> List[str]``.
2257+
for example ``(str, int) -> List[str]``.
22582258

22592259
Setting ``feature_version`` to a tuple ``(major, minor)`` will result in
22602260
a "best-effort" attempt to parse using that Python version's grammar.

Lib/asyncio/taskgroups.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,9 @@ def create_task(self, coro, **kwargs):
239239
# the current task too early. gh-128550, gh-128588
240240
self._tasks.add(task)
241241
task.add_done_callback(self._on_task_done)
242+
# gh-155418: an eager task can cancel the group before joining _tasks
243+
if self._aborting and not task.done():
244+
task.cancel()
242245
try:
243246
return task
244247
finally:

Lib/enum.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,9 +624,13 @@ def __new__(metacls, cls, bases, classdict, *, boundary=None, _simple=False, **k
624624
'__invert__'
625625
):
626626
if name not in classdict:
627+
# check for mixin overrides before replacing
627628
enum_method = getattr(Flag, name)
628-
setattr(enum_class, name, enum_method)
629-
classdict[name] = enum_method
629+
found_method = getattr(enum_class, name)
630+
data_type_method = getattr(member_type, name, None)
631+
if found_method in (enum_method, data_type_method):
632+
setattr(enum_class, name, enum_method)
633+
classdict[name] = enum_method
630634
#
631635
# replace any other __new__ with our own (as long as Enum is not None,
632636
# anyway) -- again, this is to support pickle

Lib/http/cookiejar.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ def request_host(request):
627627
628628
"""
629629
url = request.get_full_url()
630-
host = urllib.parse.urlparse(url)[1]
630+
host = urllib.parse.urlparse(url).netloc
631631
if host == "":
632632
host = request.get_header("Host", "")
633633

Lib/test/libregrtest/refleak.py

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import warnings
4+
from array import array
45
from inspect import isabstract
56
from typing import Any
67
import linecache
@@ -100,24 +101,20 @@ def runtest_refleak(test_name, test_func,
100101
for obj in ByteString.__subclasses__() + [ByteString]: # type: ignore[attr-defined]
101102
abcs[obj] = _get_dump(obj)[0]
102103

103-
# bpo-31217: Integer pool to get a single integer object for the same
104-
# value. The pool is used to prevent false alarm when checking for memory
105-
# block leaks. Fill the pool with values in -1000..1000 which are the most
106-
# common (reference, memory block, file descriptor) differences.
107-
int_pool = {value: value for value in range(-1000, 1000)}
108-
def get_pooled_int(value):
109-
return int_pool.setdefault(value, value)
110-
111104
warmups = hunt_refleak.warmups
112105
runs = hunt_refleak.runs
113106
filename = hunt_refleak.filename
114107
repcount = warmups + runs
115108

116-
# Pre-allocate to ensure that the loop doesn't allocate anything new
109+
# Pre-allocate to ensure that the loop doesn't allocate anything new.
110+
# Store the deltas as raw values in arrays rather than as int objects in
111+
# lists: each unique delta stored as an object would live until the end of
112+
# the loop and show up in the following repetition's reference and memory
113+
# block deltas (gh-75400, gh-155981).
117114
rep_range = list(range(repcount))
118-
rc_deltas = [0] * repcount
119-
alloc_deltas = [0] * repcount
120-
fd_deltas = [0] * repcount
115+
rc_deltas = array('q', [0]) * repcount
116+
alloc_deltas = array('q', [0]) * repcount
117+
fd_deltas = array('q', [0]) * repcount
121118
getallocatedblocks = sys.getallocatedblocks
122119
gettotalrefcount = sys.gettotalrefcount
123120
getunicodeinternedsize = sys.getunicodeinternedsize
@@ -161,12 +158,11 @@ def get_pooled_int(value):
161158
rc_after = gettotalrefcount()
162159
fd_after = fd_count()
163160

164-
rc_deltas[i] = get_pooled_int(rc_after - rc_before)
165-
alloc_deltas[i] = get_pooled_int(alloc_after - alloc_before)
166-
fd_deltas[i] = get_pooled_int(fd_after - fd_before)
161+
rc_deltas[i] = rc_after - rc_before
162+
alloc_deltas[i] = alloc_after - alloc_before
163+
fd_deltas[i] = fd_after - fd_before
167164

168165
if not quiet:
169-
# use max, not sum, so total_leaks is one of the pooled ints
170166
total_leaks = max(rc_deltas[i], alloc_deltas[i], fd_deltas[i])
171167
if total_leaks <= 0:
172168
symbol = '.'
@@ -212,13 +208,13 @@ def check_fd_deltas(deltas):
212208
return any(deltas)
213209

214210
failed = False
215-
for deltas, item_name, checker in [
211+
for raw_deltas, item_name, checker in [
216212
(rc_deltas, 'references', check_rc_deltas),
217213
(alloc_deltas, 'memory blocks', check_rc_deltas),
218214
(fd_deltas, 'file descriptors', check_fd_deltas)
219215
]:
220-
# ignore warmup runs
221-
deltas = deltas[warmups:]
216+
# ignore warmup runs; convert to a list for reporting
217+
deltas = list(raw_deltas[warmups:])
222218
failing = checker(deltas)
223219
suspicious = any(deltas)
224220
if failing or suspicious:

Lib/test/ssl_servers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def translate_path(self, path):
6161
6262
"""
6363
# abandon query parameters
64-
path = urllib.parse.urlparse(path)[2]
64+
path = urllib.parse.urlparse(path).path
6565
path = os.path.normpath(urllib.parse.unquote(path))
6666
words = path.split('/')
6767
words = filter(None, words)

Lib/test/support/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ def open_urlresource(url, *args, **kw):
868868

869869
check = kw.pop('check', None)
870870

871-
filename = urllib.parse.urlparse(url)[2].split('/')[-1] # '/': it's URL!
871+
filename = urllib.parse.urlparse(url).path.split('/')[-1] # '/': it's URL!
872872

873873
fn = os.path.join(TEST_DATA_DIR, filename)
874874

Lib/test/support/os_helper.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,10 @@ def _rmtree_inner(path):
434434
file=sys.__stderr__)
435435
mode = 0
436436
if stat.S_ISDIR(mode):
437-
_waitfor(_rmtree_inner, fullname, waitall=True)
437+
# Do not follow junctions, which os.lstat() reports
438+
# as directories.
439+
if not os.path.isjunction(fullname):
440+
_waitfor(_rmtree_inner, fullname, waitall=True)
438441
_force_run(fullname, os.rmdir, fullname)
439442
else:
440443
_force_run(fullname, os.unlink, fullname)

Lib/test/test_ast/test_ast.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ def test_parse_invalid_ast(self):
162162
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
163163
optimize=optval)
164164

165+
def test_parse_ast_func_type(self):
166+
# see gh-156689
167+
tree = ast.parse('(int, str) -> bool', mode='func_type')
168+
self.assertEqual(ast.dump(ast.parse(tree, mode='func_type')),
169+
ast.dump(tree))
170+
self.assertRaises(TypeError, ast.parse, ast.Constant(42),
171+
mode='func_type')
172+
self.assertRaises(TypeError, ast.parse, tree, mode='exec')
173+
165174
def test_optimization_levels__debug__(self):
166175
cases = [(-1, '__debug__'), (0, '__debug__'), (1, False), (2, False)]
167176
for (optval, expected) in cases:

Lib/test/test_asyncio/test_taskgroups.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,17 @@ async def test_taskgroup_cancel_before_create_task(self):
11871187
with self.assertRaises(RuntimeError):
11881188
tg.create_task(asyncio.sleep(1))
11891189

1190+
async def test_taskgroup_cancel_from_child_before_first_suspension(self):
1191+
# gh-155418: an eager task can cancel the group before joining _tasks
1192+
async def child(tg):
1193+
tg.cancel()
1194+
await asyncio.sleep(10)
1195+
self.fail("the child was not cancelled")
1196+
1197+
async with asyncio.TaskGroup() as tg:
1198+
task = tg.create_task(child(tg))
1199+
self.assertTrue(task.cancelled())
1200+
11901201
async def test_taskgroup_cancel_keeps_outer_cancellation(self):
11911202
# gh-155433: any cancellation from outside the group must propagate.
11921203
async def child():

0 commit comments

Comments
 (0)