From b5e11a7b218a621cf1070f4f06807a4bbe28f513 Mon Sep 17 00:00:00 2001 From: Vyron Vasileiadis Date: Wed, 29 Jul 2026 00:20:01 +0300 Subject: [PATCH] gh-154840: Keep the color pair out of curses complexchar.attr On a wide build getcchar() reports the packed color pair in the attributes, so attr carried it and saturated at 255, although the documentation says the pair is stored separately and is not limited to a color_pair() value. Mask A_COLOR out, as the narrow branch of the same function already does. repr() reads through the same function and is fixed with it. --- Lib/test/test_curses.py | 8 +++++++- Modules/_cursesmodule.c | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 9f7f8535b6d9a8..29d083250e2caa 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -584,9 +584,15 @@ def test_in_wch_color(self): stdscr.addch(0, 0, curses.complexchar('A', curses.A_BOLD, 1)) cc = stdscr.in_wch(0, 0) self.assertEqual(str(cc), 'A') - self.assertTrue(cc.attr & curses.A_BOLD) + self.assertEqual(cc.attr, curses.A_BOLD) self.assertEqual(cc.pair, 1) self.assertEqual(curses.complexchar('A', 0, 1).pair, 1) + # attr never carries the color pair, not even a pair that does not fit + # in a color_pair() value. + self.assertEqual(curses.complexchar('A', 0, 1).attr, 0) + self.assertEqual(curses.complexchar('A', 0, 300).attr, 0) + self.assertEqual(curses.complexchar('A', curses.A_BOLD, 1).attr, + curses.A_BOLD) def test_getbkgrnd(self): # getbkgrnd() returns the background as a complexchar (getbkgd() can diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 01ea3c43cce2e6..678c3c154ff867 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -889,6 +889,7 @@ curses_cell_attr_pair(cursesmodule_state *state, const curses_cell_t *cell, PyErr_SetString(state->error, "getcchar() returned ERR"); return -1; } + *attr &= ~(attr_t)A_COLOR; return 0; #else *attr = *cell & A_ATTRIBUTES & ~(attr_t)A_COLOR;