Skip to content

Commit d446ab1

Browse files
generatedunixname1734921407115435meta-codesync[bot]
authored andcommitted
Import CPython 3.14.6+ stable branch (2026-07-26)
Summary: Imported python/cpython `3.14.6+` from upstream rev [`89be6f7`](https://www.github.com/python/cpython/commit/89be6f7778edda0399950aa368658ecfb7315028) (committed 2026-07-26 19:19:06+00:00). # Commit Info - Base: (`3.14.6+`) - [`92b0ec6`](https://www.github.com/python/cpython/commit/92b0ec643970933bf87241fd4eeb0fd292f87050) (commit date: 2026-07-25 13:26:21+00:00) - Imported: (`3.14.6+`) - [`89be6f7`](https://www.github.com/python/cpython/commit/89be6f7778edda0399950aa368658ecfb7315028) (commit date: 2026-07-26 19:19:06+00:00) # Noteworthy file changes - Low-signal files (2 added) (NEWS.d, docs, .github) Complete list of added/removed files: https://www.internalfb.com/intern/everpaste/?color=0&handle=GC3NICqmKQPgYokHANJ0g_c6ef9Mbr0LAAAz Reviewed By: itamaro Differential Revision: D113763738 fbshipit-source-id: 4a83d02b949011d30006638e7123dfe0a6d26ff8
1 parent 25b2f2d commit d446ab1

12 files changed

Lines changed: 89 additions & 20 deletions

File tree

Doc/library/curses.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,9 @@ Window objects
10841084
and the color pair with :func:`pair_number`.
10851085
The character byte is the locale-encoded byte of the cell's character,
10861086
consistent with :meth:`instr`.
1087+
On a wide-character build, a character that does not fit in a single byte
1088+
in the current locale has a character byte of ``0``;
1089+
use :meth:`instr` to read such characters.
10871090

10881091

10891092
.. method:: window.insch(ch[, attr])

Lib/test/test_asyncio/test_tasks.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2752,6 +2752,18 @@ async def main():
27522752
self.assertEqual(name, "example")
27532753
await t
27542754

2755+
def test_eager_start_true_no_loop(self):
2756+
# gh-154695: eager_start must use the resolved loop, not loop=None.
2757+
async def asyncfn():
2758+
return 42
2759+
2760+
async def main():
2761+
t = self.__class__.Task(asyncfn(), eager_start=True)
2762+
self.assertTrue(t.done())
2763+
self.assertEqual(await t, 42)
2764+
2765+
asyncio.run(main(), loop_factory=asyncio.EventLoop)
2766+
27552767
def test_eager_start_false(self):
27562768
name = None
27572769

Lib/test/test_cmd_line.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,26 @@ def run_utf8_mode(arg):
331331
)
332332
test_args = [valid_utf8, invalid_utf8]
333333

334-
for run_cmd in (run_default, run_c_locale, run_utf8_mode):
335-
with self.subTest(run_cmd=run_cmd):
334+
for run_cmd, encoding in (
335+
(run_default, sys.getfilesystemencoding()),
336+
(run_c_locale, None),
337+
(run_utf8_mode, None),
338+
):
339+
with self.subTest(run_cmd=run_cmd.__name__):
340+
# Arbitrary bytes round-trip through surrogateescape only in
341+
# UTF-8 and single-byte encodings, not in a multibyte encoding
342+
# such as EUC-JP.
343+
if encoding is not None:
344+
try:
345+
lossless = len(bytes(range(256)).decode(
346+
encoding, 'surrogateescape')) == 256
347+
except UnicodeError:
348+
lossless = False
349+
else:
350+
lossless = True
351+
if not lossless:
352+
self.skipTest(f'{encoding} cannot losslessly '
353+
f'round-trip arbitrary bytes')
336354
for arg in test_args:
337355
proc = run_cmd(arg)
338356
self.assertEqual(proc.stdout.rstrip(), ascii(arg))

Lib/test/test_curses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ def test_read_from_window(self):
517517
with self.subTest(ch=ch):
518518
stdscr.addstr(2, 0, ch)
519519
self.assertEqual(stdscr.instr(2, 0, 1), b)
520-
self.assertEqual(stdscr.inch(2, 0) & curses.A_CHARTEXT, b[0])
520+
self.assertEqual(stdscr.inch(2, 0), b[0])
521521

522522
def test_coordinate_errors(self):
523523
# Addressing a cell outside the window raises curses.error.

Lib/test/test_socket.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,23 @@ def testGetaddrinfo(self):
17411741
except socket.gaierror:
17421742
pass
17431743

