From 6b6bd7363db7cfc6b60c396ca74df4abe03731ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 25 May 2025 10:08:58 +0200 Subject: [PATCH 1/5] refactor signal handling in `_curses.window.{get_wch,get_key}` --- Modules/_cursesmodule.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5e1eccee3e4a89..28c2af4df1a7f9 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1659,6 +1659,19 @@ _curses_window_getbkgd_impl(PyCursesWindowObject *self) return (long) getbkgd(self->win); } +static PyObject * +curses_check_signals_on_input_error(PyCursesWindowObject *self, + const char *curses_funcname, + const char *python_funcname) +{ + if (!PyErr_CheckSignals() && !PyErr_Occurred()) { + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_Format(state->error, "%s() (called by %s()): no input", + curses_funcname, python_funcname); + } + return NULL; +} + /*[clinic input] _curses.window.getch -> int @@ -1731,13 +1744,9 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, Py_END_ALLOW_THREADS if (rtn == ERR) { - /* getch() returns ERR in nodelay mode */ - PyErr_CheckSignals(); - if (!PyErr_Occurred()) { - cursesmodule_state *state = get_cursesmodule_state_by_win(self); - const char *funcname = group_right_1 ? "mvwgetch" : "wgetch"; - PyErr_Format(state->error, "getkey(): %s(): no input", funcname); - } + /* wgetch() returns ERR in nodelay mode */ + const char *funcname = group_right_1 ? "mvwgetch" : "wgetch"; + curses_check_signals_on_input_error(self, funcname, "getkey"); return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -1791,13 +1800,9 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, Py_END_ALLOW_THREADS if (ct == ERR) { - if (PyErr_CheckSignals()) - return NULL; - - /* get_wch() returns ERR in nodelay mode */ - cursesmodule_state *state = get_cursesmodule_state_by_win(self); + /* wget_wch() returns ERR in nodelay mode */ const char *funcname = group_right_1 ? "mvwget_wch" : "wget_wch"; - PyErr_Format(state->error, "get_wch(): %s(): no input", funcname); + curses_check_signals_on_input_error(self, funcname, "get_wch"); return NULL; } if (ct == KEY_CODE_YES) From d4ac1122e1465627d1ebc19b42503a29c802d295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 26 May 2025 12:53:21 +0200 Subject: [PATCH 2/5] remove redundant check --- Modules/_cursesmodule.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 28c2af4df1a7f9..ca392496c59b40 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1664,7 +1664,9 @@ curses_check_signals_on_input_error(PyCursesWindowObject *self, const char *curses_funcname, const char *python_funcname) { - if (!PyErr_CheckSignals() && !PyErr_Occurred()) { + assert(!PyErr_Occurred()); + if (!PyErr_CheckSignals()) { + assert(!PyErr_Occurred()); cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_Format(state->error, "%s() (called by %s()): no input", curses_funcname, python_funcname); From 32a77d3f351ec689870573ea70a270f00b502f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 26 May 2025 16:36:52 +0200 Subject: [PATCH 3/5] address Victor's review --- Modules/_cursesmodule.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index ca392496c59b40..3d7fd139f6d603 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1659,19 +1659,17 @@ _curses_window_getbkgd_impl(PyCursesWindowObject *self) return (long) getbkgd(self->win); } -static PyObject * +static void curses_check_signals_on_input_error(PyCursesWindowObject *self, const char *curses_funcname, const char *python_funcname) { assert(!PyErr_Occurred()); - if (!PyErr_CheckSignals()) { - assert(!PyErr_Occurred()); + if (PyErr_CheckSignals()) { cursesmodule_state *state = get_cursesmodule_state_by_win(self); PyErr_Format(state->error, "%s() (called by %s()): no input", curses_funcname, python_funcname); } - return NULL; } /*[clinic input] From 467883d23d3845135598c39ea209fe8cc646a51b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 26 May 2025 16:39:10 +0200 Subject: [PATCH 4/5] Update _cursesmodule.c --- Modules/_cursesmodule.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 3d7fd139f6d603..f65f82bb706c60 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1659,7 +1659,7 @@ _curses_window_getbkgd_impl(PyCursesWindowObject *self) return (long) getbkgd(self->win); } -static void +static PyObject * curses_check_signals_on_input_error(PyCursesWindowObject *self, const char *curses_funcname, const char *python_funcname) @@ -1670,6 +1670,7 @@ curses_check_signals_on_input_error(PyCursesWindowObject *self, PyErr_Format(state->error, "%s() (called by %s()): no input", curses_funcname, python_funcname); } + return NULL; } /*[clinic input] @@ -1746,8 +1747,7 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, if (rtn == ERR) { /* wgetch() returns ERR in nodelay mode */ const char *funcname = group_right_1 ? "mvwgetch" : "wgetch"; - curses_check_signals_on_input_error(self, funcname, "getkey"); - return NULL; + return curses_check_signals_on_input_error(self, funcname, "getkey"); } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR #if NCURSES_VERSION_MAJOR*100+NCURSES_VERSION_MINOR <= 507 @@ -1802,8 +1802,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, if (ct == ERR) { /* wget_wch() returns ERR in nodelay mode */ const char *funcname = group_right_1 ? "mvwget_wch" : "wget_wch"; - curses_check_signals_on_input_error(self, funcname, "get_wch"); - return NULL; + return curses_check_signals_on_input_error(self, funcname, "get_wch"); } if (ct == KEY_CODE_YES) return PyLong_FromLong(rtn); From f2b32e572cc5a09a98239dd5c3b96399dcc0aaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 26 May 2025 16:41:51 +0200 Subject: [PATCH 5/5] Update _cursesmodule.c --- Modules/_cursesmodule.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index f65f82bb706c60..ce32c9d6d495a9 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1666,10 +1666,11 @@ curses_check_signals_on_input_error(PyCursesWindowObject *self, { assert(!PyErr_Occurred()); if (PyErr_CheckSignals()) { - cursesmodule_state *state = get_cursesmodule_state_by_win(self); - PyErr_Format(state->error, "%s() (called by %s()): no input", - curses_funcname, python_funcname); + return NULL; } + cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_Format(state->error, "%s() (called by %s()): no input", + curses_funcname, python_funcname); return NULL; }