Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions Lib/test/test_curses.py
Original file line number Diff line number Diff line change
Expand Up @@ -3242,5 +3242,33 @@ def test_color(self):
curses.slk_color(0)


@unittest.skipUnless(hasattr(curses, 'newterm'), 'requires curses.newterm()')
@unittest.skipIf(BROKEN_NEWTERM, 'ncurses < 6.5 mishandles repeated newterm()')
@unittest.skipIf(not term or term == 'unknown',
f"$TERM={term!r}, newterm() may not work")
@unittest.skipIf(sys.platform == "cygwin",
"cygwin's curses mostly just hangs")
class TermAttrsTests(NewtermTestBase):
# A_ITALIC is the topmost bit of a 32-bit attribute mask, so termattrs()
# only tells a signed result from an unsigned one on a terminal that
# advertises it. Drive a known terminal type over a pseudo-terminal
# instead of relying on whatever $TERM happens to be.

def test_termattrs_is_not_negative(self):
s = self.make_pty()
try:
curses.newterm('xterm-256color', s, s)
except curses.error:
self.skipTest('no xterm-256color terminfo entry')
attrs = curses.termattrs()
italic = getattr(curses, 'A_ITALIC', 0)
if not italic or not attrs & italic:
self.skipTest('the terminal advertises no attribute in the top bit')
self.assertGreaterEqual(attrs, 0)
# termattrs() exists to be passed back to the attribute functions,
# which reject a negative mask.
curses.newwin(1, 1).attrset(attrs)


if __name__ == '__main__':
unittest.main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :func:`curses.termattrs` returning a negative value on a terminal that
supports :const:`curses.A_ITALIC`, which left its result unusable as an
attribute mask.
6 changes: 5 additions & 1 deletion Modules/_cursesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -7899,7 +7899,11 @@ Return a logical OR of all video attributes supported by the terminal.
static PyObject *
_curses_termattrs_impl(PyObject *module)
/*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/
NoArgReturnIntFunctionBody(termattrs)
{
PyCursesStatefulInitialised(module);

return PyLong_FromUnsignedLong((unsigned long)(chtype)termattrs());
}

#ifdef HAVE_CURSES_TERM_ATTRS
/*[clinic input]
Expand Down
Loading