1744+
@unittest.skipUnless(hasattr(socket, 'AI_NUMERICSERV'),
1745+
'needs socket.AI_NUMERICSERV')
1746+
@support.thread_unsafe('setlocale is not thread-safe')
1747+
@support.run_with_locales('LC_ALL',
1748+
'uk_UA.KOI8-U', 'uk_UA', 'ja_JP.eucJP', 'ja_JP.SJIS', 'ja_JP',
1749+
'ko_KR.eucKR', 'zh_CN.GB18030', 'el_GR.ISO8859-7',
1750+
'de_DE.ISO8859-1', 'ja_JP.UTF-8',
1751+
'')
1752+
def test_getaddrinfo_localized_error(self):
1753+
# gh-93251: the localized gai_strerror() message could fail to be
1754+
# decoded as UTF-8, so UnicodeDecodeError was raised
1755+
# instead of gaierror.
1756+
with self.assertRaises(socket.gaierror) as cm:
1757+
socket.getaddrinfo("localhost", "http",
1758+
flags=socket.AI_NUMERICSERV)
1759+
str(cm.exception)
1760+
17441761
@unittest.skipIf(_testcapi is None, "requires _testcapi")
17451762
def test_getaddrinfo_int_port_overflow(self):
17461763
# gh-74895: Test that getaddrinfo does not raise OverflowError on port.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :class:`asyncio.Task` raising :exc:`AttributeError` when created with
2+
``eager_start=True`` and no explicit *loop* argument.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fix :exc:`UnicodeDecodeError` in :mod:`socket` functions
2+
(such as :func:`~socket.getaddrinfo` and :func:`~socket.gethostbyaddr`)
3+
when the localized error message of the C library is not UTF-8:
4+
decode it from the locale encoding.

Modules/_asynciomodule.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2391,7 +2391,9 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop,
23912391
_PyObject_SetMaybeWeakref((PyObject *)self);
23922392
#endif
23932393
if (eager_start) {
2394-
PyObject *res = PyObject_CallMethodNoArgs(loop, &_Py_ID(is_running));
2394+
// gh-154695: loop may be None here, future_init() resolved it into task_loop.
2395+
PyObject *res = PyObject_CallMethodNoArgs(self->task_loop,
2396+
&_Py_ID(is_running));
23952397
if (res == NULL) {
23962398
return -1;
23972399
}

Modules/_cursesmodule.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1903,10 +1903,10 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1,
19031903
}
19041904

19051905
#ifdef HAVE_NCURSESW
1906-
/* winch() returns the low 8 bits of the character's code point with no locale
1907-
conversion, unlike instr(), so recover the locale byte from the wide cell
1908-
when the character maps to exactly one byte, keeping the attribute and color
1909-
bits in RTN. A character with no single-byte form is left to winch(). */
1906+
/* ncursesw's winch() returns the character's whole code point instead of its
1907+
locale byte, overflowing the chtype's 8-bit character field into the color
1908+
and attribute bits, so rebuild the value from the locale byte plus the
1909+
attributes and color pair reported by getcchar(). */
19101910
static chtype
19111911
curses_cell_locale_byte(chtype rtn, const cchar_t *cell)
19121912
{
@@ -1915,18 +1915,19 @@ curses_cell_locale_byte(chtype rtn, const cchar_t *cell)
19151915
short pair;
19161916
/* getcchar() is not guaranteed to write the text of an empty cell. */
19171917
wstr[0] = L'\0';
1918-
if (getcchar(cell, wstr, &attrs, &pair, NULL) == ERR
1919-
|| wstr[0] == L'\0' || wstr[1] != L'\0')
1920-
{
1918+
if (getcchar(cell, wstr, &attrs, &pair, NULL) == ERR) {
19211919
return rtn;
19221920
}
19231921
/* wctob() mirrors ncurses' own _nc_to_char(): the single-byte form, or EOF
1924-
when the character has none in this locale. */
1925-
int byte = wctob(wstr[0]);
1926-
if (byte != EOF) {
1927-
rtn = (rtn & ~(chtype)A_CHARTEXT) | (unsigned char)byte;
1922+
when the character has none in this locale (then use 0). */
1923+
int byte = 0;
1924+
if (wstr[0] != L'\0' && wstr[1] == L'\0') {
1925+
byte = wctob(wstr[0]);
1926+
if (byte == EOF) {
1927+
byte = 0;
1928+
}
19281929
}
1929-
return rtn;
1930+
return (chtype)byte | (attrs & ~(attr_t)A_COLOR) | COLOR_PAIR(pair);
19301931
}
19311932
#endif
19321933

Modules/_threadmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ get_thread_state(PyObject *module)
5050

5151

5252
#ifdef MS_WINDOWS
53-
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PCWSTR*);
53+
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PWSTR*);
5454
typedef HRESULT (WINAPI *PF_SET_THREAD_DESCRIPTION)(HANDLE, PCWSTR);
5555
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
5656
static PF_SET_THREAD_DESCRIPTION pSetThreadDescription = NULL;

0 commit comments

Comments
 (0)