https://github.com/python/cpython/commit/dcc4e5247a4885b76b7fc26f5f5809c7a9064e7c
commit: dcc4e5247a4885b76b7fc26f5f5809c7a9064e7c
branch: main
author: Vyron Vasileiadis <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-09-07T22:21:47+03:00
summary:
gh-156951: Do not truncate the color pair in curses.slk_color() (GH-156952)
slk_color() cast its color pair to a short, so pairs of 32768 and above
were rejected or silently applied as a different pair. Use
extended_slk_color() when it is available, like slk_attr_set() does.
files:
M Lib/test/test_curses.py
M Modules/_cursesmodule.c
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index a75b95d988b070..0c63b04a461453 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -3482,10 +3482,10 @@ class SLKTests(NewtermTestBase):
# slk_init() must run before newterm()/initscr(), so each test sets up its
# own screen rather than reusing the one TestCurses builds in setUp().
- def make_slk_screen(self, fmt=0):
+ def make_slk_screen(self, fmt=0, term='xterm'):
s = self.make_pty()
curses.slk_init(fmt)
- return curses.newterm('xterm', s, s)
+ return curses.newterm(term, s, s)
def test_init_reserves_a_line(self):
# Every layout takes the bottom line for the labels; the index-line
@@ -3568,6 +3568,26 @@ def test_color(self):
curses.slk_attr_set(curses.A_BOLD, 0)
curses.slk_color(0)
+ def test_color_wide_pair(self):
+ # Drive a terminal with enough color pairs to reach past a short,
+ # rather than relying on whatever $TERM happens to be.
+ try:
+ self.make_slk_screen(term='xterm-256color')
+ except curses.error:
+ self.skipTest('no xterm-256color terminfo entry')
+ if not curses.has_colors():
+ self.skipTest('requires colors support')
+ curses.start_color()
+ if not (curses.has_extended_color_support()
+ and curses.COLOR_PAIRS > SHORT_MAX + 1):
+ self.skipTest('requires extended color support')
+ # A pair that does not fit in a short is still a valid pair here.
+ curses.slk_color(SHORT_MAX + 1)
+ # The low 16 bits of this are pair 5, but the pair itself is out of
+ # range, so it must raise instead of selecting pair 5.
+ self.assertRaises(curses.error, curses.slk_color,
+ curses.COLOR_PAIRS * 2 + 5)
+
@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()')
@unittest.skipIf(BROKEN_NEWTERM, 'ncurses < 6.5 mishandles repeated newterm()')
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 781b39628bfa31..f22aac624a8a66 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -8866,7 +8866,13 @@ _curses_slk_color_impl(PyObject *module, int pair)
/*[clinic end generated code: output=ffe4de805f9c65f5 input=b1e691a9cc6177ee]*/
{
PyCursesStatefulInitialised(module);
- return curses_check_err(module, slk_color((short)pair), "slk_color", NULL);
+ int rtn;
+#if _NCURSES_EXTENDED_COLOR_FUNCS
+ rtn = extended_slk_color(pair);
+#else
+ rtn = slk_color((short)pair);
+#endif
+ return curses_check_err(module, rtn, "slk_color", NULL);
}
#endif /* HAVE_CURSES_SLK_COLOR */
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]