https://github.com/python/cpython/commit/7363e8d24d14abf651633865ea959702ebac73d3 commit: 7363e8d24d14abf651633865ea959702ebac73d3 branch: main author: Serhiy Storchaka <storch...@gmail.com> committer: serhiy-storchaka <storch...@gmail.com> date: 2025-05-03T23:33:22+03:00 summary:
gh-133139: Add curses.assume_default_colors() (GH-133145) This is a refinement of the curses.use_default_colors() function which allows to change the color pair 0. files: A Misc/NEWS.d/next/Library/2025-04-29-13-40-05.gh-issue-133139.9yCcC2.rst M Doc/library/curses.rst M Doc/whatsnew/3.14.rst M Lib/test/test_curses.py M Modules/_cursesmodule.c M Modules/clinic/_cursesmodule.c.h diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index 6c7fc721a3e0fb..4bccfdde664070 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -68,6 +68,21 @@ The module :mod:`curses` defines the following exception: The module :mod:`curses` defines the following functions: +.. function:: assume_default_colors(fg, bg) + + Allow use of default values for colors on terminals supporting this feature. + Use this to support transparency in your application. + + * Assign terminal default foreground/background colors to color number ``-1``. + So ``init_pair(x, COLOR_RED, -1)`` will initialize pair *x* as red + on default background and ``init_pair(x, -1, COLOR_BLUE)`` will + initialize pair *x* as default foreground on blue. + + * Change the definition of the color-pair ``0`` to ``(fg, bg)``. + + .. versionadded:: next + + .. function:: baudrate() Return the output speed of the terminal in bits per second. On software @@ -290,9 +305,11 @@ The module :mod:`curses` defines the following functions: Change the definition of a color-pair. It takes three arguments: the number of the color-pair to be changed, the foreground color number, and the background color number. The value of *pair_number* must be between ``1`` and - ``COLOR_PAIRS - 1`` (the ``0`` color pair is wired to white on black and cannot - be changed). The value of *fg* and *bg* arguments must be between ``0`` and - ``COLORS - 1``, or, after calling :func:`use_default_colors`, ``-1``. + ``COLOR_PAIRS - 1`` (the ``0`` color pair can only be changed by + :func:`use_default_colors` and :func:`assume_default_colors`). + The value of *fg* and *bg* arguments must be between ``0`` and + ``COLORS - 1``, or, after calling :func:`!use_default_colors` or + :func:`!assume_default_colors`, ``-1``. If the color-pair was previously initialized, the screen is refreshed and all occurrences of that color-pair are changed to the new definition. @@ -678,11 +695,7 @@ The module :mod:`curses` defines the following functions: .. function:: use_default_colors() - Allow use of default values for colors on terminals supporting this feature. Use - this to support transparency in your application. The default color is assigned - to the color number ``-1``. After calling this function, ``init_pair(x, - curses.COLOR_RED, -1)`` initializes, for instance, color pair *x* to a red - foreground color on the default background. + Equivalent to ``assume_default_colors(-1, -1)``. .. function:: wrapper(func, /, *args, **kwargs) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 1ebf6efffd0177..87c31d32e2264d 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -891,6 +891,14 @@ ctypes making it a :term:`generic type`. (Contributed by Brian Schubert in :gh:`132168`.) +curses +------ + +* Add the :func:`~curses.assume_default_colors` function, + a refinement of the :func:`~curses.use_default_colors` function which + allows to change the color pair ``0``. + (Contributed by Serhiy Storchaka in :gh:`133139`.) + datetime -------- diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index 6fe0e7fd4b7fe9..3f95a2b322fbb1 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -51,12 +51,6 @@ def wrapped(self, *args, **kwargs): term = os.environ.get('TERM') SHORT_MAX = 0x7fff -DEFAULT_PAIR_CONTENTS = [ - (curses.COLOR_WHITE, curses.COLOR_BLACK), - (0, 0), - (-1, -1), - (15, 0), # for xterm-256color (15 is for BRIGHT WHITE) -] # If newterm was supported we could use it instead of initscr and not exit @unittest.skipIf(not term or term == 'unknown', @@ -948,8 +942,6 @@ def get_pair_limit(self): @requires_colors def test_pair_content(self): - if not hasattr(curses, 'use_default_colors'): - self.assertIn(curses.pair_content(0), DEFAULT_PAIR_CONTENTS) curses.pair_content(0) maxpair = self.get_pair_limit() - 1 if maxpair > 0: @@ -994,13 +986,27 @@ def test_color_attrs(self): @requires_curses_func('use_default_colors') @requires_colors def test_use_default_colors(self): - old = curses.pair_content(0) try: curses.use_default_colors() except curses.error: self.skipTest('cannot change color (use_default_colors() failed)') self.assertEqual(curses.pair_content(0), (-1, -1)) - self.assertIn(old, DEFAULT_PAIR_CONTENTS) + + @requires_curses_func('assume_default_colors') + @requires_colors + def test_assume_default_colors(self): + try: + curses.assume_default_colors(-1, -1) + except curses.error: + self.skipTest('cannot change color (assume_default_colors() failed)') + self.assertEqual(curses.pair_content(0), (-1, -1)) + curses.assume_default_colors(curses.COLOR_YELLOW, curses.COLOR_BLUE) + self.assertEqual(curses.pair_content(0), (curses.COLOR_YELLOW, curses.COLOR_BLUE)) + curses.assume_default_colors(curses.COLOR_RED, -1) + self.assertEqual(curses.pair_content(0), (curses.COLOR_RED, -1)) + curses.assume_default_colors(-1, curses.COLOR_GREEN) + self.assertEqual(curses.pair_content(0), (-1, curses.COLOR_GREEN)) + curses.assume_default_colors(-1, -1) def test_keyname(self): # TODO: key_name() diff --git a/Misc/NEWS.d/next/Library/2025-04-29-13-40-05.gh-issue-133139.9yCcC2.rst b/Misc/NEWS.d/next/Library/2025-04-29-13-40-05.gh-issue-133139.9yCcC2.rst new file mode 100644 index 00000000000000..526187d924b1ee --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-04-29-13-40-05.gh-issue-133139.9yCcC2.rst @@ -0,0 +1,3 @@ +Add the :func:`curses.assume_default_colors` function, a refinement of the +:func:`curses.use_default_colors` function which allows to change the color +pair ``0``. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index bf18cb51605075..f2ddd55dbf3900 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4720,15 +4720,12 @@ _curses_use_env_impl(PyObject *module, int flag) /*[clinic input] _curses.use_default_colors -Allow use of default values for colors on terminals supporting this feature. - -Use this to support transparency in your application. The default color -is assigned to the color number -1. +Equivalent to assume_default_colors(-1, -1). [clinic start generated code]*/ static PyObject * _curses_use_default_colors_impl(PyObject *module) -/*[clinic end generated code: output=a3b81ff71dd901be input=656844367470e8fc]*/ +/*[clinic end generated code: output=a3b81ff71dd901be input=99ff0b7c69834d1f]*/ { int code; @@ -4744,6 +4741,39 @@ _curses_use_default_colors_impl(PyObject *module) return NULL; } } + +/*[clinic input] +_curses.assume_default_colors + fg: int + bg: int + / + +Allow use of default values for colors on terminals supporting this feature. + +Assign terminal default foreground/background colors to color number -1. +Change the definition of the color-pair 0 to (fg, bg). + +Use this to support transparency in your application. +[clinic start generated code]*/ + +static PyObject * +_curses_assume_default_colors_impl(PyObject *module, int fg, int bg) +/*[clinic end generated code: output=54985397a7d2b3a5 input=7fe301712ef3e9fb]*/ +{ + int code; + + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); + + code = assume_default_colors(fg, bg); + if (code != ERR) { + Py_RETURN_NONE; + } else { + cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "assume_default_colors() returned ERR"); + return NULL; + } +} #endif /* STRICT_SYSV_CURSES */ @@ -4902,6 +4932,7 @@ static PyMethodDef cursesmodule_methods[] = { _CURSES_UNGET_WCH_METHODDEF _CURSES_USE_ENV_METHODDEF _CURSES_USE_DEFAULT_COLORS_METHODDEF + _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF {NULL, NULL} /* sentinel */ }; diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 3a1c1698b1b8c6..552360eb80a545 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -4263,10 +4263,7 @@ PyDoc_STRVAR(_curses_use_default_colors__doc__, "use_default_colors($module, /)\n" "--\n" "\n" -"Allow use of default values for colors on terminals supporting this feature.\n" -"\n" -"Use this to support transparency in your application. The default color\n" -"is assigned to the color number -1."); +"Equivalent to assume_default_colors(-1, -1)."); #define _CURSES_USE_DEFAULT_COLORS_METHODDEF \ {"use_default_colors", (PyCFunction)_curses_use_default_colors, METH_NOARGS, _curses_use_default_colors__doc__}, @@ -4282,6 +4279,51 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) #endif /* !defined(STRICT_SYSV_CURSES) */ +#if !defined(STRICT_SYSV_CURSES) + +PyDoc_STRVAR(_curses_assume_default_colors__doc__, +"assume_default_colors($module, fg, bg, /)\n" +"--\n" +"\n" +"Allow use of default values for colors on terminals supporting this feature.\n" +"\n" +"Assign terminal default foreground/background colors to color number -1.\n" +"Change the definition of the color-pair 0 to (fg, bg).\n" +"\n" +"Use this to support transparency in your application."); + +#define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF \ + {"assume_default_colors", _PyCFunction_CAST(_curses_assume_default_colors), METH_FASTCALL, _curses_assume_default_colors__doc__}, + +static PyObject * +_curses_assume_default_colors_impl(PyObject *module, int fg, int bg); + +static PyObject * +_curses_assume_default_colors(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int fg; + int bg; + + if (!_PyArg_CheckPositional("assume_default_colors", nargs, 2, 2)) { + goto exit; + } + fg = PyLong_AsInt(args[0]); + if (fg == -1 && PyErr_Occurred()) { + goto exit; + } + bg = PyLong_AsInt(args[1]); + if (bg == -1 && PyErr_Occurred()) { + goto exit; + } + return_value = _curses_assume_default_colors_impl(module, fg, bg); + +exit: + return return_value; +} + +#endif /* !defined(STRICT_SYSV_CURSES) */ + PyDoc_STRVAR(_curses_has_extended_color_support__doc__, "has_extended_color_support($module, /)\n" "--\n" @@ -4394,4 +4436,8 @@ _curses_has_extended_color_support(PyObject *module, PyObject *Py_UNUSED(ignored #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF #define _CURSES_USE_DEFAULT_COLORS_METHODDEF #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ -/*[clinic end generated code: output=dbbbe86a4171799a input=a9049054013a1b77]*/ + +#ifndef _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF + #define _CURSES_ASSUME_DEFAULT_COLORS_METHODDEF +#endif /* !defined(_CURSES_ASSUME_DEFAULT_COLORS_METHODDEF) */ +/*[clinic end generated code: output=42b2923d88c8d0f6 input=a9049054013a1b77]*/ _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com