Skip to content

Commit ee58218

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Import CPython 3.14.6+ stable branch (2026-07-22)
Summary: Imported python/cpython `3.14.6+` from upstream rev [`8aa1b8b`](https://www.github.com/python/cpython/commit/8aa1b8b42ee47f252641d2a0d232bc94afd501e2) (committed 2026-07-22 04:43:51+00:00). # Commit Info - Base: (`3.14.6+`) - [`856c811`](https://www.github.com/python/cpython/commit/856c8119ea9d8f574dd56cf64afe19ee2e460c8b) (commit date: 2026-07-21 03:54:27+00:00) - Imported: (`3.14.6+`) - [`8aa1b8b`](https://www.github.com/python/cpython/commit/8aa1b8b42ee47f252641d2a0d232bc94afd501e2) (commit date: 2026-07-22 04:43:51+00:00) # Noteworthy file changes - Low-signal files (3 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GPWtPSi4v5ILyj4GAOSI1NzbaD9Jbr0LAAAz Reviewed By: ambv Differential Revision: D113225356 fbshipit-source-id: 9e0b1472dec61181e2f3f667ee954603ae6f8a08
1 parent 9b29c7c commit ee58218

17 files changed

Lines changed: 136 additions & 68 deletions

Lib/csv.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,10 @@ def _guess_quote_and_delimiter(self, data, delimiters):
283283
import re
284284

285285
matches = []
286-
for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",
287-
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?",
288-
r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)', # ,".*?"
289-
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space)
286+
for restr in (r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?P=delim)', # ,".*?",
287+
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?P<delim>[^\w\n"\'])(?P<space> ?)', # ".*?",
288+
r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\r|\n)', # ,".*?"
289+
r'(?:^|\n)(?P<quote>["\']).*?(?P=quote)(?:$|\r|\n)'): # ".*?" (no delim, no space)
290290
regexp = re.compile(restr, re.DOTALL | re.MULTILINE)
291291
matches = regexp.findall(data)
292292
if matches:

Lib/idlelib/idle_test/test_configdialog.py

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ def test_font_set(self):
244244

245245
def test_set_samples(self):
246246
d = self.page
247+
self.addCleanup(setattr, d, 'set_samples', Func()) # Re-mask for other tests.
247248
del d.set_samples # Unmask method for test
248249
orig_samples = d.font_sample, d.highlight_sample
249250
d.font_sample, d.highlight_sample = {}, {}
@@ -257,7 +258,6 @@ def test_set_samples(self):
257258
self.assertTrue(d.font_sample == d.highlight_sample == expected)
258259

259260
d.font_sample, d.highlight_sample = orig_samples
260-
d.set_samples = Func() # Re-mask for other tests.
261261

262262

263263
class HighPageTest(unittest.TestCase):
@@ -307,7 +307,7 @@ def test_load_theme_cfg(self):
307307
# builtinlist sets variable builtin_name to the CurrentTheme default.
308308
eq(d.builtin_name.get(), 'IDLE Classic')
309309
eq(d.custom_name.get(), '- no custom themes -')
310-
eq(d.custom_theme_on.state(), ('disabled',))
310+
self.assertIn('disabled', d.custom_theme_on.state())
311311
eq(d.set_theme_type.called, 1)
312312
eq(d.paint_theme_sample.called, 1)
313313
eq(d.set_highlight_target.called, 1)
@@ -495,23 +495,23 @@ def test_highlight_sample_b1_motion(self):
495495
def test_set_theme_type(self):
496496
eq = self.assertEqual
497497
d = self.page
498+
self.addCleanup(setattr, d, 'set_theme_type', Func()) # Re-mask method.
498499
del d.set_theme_type
499500

500501
# Builtin theme selected.
501502
d.theme_source.set(True)
502503
d.set_theme_type()
503504
eq(d.builtinlist['state'], NORMAL)
504505
eq(d.customlist['state'], DISABLED)
505-
eq(d.button_delete_custom.state(), ('disabled',))
506+
self.assertIn('disabled', d.button_delete_custom.state())
506507

507508
# Custom theme selected.
508509
d.theme_source.set(False)
509510
d.set_theme_type()
510511
eq(d.builtinlist['state'], DISABLED)
511-
eq(d.custom_theme_on.state(), ('selected',))
512+
self.assertNotIn('disabled', d.custom_theme_on.state())
512513
eq(d.customlist['state'], NORMAL)
513-
eq(d.button_delete_custom.state(), ())
514-
d.set_theme_type = Func()
514+
self.assertNotIn('disabled', d.button_delete_custom.state())
515515

