Skip to content

Commit de99186

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Import CPython 3.14.6+ stable branch (2026-08-03)
Summary: Imported python/cpython `3.14.6+` from upstream rev [`1f574b1`](https://www.github.com/python/cpython/commit/1f574b1ce58067f9fdaad0b5ff9a3bfb87151e4c) (committed 2026-08-03 21:14:27+00:00). # Commit Info - Base: (`3.14.6+`) - [`b0ef8b4`](https://www.github.com/python/cpython/commit/b0ef8b4f3ee5dd52748bfa991cfc765edd26e8f9) (commit date: 2026-08-02 18:18:09+00:00) - Imported: (`3.14.6+`) - [`1f574b1`](https://www.github.com/python/cpython/commit/1f574b1ce58067f9fdaad0b5ff9a3bfb87151e4c) (commit date: 2026-08-03 21:14:27+00:00) # Noteworthy file changes - Stdlib files (1 added, 1 removed) - Low-signal files (6 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GEhVgRY5LDPBVV0DAGr-MV3qj7BVbr0LAAAz Reviewed By: itamaro Differential Revision: D114726860 fbshipit-source-id: 0322f8940c8ebe5e1aa6df48589371fa07c256f4
1 parent dd0cc05 commit de99186

26 files changed

Lines changed: 192 additions & 49 deletions

Lib/csv.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ def sniff(self, sample, delimiters=None):
249249
that order, no matter how many times each of them occurs.
250250
"""
251251

252+
sample = sample.replace('\r\n', '\n').replace('\r', '\n')
253+
252254
quotechar, doublequote, delimiter, skipinitialspace = \
253255
self._guess_quote_and_delimiter(sample, delimiters)
254256
if not delimiter:
@@ -334,18 +336,22 @@ def _guess_quote_and_delimiter(self, data, delimiters):
334336
delim = ''
335337
skipinitialspace = 0
336338

337-
# if we see an extra quote between delimiters, we've got a
338-
# double quoted format
339-
dq_regexp = re.compile(
340-
r"((%(delim)s)|^)\W*%(quote)s[^%(delim)s\n]*%(quote)s[^%(delim)s\n]*%(quote)s\W*((%(delim)s)|$)" % \
341-
{'delim':re.escape(delim), 'quote':quotechar}, re.MULTILINE)
342-
343-
344-
345-
if dq_regexp.search(data):
346-
doublequote = True
347-
else:
348-
doublequote = False
339+
# A doubled quote character inside a quoted field means
340+
# a double quoted format. Match whole fields, so that a match
341+
# cannot slide across field boundaries.
342+
doublequote = False
343+
if delim:
344+
dq_regexp = re.compile(
345+
r"(?:(?<=%(delim)s)|^)%(space)s%(quote)s" # ,"
346+
r"((?:%(quote)s%(quote)s|[^%(quote)s]++)*+)" # the body
347+
r"%(quote)s(?:%(delim)s|$)" # ",
348+
% {'delim': re.escape(delim), 'quote': quotechar,
349+
# Skipping spaces after a space rescans them.
350+
'space': ' *+' if delim != ' ' else ''},
351+
re.MULTILINE)
352+
dquotechar = quotechar * 2
353+
doublequote = any(dquotechar in m[1]
354+
for m in dq_regexp.finditer(data))
349355

350356
return (quotechar, doublequote, delim, skipinitialspace)
351357

Lib/ensurepip/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
__all__ = ["version", "bootstrap"]
13-
_PIP_VERSION = "26.1.2"
13+
_PIP_VERSION = "26.2"
1414

1515
# Directory of system wheel packages. Some Linux distribution packaging
1616
# policies recommend against bundling dependencies. For example, Fedora
1.73 MB
Binary file not shown.

Lib/test/test_csv.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1501,6 +1501,50 @@ def test_doublequote(self):
15011501
dialect = sniffer.sniff(self.sample9)
15021502
self.assertTrue(dialect.doublequote)
15031503

1504+
def test_sniff_regex_backtracking(self):
1505+
# gh-109638: this artificial sample used to take minutes.
1506+
sniffer = csv.Sniffer()
1507+
sample = '"",' * 100 + '"' * 100 + '0' + '"' * 100 + '0'
1508+
self.assertEqual(sniffer.sniff(sample).delimiter, ',')
1509+
1510+
def test_sniff_doublequote_across_fields(self):
1511+
# A quoted field which contains the delimiter, followed by
1512+
# an empty quoted field, is not a doubled quote.
1513+
sniffer = csv.Sniffer()
1514+
sample = '",","",","\n' * 4
1515+
dialect = sniffer.sniff(sample)
1516+
self.assertEqual(dialect.delimiter, ',')
1517+
self.assertEqual(dialect.quotechar, '"')
1518+
self.assertIs(dialect.doublequote, False)
1519+
self.assertEqual(next(csv.reader(StringIO(sample), dialect)),
1520+
[',', '', ','])
1521+
1522+
def test_sniff_doublequote_record_separators(self):
1523+
# The record separator ends a field as a delimiter does.
1524+
sniffer = csv.Sniffer()
1525+
for sep in '\n', '\r\n', '\r':
1526+
with self.subTest(sep=sep):
1527+
sample = ('x,"a""b"' + sep + 'y,"c"' + sep) * 2
1528+
self.assertIs(sniffer.sniff(sample).doublequote, True)
1529+
sample = ('"",","' + sep) * 4
1530+
self.assertIs(sniffer.sniff(sample).doublequote, False)
1531+
1532+
def test_sniff_single_column(self):
1533+
# This sample used to be quadratic.
1534+
sniffer = csv.Sniffer()
1535+
sample = '"a"\n' + ' ' * 100000
1536+
with self.assertRaisesRegex(csv.Error, "Could not determine delimiter"):
1537+
sniffer.sniff(sample, delimiters=',;')
1538+
1539+
def test_sniff_space_delimiter(self):
1540+
# This sample used to be quadratic.
1541+
sniffer = csv.Sniffer()
1542+
sample = '"a" "b"\n' + ' ' * 100000
1543+
dialect = sniffer.sniff(sample)
1544+
self.assertEqual(dialect.delimiter, ' ')
1545+
self.assertIs(dialect.doublequote, False)
1546+
1547+
15041548
class NUL:
15051549
def write(s, *args):
15061550
pass

Lib/test/test_pyexpat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,13 @@ def test_parent_parser_outlives_its_subparsers__chain(self):
956956
del parser
957957
del subparser
958958

959+
def test_subparser_inherits_reparse_deferral(self):
960+
for enabled in (True, False):
961+
parser = expat.ParserCreate()
962+
parser.SetReparseDeferralEnabled(enabled)
963+
subparser = parser.ExternalEntityParserCreate(None)
964+
self.assertEqual(subparser.GetReparseDeferralEnabled(), enabled)
965+
959966

960967
class ExternalEntityParserCreateErrorTest(unittest.TestCase):
961968
"""ExternalEntityParserCreate error paths should not crash or leak

Lib/test/test_tcl.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ def test_eval_null_in_result(self):
5454

5555
def test_eval_surrogates_in_result(self):
5656
tcl = self.interp
57-
self.assertEqual(tcl.eval(r'set a "<\ud83d\udcbb>"'), '<\U0001f4bb>')
57+
result = tcl.eval(r'set a "<\ud83d\udcbb>"')
58+
if sys.platform == 'win32' and tcl_version >= (9, 0):
59+
self.assertEqual('<\ud83d\udcbb>', result)
60+
else:
61+
self.assertEqual('<\U0001f4bb>', result)
5862

5963
def testEvalException(self):
6064
tcl = self.interp
@@ -289,7 +293,11 @@ def test_evalfile_surrogates_in_result(self):
289293
set b "<\\ud83d\\udcbb>"
290294
""")
291295
tcl.evalfile(filename)
292-
self.assertEqual(tcl.eval('set b'), '<\U0001f4bb>')
296+
result = tcl.eval('set b')
297+
if sys.platform == 'win32' and tcl_version >= (9, 0):
298+
self.assertEqual('<\ud83d\udcbb>', result)
299+
else:
300+
self.assertEqual('<\U0001f4bb>', result)
293301

294302
def testEvalFileException(self):
295303
tcl = self.interp

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ DIST= $(DISTFILES) $(DISTDIRS)
280280
LIBRARY= @LIBRARY@
281281
LDLIBRARY= @LDLIBRARY@
282282
BLDLIBRARY= @BLDLIBRARY@
283+
MODULE_LDFLAGS_SHARED=$(if $(LIBPYTHON),$(BLDLIBRARY))
283284
PY3LIBRARY= @PY3LIBRARY@
284285
DLLLIBRARY= @DLLLIBRARY@
285286
LDLIBRARYDIR= @LDLIBRARYDIR@
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix library name in python3.pc on Android.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :meth:`!ExternalEntityParserCreate` not propagating the reparse-deferral
2+
setting to the subparser, which left :meth:`!GetReparseDeferralEnabled`
3+
returning an uninitialized value. Patch by tonghuaroot.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix exponential time in :meth:`csv.Sniffer.sniff` for a sample which contains
2+
many quote characters. A doubled quote character is now also detected in
3+
a field which contains the delimiter or a line break.

0 commit comments

Comments
 (0)