From 8e818e121921cbcfe9f1d51e088a6ca6c6b0abf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 20 May 2025 12:39:22 +0200 Subject: [PATCH 1/7] remove dead Argument Clinic for `_curses.window.chgat` --- Modules/_cursesmodule.c | 55 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 2e6ec822e2d5b6..71324b7e984b1f 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1429,32 +1429,27 @@ int py_mvwdelch(WINDOW *w, int y, int x) /* chgat, added by Fabian Kreutz */ #ifdef HAVE_CURSES_WCHGAT -/*[-clinic input] -_curses.window.chgat - [ - y: int - Y-coordinate. - x: int - X-coordinate. - ] +PyDoc_STRVAR(_curses_window_chgat__doc__, +"chgat([y, x,] [n=-1,] attr)\n" +"Set the attributes of characters.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Set the attributes of num characters at the current cursor position, or at\n" +"position (y, x) if supplied. If no value of num is given or num = -1, the\n" +"attribute will be set on all the characters to the end of the line. This\n" +"function does not move the cursor. The changed line will be touched using\n" +"the touchline() method so that the contents will be redisplayed by the next\n" +"window refresh."); - n: int = -1 - Number of characters. - - attr: long - Attributes for characters. - / - -Set the attributes of characters. - -Set the attributes of num characters at the current cursor position, or at -position (y, x) if supplied. If no value of num is given or num = -1, the -attribute will be set on all the characters to the end of the line. This -function does not move the cursor. The changed line will be touched using -the touchline() method so that the contents will be redisplayed by the next -window refresh. -[-clinic start generated code]*/ static PyObject * PyCursesWindow_ChgAt(PyObject *op, PyObject *args) { @@ -1481,19 +1476,20 @@ PyCursesWindow_ChgAt(PyObject *op, PyObject *args) attr = lattr; break; case 3: - if (!PyArg_ParseTuple(args,"iil;int,int,attr", &y, &x, &lattr)) + if (!PyArg_ParseTuple(args,"iil;y,x,attr", &y, &x, &lattr)) return NULL; attr = lattr; use_xy = TRUE; break; case 4: - if (!PyArg_ParseTuple(args,"iiil;int,int,n,attr", &y, &x, &num, &lattr)) + if (!PyArg_ParseTuple(args,"iiil;y,x,n,attr", &y, &x, &num, &lattr)) return NULL; attr = lattr; use_xy = TRUE; break; default: - PyErr_SetString(PyExc_TypeError, "chgat requires 1 to 4 arguments"); + PyErr_SetString(PyExc_TypeError, + "_curses.window.chgat requires 1 to 4 arguments"); return NULL; } @@ -2818,7 +2814,10 @@ static PyMethodDef PyCursesWindow_methods[] = { _CURSES_WINDOW_ATTRSET_METHODDEF _CURSES_WINDOW_BKGD_METHODDEF #ifdef HAVE_CURSES_WCHGAT - {"chgat", PyCursesWindow_ChgAt, METH_VARARGS}, + { + "chgat", PyCursesWindow_ChgAt, METH_VARARGS, + _curses_window_chgat__doc__ + }, #endif _CURSES_WINDOW_BKGDSET_METHODDEF _CURSES_WINDOW_BORDER_METHODDEF From 97695e549eac4e008c054eec4947b2c685e90f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 20 May 2025 12:39:55 +0200 Subject: [PATCH 2/7] add helper for parsing `(x, y)` coordinates and optional length --- Modules/_cursesmodule.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 71324b7e984b1f..5601ca9e9ce8a8 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1803,8 +1803,45 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, } #endif -/*[-clinic input] -_curses.window.getstr +/* + * Helper function for parsing parameters from getstr() and instr(). + * This function is necessary because Argument Clinic does not know + * how to handle nested optional groups with default values inside. + * + * Return 1 on success and 0 on failure, similar to PyArg_ParseTuple(). + */ +static int +curses_clinic_parse_optional_xy_n(PyObject *args, + int *y, int *x, unsigned int *n, int *use_xy, + const char *qualname) +{ + switch (PyTuple_GET_SIZE(args)) { + case 0: { + *use_xy = 0; + return 1; + } + case 1: { + *use_xy = 0; + return PyArg_ParseTuple(args, "O&;n", + _PyLong_UnsignedInt_Converter, n); + } + case 2: { + *use_xy = 1; + return PyArg_ParseTuple(args, "ii;y,x", y, x); + } + case 3: { + *use_xy = 1; + return PyArg_ParseTuple(args, "iiO&;y,x,n", y, x, + _PyLong_UnsignedInt_Converter, n); + } + default: { + *use_xy = 0; + PyErr_Format(PyExc_TypeError, "%s requires 0 to 3 arguments", + qualname); + return 0; + } + } +} [ y: int From a670d5417a110e09c2bef19eddb345c5e44dfc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 20 May 2025 12:40:22 +0200 Subject: [PATCH 3/7] remove dead Argument Clinic for `_curses.window.getstr` --- Modules/_cursesmodule.c | 93 ++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 58 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5601ca9e9ce8a8..e94c2f0fcaf2cf 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1843,77 +1843,51 @@ curses_clinic_parse_optional_xy_n(PyObject *args, } } - [ - y: int - Y-coordinate. - x: int - X-coordinate. - ] - n: int = 1023 - Maximal number of characters. - / - -Read a string from the user, with primitive line editing capacity. -[-clinic start generated code]*/ +PyDoc_STRVAR(_curses_window_getstr__doc__, +"getstr([[y, x,] n=1023])\n" +"Read a string from the user, with primitive line editing capacity.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Maximal number of characters."); static PyObject * -PyCursesWindow_GetStr(PyObject *op, PyObject *args) +PyCursesWindow_getstr(PyObject *op, PyObject *args) { PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); - - int x, y, n; + int use_xy = 0, y = 0, x = 0; + unsigned int n = 1023; char rtn[1024]; /* This should be big enough.. I hope */ int rtn2; - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - rtn2 = wgetnstr(self->win,rtn, 1023); - Py_END_ALLOW_THREADS - break; - case 1: - if (!PyArg_ParseTuple(args,"i;n", &n)) - return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); - return NULL; - } - Py_BEGIN_ALLOW_THREADS - rtn2 = wgetnstr(self->win, rtn, Py_MIN(n, 1023)); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; + if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, + "_curses.window.getstr")) + { + return NULL; + } + + n = Py_MIN(n, 1023); + if (use_xy) { Py_BEGIN_ALLOW_THREADS #ifdef STRICT_SYSV_CURSES - rtn2 = wmove(self->win,y,x)==ERR ? ERR : wgetnstr(self->win, rtn, 1023); + if (wmove(self->win, y, x) == ERR) { + rtn2 = ERR; + } + else { + rtn2 = wgetnstr(self->win, rtn, n); + } #else - rtn2 = mvwgetnstr(self->win,y,x,rtn, 1023); + rtn2 = mvwgetnstr(self->win, y, x, rtn, n); #endif Py_END_ALLOW_THREADS - break; - case 3: - if (!PyArg_ParseTuple(args,"iii;y,x,n", &y, &x, &n)) - return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); - return NULL; - } -#ifdef STRICT_SYSV_CURSES - Py_BEGIN_ALLOW_THREADS - rtn2 = wmove(self->win,y,x)==ERR ? ERR : - wgetnstr(self->win, rtn, Py_MIN(n, 1023)); - Py_END_ALLOW_THREADS -#else + } + else { Py_BEGIN_ALLOW_THREADS - rtn2 = mvwgetnstr(self->win, y, x, rtn, Py_MIN(n, 1023)); + rtn2 = wgetnstr(self->win, rtn, n); Py_END_ALLOW_THREADS -#endif - break; - default: - PyErr_SetString(PyExc_TypeError, "getstr requires 0 to 3 arguments"); - return NULL; } if (rtn2 == ERR) rtn[0] = 0; @@ -2877,7 +2851,10 @@ static PyMethodDef PyCursesWindow_methods[] = { _CURSES_WINDOW_GET_WCH_METHODDEF {"getmaxyx", PyCursesWindow_getmaxyx, METH_NOARGS}, {"getparyx", PyCursesWindow_getparyx, METH_NOARGS}, - {"getstr", PyCursesWindow_GetStr, METH_VARARGS}, + { + "getstr", PyCursesWindow_getstr, METH_VARARGS, + _curses_window_getstr__doc__ + }, {"getyx", PyCursesWindow_getyx, METH_NOARGS}, _CURSES_WINDOW_HLINE_METHODDEF {"idcok", PyCursesWindow_idcok, METH_VARARGS}, From 3b3f5f29a6a75e7e83e4eea680d7fe9bd525be87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 20 May 2025 12:40:26 +0200 Subject: [PATCH 4/7] remove dead Argument Clinic for `_curses.window.instr` --- Modules/_cursesmodule.c | 85 ++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index e94c2f0fcaf2cf..669287b8a87f1a 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2021,66 +2021,44 @@ _curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1, return rtn; } -/*[-clinic input] -_curses.window.instr - - [ - y: int - Y-coordinate. - x: int - X-coordinate. - ] - n: int = 1023 - Maximal number of characters. - / - -Return a string of characters, extracted from the window. +PyDoc_STRVAR(_curses_window_instr__doc__, +"instr([y, x,] n=1023)\n" +"Return a string of characters, extracted from the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" n\n" +" Maximal number of characters.\n" +"\n" +"Return a string of characters, extracted from the window starting at the\n" +"current cursor position, or at y, x if specified. Attributes are stripped\n" +"from the characters. If n is specified, instr() returns a string at most\n" +"n characters long (exclusive of the trailing NUL)."); -Return a string of characters, extracted from the window starting at the -current cursor position, or at y, x if specified. Attributes are stripped -from the characters. If n is specified, instr() returns a string at most -n characters long (exclusive of the trailing NUL). -[-clinic start generated code]*/ static PyObject * -PyCursesWindow_InStr(PyObject *op, PyObject *args) +PyCursesWindow_instr(PyObject *op, PyObject *args) { PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); - - int x, y, n; + int use_xy = 0, y = 0, x = 0; + unsigned int n = 1023; char rtn[1024]; /* This should be big enough.. I hope */ int rtn2; - switch (PyTuple_Size(args)) { - case 0: - rtn2 = winnstr(self->win,rtn, 1023); - break; - case 1: - if (!PyArg_ParseTuple(args,"i;n", &n)) - return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); - return NULL; - } - rtn2 = winnstr(self->win, rtn, Py_MIN(n, 1023)); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - rtn2 = mvwinnstr(self->win,y,x,rtn,1023); - break; - case 3: - if (!PyArg_ParseTuple(args, "iii;y,x,n", &y, &x, &n)) - return NULL; - if (n < 0) { - PyErr_SetString(PyExc_ValueError, "'n' must be nonnegative"); - return NULL; - } - rtn2 = mvwinnstr(self->win, y, x, rtn, Py_MIN(n,1023)); - break; - default: - PyErr_SetString(PyExc_TypeError, "instr requires 0 or 3 arguments"); + if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, + "_curses.window.instr")) + { return NULL; } + + n = Py_MIN(n, 1023); + if (use_xy) { + rtn2 = mvwinnstr(self->win, y, x, rtn, n); + } + else { + rtn2 = winnstr(self->win, rtn, n); + } if (rtn2 == ERR) rtn[0] = 0; return PyBytes_FromString(rtn); @@ -2868,7 +2846,10 @@ static PyMethodDef PyCursesWindow_methods[] = { {"insertln", PyCursesWindow_winsertln, METH_NOARGS}, _CURSES_WINDOW_INSNSTR_METHODDEF _CURSES_WINDOW_INSSTR_METHODDEF - {"instr", PyCursesWindow_InStr, METH_VARARGS}, + { + "instr", PyCursesWindow_instr, METH_VARARGS, + _curses_window_instr__doc__ + }, _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF {"is_wintouched", PyCursesWindow_is_wintouched, METH_NOARGS}, {"keypad", PyCursesWindow_keypad, METH_VARARGS}, From 2decc95ce4abccdcea604ab0d36f0617e8242615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 24 May 2025 08:37:13 +0200 Subject: [PATCH 5/7] post-merge --- Modules/_cursesmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 907927020af40f..08b8bbec5be137 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1880,8 +1880,8 @@ PyCursesWindow_getstr(PyObject *op, PyObject *args) Py_BEGIN_ALLOW_THREADS #ifdef STRICT_SYSV_CURSES rtn = wmove(self->win, y, x) == ERR - ? ERR - : wgetnstr(self->win, buf, n); + ? ERR + : wgetnstr(self->win, buf, n); #else rtn = mvwgetnstr(self->win, y, x, buf, n); #endif From 59b0a20e34bc7687a20e67521062f38398d9d73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 24 May 2025 08:41:54 +0200 Subject: [PATCH 6/7] better style consistency --- Modules/_cursesmodule.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 08b8bbec5be137..7da678ddacad17 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1861,7 +1861,7 @@ PyCursesWindow_getstr(PyObject *op, PyObject *args) PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); int rtn, use_xy = 0, y = 0, x = 0; unsigned int n = max_buf_size - 1; - PyObject *result; + PyObject *res; if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, "_curses.window.instr")) @@ -1870,11 +1870,11 @@ PyCursesWindow_getstr(PyObject *op, PyObject *args) } n = Py_MIN(n, max_buf_size - 1); - result = PyBytes_FromStringAndSize(NULL, n + 1); - if (result == NULL) { + res = PyBytes_FromStringAndSize(NULL, n + 1); + if (res == NULL) { return NULL; } - char *buf = PyBytes_AS_STRING(result); + char *buf = PyBytes_AS_STRING(res); if (use_xy) { Py_BEGIN_ALLOW_THREADS @@ -1894,11 +1894,11 @@ PyCursesWindow_getstr(PyObject *op, PyObject *args) } if (rtn == ERR) { - Py_DECREF(result); + Py_DECREF(res); return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); } - _PyBytes_Resize(&result, strlen(buf)); // result is set to NULL on failure - return result; + _PyBytes_Resize(&res, strlen(buf)); // 'res' is set to NULL on failure + return res; } /*[clinic input] @@ -2051,7 +2051,7 @@ PyCursesWindow_instr(PyObject *op, PyObject *args) PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); int rtn, use_xy = 0, y = 0, x = 0; unsigned int n = max_buf_size - 1; - PyObject *result; + PyObject *res; if (!curses_clinic_parse_optional_xy_n(args, &y, &x, &n, &use_xy, "_curses.window.instr")) @@ -2060,11 +2060,11 @@ PyCursesWindow_instr(PyObject *op, PyObject *args) } n = Py_MIN(n, max_buf_size - 1); - result = PyBytes_FromStringAndSize(NULL, n + 1); - if (result == NULL) { + res = PyBytes_FromStringAndSize(NULL, n + 1); + if (res == NULL) { return NULL; } - char *buf = PyBytes_AS_STRING(result); + char *buf = PyBytes_AS_STRING(res); if (use_xy) { rtn = mvwinnstr(self->win, y, x, buf, n); @@ -2074,11 +2074,11 @@ PyCursesWindow_instr(PyObject *op, PyObject *args) } if (rtn == ERR) { - Py_DECREF(result); + Py_DECREF(res); return Py_GetConstant(Py_CONSTANT_EMPTY_BYTES); } - _PyBytes_Resize(&result, strlen(buf)); // result is set to NULL on failure - return result; + _PyBytes_Resize(&res, strlen(buf)); // 'res' is set to NULL on failure + return res; } /*[clinic input] From 3c985f769815fb03dc2e80da3b36bb172af3f125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 24 May 2025 08:43:09 +0200 Subject: [PATCH 7/7] remove const qualifiers --- Modules/_cursesmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 7da678ddacad17..55d664cebe31ec 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1857,9 +1857,9 @@ PyDoc_STRVAR(_curses_window_getstr__doc__, static PyObject * PyCursesWindow_getstr(PyObject *op, PyObject *args) { - const unsigned int max_buf_size = 2048; PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); int rtn, use_xy = 0, y = 0, x = 0; + unsigned int max_buf_size = 2048; unsigned int n = max_buf_size - 1; PyObject *res; @@ -2047,9 +2047,9 @@ PyDoc_STRVAR(_curses_window_instr__doc__, static PyObject * PyCursesWindow_instr(PyObject *op, PyObject *args) { - const unsigned int max_buf_size = 2048; PyCursesWindowObject *self = _PyCursesWindowObject_CAST(op); int rtn, use_xy = 0, y = 0, x = 0; + unsigned int max_buf_size = 2048; unsigned int n = max_buf_size - 1; PyObject *res;