516516
def test_get_color(self):
517517
eq = self.assertEqual
@@ -637,24 +637,23 @@ def test_create_new_and_save_new(self):
637637
def test_set_highlight_target(self):
638638
eq = self.assertEqual
639639
d = self.page
640+
self.addCleanup(setattr, d, 'set_highlight_target', Func()) # Re-mask method.
640641
del d.set_highlight_target
641642

642643
# Target is cursor.
643644
d.highlight_target.set('Cursor')
644-
eq(d.fg_on.state(), ('disabled', 'selected'))
645-
eq(d.bg_on.state(), ('disabled',))
645+
self.assertIn('disabled', d.fg_on.state())
646+
self.assertIn('disabled', d.bg_on.state())
646647
self.assertTrue(d.fg_bg_toggle)
647648
eq(d.set_color_sample.called, 1)
648649

649650
# Target is not cursor.
650651
d.highlight_target.set('Comment')
651-
eq(d.fg_on.state(), ('selected',))
652-
eq(d.bg_on.state(), ())
652+
self.assertNotIn('disabled', d.fg_on.state())
653+
self.assertNotIn('disabled', d.bg_on.state())
653654
self.assertTrue(d.fg_bg_toggle)
654655
eq(d.set_color_sample.called, 2)
655656

656-
d.set_highlight_target = Func()
657-
658657
def test_set_color_sample_binding(self):
659658
d = self.page
660659
scs = d.set_color_sample
@@ -667,14 +666,14 @@ def test_set_color_sample_binding(self):
667666

668667
def test_set_color_sample(self):
669668
d = self.page
669+
self.addCleanup(setattr, d, 'set_color_sample', Func()) # Re-mask method.
670670
del d.set_color_sample
671671
d.highlight_target.set('Selected Text')
672672
d.fg_bg_toggle.set(True)
673673
d.set_color_sample()
674674
self.assertEqual(
675675
d.style.lookup(d.frame_color_set['style'], 'background'),
676676
d.highlight_sample.tag_cget('hilite', 'foreground'))
677-
d.set_color_sample = Func()
678677

679678
def test_paint_theme_sample(self):
680679
eq = self.assertEqual
@@ -745,7 +744,7 @@ def test_delete_custom(self):
745744
eq(yesno.called, 2)
746745
self.assertNotIn(theme_name, highpage)
747746
eq(idleConf.GetSectionList('user', 'highlight'), [theme_name2])
748-
eq(d.custom_theme_on.state(), ())
747+
self.assertNotIn('disabled', d.custom_theme_on.state())
749748
eq(d.custom_name.get(), theme_name2)
750749
eq(dialog.deactivate_current_config.called, 1)
751750
eq(dialog.activate_config_changes.called, 1)
@@ -758,7 +757,7 @@ def test_delete_custom(self):
758757
eq(yesno.called, 3)
759758
self.assertNotIn(theme_name, highpage)
760759
eq(idleConf.GetSectionList('user', 'highlight'), [])
761-
eq(d.custom_theme_on.state(), ('disabled',))
760+
self.assertIn('disabled', d.custom_theme_on.state())
762761
eq(d.custom_name.get(), '- no custom themes -')
763762
eq(dialog.deactivate_current_config.called, 2)
764763
eq(dialog.activate_config_changes.called, 2)
@@ -809,7 +808,7 @@ def test_load_key_cfg(self):
809808
# builtinlist sets variable builtin_name to the CurrentKeys default.
810809
eq(d.builtin_name.get(), 'IDLE Classic OSX')
811810
eq(d.custom_name.get(), '- no custom keys -')
812-
eq(d.custom_keyset_on.state(), ('disabled',))
811+
self.assertIn('disabled', d.custom_keyset_on.state())
813812
eq(d.set_keys_type.called, 1)
814813
eq(d.load_keys_list.called, 1)
815814
eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
@@ -930,23 +929,23 @@ def test_keybinding(self):
930929
def test_set_keys_type(self):
931930
eq = self.assertEqual
932931
d = self.page
932+
self.addCleanup(setattr, d, 'set_keys_type', Func()) # Re-mask method.
933933
del d.set_keys_type
934934

