From de39657404b87c918dc230ed1af401e3133551cc Mon Sep 17 00:00:00 2001 From: pranavchoudhary-tech Date: Tue, 18 Aug 2026 12:24:51 +0530 Subject: [PATCH 1/2] gh-155976: Refresh COLORS and COLOR_PAIRS in update_lines_cols --- Lib/test/test_curses.py | 36 ++++++++++++++++++++++++++++++++++++ Modules/_cursesmodule.c | 26 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py index f582336fae17344..f494c0fbf9d567e 100644 --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -3047,6 +3047,42 @@ def test_set_term(self): self.assertIs(curses.set_term(a), b) # returns the previous one self.assertIs(curses.set_term(b), a) + def test_set_term_refreshes_lines_cols_colors(self): + s1 = self.make_pty() + s2 = self.make_pty() + a = curses.newterm('xterm', s1, s1) + if hasattr(curses, 'start_color'): + try: + curses.start_color() + except curses.error: + pass + b = curses.newterm('xterm-256color', s2, s2) + if hasattr(curses, 'start_color'): + try: + curses.start_color() + except curses.error: + pass + + curses.set_term(a) + lines_a, cols_a = curses.LINES, curses.COLS + colors_a = getattr(curses, 'COLORS', None) + + curses.set_term(b) + lines_b, cols_b = curses.LINES, curses.COLS + colors_b = getattr(curses, 'COLORS', None) + + self.assertEqual(curses.set_term(a), b) + self.assertEqual(curses.LINES, lines_a) + self.assertEqual(curses.COLS, cols_a) + if colors_a is not None: + self.assertEqual(curses.COLORS, colors_a) + + self.assertEqual(curses.set_term(b), a) + self.assertEqual(curses.LINES, lines_b) + self.assertEqual(curses.COLS, cols_b) + if colors_b is not None: + self.assertEqual(curses.COLORS, colors_b) + def test_window_keeps_screen_alive(self): # The standard window keeps its screen alive; dropping every other # reference and collecting must not invalidate the window. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 006e27d55d8925d..da0e46e44131586 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -7557,6 +7557,32 @@ update_lines_cols(PyObject *private_module) goto error; } Py_DECREF(o); + + if (curses_start_color_called) { + o = PyLong_FromUnsignedLongLong((unsigned long long)COLORS); + if (o == NULL) { + goto error; + } + if (PyDict_SetItemString(exposed_module_dict, "COLORS", o) < 0) { + goto error; + } + if (PyDict_SetItemString(private_module_dict, "COLORS", o) < 0) { + goto error; + } + Py_DECREF(o); + + o = PyLong_FromUnsignedLongLong((unsigned long long)COLOR_PAIRS); + if (o == NULL) { + goto error; + } + if (PyDict_SetItemString(exposed_module_dict, "COLOR_PAIRS", o) < 0) { + goto error; + } + if (PyDict_SetItemString(private_module_dict, "COLOR_PAIRS", o) < 0) { + goto error; + } + Py_DECREF(o); + } Py_DECREF(exposed_module); return 1; From 71719c036f87478e0a21aaf681b114c719d1b31d Mon Sep 17 00:00:00 2001 From: pranavchoudhary-tech Date: Tue, 18 Aug 2026 14:08:08 +0530 Subject: [PATCH 2/2] gh-155976: Add news entry --- .../next/C_API/2026-08-18-12-30-00.gh-issue-155976.xyz123.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/C_API/2026-08-18-12-30-00.gh-issue-155976.xyz123.rst diff --git a/Misc/NEWS.d/next/C_API/2026-08-18-12-30-00.gh-issue-155976.xyz123.rst b/Misc/NEWS.d/next/C_API/2026-08-18-12-30-00.gh-issue-155976.xyz123.rst new file mode 100644 index 000000000000000..4395f8c1503f1fc --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2026-08-18-12-30-00.gh-issue-155976.xyz123.rst @@ -0,0 +1 @@ +Fix an issue where :func:`curses.set_term` did not update :const:`curses.COLORS` and :const:`curses.COLOR_PAIRS` when switching terminal screens.