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
67 changes: 67 additions & 0 deletions Doc/library/curses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,55 @@ Window objects
``0`` (no attributes).


.. method:: window.attr_get()

Return the window's current rendition as a ``(attrs, pair)`` tuple,
where *attrs* is the set of attributes and *pair* is the color pair number.

Unlike :meth:`attron` and friends, which take packed ``A_*`` attributes,
this method and the other ``attr_*`` methods work with the
:ref:`WA_* attributes <curses-wa-constants>` and keep the color pair as a
separate number, which lets them use color pairs that do not fit alongside
the attributes in a single value.

.. versionadded:: next


.. method:: window.attr_set(attr, pair=0)

Set the window's rendition to the attributes *attr* and the color pair *pair*.

.. versionadded:: next


.. method:: window.attr_on(attr)

Turn on the attributes *attr* without affecting any others.

.. versionadded:: next


.. method:: window.attr_off(attr)

Turn off the attributes *attr* without affecting any others.

.. versionadded:: next


.. method:: window.color_set(pair)

Set the window's color pair to *pair*, leaving the other attributes unchanged.

.. versionadded:: next


.. method:: window.getattrs()

Return the window's current attributes.

.. versionadded:: next


.. method:: window.bkgd(ch[, attr])

Set the background property of the window to the character *ch*, with
Expand Down Expand Up @@ -1888,6 +1937,24 @@ The exact constants available are system dependent.
.. versionadded:: 3.7
``A_ITALIC`` was added.

.. _curses-wa-constants:

The :meth:`~window.attr_get`, :meth:`~window.attr_set`, :meth:`~window.attr_on`
and :meth:`~window.attr_off` methods use a parallel set of ``WA_*`` constants.
These have the same meaning as the corresponding ``A_*`` attributes above
(``WA_BOLD`` like :const:`A_BOLD`, and so on), but belong to the ``attr_t`` type
rather than being packed into a character. In ncurses the two sets share the
same values, but other curses implementations may give them different ones, so
use the ``WA_*`` constants with the ``attr_*`` methods. The available names are
``WA_ATTRIBUTES``, ``WA_NORMAL``, ``WA_STANDOUT``, ``WA_UNDERLINE``,
``WA_REVERSE``, ``WA_BLINK``, ``WA_DIM``, ``WA_BOLD``, ``WA_ALTCHARSET``,
``WA_INVIS``, ``WA_PROTECT``, ``WA_HORIZONTAL``, ``WA_LEFT``, ``WA_LOW``,
``WA_RIGHT``, ``WA_TOP``, ``WA_VERTICAL`` and ``WA_ITALIC`` (each available only
where the platform defines it).

.. versionadded:: next
The ``WA_*`` constants were added.

Several constants are available to extract corresponding attributes returned
by some methods.

Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,13 @@ curses
available when built against an ncurses with ``NCURSES_EXT_FUNCS``.
(Contributed by Serhiy Storchaka in :gh:`151776`.)

* Add the :mod:`curses` window methods :meth:`~curses.window.attr_get`,
:meth:`~curses.window.attr_set`, :meth:`~curses.window.attr_on`,
:meth:`~curses.window.attr_off` and :meth:`~curses.window.color_set`, which
pass the color pair as a separate argument instead of packing it into the
attribute value, and the corresponding ``WA_*`` attribute constants.
(Contributed by Serhiy Storchaka in :gh:`152219`.)

gzip
----

Expand Down
45 changes: 44 additions & 1 deletion Lib/test/test_curses.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,6 @@ def test_scroll(self):
win.scrollok(False)

def test_attributes(self):
# TODO: attr_get(), attr_set(), ...
win = curses.newwin(5, 15, 5, 2)
win.attron(curses.A_BOLD)
win.attroff(curses.A_BOLD)
Expand All @@ -660,6 +659,45 @@ def test_attributes(self):
win.standout()
win.standend()

# The attr_*() family works on attr_t attributes paired with a color
# pair, unlike the chtype-based attron()/attroff()/attrset().
win.attr_set(curses.A_BOLD | curses.A_UNDERLINE)
attrs, pair = win.attr_get()
self.assertTrue(attrs & curses.A_BOLD)
self.assertTrue(attrs & curses.A_UNDERLINE)
self.assertEqual(pair, 0)
self.assertEqual(win.getattrs(), attrs)

win.attr_on(curses.A_REVERSE)
self.assertTrue(win.attr_get()[0] & curses.A_REVERSE)
win.attr_off(curses.A_REVERSE)
self.assertFalse(win.attr_get()[0] & curses.A_REVERSE)

# color_set() with a real pair needs start_color(); see
# test_attr_color_pair. Here only the argument validation is checked,
# which fails before wcolor_set() is reached.
self.assertRaises(TypeError, win.attr_set, 'x')
self.assertRaises(TypeError, win.attr_set, curses.A_BOLD, 'x')
self.assertRaises(TypeError, win.attr_on, 'x')
self.assertRaises(TypeError, win.color_set, 'x')
self.assertRaises(ValueError, win.color_set, -1)
self.assertRaises(ValueError, win.attr_set, curses.A_BOLD, -1)
# attr_t is unsigned: a negative or too-large attribute overflows.
self.assertRaises(OverflowError, win.attr_set, -1)
self.assertRaises(OverflowError, win.attr_on, -1)
self.assertRaises(OverflowError, win.attr_set, 1 << 64)

@requires_colors
def test_attr_color_pair(self):
win = curses.newwin(5, 15, 5, 2)
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
win.attr_set(curses.A_BOLD, 1)
attrs, pair = win.attr_get()
self.assertTrue(attrs & curses.A_BOLD)
self.assertEqual(pair, 1)
win.color_set(0)
self.assertEqual(win.attr_get()[1], 0)

@requires_curses_window_meth('chgat')
def test_chgat(self):
win = curses.newwin(5, 15, 5, 2)
Expand Down Expand Up @@ -691,6 +729,11 @@ def test_chgat(self):
self.assertEqual(win.inch(3, 11), b'm'[0] | curses.A_UNDERLINE)
self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)

# attr_t is unsigned: a negative or too-large attribute overflows.
self.assertRaises(TypeError, win.chgat, 'x')
self.assertRaises(OverflowError, win.chgat, -1)
self.assertRaises(OverflowError, win.chgat, 1 << 64)

def test_background(self):
win = curses.newwin(5, 15, 5, 2)
win.addstr(0, 0, 'Lorem ipsum')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Add the :mod:`curses` window methods :meth:`~curses.window.attr_get`,
:meth:`~curses.window.attr_set`, :meth:`~curses.window.attr_on`,
:meth:`~curses.window.attr_off` and :meth:`~curses.window.color_set`, which use
a separate color pair argument instead of packing it into the attribute value,
and the corresponding ``WA_*`` attribute constants.
Loading
Loading