935935
# Builtin keyset selected.
936936
d.keyset_source.set(True)
937937
d.set_keys_type()
938938
eq(d.builtinlist['state'], NORMAL)
939939
eq(d.customlist['state'], DISABLED)
940-
eq(d.button_delete_custom_keys.state(), ('disabled',))
940+
self.assertIn('disabled', d.button_delete_custom_keys.state())
941941

942942
# Custom keyset selected.
943943
d.keyset_source.set(False)
944944
d.set_keys_type()
945945
eq(d.builtinlist['state'], DISABLED)
946-
eq(d.custom_keyset_on.state(), ('selected',))
946+
self.assertNotIn('disabled', d.custom_keyset_on.state())
947947
eq(d.customlist['state'], NORMAL)
948-
eq(d.button_delete_custom_keys.state(), ())
949-
d.set_keys_type = Func()
948+
self.assertNotIn('disabled', d.button_delete_custom_keys.state())
950949

951950
def test_get_new_keys(self):
952951
eq = self.assertEqual
@@ -1043,7 +1042,7 @@ def test_on_bindingslist_select(self):
10431042
b.event_generate('<Button-1>', x=x, y=y)
10441043
b.event_generate('<ButtonRelease-1>', x=x, y=y)
10451044
self.assertEqual(b.get('anchor'), 'find')
1046-
self.assertEqual(d.button_new_keys.state(), ())
1045+
self.assertNotIn('disabled', d.button_new_keys.state())
10471046

10481047
def test_create_new_key_set_and_save_new_key_set(self):
10491048
eq = self.assertEqual
@@ -1080,6 +1079,7 @@ def test_load_keys_list(self):
10801079
eq = self.assertEqual
10811080
d = self.page
10821081
gks = idleConf.GetKeySet = Func()
1082+
self.addCleanup(setattr, d, 'load_keys_list', Func()) # Re-mask method.
10831083
del d.load_keys_list
10841084
b = d.bindingslist
10851085

@@ -1115,7 +1115,6 @@ def test_load_keys_list(self):
11151115
eq(b.get(0, 'end'), expected)
11161116
eq(b.get('anchor'), 'spam - <Shift-Key-a>')
11171117
eq(b.curselection(), (2, ))
1118-
d.load_keys_list = Func()
11191118

11201119
del idleConf.GetKeySet
11211120

@@ -1156,7 +1155,7 @@ def test_delete_custom_keys(self):
11561155
eq(yesno.called, 2)
11571156
self.assertNotIn(keyset_name, keyspage)
11581157
eq(idleConf.GetSectionList('user', 'keys'), [keyset_name2])
1159-
eq(d.custom_keyset_on.state(), ())
1158+
self.assertNotIn('disabled', d.custom_keyset_on.state())
11601159
eq(d.custom_name.get(), keyset_name2)
11611160
eq(dialog.deactivate_current_config.called, 1)
11621161
eq(dialog.activate_config_changes.called, 1)
@@ -1169,7 +1168,7 @@ def test_delete_custom_keys(self):
11691168
eq(yesno.called, 3)
11701169
self.assertNotIn(keyset_name, keyspage)
11711170
eq(idleConf.GetSectionList('user', 'keys'), [])
1172-
eq(d.custom_keyset_on.state(), ('disabled',))
1171+
self.assertIn('disabled', d.custom_keyset_on.state())
11731172
eq(d.custom_name.get(), '- no custom keys -')
11741173
eq(dialog.deactivate_current_config.called, 2)
11751174
eq(dialog.activate_config_changes.called, 2)
@@ -1365,25 +1364,25 @@ def test_set_add_delete_state(self):
13651364
# Call with 0 items, 1 unselected item, 1 selected item.
13661365
eq = self.assertEqual
13671366
fr = self.frame
1367+
self.addCleanup(setattr, fr, 'set_add_delete_state', Func()) # Re-mask method.
13681368
del fr.set_add_delete_state # Unmask method.
13691369
sad = fr.set_add_delete_state
13701370
h = fr.helplist
13711371

13721372
h.delete(0, 'end')
13731373
sad()
1374-
eq(fr.button_helplist_edit.state(), ('disabled',))
1375-
eq(fr.button_helplist_remove.state(), ('disabled',))
1374+
self.assertIn('disabled', fr.button_helplist_edit.state())
1375+
self.assertIn('disabled', fr.button_helplist_remove.state())
13761376

