From d3bafbc3ac60d219167eac76e6a424c2da29344b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 26 Jun 2026 22:57:08 +0300 Subject: [PATCH] gh-152332: Add the curses.term_attrs() function term_attrs() returns the video attributes supported by the terminal as WA_* values, the counterpart of termattrs() for the A_* values. Co-Authored-By: Claude Opus 4.8 --- Doc/library/curses.rst | 8 +++++++ Doc/whatsnew/3.16.rst | 5 ++++ Lib/test/test_curses.py | 2 +- ...-06-26-22-15-00.gh-issue-152332.Lp3WqN.rst | 2 ++ Modules/_cursesmodule.c | 19 +++++++++++++++ Modules/clinic/_cursesmodule.c.h | 23 ++++++++++++++++++- 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-06-26-22-15-00.gh-issue-152332.Lp3WqN.rst diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index ba4fe55e4a22c64..e7d4ddd9aced780 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -807,6 +807,14 @@ The module :mod:`!curses` defines the following functions: appearance of the screen. +.. function:: term_attrs() + + Like :func:`termattrs`, but return the attributes as :ref:`WA_* + ` values rather than ``A_*`` values. + + .. versionadded:: next + + .. function:: termname() Return the value of the environment variable :envvar:`TERM`, as a bytes object, diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 8dfd3bf81695584..9a5b59ec8ae420b 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -165,6 +165,11 @@ curses :func:`~curses.scr_set`, which dump the whole screen to a file and restore it. (Contributed by Serhiy Storchaka in :gh:`152260`.) +* Add the :func:`curses.term_attrs` function, which returns the supported + video attributes as :ref:`WA_* ` values, the + counterpart of :func:`curses.termattrs`. + (Contributed by Serhiy Storchaka in :gh:`152332`.) + gzip ---- diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 7157896d8cbccda..a60274f3fce2b9c 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -1282,13 +1282,13 @@ def test_misc_module_funcs(self): curses.newpad(50, 50) def test_env_queries(self): - # TODO: term_attrs() self.assertIsInstance(curses.termname(), bytes) self.assertIsInstance(curses.longname(), bytes) self.assertIsInstance(curses.baudrate(), int) self.assertIsInstance(curses.has_ic(), bool) self.assertIsInstance(curses.has_il(), bool) self.assertIsInstance(curses.termattrs(), int) + self.assertIsInstance(curses.term_attrs(), int) c = curses.killchar() self.assertIsInstance(c, bytes) diff --git a/Misc/NEWS.d/next/Library/2026-06-26-22-15-00.gh-issue-152332.Lp3WqN.rst b/Misc/NEWS.d/next/Library/2026-06-26-22-15-00.gh-issue-152332.Lp3WqN.rst new file mode 100644 index 000000000000000..32875cdac5c9d0c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-06-26-22-15-00.gh-issue-152332.Lp3WqN.rst @@ -0,0 +1,2 @@ +Add the :func:`curses.term_attrs` function, the counterpart of +:func:`curses.termattrs` for the ``WA_*`` attributes. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 3d6748340930ee8..cd51be3d6124418 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -7262,6 +7262,24 @@ _curses_termattrs_impl(PyObject *module) /*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/ NoArgReturnIntFunctionBody(termattrs) +/*[clinic input] +_curses.term_attrs + +Return a logical OR of all video attributes supported by the terminal. + +The attributes are WA_* values, the extended-attribute counterparts of +the A_* values returned by termattrs(). +[clinic start generated code]*/ + +static PyObject * +_curses_term_attrs_impl(PyObject *module) +/*[clinic end generated code: output=c559daa1370948d6 input=963136fd17ab797a]*/ +{ + PyCursesStatefulInitialised(module); + + return PyLong_FromUnsignedLong(term_attrs()); +} + /*[clinic input] @permit_long_summary _curses.termname @@ -7817,6 +7835,7 @@ static PyMethodDef cursesmodule_methods[] = { _CURSES_SETUPTERM_METHODDEF _CURSES_START_COLOR_METHODDEF _CURSES_TERMATTRS_METHODDEF + _CURSES_TERM_ATTRS_METHODDEF _CURSES_TERMNAME_METHODDEF _CURSES_TIGETFLAG_METHODDEF _CURSES_TIGETNUM_METHODDEF diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 8fbcf1d99bbbeda..f2c8fc6f5d168f0 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -4921,6 +4921,27 @@ _curses_termattrs(PyObject *module, PyObject *Py_UNUSED(ignored)) return _curses_termattrs_impl(module); } +PyDoc_STRVAR(_curses_term_attrs__doc__, +"term_attrs($module, /)\n" +"--\n" +"\n" +"Return a logical OR of all video attributes supported by the terminal.\n" +"\n" +"The attributes are WA_* values, the extended-attribute counterparts of\n" +"the A_* values returned by termattrs()."); + +#define _CURSES_TERM_ATTRS_METHODDEF \ + {"term_attrs", (PyCFunction)_curses_term_attrs, METH_NOARGS, _curses_term_attrs__doc__}, + +static PyObject * +_curses_term_attrs_impl(PyObject *module); + +static PyObject * +_curses_term_attrs(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_term_attrs_impl(module); +} + PyDoc_STRVAR(_curses_termname__doc__, "termname($module, /)\n" "--\n" @@ -5481,4 +5502,4 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=864fa5c0f22fcad3 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=eb5a451ae2b2e8d7 input=a9049054013a1b77]*/