Skip to content

Commit e5cf968

Browse files
fedonmancursoragent
authored andcommitted
[3.15] gh-154874: Fix the sign of curses.termattrs() (GH-154875)
termattrs() returns a chtype mask, but it was routed through an int, so a terminal that advertises A_ITALIC came back negative and the result could no longer be passed to the attribute functions. (cherry picked from commit 0b083c4) Co-authored-by: Vyron Vasileiadis <hi@fedonman.com> Signed-off-by: Sankalp Thakur <sankalphimself@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 74da6fb commit e5cf968

3 files changed

Lines changed: 22 additions & 1 deletion

File tree

Lib/test/test_curses.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,20 @@ def test_env_queries(self):
10231023
self.assertIsInstance(c, bytes)
10241024
self.assertEqual(len(c), 1)
10251025

1026+
def test_termattrs_is_not_negative(self):
1027+
# A_ITALIC is the topmost bit of a 32-bit attribute mask, so termattrs()
1028+
# only tells a signed result from an unsigned one on a terminal that
1029+
# advertises it. 3.15 lacks the newterm()/pty harness used on main, so
1030+
# exercise the current screen: skip when the top bit is not advertised.
1031+
attrs = curses.termattrs()
1032+
italic = getattr(curses, 'A_ITALIC', 0)
1033+
if not italic or not attrs & italic:
1034+
self.skipTest('the terminal advertises no attribute in the top bit')
1035+
self.assertGreaterEqual(attrs, 0)
1036+
# termattrs() exists to be passed back to the attribute functions,
1037+
# which reject a negative mask.
1038+
self.stdscr.attrset(attrs)
1039+
10261040
def test_output_options(self):
10271041
stdscr = self.stdscr
10281042

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix :func:`curses.termattrs` returning a negative value on a terminal that
2+
supports :const:`curses.A_ITALIC`, which left its result unusable as an
3+
attribute mask.

Modules/_cursesmodule.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4959,7 +4959,11 @@ Return a logical OR of all video attributes supported by the terminal.
49594959
static PyObject *
49604960
_curses_termattrs_impl(PyObject *module)
49614961
/*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/
4962-
NoArgReturnIntFunctionBody(termattrs)
4962+
{
4963+
PyCursesStatefulInitialised(module);
4964+
4965+
return PyLong_FromUnsignedLong((unsigned long)(chtype)termattrs());
4966+
}
49634967

49644968
/*[clinic input]
49654969
@permit_long_summary

0 commit comments

Comments
 (0)