13771377
h.insert(0, 'source')
13781378
sad()
1379-
eq(fr.button_helplist_edit.state(), ('disabled',))
1380-
eq(fr.button_helplist_remove.state(), ('disabled',))
1379+
self.assertIn('disabled', fr.button_helplist_edit.state())
1380+
self.assertIn('disabled', fr.button_helplist_remove.state())
13811381

13821382
h.selection_set(0)
13831383
sad()
1384-
eq(fr.button_helplist_edit.state(), ())
1385-
eq(fr.button_helplist_remove.state(), ())
1386-
fr.set_add_delete_state = Func() # Mask method.
1384+
self.assertNotIn('disabled', fr.button_helplist_edit.state())
1385+
self.assertNotIn('disabled', fr.button_helplist_remove.state())
13871386

13881387
def test_helplist_item_add(self):
13891388
# Call without and twice with HelpSource result.
@@ -1461,6 +1460,7 @@ def test_helplist_item_remove(self):
14611460

14621461
def test_update_help_changes(self):
14631462
fr = self.frame
1463+
self.addCleanup(setattr, fr, 'update_help_changes', Func()) # Re-mask method.
14641464
del fr.update_help_changes
14651465
fr.user_helplist.clear()
14661466
fr.user_helplist.append(('name1', 'file1'))
@@ -1469,7 +1469,6 @@ def test_update_help_changes(self):
14691469
fr.update_help_changes()
14701470
self.assertEqual(mainpage['HelpFiles'],
14711471
{'1': 'name1;file1', '2': 'name2;file2'})
1472-
fr.update_help_changes = Func()
14731472

14741473

14751474
class VarTraceTest(unittest.TestCase):

Lib/idlelib/idle_test/test_sidebar.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,19 +695,23 @@ def test_mousewheel(self):
695695
last_lineno = get_end_linenumber(text)
696696
self.assertIsNotNone(text.dlineinfo(text.index(f'{last_lineno}.0')))
697697

698-
# Delta for <MouseWheel>, whose meaning is platform-dependent.
698+
# Simulate a mouse wheel notch. Tk 8.7 replaced the X11
699+
# <Button-4>/<Button-5> wheel events with <MouseWheel> (whose delta is
700+
# platform-dependent); older Tk on X11 still uses the button events.
701+
x11_buttons = (sidebar.canvas._windowingsystem == 'x11'
702+
and tk.TkVersion < 8.7)
699703
delta = 1 if sidebar.canvas._windowingsystem == 'aqua' else 120
700704

701705
# Scroll up.
702-
if sidebar.canvas._windowingsystem == 'x11':
706+
if x11_buttons:
703707
sidebar.canvas.event_generate('<Button-4>', x=0, y=0)
704708
else:
705709
sidebar.canvas.event_generate('<MouseWheel>', x=0, y=0, delta=delta)
706710
yield
707711
self.assertIsNone(text.dlineinfo(text.index(f'{last_lineno}.0')))
708712

709713
# Scroll back down.
710-
if sidebar.canvas._windowingsystem == 'x11':
714+
if x11_buttons:
711715
sidebar.canvas.event_generate('<Button-5>', x=0, y=0)
712716
else:
713717
sidebar.canvas.event_generate('<MouseWheel>', x=0, y=0, delta=-delta)

Lib/test/libregrtest/run_workers.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,12 @@ def _kill(self) -> None:
147147

148148
use_killpg = USE_PROCESS_GROUP
149149
if use_killpg:
150-
parent_sid = os.getsid(0)
151-
sid = os.getsid(popen.pid)
152-
use_killpg = (sid != parent_sid)
150+
try:
151+
use_killpg = (os.getsid(popen.pid) != os.getsid(0))
152+
except PermissionError:
153+
# On OpenBSD getsid() is only allowed for a process in the
154+
# same session, so the failure means that it is not.
155+
use_killpg = True
153156

154157
if use_killpg:
155158
what = f"{self} process group"

Lib/test/test_asyncio/test_sendfile.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ class SendfileBase:
9898
# 64 KiB page configuration.
9999
DATA = b"x" * (1024 * 17 * 64 + 1)
100100
# Reduce socket buffer size to test on relative small data sets.
101-
BUF_SIZE = 4 * 1024 # 4 KiB
101+
if sys.platform.startswith('dragonfly'):
102+
# A smaller buffer makes every window update wait 100 ms for the
103+
# delayed ACK timer.
104+
BUF_SIZE = 32 * 1024 # 32 KiB
105+
else:
106+
BUF_SIZE = 4 * 1024 # 4 KiB
102107

