gh-154840: Keep the color pair out of curses complexchar.attr (GH-154841)

serhiy-storchaka <[email protected]> Tue, 11 Aug 2026 05:09:41 -0400 (EDT)
Newsgroups gmane.comp.python.cvs
Message-ID <[email protected]>
https://github.com/python/cpython/commit/a7541c3843640d0112857ad0c0006916d958775a
commit: a7541c3843640d0112857ad0c0006916d958775a
branch: main
author: Vyron Vasileiadis <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-08-11T11:50:14+03:00
summary:

gh-154840: Keep the color pair out of curses complexchar.attr (GH-154841)

On a wide build getcchar() also reports the color pair in the A_COLOR
bits of the attributes, where it saturates at 255, so complexchar.attr
carried it.  Mask those bits out in curses_getcchar(), as the narrow
build already does when packing a cell.

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 f7584a39b182d9..d87374a298fc33 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -537,6 +537,11 @@ def test_complexchar(self):
         self.assertEqual(str(cc), 'z')
         self.assertEqual(cc.attr, 0)
         self.assertEqual(cc.pair, 0)
+        # attr never carries the color pair.
+        self.assertEqual(curses.complexchar('A', 0, 1).attr, 0)
+        self.assertEqual(curses.complexchar('A', curses.A_BOLD, 1).attr,
+                         curses.A_BOLD)
+        self.assertEqual(curses.complexchar('A', 0, 1).pair, 1)
         # Immutable rendition.
         self.assertRaises(AttributeError, setattr, cc, 'attr', 1)
         self.assertRaises(AttributeError, setattr, cc, 'pair', 1)
@@ -592,7 +597,7 @@ 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)
 
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 07e924b0fc564b..383de378670ea9 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -798,6 +798,9 @@ curses_getcchar(const cchar_t *wcval, wchar_t *wstr, attr_t *attrs, int *pair)
         *pair = spair;
     }
 #endif
+    if (rtn != ERR) {
+        *attrs &= ~(attr_t)A_COLOR;
+    }
     return rtn;
 }
 
@@ -3674,7 +3677,7 @@ _curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1,
             byte = 0;
         }
     }
-    rtn = (chtype)byte | (attrs & ~(attr_t)A_COLOR) | COLOR_PAIR(pair);
+    rtn = (chtype)byte | attrs | COLOR_PAIR(pair);
 #else
     if (!group_right_1) {
         rtn = winch(self->win);

_______________________________________________
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]