103108
def create_event_loop(self):
104109
raise NotImplementedError

Lib/test/test_csv.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,9 @@ class TestSniffer(unittest.TestCase):
14021402
sample18.append("v,twenty_one") # 'u' was not skipped
14031403
sample18 = '\n'.join(sample18)
14041404

1405+
sample19 = ('time,title\r\n'
1406+
'2020-10-01,"Pocket - Save news, videos, stories and more"\r\n')
1407+
14051408
def test_issue43625(self):
14061409
sniffer = csv.Sniffer()
14071410
self.assertTrue(sniffer.has_header(self.sample12))
@@ -1481,6 +1484,9 @@ def test_delimiters(self):
14811484
sniffer.sniff, self.sample15)
14821485
self.assertRaisesRegex(csv.Error, "Could not determine delimiter",
14831486
sniffer.sniff, self.sample16)
1487+
dialect = sniffer.sniff(self.sample19)
1488+
self.assertEqual(dialect.delimiter, ',')
1489+
self.assertEqual(dialect.quotechar, '"')
14841490

14851491
def test_doublequote(self):
14861492
sniffer = csv.Sniffer()

Lib/test/test_epoll.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import os
2626
import select
2727
import socket
28+
import sys
2829
import time
2930
import unittest
3031
from test import support
@@ -52,12 +53,11 @@ def tearDown(self):
5253
def _connected_pair(self):
5354
client = socket.socket()
5455
client.setblocking(False)
56+
# The connection is either established immediately or in progress.
5557
try:
5658
client.connect(('127.0.0.1', self.serverSocket.getsockname()[1]))
5759
except OSError as e:
5860
self.assertEqual(e.args[0], errno.EINPROGRESS)
59-
else:
60-
raise AssertionError("Connect should have raised EINPROGRESS")
6161
server, addr = self.serverSocket.accept()
6262

6363
self.connections.extend((client, server))
@@ -218,6 +218,9 @@ def test_errors(self):
218218
self.assertRaises(ValueError, select.epoll().register, -1,
219219
select.EPOLLIN)
220220

221+
@unittest.skipIf(sys.platform.startswith('sunos'),
222+
'unregistering a closed file descriptor succeeds '
223+
'on Solaris')
221224
def test_unregister_closed(self):
222225
server, client = self._connected_pair()
223226
fd = server.fileno()

Lib/test/test_os.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4955,12 +4955,27 @@ def test_posix_pty_functions(self):
49554955
son_fd = os.open(son_path, os.O_RDWR|os.O_NOCTTY)
49564956
self.addCleanup(os.close, son_fd)
49574957
if sys.platform.startswith('sunos'):
4958-
# The slave is not a terminal until these STREAMS modules
4959-
# are pushed onto it.
49604958
import fcntl
49614959
I_PUSH = 0x5302
4960+
TIOCNOTTY = 0x7471
4961+
# Pushing "ptem" makes the slave a terminal, which a session
4962+
# leader without a controlling terminal then acquires as one
4963+
# despite O_NOCTTY. Note whether we already had one.
4964+
try:
4965+
os.close(os.open('/dev/tty', os.O_RDONLY|os.O_NOCTTY))
4966+
had_ctty = True
4967+
except OSError:
4968+
had_ctty = False
49624969
fcntl.ioctl(son_fd, I_PUSH, b'ptem\0')
49634970
fcntl.ioctl(son_fd, I_PUSH, b'ldterm\0')
4971+
if not had_ctty and os.getsid(0) == os.getpid():
4972+
# Disown it, otherwise closing the file descriptors sends
4973+
# SIGHUP to the session. TIOCNOTTY sends it too.
4974+
old_handler = signal.signal(signal.SIGHUP, signal.SIG_IGN)
4975+
try:
4976+
fcntl.ioctl(son_fd, TIOCNOTTY)
4977+
finally:
4978+
signal.signal(signal.SIGHUP, old_handler)
49644979
self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
49654980

49664981
@unittest.skipUnless(hasattr(os, 'spawnl'), "need os.spawnl()")

0 commit comments

Comments
 (0)