From 3148d86f6058beb15cac8ea35974b9e50ad58f5d 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, 28 Sep 2024 13:36:26 +0200 Subject: [PATCH 01/38] Introduce module's state and logic. --- Modules/_cursesmodule.c | 101 ++++++++++++++++++++++++------- Modules/clinic/_cursesmodule.c.h | 10 +-- 2 files changed, 83 insertions(+), 28 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index c9ee5687c2b5d9..fe463586fdd0a2 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -159,11 +159,32 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ +typedef struct _cursesmodule_state { + PyObject *PyCursesError; + PyTypeObject *PyCursesWindow_Type; +} _cursesmodule_state; + +static inline _cursesmodule_state * +get_cursesmodule_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_cursesmodule_state *)state; +} + +static inline _cursesmodule_state * +get_cursesmodule_state_by_cls(PyTypeObject *cls) +{ + void *state = PyType_GetModuleState(cls); + assert(state != NULL); + return (_cursesmodule_state *)state; +} + /*[clinic input] module _curses -class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" +class _curses.window "PyCursesWindowObject *" "clinic_state()->PyCursesWindow_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=83369be6e20ef0da]*/ /* Definition of exception curses.error */ @@ -2078,7 +2099,8 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) /*[clinic input] _curses.window.overlay - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *",\ + subclass_of="clinic_state()->PyCursesWindow_Type") [ sminrow: int @@ -2107,7 +2129,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, PyCursesWindowObject *destwin, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984]*/ +/*[clinic end generated code: output=82bb2c4cb443ca58 input=a1fa2bb9dd91ab1d]*/ { int rtn; @@ -2125,7 +2147,8 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, /*[clinic input] _curses.window.overwrite - destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *",\ + subclass_of="clinic_state()->PyCursesWindow_Type") [ sminrow: int @@ -2155,7 +2178,7 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/ +/*[clinic end generated code: output=12ae007d1681be28 input=c5b2388e80206a47]*/ { int rtn; @@ -2500,7 +2523,9 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P return 0; } +#define clinic_state() (get_cursesmodule_state_by_cls(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" +#undef clinic_state static PyMethodDef PyCursesWindow_Methods[] = { _CURSES_WINDOW_ADDCH_METHODDEF @@ -4674,7 +4699,7 @@ _curses_has_extended_color_support_impl(PyObject *module) /* List of functions defined in the module */ -static PyMethodDef PyCurses_methods[] = { +static PyMethodDef _cursesmodule_methods[] = { _CURSES_BAUDRATE_METHODDEF _CURSES_BEEP_METHODDEF _CURSES_CAN_CHANGE_COLOR_METHODDEF @@ -4759,20 +4784,7 @@ static PyMethodDef PyCurses_methods[] = { {NULL, NULL} /* sentinel */ }; -/* Initialization function for the module */ - - -static struct PyModuleDef _cursesmodule = { - PyModuleDef_HEAD_INIT, - "_curses", - NULL, - -1, - PyCurses_methods, - NULL, - NULL, - NULL, - NULL -}; +/* Module initialization and cleanup functions. */ static void curses_destructor(PyObject *op) @@ -4783,7 +4795,7 @@ curses_destructor(PyObject *op) } static int -cursesmodule_exec(PyObject *module) +_cursesmodule_exec(PyObject *module) { /* Initialize object type */ if (PyType_Ready(&PyCursesWindow_Type) < 0) { @@ -5022,6 +5034,49 @@ cursesmodule_exec(PyObject *module) return 0; } +static int +_cursesmodule_traverse(PyObject *mod, visitproc visit, void *arg) +{ + _cursesmodule_state *st = get_cursesmodule_state(mod); + Py_VISIT(st->PyCursesError); + Py_VISIT(st->PyCursesWindow_Type); + return 0; +} + +static int +_cursesmodule_clear(PyObject *mod) +{ + _cursesmodule_state *st = get_cursesmodule_state(mod); + Py_CLEAR(st->PyCursesError); + Py_CLEAR(st->PyCursesWindow_Type); + return 0; +} + +static void +_cursesmodule_free(void *mod) +{ + (void)_cursesmodule_clear((PyObject *)mod); +} + +static PyModuleDef_Slot _cursesmodule_slots[] = { + {Py_mod_exec, _cursesmodule_exec}, + {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, + {Py_mod_gil, Py_MOD_GIL_NOT_USED}, + {0, NULL} +}; + +static struct PyModuleDef _cursesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_curses", + .m_doc = NULL, + .m_size = sizeof(_cursesmodule_state), + .m_methods = _cursesmodule_methods, + .m_slots = _cursesmodule_slots, + .m_traverse = _cursesmodule_traverse, + .m_clear = _cursesmodule_clear, + .m_free = _cursesmodule_free +}; + PyMODINIT_FUNC PyInit__curses(void) { @@ -5036,7 +5091,7 @@ PyInit__curses(void) } #endif // populate the module - if (cursesmodule_exec(mod) < 0) { + if (_cursesmodule_exec(mod) < 0) { goto error; } return mod; diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index f7e0aaf7b23649..9ac2e7d55f8ef4 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -1389,12 +1389,12 @@ _curses_window_overlay(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overlay", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overlay", clinic_state()->PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -1448,12 +1448,12 @@ _curses_window_overwrite(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overwrite", &PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overwrite", clinic_state()->PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -4318,4 +4318,4 @@ _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=96887782374f070a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8463fe82c8906325 input=a9049054013a1b77]*/ From 75bd7b63e8d1dcdbacd9467e958c24048711aa0d 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, 28 Sep 2024 13:39:16 +0200 Subject: [PATCH 02/38] Store exception in the module's state. --- Modules/_cursesmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index fe463586fdd0a2..3dc5fc4bce7fbc 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4797,6 +4797,7 @@ curses_destructor(PyObject *op) static int _cursesmodule_exec(PyObject *module) { + _cursesmodule_state *st = get_cursesmodule_state(module); /* Initialize object type */ if (PyType_Ready(&PyCursesWindow_Type) < 0) { return -1; @@ -4837,12 +4838,11 @@ _cursesmodule_exec(PyObject *module) } /* For exception curses.error */ - PyCursesError = PyErr_NewException("_curses.error", NULL, NULL); - if (PyCursesError == NULL) { + st->PyCursesError = PyErr_NewException("_curses.error", NULL, NULL); + if (st->PyCursesError == NULL) { return -1; } - rc = PyDict_SetItemString(module_dict, "error", PyCursesError); - Py_DECREF(PyCursesError); + rc = PyDict_SetItemString(module_dict, "error", st->PyCursesError); if (rc < 0) { return -1; } From b29591902a374d625f4b859159a76faf37f3fef0 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, 28 Sep 2024 13:39:54 +0200 Subject: [PATCH 03/38] Rename `curses_destructor` to `_curses_capi_destructor` --- Modules/_cursesmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 3dc5fc4bce7fbc..5407bcb6ed79b6 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4787,7 +4787,7 @@ static PyMethodDef _cursesmodule_methods[] = { /* Module initialization and cleanup functions. */ static void -curses_destructor(PyObject *op) +_curses_capi_destructor(PyObject *op) { void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); Py_DECREF(*(void **)ptr); @@ -4825,7 +4825,7 @@ _cursesmodule_exec(PyObject *module) /* Add a capsule for the C API */ PyObject *c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, - curses_destructor); + _curses_capi_destructor); if (c_api_object == NULL) { Py_DECREF(PyCurses_API[0]); PyMem_Free(PyCurses_API); From 1665f381b548c6c252cc6e9b778a675a1f181324 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, 28 Sep 2024 13:48:06 +0200 Subject: [PATCH 04/38] Introduce macros for initialization checks. --- Modules/_cursesmodule.c | 65 ++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5407bcb6ed79b6..8556030eb16348 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -186,10 +186,6 @@ class _curses.window "PyCursesWindowObject *" "clinic_state()->PyCursesWindow_Ty [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=83369be6e20ef0da]*/ -/* Definition of exception curses.error */ - -static PyObject *PyCursesError; - /* Tells whether setupterm() has been called to initialise terminfo. */ static int curses_setupterm_called = FALSE; @@ -201,33 +197,54 @@ static int curses_start_color_called = FALSE; static const char *curses_screen_encoding = NULL; -/* Utility Macros */ -#define PyCursesSetupTermCalled \ +/* + * Macro to check that FUNC_NAME has been called by testing + * the CALLED boolean. If an error occurs, a PyCursesError + * is raised. + * + * Since these macros can be called in functions that do not + * have a direct access to the module's state, the exception + * type is imported on demand as well. + */ +#define _PyCursesCheckFunction(CALLED, FUNC_NAME) \ do { \ - if (curses_setupterm_called != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call (at least) setupterm() first"); \ + if ((CALLED) != TRUE) { \ + PyObject *exc = _PyImport_GetModuleAttrString("_curses", \ + "error"); \ + if (exc == NULL) { \ + return 0; \ + } \ + PyErr_SetString(exc, "must call " # FUNC_NAME "() first"); \ + Py_DECREF(exc); \ return 0; \ } \ } while (0) -#define PyCursesInitialised \ - do { \ - if (curses_initscr_called != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call initscr() first"); \ - return 0; \ - } \ +/* + * Macro to check that FUNC_NAME has been called by testing + * the CALLED boolean. If an error occurs, a PyCursesError + * is raised. The exception type is obtained from the module + * state. + */ +#define _PyCursesStatefulCheckFunction(CALLED, FUNC_NAME, MODULE) \ + do { \ + if ((CALLED) != TRUE) { \ + _cursesmodule_state *st = get_cursesmodule_state((MODULE)); \ + PyErr_SetString(st->PyCursesError, \ + "must call " # FUNC_NAME "() first"); \ + return 0; \ + } \ } while (0) -#define PyCursesInitialisedColor \ - do { \ - if (curses_start_color_called != TRUE) { \ - PyErr_SetString(PyCursesError, \ - "must call start_color() first"); \ - return 0; \ - } \ - } while (0) +#define PyCursesStatefulSetupTermCalled(MODULE) \ + _PyCursesStatefulCheckFunction(curses_setupterm_called, \ + "setupterm", (MODULE)) +#define PyCursesStatefulInitialised(MODULE) \ + _PyCursesStatefulCheckFunction(curses_initscr_called, \ + "initscr", (MODULE)) +#define PyCursesStatefulInitialisedColor(MODULE) \ + _PyCursesStatefulCheckFunction(curses_start_color_called, \ + "start_color", (MODULE)) /* Utility Functions */ From 2a1e13a0e312efb5813a6addb24b6f9b48452973 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, 28 Sep 2024 13:49:05 +0200 Subject: [PATCH 05/38] Update C API functions --- Modules/_cursesmodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 8556030eb16348..01885b0b9e4d84 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -593,19 +593,19 @@ class component_converter(CConverter): static int func_PyCursesSetupTermCalled(void) { - PyCursesSetupTermCalled; + _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); return 1; } static int func_PyCursesInitialised(void) { - PyCursesInitialised; + _PyCursesCheckFunction(curses_initscr_called, "initscr"); return 1; } static int func_PyCursesInitialisedColor(void) { - PyCursesInitialisedColor; + _PyCursesCheckFunction(curses_start_color_called, "start_color"); return 1; } From 9e29bd52d3eb752e265d3b64ebd605c8c3ec76f0 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, 28 Sep 2024 14:05:26 +0200 Subject: [PATCH 06/38] Update macros checking the functions being called. --- Modules/_cursesmodule.c | 90 ++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 01885b0b9e4d84..c38c7f55ada6aa 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2812,8 +2812,8 @@ _curses_color_content_impl(PyObject *module, int color_number) { _CURSES_COLOR_VAL_TYPE r,g,b; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { PyErr_Format(PyCursesError, "%s() returned ERR", @@ -2841,8 +2841,8 @@ static PyObject * _curses_color_pair_impl(PyObject *module, int pair_number) /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyLong_FromLong(COLOR_PAIR(pair_number)); } @@ -2868,7 +2868,7 @@ _curses_curs_set_impl(PyObject *module, int visibility) { int erg; - PyCursesInitialised; + PyCursesStatefulInitialised(module); erg = curs_set(visibility); if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); @@ -2920,7 +2920,7 @@ static PyObject * _curses_delay_output_impl(PyObject *module, int ms) /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(delay_output(ms), "delay_output"); } @@ -2976,7 +2976,7 @@ _curses_erasechar_impl(PyObject *module) { char ch; - PyCursesInitialised; + PyCursesStatefulInitialised(module); ch = erasechar(); @@ -3026,7 +3026,7 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - PyCursesInitialised; + PyCursesStatefulInitialised(module); getsyx(y, x); @@ -3051,7 +3051,7 @@ _curses_getmouse_impl(PyObject *module) int rtn; MEVENT event; - PyCursesInitialised; + PyCursesStatefulInitialised(module); rtn = getmouse( &event ); if (rtn == ERR) { @@ -3086,7 +3086,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, { MEVENT event; - PyCursesInitialised; + PyCursesStatefulInitialised(module); event.id = id; event.x = x; @@ -3119,7 +3119,7 @@ _curses_getwin(PyObject *module, PyObject *file) WINDOW *win; PyObject *res = NULL; - PyCursesInitialised; + PyCursesStatefulInitialised(module); fp = tmpfile(); if (fp == NULL) @@ -3175,7 +3175,7 @@ static PyObject * _curses_halfdelay_impl(PyObject *module, unsigned char tenths) /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); } @@ -3228,7 +3228,7 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyBool_FromLong(has_key(key)); } @@ -3259,8 +3259,8 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, short b) /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); @@ -3287,8 +3287,8 @@ static PyObject * _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3584,7 +3584,7 @@ static PyObject * _curses_intrflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); } @@ -3617,7 +3617,7 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyBool_FromLong(is_term_resized(nlines, ncols)); } @@ -3639,7 +3639,7 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); @@ -3697,7 +3697,7 @@ static PyObject * _curses_meta_impl(PyObject *module, int yes) /*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(meta(stdscr, yes), "meta"); } @@ -3721,7 +3721,7 @@ static PyObject * _curses_mouseinterval_impl(PyObject *module, int interval) /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); } @@ -3746,7 +3746,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - PyCursesInitialised; + PyCursesStatefulInitialised(module); availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); @@ -3767,7 +3767,7 @@ static int _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=5f292a6a724491bd input=c6d6e01f2f1df9f7]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return napms(ms); } @@ -3791,7 +3791,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) { WINDOW *win; - PyCursesInitialised; + PyCursesStatefulInitialised(module); win = newpad(nlines, ncols); @@ -3831,7 +3831,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, { WINDOW *win; - PyCursesInitialised; + PyCursesStatefulInitialised(module); win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { @@ -3943,8 +3943,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number) { _CURSES_COLOR_NUM_TYPE f, b; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3977,8 +3977,8 @@ static PyObject * _curses_pair_number_impl(PyObject *module, int attr) /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyLong_FromLong(PAIR_NUMBER(attr)); } @@ -4018,7 +4018,7 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (flag) { qiflush(); @@ -4173,7 +4173,7 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + PyCursesStatefulInitialised(module); result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); if (!result) @@ -4212,7 +4212,7 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + PyCursesStatefulInitialised(module); result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); if (!result) @@ -4255,7 +4255,7 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); setsyx(y,x); @@ -4280,7 +4280,7 @@ static PyObject * _curses_start_color_impl(PyObject *module) /*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (start_color() == ERR) { PyErr_SetString(PyCursesError, "start_color() returned ERR"); @@ -4352,7 +4352,7 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); } @@ -4374,7 +4374,7 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); } @@ -4396,7 +4396,7 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); capname = tigetstr( (char *)capname ); if (capname == NULL || capname == (char*) -1) { @@ -4431,7 +4431,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, { char* result = NULL; - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { @@ -4459,7 +4459,7 @@ static PyObject * _curses_typeahead_impl(PyObject *module, int fd) /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(typeahead( fd ), "typeahead"); } @@ -4483,7 +4483,7 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4506,7 +4506,7 @@ _curses_ungetch(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4577,7 +4577,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch) { wchar_t wch; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; @@ -4629,8 +4629,8 @@ _curses_use_default_colors_impl(PyObject *module) { int code; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); code = use_default_colors(); if (code != ERR) { From e1cab2f8daf5e5ce400f1014a1797841b5d62082 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, 28 Sep 2024 13:51:49 +0200 Subject: [PATCH 07/38] Update `PyCursesCheckERR` to use the module's state --- Modules/_cursesmodule.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index c38c7f55ada6aa..cf207524439368 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -255,15 +255,18 @@ static const char *curses_screen_encoding = NULL; */ static PyObject * -PyCursesCheckERR(int code, const char *fname) +PyCursesCheckERR(PyObject *module, int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; - } else { + } + else { + _cursesmodule_state *st = get_cursesmodule_state(module); if (fname == NULL) { - PyErr_SetString(PyCursesError, catchall_ERR); - } else { - PyErr_Format(PyCursesError, "%s() returned ERR", fname); + PyErr_SetString(st->PyCursesError, catchall_ERR); + } + else { + PyErr_Format(st->PyCursesError, "%s() returned ERR", fname); } return NULL; } From 5f28eb86cf7c7452e668a911f656525289fd3718 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, 28 Sep 2024 13:53:43 +0200 Subject: [PATCH 08/38] Add `PyCursesCheckERR_FromSelf` to prepare when the type is a heap type. --- Modules/_cursesmodule.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index cf207524439368..5077107b9c0044 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -272,6 +272,13 @@ PyCursesCheckERR(PyObject *module, int code, const char *fname) } } +static inline PyObject * +PyCursesCheckERR_FromSelf(PyCursesWindowObject *self, int code, const char *fname) +{ + PyObject *module = PyType_GetModule(Py_TYPE(self)); + return PyCursesCheckERR(module, code, fname); +} + /* Convert an object to a byte (an integer of type chtype): - int From bcbbdd49cc54193006692a21554802a73b580772 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, 28 Sep 2024 13:54:28 +0200 Subject: [PATCH 09/38] Update Function Prototype Macros. --- Modules/_cursesmodule.c | 96 +++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 5077107b9c0044..a1e7678cad1c10 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -638,50 +638,70 @@ PyTypeObject PyCursesWindow_Type; #define Window_NoArgNoReturnFunction(X) \ static PyObject *PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { return PyCursesCheckERR(X(self->win), # X); } + { \ + int rtn = X(self->win); \ + return PyCursesCheckERR_FromSelf(self, rtn, # X); \ + } -#define Window_NoArgTrueFalseFunction(X) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { \ - return PyBool_FromLong(X(self->win)); } +#define Window_NoArgTrueFalseFunction(X) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ + { \ + return PyBool_FromLong(X(self->win)); \ + } #define Window_NoArgNoReturnVoidFunction(X) \ static PyObject * PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ { \ - X(self->win); Py_RETURN_NONE; } - -#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { \ - TYPE arg1, arg2; \ - X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); } - -#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL; \ - X(self->win,arg1); Py_RETURN_NONE; } - -#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1), # X); } - -#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1, arg2; \ - if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1, arg2), # X); } + X(self->win); \ + Py_RETURN_NONE; \ + } + +#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ + { \ + TYPE arg1, arg2; \ + X(self->win,arg1,arg2); \ + return Py_BuildValue(ERGSTR, arg1, arg2); \ + } + +#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ + return NULL; \ + } \ + X(self->win,arg1); \ + Py_RETURN_NONE; \ + } + +#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ + return NULL; \ + } \ + int rtn = X(self->win, arg1); \ + return PyCursesCheckERR_FromSelf(self, rtn, # X); \ + } + +#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1, arg2; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) { \ + return NULL; \ + } \ + int rtn = X(self->win, arg1, arg2); \ + return PyCursesCheckERR_FromSelf(self, rtn, # X); \ + } /* ------------- WINDOW routines --------------- */ From faf4e874fcea15f129b862acae5f74a14771ef20 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, 28 Sep 2024 14:02:16 +0200 Subject: [PATCH 10/38] Update Function Body Macros. --- Modules/_cursesmodule.c | 62 +++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index a1e7678cad1c10..c50e75ee9aa7dc 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2704,7 +2704,7 @@ PyTypeObject PyCursesWindow_Type = { PyCursesWindow_getsets, /* tp_getset */ }; -/* Function Prototype Macros - They are ugly but very, very useful. ;-) +/* Function Body Macros - They are ugly but very, very useful. ;-) X - function name TYPE - parameter Type @@ -2712,41 +2712,43 @@ PyTypeObject PyCursesWindow_Type = { PARSESTR - format string for argument parsing */ -#define NoArgNoReturnFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyCursesCheckERR(X(), # X); } - -#define NoArgOrFlagNoReturnFunctionBody(X, flag) \ -{ \ - PyCursesInitialised; \ - if (flag) \ - return PyCursesCheckERR(X(), # X); \ - else \ - return PyCursesCheckERR(no ## X(), # X); \ +#define NoArgNoReturnFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return PyCursesCheckERR(module, X(), # X); \ } -#define NoArgReturnIntFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyLong_FromLong((long) X()); } +#define NoArgOrFlagNoReturnFunctionBody(X, flag) \ +{ \ + PyCursesStatefulInitialised(module); \ + int rtn = (flag) ? X() : no ## X(); \ + return PyCursesCheckERR(module, rtn, # X); \ +} +#define NoArgReturnIntFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return PyLong_FromLong((long) X()); \ +} -#define NoArgReturnStringFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyBytes_FromString(X()); } +#define NoArgReturnStringFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return PyBytes_FromString(X()); \ +} -#define NoArgTrueFalseFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyBool_FromLong(X()); } +#define NoArgTrueFalseFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + return PyBool_FromLong(X()); \ +} -#define NoArgNoReturnVoidFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - X(); \ - Py_RETURN_NONE; } +#define NoArgNoReturnVoidFunctionBody(X) \ +{ \ + PyCursesStatefulInitialised(module); \ + X(); \ + Py_RETURN_NONE; \ +} /********************************************************************* Global Functions From 885c94c41b02925bd49057ef17926cb9bd44cc84 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, 28 Sep 2024 13:57:58 +0200 Subject: [PATCH 11/38] Update `PyCursesCheckERR` usage for Window methods --- Modules/_cursesmodule.c | 76 +++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index c50e75ee9aa7dc..a5b73fb26af020 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -875,7 +875,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, else { return NULL; } - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_FromSelf(self, rtn, funcname); } /*[clinic input] @@ -955,7 +955,7 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_FromSelf(self, rtn, funcname); } /*[clinic input] @@ -1038,7 +1038,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_FromSelf(self, rtn, funcname); } /*[clinic input] @@ -1062,7 +1062,7 @@ _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; - return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); + return PyCursesCheckERR_FromSelf(self, wbkgd(self->win, bkgd | attr), "bkgd"); } /*[clinic input] @@ -1078,7 +1078,7 @@ static PyObject * _curses_window_attroff_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ { - return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff"); + return PyCursesCheckERR_FromSelf(self, wattroff(self->win, (attr_t)attr), "attroff"); } /*[clinic input] @@ -1094,7 +1094,7 @@ static PyObject * _curses_window_attron_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/ { - return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron"); + return PyCursesCheckERR_FromSelf(self, wattron(self->win, (attr_t)attr), "attron"); } /*[clinic input] @@ -1110,7 +1110,7 @@ static PyObject * _curses_window_attrset_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ { - return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset"); + return PyCursesCheckERR_FromSelf(self, wattrset(self->win, (attr_t)attr), "attrset"); } /*[clinic input] @@ -1136,7 +1136,7 @@ _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, return NULL; wbkgdset(self->win, bkgd | attr); - return PyCursesCheckERR(0, "bkgdset"); + return PyCursesCheckERR_FromSelf(self, 0, "bkgdset"); } /*[clinic input] @@ -1336,7 +1336,7 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) rtn = wchgat(self->win,num,attr,color,NULL); touchline(self->win,y,1); } - return PyCursesCheckERR(rtn, "chgat"); + return PyCursesCheckERR_FromSelf(self, rtn, "chgat"); } #endif @@ -1360,10 +1360,10 @@ _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ { if (!group_right_1) { - return PyCursesCheckERR(wdelch(self->win), "wdelch"); + return PyCursesCheckERR_FromSelf(self, wdelch(self->win), "wdelch"); } else { - return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch"); + return PyCursesCheckERR_FromSelf(self, py_mvwdelch(self->win, y, x), "mvwdelch"); } } @@ -1431,13 +1431,15 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR_FromSelf(self, + pechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } else #endif - return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR_FromSelf(self, + wechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } #ifdef NCURSES_MOUSE_VERSION @@ -1731,10 +1733,10 @@ _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) { - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR_FromSelf(self, ERR, "wmove"); } } - return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline"); + return PyCursesCheckERR_FromSelf(self, whline(self->win, ch_ | (attr_t)attr, n), "hline"); } /*[clinic input] @@ -1781,7 +1783,7 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); } - return PyCursesCheckERR(rtn, "insch"); + return PyCursesCheckERR_FromSelf(self, rtn, "insch"); } /*[clinic input] @@ -1958,7 +1960,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_FromSelf(self, rtn, funcname); } /*[clinic input] @@ -2043,7 +2045,7 @@ _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_FromSelf(self, rtn, funcname); } /*[clinic input] @@ -2129,7 +2131,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) rtn = pnoutrefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); + return PyCursesCheckERR_FromSelf(self, rtn, "pnoutrefresh"); } if (group_right_1) { PyErr_SetString(PyExc_TypeError, @@ -2140,7 +2142,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) Py_BEGIN_ALLOW_THREADS rtn = wnoutrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); + return PyCursesCheckERR_FromSelf(self, rtn, "wnoutrefresh"); } /*[clinic input] @@ -2183,11 +2185,11 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, TRUE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR_FromSelf(self, rtn, "copywin"); } else { rtn = overlay(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overlay"); + return PyCursesCheckERR_FromSelf(self, rtn, "overlay"); } } @@ -2232,11 +2234,11 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, FALSE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR_FromSelf(self, rtn, "copywin"); } else { rtn = overwrite(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overwrite"); + return PyCursesCheckERR_FromSelf(self, rtn, "overwrite"); } } @@ -2265,7 +2267,7 @@ _curses_window_putwin(PyCursesWindowObject *self, PyObject *file) return PyErr_SetFromErrno(PyExc_OSError); if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) goto exit; - res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); + res = PyCursesCheckERR_FromSelf(self, putwin(self->win, fp), "putwin"); if (res == NULL) goto exit; fseek(fp, 0, 0); @@ -2304,7 +2306,7 @@ static PyObject * _curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) /*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ { - return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); + return PyCursesCheckERR_FromSelf(self, wredrawln(self->win,beg,num), "redrawln"); } /*[clinic input] @@ -2354,7 +2356,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, rtn = prefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR_FromSelf(self, rtn, "prefresh"); } #endif if (group_right_1) { @@ -2365,7 +2367,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, Py_BEGIN_ALLOW_THREADS rtn = wrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR_FromSelf(self, rtn, "prefresh"); } /*[clinic input] @@ -2387,7 +2389,7 @@ _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, int bottom) /*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ { - return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg"); + return PyCursesCheckERR_FromSelf(self, wsetscrreg(self->win, top, bottom), "wsetscrreg"); } /*[clinic input] @@ -2455,10 +2457,10 @@ _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/ { if (!group_right_1) { - return PyCursesCheckERR(scroll(self->win), "scroll"); + return PyCursesCheckERR_FromSelf(self, scroll(self->win), "scroll"); } else { - return PyCursesCheckERR(wscrl(self->win, lines), "scroll"); + return PyCursesCheckERR_FromSelf(self, wscrl(self->win, lines), "scroll"); } } @@ -2484,10 +2486,10 @@ _curses_window_touchline_impl(PyCursesWindowObject *self, int start, /*[clinic end generated code: output=65d05b3f7438c61d input=a98aa4f79b6be845]*/ { if (!group_right_1) { - return PyCursesCheckERR(touchline(self->win, start, count), "touchline"); + return PyCursesCheckERR_FromSelf(self, touchline(self->win, start, count), "touchline"); } else { - return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline"); + return PyCursesCheckERR_FromSelf(self, wtouchln(self->win, start, count, changed), "touchline"); } } @@ -2527,9 +2529,9 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR_FromSelf(self, ERR, "wmove"); } - return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline"); + return PyCursesCheckERR_FromSelf(self, wvline(self->win, ch_ | (attr_t)attr, n), "vline"); } static PyObject * From da98de4be8a0464139d13e995ded368dd3401200 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, 28 Sep 2024 13:59:38 +0200 Subject: [PATCH 12/38] Update `PyCursesCheckERR` usage for module's methods --- Modules/_cursesmodule.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index a5b73fb26af020..be7d05fbf686cf 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2905,7 +2905,7 @@ _curses_curs_set_impl(PyObject *module, int visibility) PyCursesStatefulInitialised(module); erg = curs_set(visibility); - if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); + if (erg == ERR) return PyCursesCheckERR(module, erg, "curs_set"); return PyLong_FromLong((long) erg); } @@ -2956,7 +2956,7 @@ _curses_delay_output_impl(PyObject *module, int ms) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(delay_output(ms), "delay_output"); + return PyCursesCheckERR(module, delay_output(ms), "delay_output"); } /*[clinic input] @@ -3127,7 +3127,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, event.y = y; event.z = z; event.bstate = bstate; - return PyCursesCheckERR(ungetmouse(&event), "ungetmouse"); + return PyCursesCheckERR(module, ungetmouse(&event), "ungetmouse"); } #endif @@ -3211,7 +3211,7 @@ _curses_halfdelay_impl(PyObject *module, unsigned char tenths) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); + return PyCursesCheckERR(module, halfdelay(tenths), "halfdelay"); } /*[clinic input] @@ -3296,7 +3296,8 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, PyCursesStatefulInitialised(module); PyCursesStatefulInitialisedColor(module); - return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), + return PyCursesCheckERR(module, + _CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); } @@ -3563,7 +3564,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - return PyCursesCheckERR(set_escdelay(ms), "set_escdelay"); + return PyCursesCheckERR(module, set_escdelay(ms), "set_escdelay"); } /*[clinic input] @@ -3602,7 +3603,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - return PyCursesCheckERR(set_tabsize(size), "set_tabsize"); + return PyCursesCheckERR(module, set_tabsize(size), "set_tabsize"); } #endif @@ -3620,7 +3621,7 @@ _curses_intrflush_impl(PyObject *module, int flag) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); + return PyCursesCheckERR(module, intrflush(NULL, flag), "intrflush"); } /*[clinic input] @@ -3733,7 +3734,7 @@ _curses_meta_impl(PyObject *module, int yes) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(meta(stdscr, yes), "meta"); + return PyCursesCheckERR(module, meta(stdscr, yes), "meta"); } #ifdef NCURSES_MOUSE_VERSION @@ -3757,7 +3758,7 @@ _curses_mouseinterval_impl(PyObject *module, int interval) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); + return PyCursesCheckERR(module, mouseinterval(interval), "mouseinterval"); } /*[clinic input] @@ -4032,7 +4033,7 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - return PyCursesCheckERR(putp(string), "putp"); + return PyCursesCheckERR(module, putp(string), "putp"); } /*[clinic input] @@ -4209,7 +4210,7 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) PyCursesStatefulInitialised(module); - result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); + result = PyCursesCheckERR(module, resizeterm(nlines, ncols), "resizeterm"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4248,7 +4249,7 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) PyCursesStatefulInitialised(module); - result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); + result = PyCursesCheckERR(module, resize_term(nlines, ncols), "resize_term"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4495,7 +4496,7 @@ _curses_typeahead_impl(PyObject *module, int fd) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(typeahead( fd ), "typeahead"); + return PyCursesCheckERR(module, typeahead( fd ), "typeahead"); } #endif @@ -4545,7 +4546,7 @@ _curses_ungetch(PyObject *module, PyObject *ch) if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyCursesCheckERR(ungetch(ch_), "ungetch"); + return PyCursesCheckERR(module, ungetch(ch_), "ungetch"); } #ifdef HAVE_NCURSESW @@ -4615,7 +4616,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch) if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; - return PyCursesCheckERR(unget_wch(wch), "unget_wch"); + return PyCursesCheckERR(module, unget_wch(wch), "unget_wch"); } #endif From 65c5f600e0daa851ee719b2282629bc11da83c47 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, 28 Sep 2024 14:13:02 +0200 Subject: [PATCH 13/38] Update global references to `PyCursesError` --- Modules/_cursesmodule.c | 64 ++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index be7d05fbf686cf..42d0c80340967a 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1399,7 +1399,8 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, catchall_NULL); return NULL; } @@ -1550,8 +1551,10 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, if (rtn == ERR) { /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); - if (!PyErr_Occurred()) - PyErr_SetString(PyCursesError, "no input"); + if (!PyErr_Occurred()) { + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, "no input"); + } return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -1609,7 +1612,8 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - PyErr_SetString(PyCursesError, "no input"); + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -2122,7 +2126,8 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(PyCursesError, + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2348,7 +2353,8 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(PyCursesError, + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2430,7 +2436,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + PyErr_SetString(st->PyCursesError, catchall_NULL); return NULL; } @@ -2850,8 +2857,9 @@ _curses_color_content_impl(PyObject *module, int color_number) PyCursesStatefulInitialisedColor(module); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { - PyErr_Format(PyCursesError, "%s() returned ERR", - Py_STRINGIFY(_COLOR_CONTENT_FUNC)); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_Format(st->PyCursesError, "%s() returned ERR", + Py_STRINGIFY(_COLOR_CONTENT_FUNC)); return NULL; } @@ -3089,7 +3097,8 @@ _curses_getmouse_impl(PyObject *module) rtn = getmouse( &event ); if (rtn == ERR) { - PyErr_SetString(PyCursesError, "getmouse() returned ERR"); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, "getmouse() returned ERR"); return NULL; } return Py_BuildValue("(hiiik)", @@ -3183,7 +3192,8 @@ _curses_getwin(PyObject *module, PyObject *file) fseek(fp, 0, 0); win = getwin(fp); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, catchall_NULL); goto error; } res = PyCursesWindow_New(win, NULL); @@ -3332,7 +3342,8 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) COLOR_PAIRS - 1); } else { - PyErr_Format(PyCursesError, "%s() returned ERR", + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_Format(st->PyCursesError, "%s() returned ERR", Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)); } return NULL; @@ -3363,7 +3374,8 @@ _curses_initscr_impl(PyObject *module) win = initscr(); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, catchall_NULL); return NULL; } @@ -3492,9 +3504,8 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) sys_stdout = PySys_GetObject("stdout"); if (sys_stdout == NULL || sys_stdout == Py_None) { - PyErr_SetString( - PyCursesError, - "lost sys.stdout"); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, "lost sys.stdout"); return NULL; } @@ -3514,7 +3525,8 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) s = "setupterm: could not find terminfo database"; } - PyErr_SetString(PyCursesError,s); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, s); return NULL; } @@ -3831,7 +3843,8 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) win = newpad(nlines, ncols); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, catchall_NULL); return NULL; } @@ -3870,7 +3883,8 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(PyCursesError, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, catchall_NULL); return NULL; } @@ -3988,7 +4002,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number) COLOR_PAIRS - 1); } else { - PyErr_Format(PyCursesError, "%s() returned ERR", + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_Format(st->PyCursesError, "%s() returned ERR", Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC)); } return NULL; @@ -4318,7 +4333,8 @@ _curses_start_color_impl(PyObject *module) PyCursesStatefulInitialised(module); if (start_color() == ERR) { - PyErr_SetString(PyCursesError, "start_color() returned ERR"); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, "start_color() returned ERR"); return NULL; } @@ -4470,7 +4486,8 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { - PyErr_SetString(PyCursesError, "tparm() returned NULL"); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, "tparm() returned NULL"); return NULL; } @@ -4671,7 +4688,8 @@ _curses_use_default_colors_impl(PyObject *module) if (code != ERR) { Py_RETURN_NONE; } else { - PyErr_SetString(PyCursesError, "use_default_colors() returned ERR"); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyErr_SetString(st->PyCursesError, "use_default_colors() returned ERR"); return NULL; } } From e3e1131fdde6ffe62206f7fcb671cb1a342ecad3 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, 28 Sep 2024 14:16:17 +0200 Subject: [PATCH 14/38] Make `PyCursesWindow_Type` a heap type. --- Modules/_cursesmodule.c | 72 +++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 42d0c80340967a..ebe49a918a4d83 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -623,10 +623,6 @@ static int func_PyCursesInitialisedColor(void) The Window Object ******************************************************************************/ -/* Definition of the window type */ - -PyTypeObject PyCursesWindow_Type; - /* Function prototype macros for Window object X - function name @@ -756,7 +752,7 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") /* Allocation and deallocation of Window Objects */ static PyObject * -PyCursesWindow_New(WINDOW *win, const char *encoding) +PyCursesWindow_New(_cursesmodule_state *st, WINDOW *win, const char *encoding) { PyCursesWindowObject *wo; @@ -778,8 +774,11 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) encoding = "utf-8"; } - wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type); - if (wo == NULL) return NULL; + PyTypeObject *type = st->PyCursesWindow_Type; + wo = (PyCursesWindowObject *)type->tp_alloc(type, 0); + if (wo == NULL) { + return NULL; + } wo->win = win; wo->encoding = _PyMem_Strdup(encoding); if (wo->encoding == NULL) { @@ -793,6 +792,7 @@ PyCursesWindow_New(WINDOW *win, const char *encoding) static void PyCursesWindow_Dealloc(PyCursesWindowObject *wo) { + PyTypeObject *tp = Py_TYPE(wo); if (wo->win != stdscr && wo->win != NULL) { // silently ignore errors in delwin(3) (void)delwin(wo->win); @@ -800,7 +800,8 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) if (wo->encoding != NULL) { PyMem_Free(wo->encoding); } - PyObject_Free(wo); + tp->tp_free(wo); + Py_DECREF(tp); } /* Addch, Addstr, Addnstr */ @@ -2677,42 +2678,22 @@ static PyGetSetDef PyCursesWindow_getsets[] = { {NULL, NULL, NULL, NULL } /* sentinel */ }; -/* -------------------------------------------------------*/ +static PyType_Slot PyCursesWindow_Type_slots[] = { + {Py_tp_dealloc, PyCursesWindow_Dealloc}, + {Py_tp_methods, PyCursesWindow_Methods}, + {Py_tp_getset, PyCursesWindow_getsets}, + {0, NULL} +}; -PyTypeObject PyCursesWindow_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "_curses.window", /*tp_name*/ - sizeof(PyCursesWindowObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/ - 0, /*tp_vectorcall_offset*/ - (getattrfunc)0, /*tp_getattr*/ - (setattrfunc)0, /*tp_setattr*/ - 0, /*tp_as_async*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /*tp_traverse*/ - 0, /*tp_clear*/ - 0, /*tp_richcompare*/ - 0, /*tp_weaklistoffset*/ - 0, /*tp_iter*/ - 0, /*tp_iternext*/ - PyCursesWindow_Methods, /*tp_methods*/ - 0, /* tp_members */ - PyCursesWindow_getsets, /* tp_getset */ +static PyType_Spec PyCursesWindow_Type_spec = { + .name = "_curses.window", + .basicsize = sizeof(PyCursesWindowObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = PyCursesWindow_Type_slots }; +/* -------------------------------------------------------*/ + /* Function Body Macros - They are ugly but very, very useful. ;-) X - function name @@ -4869,10 +4850,9 @@ _cursesmodule_exec(PyObject *module) { _cursesmodule_state *st = get_cursesmodule_state(module); /* Initialize object type */ - if (PyType_Ready(&PyCursesWindow_Type) < 0) { - return -1; - } - if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { + st->PyCursesWindow_Type = (PyTypeObject *)PyType_FromModuleAndSpec( + module, &PyCursesWindow_Type_spec, NULL); + if (PyModule_AddType(module, st->PyCursesWindow_Type) < 0) { return -1; } @@ -4888,7 +4868,7 @@ _cursesmodule_exec(PyObject *module) return -1; } /* Initialize the C API pointer array */ - PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type); + PyCurses_API[0] = (void *)Py_NewRef(st->PyCursesWindow_Type); PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; PyCurses_API[2] = (void *)func_PyCursesInitialised; PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; From 9617f50e80df95d240e0ec5b8f31a5d2fd0320de 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, 28 Sep 2024 14:17:41 +0200 Subject: [PATCH 15/38] Correct calls to `PyCursesWindow_New` --- Modules/_cursesmodule.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index ebe49a918a4d83..d5fc4c77fb8acd 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1405,7 +1405,8 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + return (PyObject *)PyCursesWindow_New(st, win, NULL); } /*[clinic input] @@ -2442,7 +2443,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, return NULL; } - return (PyObject *)PyCursesWindow_New(win, self->encoding); + _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); + return (PyObject *)PyCursesWindow_New(st, win, self->encoding); } /*[clinic input] @@ -3177,7 +3179,8 @@ _curses_getwin(PyObject *module, PyObject *file) PyErr_SetString(st->PyCursesError, catchall_NULL); goto error; } - res = PyCursesWindow_New(win, NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + res = PyCursesWindow_New(st, win, NULL); error: fclose(fp); @@ -3349,7 +3352,8 @@ _curses_initscr_impl(PyObject *module) if (curses_initscr_called) { wrefresh(stdscr); - return (PyObject *)PyCursesWindow_New(stdscr, NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + return (PyObject *)PyCursesWindow_New(st, stdscr, NULL); } win = initscr(); @@ -3452,7 +3456,8 @@ _curses_initscr_impl(PyObject *module) SetDictInt("COLS", COLS); #undef SetDictInt - PyCursesWindowObject *winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + PyCursesWindowObject *winobj = (PyCursesWindowObject *)PyCursesWindow_New(st, win, NULL); if (winobj == NULL) { return NULL; } @@ -3829,7 +3834,8 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + return (PyObject *)PyCursesWindow_New(st, win, NULL); } /*[clinic input] @@ -3869,7 +3875,8 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, return NULL; } - return (PyObject *)PyCursesWindow_New(win, NULL); + _cursesmodule_state *st = get_cursesmodule_state(module); + return (PyObject *)PyCursesWindow_New(st, win, NULL); } /*[clinic input] From 1db7bea875a11b284f54f88f1792cde31b48d551 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, 28 Sep 2024 14:18:43 +0200 Subject: [PATCH 16/38] Do not expose `PyCursesWindow_Check` when compiling `_cursesmodule.c` --- Include/py_curses.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/py_curses.h b/Include/py_curses.h index 79b1b01fcfa594..e11bfedb17d205 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -81,8 +81,6 @@ typedef struct { char *encoding; } PyCursesWindowObject; -#define PyCursesWindow_Check(v) Py_IS_TYPE((v), &PyCursesWindow_Type) - #define PyCurses_CAPSULE_NAME "_curses._C_API" @@ -99,6 +97,8 @@ static void **PyCurses_API; #define PyCursesInitialised {if (! ((int (*)(void))PyCurses_API[2]) () ) return NULL;} #define PyCursesInitialisedColor {if (! ((int (*)(void))PyCurses_API[3]) () ) return NULL;} +#define PyCursesWindow_Check(v) Py_IS_TYPE((v), &PyCursesWindow_Type) + #define import_curses() \ PyCurses_API = (void **)PyCapsule_Import(PyCurses_CAPSULE_NAME, 1); From 4c207d34896625650544f01131646846139e61cb 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, 28 Sep 2024 14:27:42 +0200 Subject: [PATCH 17/38] Finalize multi-phase initialization for `curses`. --- Modules/_cursesmodule.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index d5fc4c77fb8acd..1cf00de581a66f 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -5137,23 +5137,5 @@ static struct PyModuleDef _cursesmodule = { PyMODINIT_FUNC PyInit__curses(void) { - // create the module - PyObject *mod = PyModule_Create(&_cursesmodule); - if (mod == NULL) { - goto error; - } -#ifdef Py_GIL_DISABLED - if (PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED) < 0) { - goto error; - } -#endif - // populate the module - if (_cursesmodule_exec(mod) < 0) { - goto error; - } - return mod; - -error: - Py_XDECREF(mod); - return NULL; + return PyModuleDef_Init(&_cursesmodule); } From 228348c812a78e723d07981be36ea26d8f66d597 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, 28 Sep 2024 14:33:08 +0200 Subject: [PATCH 18/38] Remove redundant cast to `PyObject *`. --- Modules/_cursesmodule.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 1cf00de581a66f..bf197caf305fd8 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1406,7 +1406,7 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, } _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - return (PyObject *)PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(st, win, NULL); } /*[clinic input] @@ -2444,7 +2444,7 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, } _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - return (PyObject *)PyCursesWindow_New(st, win, self->encoding); + return PyCursesWindow_New(st, win, self->encoding); } /*[clinic input] @@ -3353,7 +3353,7 @@ _curses_initscr_impl(PyObject *module) if (curses_initscr_called) { wrefresh(stdscr); _cursesmodule_state *st = get_cursesmodule_state(module); - return (PyObject *)PyCursesWindow_New(st, stdscr, NULL); + return PyCursesWindow_New(st, stdscr, NULL); } win = initscr(); @@ -3835,7 +3835,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) } _cursesmodule_state *st = get_cursesmodule_state(module); - return (PyObject *)PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(st, win, NULL); } /*[clinic input] @@ -3876,7 +3876,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, } _cursesmodule_state *st = get_cursesmodule_state(module); - return (PyObject *)PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(st, win, NULL); } /*[clinic input] From b8b0751807a3b3dfa55febf475366cf2c531ce3a 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, 28 Sep 2024 15:55:08 +0200 Subject: [PATCH 19/38] reduce diff (remove some PEP-7 changes) --- Modules/_cursesmodule.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index bf197caf305fd8..e6c7bc8277a415 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -264,8 +264,7 @@ PyCursesCheckERR(PyObject *module, int code, const char *fname) _cursesmodule_state *st = get_cursesmodule_state(module); if (fname == NULL) { PyErr_SetString(st->PyCursesError, catchall_ERR); - } - else { + } else { PyErr_Format(st->PyCursesError, "%s() returned ERR", fname); } return NULL; @@ -776,9 +775,7 @@ PyCursesWindow_New(_cursesmodule_state *st, WINDOW *win, const char *encoding) PyTypeObject *type = st->PyCursesWindow_Type; wo = (PyCursesWindowObject *)type->tp_alloc(type, 0); - if (wo == NULL) { - return NULL; - } + if (wo == NULL) return NULL; wo->win = win; wo->encoding = _PyMem_Strdup(encoding); if (wo->encoding == NULL) { From 83fab158eba2b25c73e65d91c64cdc4d149894ea 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, 28 Sep 2024 15:56:07 +0200 Subject: [PATCH 20/38] reduce diff (remove some PEP-7 changes) --- Modules/_cursesmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index e6c7bc8277a415..75838e3c51eeab 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -259,8 +259,7 @@ PyCursesCheckERR(PyObject *module, int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; - } - else { + } else { _cursesmodule_state *st = get_cursesmodule_state(module); if (fname == NULL) { PyErr_SetString(st->PyCursesError, catchall_ERR); From 9ff69e426e0f087858d23411e51e5fc857ef9a8f 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, 28 Sep 2024 17:33:19 +0200 Subject: [PATCH 21/38] Revert "Finalize multi-phase initialization for `curses`." This reverts commit 4c207d34896625650544f01131646846139e61cb. --- Modules/_cursesmodule.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 75838e3c51eeab..93ab886bfb533e 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -5133,5 +5133,23 @@ static struct PyModuleDef _cursesmodule = { PyMODINIT_FUNC PyInit__curses(void) { - return PyModuleDef_Init(&_cursesmodule); + // create the module + PyObject *mod = PyModule_Create(&_cursesmodule); + if (mod == NULL) { + goto error; + } +#ifdef Py_GIL_DISABLED + if (PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED) < 0) { + goto error; + } +#endif + // populate the module + if (_cursesmodule_exec(mod) < 0) { + goto error; + } + return mod; + +error: + Py_XDECREF(mod); + return NULL; } From 13bd86876b3d35cbf16b1f09f06f8e21bf0e5dc7 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, 28 Sep 2024 17:33:54 +0200 Subject: [PATCH 22/38] Revert "Introduce module's state and logic." This reverts commit 3148d86f6058beb15cac8ea35974b9e50ad58f5d. --- Modules/_cursesmodule.c | 101 +++++++------------------------ Modules/clinic/_cursesmodule.c.h | 10 +-- 2 files changed, 28 insertions(+), 83 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 93ab886bfb533e..854e4f8ffa3b65 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -159,32 +159,11 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ -typedef struct _cursesmodule_state { - PyObject *PyCursesError; - PyTypeObject *PyCursesWindow_Type; -} _cursesmodule_state; - -static inline _cursesmodule_state * -get_cursesmodule_state(PyObject *module) -{ - void *state = PyModule_GetState(module); - assert(state != NULL); - return (_cursesmodule_state *)state; -} - -static inline _cursesmodule_state * -get_cursesmodule_state_by_cls(PyTypeObject *cls) -{ - void *state = PyType_GetModuleState(cls); - assert(state != NULL); - return (_cursesmodule_state *)state; -} - /*[clinic input] module _curses -class _curses.window "PyCursesWindowObject *" "clinic_state()->PyCursesWindow_Type" +class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=83369be6e20ef0da]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/ /* Tells whether setupterm() has been called to initialise terminfo. */ static int curses_setupterm_called = FALSE; @@ -2151,8 +2130,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) /*[clinic input] _curses.window.overlay - destwin: object(type="PyCursesWindowObject *",\ - subclass_of="clinic_state()->PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") [ sminrow: int @@ -2181,7 +2159,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, PyCursesWindowObject *destwin, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=82bb2c4cb443ca58 input=a1fa2bb9dd91ab1d]*/ +/*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984]*/ { int rtn; @@ -2199,8 +2177,7 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, /*[clinic input] _curses.window.overwrite - destwin: object(type="PyCursesWindowObject *",\ - subclass_of="clinic_state()->PyCursesWindow_Type") + destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") [ sminrow: int @@ -2230,7 +2207,7 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, int group_right_1, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol) -/*[clinic end generated code: output=12ae007d1681be28 input=c5b2388e80206a47]*/ +/*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/ { int rtn; @@ -2578,9 +2555,7 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value, void *P return 0; } -#define clinic_state() (get_cursesmodule_state_by_cls(Py_TYPE(self))) #include "clinic/_cursesmodule.c.h" -#undef clinic_state static PyMethodDef PyCursesWindow_Methods[] = { _CURSES_WINDOW_ADDCH_METHODDEF @@ -4753,7 +4728,7 @@ _curses_has_extended_color_support_impl(PyObject *module) /* List of functions defined in the module */ -static PyMethodDef _cursesmodule_methods[] = { +static PyMethodDef PyCurses_methods[] = { _CURSES_BAUDRATE_METHODDEF _CURSES_BEEP_METHODDEF _CURSES_CAN_CHANGE_COLOR_METHODDEF @@ -4838,7 +4813,20 @@ static PyMethodDef _cursesmodule_methods[] = { {NULL, NULL} /* sentinel */ }; -/* Module initialization and cleanup functions. */ +/* Initialization function for the module */ + + +static struct PyModuleDef _cursesmodule = { + PyModuleDef_HEAD_INIT, + "_curses", + NULL, + -1, + PyCurses_methods, + NULL, + NULL, + NULL, + NULL +}; static void _curses_capi_destructor(PyObject *op) @@ -4849,7 +4837,7 @@ _curses_capi_destructor(PyObject *op) } static int -_cursesmodule_exec(PyObject *module) +cursesmodule_exec(PyObject *module) { _cursesmodule_state *st = get_cursesmodule_state(module); /* Initialize object type */ @@ -5087,49 +5075,6 @@ _cursesmodule_exec(PyObject *module) return 0; } -static int -_cursesmodule_traverse(PyObject *mod, visitproc visit, void *arg) -{ - _cursesmodule_state *st = get_cursesmodule_state(mod); - Py_VISIT(st->PyCursesError); - Py_VISIT(st->PyCursesWindow_Type); - return 0; -} - -static int -_cursesmodule_clear(PyObject *mod) -{ - _cursesmodule_state *st = get_cursesmodule_state(mod); - Py_CLEAR(st->PyCursesError); - Py_CLEAR(st->PyCursesWindow_Type); - return 0; -} - -static void -_cursesmodule_free(void *mod) -{ - (void)_cursesmodule_clear((PyObject *)mod); -} - -static PyModuleDef_Slot _cursesmodule_slots[] = { - {Py_mod_exec, _cursesmodule_exec}, - {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED}, - {Py_mod_gil, Py_MOD_GIL_NOT_USED}, - {0, NULL} -}; - -static struct PyModuleDef _cursesmodule = { - PyModuleDef_HEAD_INIT, - .m_name = "_curses", - .m_doc = NULL, - .m_size = sizeof(_cursesmodule_state), - .m_methods = _cursesmodule_methods, - .m_slots = _cursesmodule_slots, - .m_traverse = _cursesmodule_traverse, - .m_clear = _cursesmodule_clear, - .m_free = _cursesmodule_free -}; - PyMODINIT_FUNC PyInit__curses(void) { @@ -5144,7 +5089,7 @@ PyInit__curses(void) } #endif // populate the module - if (_cursesmodule_exec(mod) < 0) { + if (cursesmodule_exec(mod) < 0) { goto error; } return mod; diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 9ac2e7d55f8ef4..f7e0aaf7b23649 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -1389,12 +1389,12 @@ _curses_window_overlay(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overlay", clinic_state()->PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overlay", &PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -1448,12 +1448,12 @@ _curses_window_overwrite(PyCursesWindowObject *self, PyObject *args) switch (PyTuple_GET_SIZE(args)) { case 1: - if (!PyArg_ParseTuple(args, "O!:overwrite", clinic_state()->PyCursesWindow_Type, &destwin)) { + if (!PyArg_ParseTuple(args, "O!:overwrite", &PyCursesWindow_Type, &destwin)) { goto exit; } break; case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", clinic_state()->PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { goto exit; } group_right_1 = 1; @@ -4318,4 +4318,4 @@ _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=8463fe82c8906325 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=96887782374f070a input=a9049054013a1b77]*/ From f32dee9ca27a852d883c7276cfe46fdf948cfeb1 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, 28 Sep 2024 17:39:28 +0200 Subject: [PATCH 23/38] Revert "Make `PyCursesWindow_Type` a heap type." This reverts commit e3e1131fdde6ffe62206f7fcb671cb1a342ecad3. --- Modules/_cursesmodule.c | 68 +++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 854e4f8ffa3b65..3cfbc44ffb723f 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -600,6 +600,10 @@ static int func_PyCursesInitialisedColor(void) The Window Object ******************************************************************************/ +/* Definition of the window type */ + +PyTypeObject PyCursesWindow_Type; + /* Function prototype macros for Window object X - function name @@ -729,7 +733,7 @@ Window_TwoArgNoReturnFunction(wresize, int, "ii;lines,columns") /* Allocation and deallocation of Window Objects */ static PyObject * -PyCursesWindow_New(_cursesmodule_state *st, WINDOW *win, const char *encoding) +PyCursesWindow_New(WINDOW *win, const char *encoding) { PyCursesWindowObject *wo; @@ -751,8 +755,7 @@ PyCursesWindow_New(_cursesmodule_state *st, WINDOW *win, const char *encoding) encoding = "utf-8"; } - PyTypeObject *type = st->PyCursesWindow_Type; - wo = (PyCursesWindowObject *)type->tp_alloc(type, 0); + wo = PyObject_New(PyCursesWindowObject, &PyCursesWindow_Type); if (wo == NULL) return NULL; wo->win = win; wo->encoding = _PyMem_Strdup(encoding); @@ -767,7 +770,6 @@ PyCursesWindow_New(_cursesmodule_state *st, WINDOW *win, const char *encoding) static void PyCursesWindow_Dealloc(PyCursesWindowObject *wo) { - PyTypeObject *tp = Py_TYPE(wo); if (wo->win != stdscr && wo->win != NULL) { // silently ignore errors in delwin(3) (void)delwin(wo->win); @@ -775,8 +777,7 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) if (wo->encoding != NULL) { PyMem_Free(wo->encoding); } - tp->tp_free(wo); - Py_DECREF(tp); + PyObject_Free(wo); } /* Addch, Addstr, Addnstr */ @@ -2651,22 +2652,42 @@ static PyGetSetDef PyCursesWindow_getsets[] = { {NULL, NULL, NULL, NULL } /* sentinel */ }; -static PyType_Slot PyCursesWindow_Type_slots[] = { - {Py_tp_dealloc, PyCursesWindow_Dealloc}, - {Py_tp_methods, PyCursesWindow_Methods}, - {Py_tp_getset, PyCursesWindow_getsets}, - {0, NULL} -}; +/* -------------------------------------------------------*/ -static PyType_Spec PyCursesWindow_Type_spec = { - .name = "_curses.window", - .basicsize = sizeof(PyCursesWindowObject), - .flags = Py_TPFLAGS_DEFAULT, - .slots = PyCursesWindow_Type_slots +PyTypeObject PyCursesWindow_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "_curses.window", /*tp_name*/ + sizeof(PyCursesWindowObject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)PyCursesWindow_Dealloc, /*tp_dealloc*/ + 0, /*tp_vectorcall_offset*/ + (getattrfunc)0, /*tp_getattr*/ + (setattrfunc)0, /*tp_setattr*/ + 0, /*tp_as_async*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT, /*tp_flags*/ + 0, /*tp_doc*/ + 0, /*tp_traverse*/ + 0, /*tp_clear*/ + 0, /*tp_richcompare*/ + 0, /*tp_weaklistoffset*/ + 0, /*tp_iter*/ + 0, /*tp_iternext*/ + PyCursesWindow_Methods, /*tp_methods*/ + 0, /* tp_members */ + PyCursesWindow_getsets, /* tp_getset */ }; -/* -------------------------------------------------------*/ - /* Function Body Macros - They are ugly but very, very useful. ;-) X - function name @@ -4841,9 +4862,10 @@ cursesmodule_exec(PyObject *module) { _cursesmodule_state *st = get_cursesmodule_state(module); /* Initialize object type */ - st->PyCursesWindow_Type = (PyTypeObject *)PyType_FromModuleAndSpec( - module, &PyCursesWindow_Type_spec, NULL); - if (PyModule_AddType(module, st->PyCursesWindow_Type) < 0) { + if (PyType_Ready(&PyCursesWindow_Type) < 0) { + return -1; + } + if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { return -1; } @@ -4859,7 +4881,7 @@ cursesmodule_exec(PyObject *module) return -1; } /* Initialize the C API pointer array */ - PyCurses_API[0] = (void *)Py_NewRef(st->PyCursesWindow_Type); + PyCurses_API[0] = (void *)Py_NewRef(&PyCursesWindow_Type); PyCurses_API[1] = (void *)func_PyCursesSetupTermCalled; PyCurses_API[2] = (void *)func_PyCursesInitialised; PyCurses_API[3] = (void *)func_PyCursesInitialisedColor; From fd388508befbfc8d88b82abcb13ad563300c390a 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, 28 Sep 2024 17:49:48 +0200 Subject: [PATCH 24/38] address Victor's review --- Modules/_cursesmodule.c | 445 ++++++++++++++++++---------------------- 1 file changed, 197 insertions(+), 248 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 3cfbc44ffb723f..c2021ed0089fe2 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -159,6 +159,20 @@ typedef chtype attr_t; /* No attr_t type is available */ #define _CURSES_PAIR_CONTENT_FUNC pair_content #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ +typedef struct _cursesmodule_state { + PyObject *PyCursesError; + PyTypeObject *PyCursesWindow_Type; +} _cursesmodule_state; + +// For now, we keep a global state variable to prepare for PEP 489. +static _cursesmodule_state curses_global_state; + +static inline _cursesmodule_state * +get_cursesmodule_state(PyObject *Py_UNUSED(module)) +{ + return &curses_global_state; +} + /*[clinic input] module _curses class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" @@ -176,54 +190,33 @@ static int curses_start_color_called = FALSE; static const char *curses_screen_encoding = NULL; -/* - * Macro to check that FUNC_NAME has been called by testing - * the CALLED boolean. If an error occurs, a PyCursesError - * is raised. - * - * Since these macros can be called in functions that do not - * have a direct access to the module's state, the exception - * type is imported on demand as well. - */ -#define _PyCursesCheckFunction(CALLED, FUNC_NAME) \ +/* Utility Macros */ +#define PyCursesSetupTermCalled \ do { \ - if ((CALLED) != TRUE) { \ - PyObject *exc = _PyImport_GetModuleAttrString("_curses", \ - "error"); \ - if (exc == NULL) { \ - return 0; \ - } \ - PyErr_SetString(exc, "must call " # FUNC_NAME "() first"); \ - Py_DECREF(exc); \ + if (curses_setupterm_called != TRUE) { \ + PyErr_SetString(curses_global_state.PyCursesError, \ + "must call (at least) setupterm() first"); \ return 0; \ } \ } while (0) -/* - * Macro to check that FUNC_NAME has been called by testing - * the CALLED boolean. If an error occurs, a PyCursesError - * is raised. The exception type is obtained from the module - * state. - */ -#define _PyCursesStatefulCheckFunction(CALLED, FUNC_NAME, MODULE) \ - do { \ - if ((CALLED) != TRUE) { \ - _cursesmodule_state *st = get_cursesmodule_state((MODULE)); \ - PyErr_SetString(st->PyCursesError, \ - "must call " # FUNC_NAME "() first"); \ - return 0; \ - } \ +#define PyCursesInitialised \ + do { \ + if (curses_initscr_called != TRUE) { \ + PyErr_SetString(curses_global_state.PyCursesError, \ + "must call initscr() first"); \ + return 0; \ + } \ } while (0) -#define PyCursesStatefulSetupTermCalled(MODULE) \ - _PyCursesStatefulCheckFunction(curses_setupterm_called, \ - "setupterm", (MODULE)) -#define PyCursesStatefulInitialised(MODULE) \ - _PyCursesStatefulCheckFunction(curses_initscr_called, \ - "initscr", (MODULE)) -#define PyCursesStatefulInitialisedColor(MODULE) \ - _PyCursesStatefulCheckFunction(curses_start_color_called, \ - "start_color", (MODULE)) +#define PyCursesInitialisedColor \ + do { \ + if (curses_start_color_called != TRUE) { \ + PyErr_SetString(curses_global_state.PyCursesError, \ + "must call start_color() first"); \ + return 0; \ + } \ + } while (0) /* Utility Functions */ @@ -234,28 +227,20 @@ static const char *curses_screen_encoding = NULL; */ static PyObject * -PyCursesCheckERR(PyObject *module, int code, const char *fname) +PyCursesCheckERR(int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *st = get_cursesmodule_state(module); if (fname == NULL) { - PyErr_SetString(st->PyCursesError, catchall_ERR); + PyErr_SetString(curses_global_state.PyCursesError, catchall_ERR); } else { - PyErr_Format(st->PyCursesError, "%s() returned ERR", fname); + PyErr_Format(curses_global_state.PyCursesError, "%s() returned ERR", fname); } return NULL; } } -static inline PyObject * -PyCursesCheckERR_FromSelf(PyCursesWindowObject *self, int code, const char *fname) -{ - PyObject *module = PyType_GetModule(Py_TYPE(self)); - return PyCursesCheckERR(module, code, fname); -} - /* Convert an object to a byte (an integer of type chtype): - int @@ -580,19 +565,19 @@ class component_converter(CConverter): static int func_PyCursesSetupTermCalled(void) { - _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); + PyCursesSetupTermCalled; return 1; } static int func_PyCursesInitialised(void) { - _PyCursesCheckFunction(curses_initscr_called, "initscr"); + PyCursesInitialised; return 1; } static int func_PyCursesInitialisedColor(void) { - _PyCursesCheckFunction(curses_start_color_called, "start_color"); + PyCursesInitialisedColor; return 1; } @@ -615,70 +600,50 @@ PyTypeObject PyCursesWindow_Type; #define Window_NoArgNoReturnFunction(X) \ static PyObject *PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { \ - int rtn = X(self->win); \ - return PyCursesCheckERR_FromSelf(self, rtn, # X); \ - } + { return PyCursesCheckERR(X(self->win), # X); } -#define Window_NoArgTrueFalseFunction(X) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { \ - return PyBool_FromLong(X(self->win)); \ - } +#define Window_NoArgTrueFalseFunction(X) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ + { \ + return PyBool_FromLong(X(self->win)); } #define Window_NoArgNoReturnVoidFunction(X) \ static PyObject * PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ { \ - X(self->win); \ - Py_RETURN_NONE; \ - } - -#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { \ - TYPE arg1, arg2; \ - X(self->win,arg1,arg2); \ - return Py_BuildValue(ERGSTR, arg1, arg2); \ - } - -#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ - return NULL; \ - } \ - X(self->win,arg1); \ - Py_RETURN_NONE; \ - } - -#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) { \ - return NULL; \ - } \ - int rtn = X(self->win, arg1); \ - return PyCursesCheckERR_FromSelf(self, rtn, # X); \ - } - -#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ - static PyObject * PyCursesWindow_ ## X \ - (PyCursesWindowObject *self, PyObject *args) \ - { \ - TYPE arg1, arg2; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) { \ - return NULL; \ - } \ - int rtn = X(self->win, arg1, arg2); \ - return PyCursesCheckERR_FromSelf(self, rtn, # X); \ - } + X(self->win); Py_RETURN_NONE; } + +#define Window_NoArg2TupleReturnFunction(X, TYPE, ERGSTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ + { \ + TYPE arg1, arg2; \ + X(self->win,arg1,arg2); return Py_BuildValue(ERGSTR, arg1, arg2); } + +#define Window_OneArgNoReturnVoidFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args, PARSESTR, &arg1)) return NULL; \ + X(self->win,arg1); Py_RETURN_NONE; } + +#define Window_OneArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1; \ + if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \ + return PyCursesCheckERR(X(self->win, arg1), # X); } + +#define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ + static PyObject * PyCursesWindow_ ## X \ + (PyCursesWindowObject *self, PyObject *args) \ + { \ + TYPE arg1, arg2; \ + if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \ + return PyCursesCheckERR(X(self->win, arg1, arg2), # X); } /* ------------- WINDOW routines --------------- */ @@ -852,7 +817,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, else { return NULL; } - return PyCursesCheckERR_FromSelf(self, rtn, funcname); + return PyCursesCheckERR(rtn, funcname); } /*[clinic input] @@ -932,7 +897,7 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR_FromSelf(self, rtn, funcname); + return PyCursesCheckERR(rtn, funcname); } /*[clinic input] @@ -1015,7 +980,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR_FromSelf(self, rtn, funcname); + return PyCursesCheckERR(rtn, funcname); } /*[clinic input] @@ -1039,7 +1004,7 @@ _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; - return PyCursesCheckERR_FromSelf(self, wbkgd(self->win, bkgd | attr), "bkgd"); + return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); } /*[clinic input] @@ -1055,7 +1020,7 @@ static PyObject * _curses_window_attroff_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ { - return PyCursesCheckERR_FromSelf(self, wattroff(self->win, (attr_t)attr), "attroff"); + return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff"); } /*[clinic input] @@ -1071,7 +1036,7 @@ static PyObject * _curses_window_attron_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/ { - return PyCursesCheckERR_FromSelf(self, wattron(self->win, (attr_t)attr), "attron"); + return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron"); } /*[clinic input] @@ -1087,7 +1052,7 @@ static PyObject * _curses_window_attrset_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ { - return PyCursesCheckERR_FromSelf(self, wattrset(self->win, (attr_t)attr), "attrset"); + return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset"); } /*[clinic input] @@ -1113,7 +1078,7 @@ _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, return NULL; wbkgdset(self->win, bkgd | attr); - return PyCursesCheckERR_FromSelf(self, 0, "bkgdset"); + return PyCursesCheckERR(0, "bkgdset"); } /*[clinic input] @@ -1313,7 +1278,7 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) rtn = wchgat(self->win,num,attr,color,NULL); touchline(self->win,y,1); } - return PyCursesCheckERR_FromSelf(self, rtn, "chgat"); + return PyCursesCheckERR(rtn, "chgat"); } #endif @@ -1337,10 +1302,10 @@ _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ { if (!group_right_1) { - return PyCursesCheckERR_FromSelf(self, wdelch(self->win), "wdelch"); + return PyCursesCheckERR(wdelch(self->win), "wdelch"); } else { - return PyCursesCheckERR_FromSelf(self, py_mvwdelch(self->win, y, x), "mvwdelch"); + return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch"); } } @@ -1376,13 +1341,11 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(curses_global_state.PyCursesError, catchall_NULL); return NULL; } - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - return PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(win, NULL); } /*[clinic input] @@ -1410,15 +1373,11 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR_FromSelf(self, - pechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), "echochar"); } else #endif - return PyCursesCheckERR_FromSelf(self, - wechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), "echochar"); } #ifdef NCURSES_MOUSE_VERSION @@ -1530,8 +1489,7 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); if (!PyErr_Occurred()) { - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, "no input"); + PyErr_SetString(curses_global_state.PyCursesError, "no input"); } return NULL; } else if (rtn <= 255) { @@ -1590,8 +1548,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, "no input"); + PyErr_SetString(curses_global_state.PyCursesError, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -1715,10 +1672,10 @@ _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) { - return PyCursesCheckERR_FromSelf(self, ERR, "wmove"); + return PyCursesCheckERR(ERR, "wmove"); } } - return PyCursesCheckERR_FromSelf(self, whline(self->win, ch_ | (attr_t)attr, n), "hline"); + return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline"); } /*[clinic input] @@ -1765,7 +1722,7 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); } - return PyCursesCheckERR_FromSelf(self, rtn, "insch"); + return PyCursesCheckERR(rtn, "insch"); } /*[clinic input] @@ -1942,7 +1899,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR_FromSelf(self, rtn, funcname); + return PyCursesCheckERR(rtn, funcname); } /*[clinic input] @@ -2027,7 +1984,7 @@ _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR_FromSelf(self, rtn, funcname); + return PyCursesCheckERR(rtn, funcname); } /*[clinic input] @@ -2104,8 +2061,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, + PyErr_SetString(curses_global_state.PyCursesError, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2114,7 +2070,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) rtn = pnoutrefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR_FromSelf(self, rtn, "pnoutrefresh"); + return PyCursesCheckERR(rtn, "pnoutrefresh"); } if (group_right_1) { PyErr_SetString(PyExc_TypeError, @@ -2125,7 +2081,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) Py_BEGIN_ALLOW_THREADS rtn = wnoutrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR_FromSelf(self, rtn, "wnoutrefresh"); + return PyCursesCheckERR(rtn, "wnoutrefresh"); } /*[clinic input] @@ -2167,11 +2123,11 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, TRUE); - return PyCursesCheckERR_FromSelf(self, rtn, "copywin"); + return PyCursesCheckERR(rtn, "copywin"); } else { rtn = overlay(self->win, destwin->win); - return PyCursesCheckERR_FromSelf(self, rtn, "overlay"); + return PyCursesCheckERR(rtn, "overlay"); } } @@ -2215,11 +2171,11 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, FALSE); - return PyCursesCheckERR_FromSelf(self, rtn, "copywin"); + return PyCursesCheckERR(rtn, "copywin"); } else { rtn = overwrite(self->win, destwin->win); - return PyCursesCheckERR_FromSelf(self, rtn, "overwrite"); + return PyCursesCheckERR(rtn, "overwrite"); } } @@ -2248,7 +2204,7 @@ _curses_window_putwin(PyCursesWindowObject *self, PyObject *file) return PyErr_SetFromErrno(PyExc_OSError); if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) goto exit; - res = PyCursesCheckERR_FromSelf(self, putwin(self->win, fp), "putwin"); + res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); if (res == NULL) goto exit; fseek(fp, 0, 0); @@ -2287,7 +2243,7 @@ static PyObject * _curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) /*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ { - return PyCursesCheckERR_FromSelf(self, wredrawln(self->win,beg,num), "redrawln"); + return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); } /*[clinic input] @@ -2329,8 +2285,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, + PyErr_SetString(curses_global_state.PyCursesError, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2338,7 +2293,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, rtn = prefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR_FromSelf(self, rtn, "prefresh"); + return PyCursesCheckERR(rtn, "prefresh"); } #endif if (group_right_1) { @@ -2349,7 +2304,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, Py_BEGIN_ALLOW_THREADS rtn = wrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR_FromSelf(self, rtn, "prefresh"); + return PyCursesCheckERR(rtn, "prefresh"); } /*[clinic input] @@ -2371,7 +2326,7 @@ _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, int bottom) /*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ { - return PyCursesCheckERR_FromSelf(self, wsetscrreg(self->win, top, bottom), "wsetscrreg"); + return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg"); } /*[clinic input] @@ -2412,13 +2367,11 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(curses_global_state.PyCursesError, catchall_NULL); return NULL; } - _cursesmodule_state *st = get_cursesmodule_state_by_cls(Py_TYPE(self)); - return PyCursesWindow_New(st, win, self->encoding); + return PyCursesWindow_New(win, self->encoding); } /*[clinic input] @@ -2441,10 +2394,10 @@ _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/ { if (!group_right_1) { - return PyCursesCheckERR_FromSelf(self, scroll(self->win), "scroll"); + return PyCursesCheckERR(scroll(self->win), "scroll"); } else { - return PyCursesCheckERR_FromSelf(self, wscrl(self->win, lines), "scroll"); + return PyCursesCheckERR(wscrl(self->win, lines), "scroll"); } } @@ -2470,10 +2423,10 @@ _curses_window_touchline_impl(PyCursesWindowObject *self, int start, /*[clinic end generated code: output=65d05b3f7438c61d input=a98aa4f79b6be845]*/ { if (!group_right_1) { - return PyCursesCheckERR_FromSelf(self, touchline(self->win, start, count), "touchline"); + return PyCursesCheckERR(touchline(self->win, start, count), "touchline"); } else { - return PyCursesCheckERR_FromSelf(self, wtouchln(self->win, start, count, changed), "touchline"); + return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline"); } } @@ -2513,9 +2466,9 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) - return PyCursesCheckERR_FromSelf(self, ERR, "wmove"); + return PyCursesCheckERR(ERR, "wmove"); } - return PyCursesCheckERR_FromSelf(self, wvline(self->win, ch_ | (attr_t)attr, n), "vline"); + return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline"); } static PyObject * @@ -2698,38 +2651,38 @@ PyTypeObject PyCursesWindow_Type = { #define NoArgNoReturnFunctionBody(X) \ { \ - PyCursesStatefulInitialised(module); \ - return PyCursesCheckERR(module, X(), # X); \ + PyCursesInitialised; \ + return PyCursesCheckERR(X(), # X); \ } #define NoArgOrFlagNoReturnFunctionBody(X, flag) \ { \ - PyCursesStatefulInitialised(module); \ + PyCursesInitialised; \ int rtn = (flag) ? X() : no ## X(); \ - return PyCursesCheckERR(module, rtn, # X); \ + return PyCursesCheckERR(rtn, # X); \ } #define NoArgReturnIntFunctionBody(X) \ { \ - PyCursesStatefulInitialised(module); \ + PyCursesInitialised; \ return PyLong_FromLong((long) X()); \ } #define NoArgReturnStringFunctionBody(X) \ { \ - PyCursesStatefulInitialised(module); \ + PyCursesInitialised; \ return PyBytes_FromString(X()); \ } #define NoArgTrueFalseFunctionBody(X) \ { \ - PyCursesStatefulInitialised(module); \ + PyCursesInitialised; \ return PyBool_FromLong(X()); \ } #define NoArgNoReturnVoidFunctionBody(X) \ { \ - PyCursesStatefulInitialised(module); \ + PyCursesInitialised; \ X(); \ Py_RETURN_NONE; \ } @@ -2828,8 +2781,8 @@ _curses_color_content_impl(PyObject *module, int color_number) { _CURSES_COLOR_VAL_TYPE r,g,b; - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); @@ -2858,8 +2811,8 @@ static PyObject * _curses_color_pair_impl(PyObject *module, int pair_number) /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ { - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; return PyLong_FromLong(COLOR_PAIR(pair_number)); } @@ -2885,10 +2838,10 @@ _curses_curs_set_impl(PyObject *module, int visibility) { int erg; - PyCursesStatefulInitialised(module); + PyCursesInitialised; erg = curs_set(visibility); - if (erg == ERR) return PyCursesCheckERR(module, erg, "curs_set"); + if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); return PyLong_FromLong((long) erg); } @@ -2937,9 +2890,9 @@ static PyObject * _curses_delay_output_impl(PyObject *module, int ms) /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, delay_output(ms), "delay_output"); + return PyCursesCheckERR(delay_output(ms), "delay_output"); } /*[clinic input] @@ -2993,7 +2946,7 @@ _curses_erasechar_impl(PyObject *module) { char ch; - PyCursesStatefulInitialised(module); + PyCursesInitialised; ch = erasechar(); @@ -3043,7 +2996,7 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - PyCursesStatefulInitialised(module); + PyCursesInitialised; getsyx(y, x); @@ -3068,7 +3021,7 @@ _curses_getmouse_impl(PyObject *module) int rtn; MEVENT event; - PyCursesStatefulInitialised(module); + PyCursesInitialised; rtn = getmouse( &event ); if (rtn == ERR) { @@ -3104,14 +3057,14 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, { MEVENT event; - PyCursesStatefulInitialised(module); + PyCursesInitialised; event.id = id; event.x = x; event.y = y; event.z = z; event.bstate = bstate; - return PyCursesCheckERR(module, ungetmouse(&event), "ungetmouse"); + return PyCursesCheckERR(ungetmouse(&event), "ungetmouse"); } #endif @@ -3137,7 +3090,7 @@ _curses_getwin(PyObject *module, PyObject *file) WINDOW *win; PyObject *res = NULL; - PyCursesStatefulInitialised(module); + PyCursesInitialised; fp = tmpfile(); if (fp == NULL) @@ -3171,8 +3124,7 @@ _curses_getwin(PyObject *module, PyObject *file) PyErr_SetString(st->PyCursesError, catchall_NULL); goto error; } - _cursesmodule_state *st = get_cursesmodule_state(module); - res = PyCursesWindow_New(st, win, NULL); + res = PyCursesWindow_New(win, NULL); error: fclose(fp); @@ -3195,9 +3147,9 @@ static PyObject * _curses_halfdelay_impl(PyObject *module, unsigned char tenths) /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, halfdelay(tenths), "halfdelay"); + return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); } /*[clinic input] @@ -3248,7 +3200,7 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; return PyBool_FromLong(has_key(key)); } @@ -3279,11 +3231,10 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, short b) /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ { - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; - return PyCursesCheckERR(module, - _CURSES_INIT_COLOR_FUNC(color_number, r, g, b), + return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); } @@ -3308,8 +3259,8 @@ static PyObject * _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ { - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3344,8 +3295,7 @@ _curses_initscr_impl(PyObject *module) if (curses_initscr_called) { wrefresh(stdscr); - _cursesmodule_state *st = get_cursesmodule_state(module); - return PyCursesWindow_New(st, stdscr, NULL); + return PyCursesWindow_New(stdscr, NULL); } win = initscr(); @@ -3448,8 +3398,7 @@ _curses_initscr_impl(PyObject *module) SetDictInt("COLS", COLS); #undef SetDictInt - _cursesmodule_state *st = get_cursesmodule_state(module); - PyCursesWindowObject *winobj = (PyCursesWindowObject *)PyCursesWindow_New(st, win, NULL); + PyCursesWindowObject *winobj = (PyCursesWindowObject *)PyCursesWindow_New(win, NULL); if (winobj == NULL) { return NULL; } @@ -3554,7 +3503,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - return PyCursesCheckERR(module, set_escdelay(ms), "set_escdelay"); + return PyCursesCheckERR(set_escdelay(ms), "set_escdelay"); } /*[clinic input] @@ -3593,7 +3542,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - return PyCursesCheckERR(module, set_tabsize(size), "set_tabsize"); + return PyCursesCheckERR(set_tabsize(size), "set_tabsize"); } #endif @@ -3609,9 +3558,9 @@ static PyObject * _curses_intrflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, intrflush(NULL, flag), "intrflush"); + return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); } /*[clinic input] @@ -3642,7 +3591,7 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; return PyBool_FromLong(is_term_resized(nlines, ncols)); } @@ -3664,7 +3613,7 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); @@ -3722,9 +3671,9 @@ static PyObject * _curses_meta_impl(PyObject *module, int yes) /*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, meta(stdscr, yes), "meta"); + return PyCursesCheckERR(meta(stdscr, yes), "meta"); } #ifdef NCURSES_MOUSE_VERSION @@ -3746,9 +3695,9 @@ static PyObject * _curses_mouseinterval_impl(PyObject *module, int interval) /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, mouseinterval(interval), "mouseinterval"); + return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); } /*[clinic input] @@ -3771,7 +3720,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - PyCursesStatefulInitialised(module); + PyCursesInitialised; availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); @@ -3792,7 +3741,7 @@ static int _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=5f292a6a724491bd input=c6d6e01f2f1df9f7]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; return napms(ms); } @@ -3816,7 +3765,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) { WINDOW *win; - PyCursesStatefulInitialised(module); + PyCursesInitialised; win = newpad(nlines, ncols); @@ -3826,8 +3775,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) return NULL; } - _cursesmodule_state *st = get_cursesmodule_state(module); - return PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(win, NULL); } /*[clinic input] @@ -3858,7 +3806,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, { WINDOW *win; - PyCursesStatefulInitialised(module); + PyCursesInitialised; win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { @@ -3867,8 +3815,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, return NULL; } - _cursesmodule_state *st = get_cursesmodule_state(module); - return PyCursesWindow_New(st, win, NULL); + return PyCursesWindow_New(win, NULL); } /*[clinic input] @@ -3972,8 +3919,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number) { _CURSES_COLOR_NUM_TYPE f, b; - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -4007,8 +3954,8 @@ static PyObject * _curses_pair_number_impl(PyObject *module, int attr) /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; return PyLong_FromLong(PAIR_NUMBER(attr)); } @@ -4028,7 +3975,7 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - return PyCursesCheckERR(module, putp(string), "putp"); + return PyCursesCheckERR(putp(string), "putp"); } /*[clinic input] @@ -4048,7 +3995,7 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (flag) { qiflush(); @@ -4203,9 +4150,9 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesStatefulInitialised(module); + PyCursesInitialised; - result = PyCursesCheckERR(module, resizeterm(nlines, ncols), "resizeterm"); + result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4242,9 +4189,9 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesStatefulInitialised(module); + PyCursesInitialised; - result = PyCursesCheckERR(module, resize_term(nlines, ncols), "resize_term"); + result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4285,7 +4232,7 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; setsyx(y,x); @@ -4310,7 +4257,7 @@ static PyObject * _curses_start_color_impl(PyObject *module) /*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (start_color() == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); @@ -4383,7 +4330,7 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - PyCursesStatefulSetupTermCalled(module); + PyCursesSetupTermCalled; return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); } @@ -4405,7 +4352,7 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - PyCursesStatefulSetupTermCalled(module); + PyCursesSetupTermCalled; return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); } @@ -4427,7 +4374,7 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - PyCursesStatefulSetupTermCalled(module); + PyCursesSetupTermCalled; capname = tigetstr( (char *)capname ); if (capname == NULL || capname == (char*) -1) { @@ -4462,7 +4409,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, { char* result = NULL; - PyCursesStatefulSetupTermCalled(module); + PyCursesSetupTermCalled; result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { @@ -4491,9 +4438,9 @@ static PyObject * _curses_typeahead_impl(PyObject *module, int fd) /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - PyCursesStatefulInitialised(module); + PyCursesInitialised; - return PyCursesCheckERR(module, typeahead( fd ), "typeahead"); + return PyCursesCheckERR(typeahead( fd ), "typeahead"); } #endif @@ -4515,7 +4462,7 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4538,12 +4485,12 @@ _curses_ungetch(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyCursesCheckERR(module, ungetch(ch_), "ungetch"); + return PyCursesCheckERR(ungetch(ch_), "ungetch"); } #ifdef HAVE_NCURSESW @@ -4609,11 +4556,11 @@ _curses_unget_wch(PyObject *module, PyObject *ch) { wchar_t wch; - PyCursesStatefulInitialised(module); + PyCursesInitialised; if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; - return PyCursesCheckERR(module, unget_wch(wch), "unget_wch"); + return PyCursesCheckERR(unget_wch(wch), "unget_wch"); } #endif @@ -4661,8 +4608,8 @@ _curses_use_default_colors_impl(PyObject *module) { int code; - PyCursesStatefulInitialised(module); - PyCursesStatefulInitialisedColor(module); + PyCursesInitialised; + PyCursesInitialisedColor; code = use_default_colors(); if (code != ERR) { @@ -4868,6 +4815,7 @@ cursesmodule_exec(PyObject *module) if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { return -1; } + st->PyCursesWindow_Type = &PyCursesWindow_Type; /* Add some symbolic constants to the module */ PyObject *module_dict = PyModule_GetDict(module); @@ -4906,6 +4854,7 @@ cursesmodule_exec(PyObject *module) return -1; } rc = PyDict_SetItemString(module_dict, "error", st->PyCursesError); + Py_DECREF(st->PyCursesError); if (rc < 0) { return -1; } From e70175cfbaf5abe394c974b722d50d9d0c303f67 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, 28 Sep 2024 18:01:22 +0200 Subject: [PATCH 25/38] Revert "Remove redundant cast to `PyObject *`." This reverts commit 228348c812a78e723d07981be36ea26d8f66d597. --- Modules/_cursesmodule.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index c2021ed0089fe2..8fc09ba9a5ece0 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1345,7 +1345,7 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, return NULL; } - return PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(win, NULL); } /*[clinic input] @@ -2371,7 +2371,7 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, return NULL; } - return PyCursesWindow_New(win, self->encoding); + return (PyObject *)PyCursesWindow_New(win, self->encoding); } /*[clinic input] @@ -3295,7 +3295,7 @@ _curses_initscr_impl(PyObject *module) if (curses_initscr_called) { wrefresh(stdscr); - return PyCursesWindow_New(stdscr, NULL); + return (PyObject *)PyCursesWindow_New(stdscr, NULL); } win = initscr(); @@ -3775,7 +3775,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) return NULL; } - return PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(win, NULL); } /*[clinic input] @@ -3815,7 +3815,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, return NULL; } - return PyCursesWindow_New(win, NULL); + return (PyObject *)PyCursesWindow_New(win, NULL); } /*[clinic input] From 676d1cefcb0b2ca582f39771a3842f9d025aaa44 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, 28 Sep 2024 18:03:54 +0200 Subject: [PATCH 26/38] reduce diff --- Modules/_cursesmodule.c | 69 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 8fc09ba9a5ece0..99b15080056921 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1373,11 +1373,13 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), "echochar"); + return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } else #endif - return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), "echochar"); + return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } #ifdef NCURSES_MOUSE_VERSION @@ -1488,9 +1490,8 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, if (rtn == ERR) { /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); - if (!PyErr_Occurred()) { + if (!PyErr_Occurred()) PyErr_SetString(curses_global_state.PyCursesError, "no input"); - } return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -2649,43 +2650,41 @@ PyTypeObject PyCursesWindow_Type = { PARSESTR - format string for argument parsing */ -#define NoArgNoReturnFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyCursesCheckERR(X(), # X); \ +#define NoArgNoReturnFunctionBody(X) \ +{ \ + PyCursesInitialised; \ + return PyCursesCheckERR(X(), # X); } + +#define NoArgOrFlagNoReturnFunctionBody(X, flag) \ +{ \ + PyCursesInitialised; \ + if (flag) \ + return PyCursesCheckERR(X(), # X); \ + else \ + return PyCursesCheckERR(no ## X(), # X); \ } -#define NoArgOrFlagNoReturnFunctionBody(X, flag) \ -{ \ - PyCursesInitialised; \ - int rtn = (flag) ? X() : no ## X(); \ - return PyCursesCheckERR(rtn, # X); \ -} +#define NoArgReturnIntFunctionBody(X) \ +{ \ + PyCursesInitialised; \ + return PyLong_FromLong((long) X()); } -#define NoArgReturnIntFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyLong_FromLong((long) X()); \ -} -#define NoArgReturnStringFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyBytes_FromString(X()); \ -} +#define NoArgReturnStringFunctionBody(X) \ +{ \ + PyCursesInitialised; \ + return PyBytes_FromString(X()); } -#define NoArgTrueFalseFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - return PyBool_FromLong(X()); \ -} +#define NoArgTrueFalseFunctionBody(X) \ +{ \ + PyCursesInitialised; \ + return PyBool_FromLong(X()); } -#define NoArgNoReturnVoidFunctionBody(X) \ -{ \ - PyCursesInitialised; \ - X(); \ - Py_RETURN_NONE; \ -} +#define NoArgNoReturnVoidFunctionBody(X) \ +{ \ + PyCursesInitialised; \ + X(); \ + Py_RETURN_NONE; } /********************************************************************* Global Functions From 8a60d53a9429ae35c21fff74bb7850948b740cf8 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, 28 Sep 2024 18:06:25 +0200 Subject: [PATCH 27/38] reduce diff --- Modules/_cursesmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 99b15080056921..409930b6e91bd5 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -4796,7 +4796,7 @@ static struct PyModuleDef _cursesmodule = { }; static void -_curses_capi_destructor(PyObject *op) +curses_destructor(PyObject *op) { void *ptr = PyCapsule_GetPointer(op, PyCurses_CAPSULE_NAME); Py_DECREF(*(void **)ptr); @@ -4835,7 +4835,7 @@ cursesmodule_exec(PyObject *module) /* Add a capsule for the C API */ PyObject *c_api_object = PyCapsule_New(PyCurses_API, PyCurses_CAPSULE_NAME, - _curses_capi_destructor); + curses_destructor); if (c_api_object == NULL) { Py_DECREF(PyCurses_API[0]); PyMem_Free(PyCurses_API); From e0dfc4ad06e0b380d6c69ba9f3cf2de752989750 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, 28 Sep 2024 18:17:38 +0200 Subject: [PATCH 28/38] fix globals --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index e1c07f88b963bc..a0be2a0a203f8c 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -423,6 +423,7 @@ Modules/readline.c - libedit_history_start - Modules/_ctypes/cfield.c - formattable - Modules/_ctypes/malloc_closure.c - free_list - +Modules/_cursesmodule.c - curses_global_state - Modules/_curses_panel.c - lop - Modules/_ssl/debughelpers.c _PySSL_keylog_callback lock - Modules/_tkinter.c - quitMainLoop - From e596924d767a9adef280efc8e440460f09a6d53a 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, 28 Sep 2024 18:17:38 +0200 Subject: [PATCH 29/38] fix globals --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 1 + 1 file changed, 1 insertion(+) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index e1c07f88b963bc..a0be2a0a203f8c 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -423,6 +423,7 @@ Modules/readline.c - libedit_history_start - Modules/_ctypes/cfield.c - formattable - Modules/_ctypes/malloc_closure.c - free_list - +Modules/_cursesmodule.c - curses_global_state - Modules/_curses_panel.c - lop - Modules/_ssl/debughelpers.c _PySSL_keylog_callback lock - Modules/_tkinter.c - quitMainLoop - From fc9dacbf66013ade9c688d0434e0b861c3242603 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, 29 Sep 2024 13:48:43 +0200 Subject: [PATCH 30/38] rename the state fields --- Modules/_cursesmodule.c | 74 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 409930b6e91bd5..29ce68d9c74dc4 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -160,8 +160,8 @@ typedef chtype attr_t; /* No attr_t type is available */ #endif /* _NCURSES_EXTENDED_COLOR_FUNCS */ typedef struct _cursesmodule_state { - PyObject *PyCursesError; - PyTypeObject *PyCursesWindow_Type; + PyObject *error; // PyCursesError + PyTypeObject *window_type; // PyCursesWindow_Type } _cursesmodule_state; // For now, we keep a global state variable to prepare for PEP 489. @@ -194,25 +194,25 @@ static const char *curses_screen_encoding = NULL; #define PyCursesSetupTermCalled \ do { \ if (curses_setupterm_called != TRUE) { \ - PyErr_SetString(curses_global_state.PyCursesError, \ + PyErr_SetString(curses_global_state.error, \ "must call (at least) setupterm() first"); \ return 0; \ } \ } while (0) -#define PyCursesInitialised \ - do { \ - if (curses_initscr_called != TRUE) { \ - PyErr_SetString(curses_global_state.PyCursesError, \ - "must call initscr() first"); \ - return 0; \ - } \ +#define PyCursesInitialised \ + do { \ + if (curses_initscr_called != TRUE) { \ + PyErr_SetString(curses_global_state.error, \ + "must call initscr() first"); \ + return 0; \ + } \ } while (0) #define PyCursesInitialisedColor \ do { \ if (curses_start_color_called != TRUE) { \ - PyErr_SetString(curses_global_state.PyCursesError, \ + PyErr_SetString(curses_global_state.error, \ "must call start_color() first"); \ return 0; \ } \ @@ -233,9 +233,9 @@ PyCursesCheckERR(int code, const char *fname) Py_RETURN_NONE; } else { if (fname == NULL) { - PyErr_SetString(curses_global_state.PyCursesError, catchall_ERR); + PyErr_SetString(curses_global_state.error, catchall_ERR); } else { - PyErr_Format(curses_global_state.PyCursesError, "%s() returned ERR", fname); + PyErr_Format(curses_global_state.error, "%s() returned ERR", fname); } return NULL; } @@ -1341,7 +1341,7 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(curses_global_state.PyCursesError, catchall_NULL); + PyErr_SetString(curses_global_state.error, catchall_NULL); return NULL; } @@ -1491,7 +1491,7 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); if (!PyErr_Occurred()) - PyErr_SetString(curses_global_state.PyCursesError, "no input"); + PyErr_SetString(curses_global_state.error, "no input"); return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -1549,7 +1549,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - PyErr_SetString(curses_global_state.PyCursesError, "no input"); + PyErr_SetString(curses_global_state.error, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -2062,7 +2062,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(curses_global_state.PyCursesError, + PyErr_SetString(curses_global_state.error, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2286,7 +2286,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(curses_global_state.PyCursesError, + PyErr_SetString(curses_global_state.error, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2368,7 +2368,7 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - PyErr_SetString(curses_global_state.PyCursesError, catchall_NULL); + PyErr_SetString(curses_global_state.error, catchall_NULL); return NULL; } @@ -2785,7 +2785,7 @@ _curses_color_content_impl(PyObject *module, int color_number) if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->PyCursesError, "%s() returned ERR", + PyErr_Format(st->error, "%s() returned ERR", Py_STRINGIFY(_COLOR_CONTENT_FUNC)); return NULL; } @@ -3025,7 +3025,7 @@ _curses_getmouse_impl(PyObject *module) rtn = getmouse( &event ); if (rtn == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, "getmouse() returned ERR"); + PyErr_SetString(st->error, "getmouse() returned ERR"); return NULL; } return Py_BuildValue("(hiiik)", @@ -3120,7 +3120,7 @@ _curses_getwin(PyObject *module, PyObject *file) win = getwin(fp); if (win == NULL) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(st->error, catchall_NULL); goto error; } res = PyCursesWindow_New(win, NULL); @@ -3269,7 +3269,7 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) } else { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->PyCursesError, "%s() returned ERR", + PyErr_Format(st->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)); } return NULL; @@ -3301,7 +3301,7 @@ _curses_initscr_impl(PyObject *module) if (win == NULL) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(st->error, catchall_NULL); return NULL; } @@ -3431,7 +3431,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) if (sys_stdout == NULL || sys_stdout == Py_None) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, "lost sys.stdout"); + PyErr_SetString(st->error, "lost sys.stdout"); return NULL; } @@ -3452,7 +3452,7 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) } _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, s); + PyErr_SetString(st->error, s); return NULL; } @@ -3770,7 +3770,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) if (win == NULL) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(st->error, catchall_NULL); return NULL; } @@ -3810,7 +3810,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, catchall_NULL); + PyErr_SetString(st->error, catchall_NULL); return NULL; } @@ -3929,7 +3929,7 @@ _curses_pair_content_impl(PyObject *module, int pair_number) } else { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->PyCursesError, "%s() returned ERR", + PyErr_Format(st->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC)); } return NULL; @@ -4260,7 +4260,7 @@ _curses_start_color_impl(PyObject *module) if (start_color() == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, "start_color() returned ERR"); + PyErr_SetString(st->error, "start_color() returned ERR"); return NULL; } @@ -4413,7 +4413,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, "tparm() returned NULL"); + PyErr_SetString(st->error, "tparm() returned NULL"); return NULL; } @@ -4615,7 +4615,7 @@ _curses_use_default_colors_impl(PyObject *module) Py_RETURN_NONE; } else { _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->PyCursesError, "use_default_colors() returned ERR"); + PyErr_SetString(st->error, "use_default_colors() returned ERR"); return NULL; } } @@ -4814,7 +4814,7 @@ cursesmodule_exec(PyObject *module) if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { return -1; } - st->PyCursesWindow_Type = &PyCursesWindow_Type; + st->window_type = &PyCursesWindow_Type; /* Add some symbolic constants to the module */ PyObject *module_dict = PyModule_GetDict(module); @@ -4848,12 +4848,12 @@ cursesmodule_exec(PyObject *module) } /* For exception curses.error */ - st->PyCursesError = PyErr_NewException("_curses.error", NULL, NULL); - if (st->PyCursesError == NULL) { + st->error = PyErr_NewException("_curses.error", NULL, NULL); + if (st->error == NULL) { return -1; } - rc = PyDict_SetItemString(module_dict, "error", st->PyCursesError); - Py_DECREF(st->PyCursesError); + rc = PyDict_SetItemString(module_dict, "error", st->error); + Py_DECREF(st->error); if (rc < 0) { return -1; } From f548f4b0265c77bc73defff97de795529af27987 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, 29 Sep 2024 13:50:25 +0200 Subject: [PATCH 31/38] Introduce macros for initialization checks. --- Modules/_cursesmodule.c | 61 ++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 29ce68d9c74dc4..83eb74039502d4 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -191,32 +191,55 @@ static int curses_start_color_called = FALSE; static const char *curses_screen_encoding = NULL; /* Utility Macros */ -#define PyCursesSetupTermCalled \ + +/* + * Macro to check that FUNC_NAME has been called by testing + * the CALLED boolean. If an error occurs, a PyCursesError + * is raised. + * + * Since these macros can be called in functions that do not + * have a direct access to the module's state, the exception + * type is imported on demand as well. + */ +#define _PyCursesCheckFunction(CALLED, FUNC_NAME) \ do { \ - if (curses_setupterm_called != TRUE) { \ - PyErr_SetString(curses_global_state.error, \ - "must call (at least) setupterm() first"); \ + if ((CALLED) != TRUE) { \ + PyObject *exc = _PyImport_GetModuleAttrString("_curses", \ + "error"); \ + if (exc == NULL) { \ + return 0; \ + } \ + PyErr_SetString(exc, "must call " # FUNC_NAME "() first"); \ + Py_DECREF(exc); \ return 0; \ } \ } while (0) -#define PyCursesInitialised \ - do { \ - if (curses_initscr_called != TRUE) { \ - PyErr_SetString(curses_global_state.error, \ - "must call initscr() first"); \ - return 0; \ - } \ +/* + * Macro to check that FUNC_NAME has been called by testing + * the CALLED boolean. If an error occurs, a PyCursesError + * is raised. The exception type is obtained from the module + * state. + */ +#define _PyCursesStatefulCheckFunction(CALLED, FUNC_NAME, MODULE) \ + do { \ + if ((CALLED) != TRUE) { \ + _cursesmodule_state *st = get_cursesmodule_state((MODULE)); \ + PyErr_SetString(st->error, \ + "must call " # FUNC_NAME "() first"); \ + return 0; \ + } \ } while (0) -#define PyCursesInitialisedColor \ - do { \ - if (curses_start_color_called != TRUE) { \ - PyErr_SetString(curses_global_state.error, \ - "must call start_color() first"); \ - return 0; \ - } \ - } while (0) +#define PyCursesStatefulSetupTermCalled(MODULE) \ + _PyCursesStatefulCheckFunction(curses_setupterm_called, \ + "setupterm", (MODULE)) +#define PyCursesStatefulInitialised(MODULE) \ + _PyCursesStatefulCheckFunction(curses_initscr_called, \ + "initscr", (MODULE)) +#define PyCursesStatefulInitialisedColor(MODULE) \ + _PyCursesStatefulCheckFunction(curses_start_color_called, \ + "start_color", (MODULE)) /* Utility Functions */ From 3e5c37c02f4336315c3a4c9860fc6f7199e85320 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, 29 Sep 2024 13:52:01 +0200 Subject: [PATCH 32/38] Update C API functions --- Modules/_cursesmodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 83eb74039502d4..7d4dfc9b5eac36 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -588,19 +588,19 @@ class component_converter(CConverter): static int func_PyCursesSetupTermCalled(void) { - PyCursesSetupTermCalled; + _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); return 1; } static int func_PyCursesInitialised(void) { - PyCursesInitialised; + _PyCursesCheckFunction(curses_initscr_called, "initscr"); return 1; } static int func_PyCursesInitialisedColor(void) { - PyCursesInitialisedColor; + _PyCursesCheckFunction(curses_start_color_called, "start_color");; return 1; } From b94438f2433bff6fbd90e7c3e11f2441f6dcd247 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, 29 Sep 2024 13:54:37 +0200 Subject: [PATCH 33/38] Improve macros to use module's state when possible --- Modules/_cursesmodule.c | 102 ++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 7d4dfc9b5eac36..75e6dea7e06435 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -2675,12 +2675,12 @@ PyTypeObject PyCursesWindow_Type = { #define NoArgNoReturnFunctionBody(X) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ return PyCursesCheckERR(X(), # X); } #define NoArgOrFlagNoReturnFunctionBody(X, flag) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ if (flag) \ return PyCursesCheckERR(X(), # X); \ else \ @@ -2689,23 +2689,23 @@ PyTypeObject PyCursesWindow_Type = { #define NoArgReturnIntFunctionBody(X) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ return PyLong_FromLong((long) X()); } #define NoArgReturnStringFunctionBody(X) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ return PyBytes_FromString(X()); } #define NoArgTrueFalseFunctionBody(X) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ return PyBool_FromLong(X()); } #define NoArgNoReturnVoidFunctionBody(X) \ { \ - PyCursesInitialised; \ + PyCursesStatefulInitialised(module); \ X(); \ Py_RETURN_NONE; } @@ -2803,8 +2803,8 @@ _curses_color_content_impl(PyObject *module, int color_number) { _CURSES_COLOR_VAL_TYPE r,g,b; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); @@ -2833,8 +2833,8 @@ static PyObject * _curses_color_pair_impl(PyObject *module, int pair_number) /*[clinic end generated code: output=60718abb10ce9feb input=6034e9146f343802]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyLong_FromLong(COLOR_PAIR(pair_number)); } @@ -2860,7 +2860,7 @@ _curses_curs_set_impl(PyObject *module, int visibility) { int erg; - PyCursesInitialised; + PyCursesStatefulInitialised(module); erg = curs_set(visibility); if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); @@ -2912,7 +2912,7 @@ static PyObject * _curses_delay_output_impl(PyObject *module, int ms) /*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(delay_output(ms), "delay_output"); } @@ -2968,7 +2968,7 @@ _curses_erasechar_impl(PyObject *module) { char ch; - PyCursesInitialised; + PyCursesStatefulInitialised(module); ch = erasechar(); @@ -3018,7 +3018,7 @@ _curses_getsyx_impl(PyObject *module) int x = 0; int y = 0; - PyCursesInitialised; + PyCursesStatefulInitialised(module); getsyx(y, x); @@ -3043,7 +3043,7 @@ _curses_getmouse_impl(PyObject *module) int rtn; MEVENT event; - PyCursesInitialised; + PyCursesStatefulInitialised(module); rtn = getmouse( &event ); if (rtn == ERR) { @@ -3079,7 +3079,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, { MEVENT event; - PyCursesInitialised; + PyCursesStatefulInitialised(module); event.id = id; event.x = x; @@ -3112,7 +3112,7 @@ _curses_getwin(PyObject *module, PyObject *file) WINDOW *win; PyObject *res = NULL; - PyCursesInitialised; + PyCursesStatefulInitialised(module); fp = tmpfile(); if (fp == NULL) @@ -3169,7 +3169,7 @@ static PyObject * _curses_halfdelay_impl(PyObject *module, unsigned char tenths) /*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); } @@ -3222,7 +3222,7 @@ static PyObject * _curses_has_key_impl(PyObject *module, int key) /*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyBool_FromLong(has_key(key)); } @@ -3253,8 +3253,8 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, short b) /*[clinic end generated code: output=d7ed71b2d818cdf2 input=ae2b8bea0f152c80]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); @@ -3281,8 +3281,8 @@ static PyObject * _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) /*[clinic end generated code: output=a0bba03d2bbc3ee6 input=54b421b44c12c389]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_CURSES_INIT_PAIR_FUNC(pair_number, fg, bg) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3580,7 +3580,7 @@ static PyObject * _curses_intrflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=c1986df35e999a0f input=c65fe2ef973fe40a]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); } @@ -3613,7 +3613,7 @@ static PyObject * _curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) /*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyBool_FromLong(is_term_resized(nlines, ncols)); } @@ -3635,7 +3635,7 @@ _curses_keyname_impl(PyObject *module, int key) { const char *knp; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); @@ -3693,7 +3693,7 @@ static PyObject * _curses_meta_impl(PyObject *module, int yes) /*[clinic end generated code: output=22f5abda46a605d8 input=cfe7da79f51d0e30]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(meta(stdscr, yes), "meta"); } @@ -3717,7 +3717,7 @@ static PyObject * _curses_mouseinterval_impl(PyObject *module, int interval) /*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); } @@ -3742,7 +3742,7 @@ _curses_mousemask_impl(PyObject *module, unsigned long newmask) { mmask_t oldmask, availmask; - PyCursesInitialised; + PyCursesStatefulInitialised(module); availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); @@ -3763,7 +3763,7 @@ static int _curses_napms_impl(PyObject *module, int ms) /*[clinic end generated code: output=5f292a6a724491bd input=c6d6e01f2f1df9f7]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return napms(ms); } @@ -3787,7 +3787,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) { WINDOW *win; - PyCursesInitialised; + PyCursesStatefulInitialised(module); win = newpad(nlines, ncols); @@ -3828,7 +3828,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, { WINDOW *win; - PyCursesInitialised; + PyCursesStatefulInitialised(module); win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { @@ -3941,8 +3941,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number) { _CURSES_COLOR_NUM_TYPE f, b; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); if (_CURSES_PAIR_CONTENT_FUNC(pair_number, &f, &b) == ERR) { if (pair_number >= COLOR_PAIRS) { @@ -3976,8 +3976,8 @@ static PyObject * _curses_pair_number_impl(PyObject *module, int attr) /*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); return PyLong_FromLong(PAIR_NUMBER(attr)); } @@ -4017,7 +4017,7 @@ static PyObject * _curses_qiflush_impl(PyObject *module, int flag) /*[clinic end generated code: output=9167e862f760ea30 input=6ec8b3e2b717ec40]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (flag) { qiflush(); @@ -4172,7 +4172,7 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + PyCursesStatefulInitialised(module); result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); if (!result) @@ -4211,7 +4211,7 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) { PyObject *result; - PyCursesInitialised; + PyCursesStatefulInitialised(module); result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); if (!result) @@ -4254,7 +4254,7 @@ static PyObject * _curses_setsyx_impl(PyObject *module, int y, int x) /*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); setsyx(y,x); @@ -4279,7 +4279,7 @@ static PyObject * _curses_start_color_impl(PyObject *module) /*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (start_color() == ERR) { _cursesmodule_state *st = get_cursesmodule_state(module); @@ -4352,7 +4352,7 @@ static PyObject * _curses_tigetflag_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); return PyLong_FromLong( (long) tigetflag( (char *)capname ) ); } @@ -4374,7 +4374,7 @@ static PyObject * _curses_tigetnum_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); return PyLong_FromLong( (long) tigetnum( (char *)capname ) ); } @@ -4396,7 +4396,7 @@ static PyObject * _curses_tigetstr_impl(PyObject *module, const char *capname) /*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); capname = tigetstr( (char *)capname ); if (capname == NULL || capname == (char*) -1) { @@ -4431,7 +4431,7 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, { char* result = NULL; - PyCursesSetupTermCalled; + PyCursesStatefulSetupTermCalled(module); result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { @@ -4460,7 +4460,7 @@ static PyObject * _curses_typeahead_impl(PyObject *module, int fd) /*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - PyCursesInitialised; + PyCursesStatefulInitialised(module); return PyCursesCheckERR(typeahead( fd ), "typeahead"); } @@ -4484,7 +4484,7 @@ _curses_unctrl(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4507,7 +4507,7 @@ _curses_ungetch(PyObject *module, PyObject *ch) { chtype ch_; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; @@ -4578,7 +4578,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch) { wchar_t wch; - PyCursesInitialised; + PyCursesStatefulInitialised(module); if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; @@ -4630,8 +4630,8 @@ _curses_use_default_colors_impl(PyObject *module) { int code; - PyCursesInitialised; - PyCursesInitialisedColor; + PyCursesStatefulInitialised(module); + PyCursesStatefulInitialisedColor(module); code = use_default_colors(); if (code != ERR) { From b98749925a7158a4ba40e88ded08db75f10d94cd 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, 29 Sep 2024 14:24:46 +0200 Subject: [PATCH 34/38] Make use of module's state whenever possible. --- Modules/_cursesmodule.c | 165 ++++++++++++++++++++++++---------------- 1 file changed, 100 insertions(+), 65 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 75e6dea7e06435..adee475c13cfdb 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -173,6 +173,18 @@ get_cursesmodule_state(PyObject *Py_UNUSED(module)) return &curses_global_state; } +static inline _cursesmodule_state * +get_cursesmodule_state_by_cls(PyObject *Py_UNUSED(cls)) +{ + return &curses_global_state; +} + +static inline _cursesmodule_state * +get_cursesmodule_state_by_win(PyCursesWindowObject *Py_UNUSED(win)) +{ + return &curses_global_state; +} + /*[clinic input] module _curses class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" @@ -249,17 +261,37 @@ static const char *curses_screen_encoding = NULL; * capsule API. */ +#define _PyCursesSetError(MODULE_STATE, FUNCNAME) \ + do { \ + if ((FUNCNAME) == NULL) { \ + PyErr_SetString((MODULE_STATE)->error, catchall_ERR); \ + } \ + else { \ + PyErr_Format((MODULE_STATE)->error, \ + "%s() returned ERR", (FUNCNAME)); \ + } \ + } while (0) + static PyObject * -PyCursesCheckERR(int code, const char *fname) +PyCursesCheckERR(PyObject *module, int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; } else { - if (fname == NULL) { - PyErr_SetString(curses_global_state.error, catchall_ERR); - } else { - PyErr_Format(curses_global_state.error, "%s() returned ERR", fname); - } + _cursesmodule_state *st = get_cursesmodule_state(module); + _PyCursesSetError(st, fname); + return NULL; + } +} + +static PyObject * +PyCursesCheckERR_ForWin(PyCursesWindowObject *win, int code, const char *fname) +{ + if (code != ERR) { + Py_RETURN_NONE; + } else { + _cursesmodule_state *st = get_cursesmodule_state_by_win(win); + _PyCursesSetError(st, fname); return NULL; } } @@ -623,7 +655,7 @@ PyTypeObject PyCursesWindow_Type; #define Window_NoArgNoReturnFunction(X) \ static PyObject *PyCursesWindow_ ## X \ (PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) \ - { return PyCursesCheckERR(X(self->win), # X); } + { return PyCursesCheckERR_ForWin(self, X(self->win), # X); } #define Window_NoArgTrueFalseFunction(X) \ static PyObject * PyCursesWindow_ ## X \ @@ -658,7 +690,7 @@ PyTypeObject PyCursesWindow_Type; { \ TYPE arg1; \ if (!PyArg_ParseTuple(args,PARSESTR, &arg1)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1), # X); } + return PyCursesCheckERR_ForWin(self, X(self->win, arg1), # X); } #define Window_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ static PyObject * PyCursesWindow_ ## X \ @@ -666,7 +698,7 @@ PyTypeObject PyCursesWindow_Type; { \ TYPE arg1, arg2; \ if (!PyArg_ParseTuple(args,PARSESTR, &arg1, &arg2)) return NULL; \ - return PyCursesCheckERR(X(self->win, arg1, arg2), # X); } + return PyCursesCheckERR_ForWin(self, X(self->win, arg1, arg2), # X); } /* ------------- WINDOW routines --------------- */ @@ -840,7 +872,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, else { return NULL; } - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_ForWin(self, rtn, funcname); } /*[clinic input] @@ -920,7 +952,7 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_ForWin(self, rtn, funcname); } /*[clinic input] @@ -1003,7 +1035,7 @@ _curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_ForWin(self, rtn, funcname); } /*[clinic input] @@ -1027,7 +1059,7 @@ _curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; - return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); + return PyCursesCheckERR_ForWin(self, wbkgd(self->win, bkgd | attr), "bkgd"); } /*[clinic input] @@ -1043,7 +1075,7 @@ static PyObject * _curses_window_attroff_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ { - return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff"); + return PyCursesCheckERR_ForWin(self, wattroff(self->win, (attr_t)attr), "attroff"); } /*[clinic input] @@ -1059,7 +1091,7 @@ static PyObject * _curses_window_attron_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/ { - return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron"); + return PyCursesCheckERR_ForWin(self, wattron(self->win, (attr_t)attr), "attron"); } /*[clinic input] @@ -1075,7 +1107,7 @@ static PyObject * _curses_window_attrset_impl(PyCursesWindowObject *self, long attr) /*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ { - return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset"); + return PyCursesCheckERR_ForWin(self, wattrset(self->win, (attr_t)attr), "attrset"); } /*[clinic input] @@ -1101,7 +1133,7 @@ _curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, return NULL; wbkgdset(self->win, bkgd | attr); - return PyCursesCheckERR(0, "bkgdset"); + return PyCursesCheckERR_ForWin(self, 0, "bkgdset"); } /*[clinic input] @@ -1301,7 +1333,7 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) rtn = wchgat(self->win,num,attr,color,NULL); touchline(self->win,y,1); } - return PyCursesCheckERR(rtn, "chgat"); + return PyCursesCheckERR_ForWin(self, rtn, "chgat"); } #endif @@ -1325,10 +1357,10 @@ _curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ { if (!group_right_1) { - return PyCursesCheckERR(wdelch(self->win), "wdelch"); + return PyCursesCheckERR_ForWin(self, wdelch(self->win), "wdelch"); } else { - return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch"); + return PyCursesCheckERR_ForWin(self, py_mvwdelch(self->win, y, x), "mvwdelch"); } } @@ -1396,13 +1428,15 @@ _curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR_ForWin(self, + pechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } else #endif - return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), - "echochar"); + return PyCursesCheckERR_ForWin(self, + wechochar(self->win, ch_ | (attr_t)attr), + "echochar"); } #ifdef NCURSES_MOUSE_VERSION @@ -1696,10 +1730,10 @@ _curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) { - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR_ForWin(self, ERR, "wmove"); } } - return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline"); + return PyCursesCheckERR_ForWin(self, whline(self->win, ch_ | (attr_t)attr, n), "hline"); } /*[clinic input] @@ -1746,7 +1780,7 @@ _curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); } - return PyCursesCheckERR(rtn, "insch"); + return PyCursesCheckERR_ForWin(self, rtn, "insch"); } /*[clinic input] @@ -1923,7 +1957,7 @@ _curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_ForWin(self, rtn, funcname); } /*[clinic input] @@ -2008,7 +2042,7 @@ _curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, } if (use_attr) (void)wattrset(self->win,attr_old); - return PyCursesCheckERR(rtn, funcname); + return PyCursesCheckERR_ForWin(self, rtn, funcname); } /*[clinic input] @@ -2094,7 +2128,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) rtn = pnoutrefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); + return PyCursesCheckERR_ForWin(self, rtn, "pnoutrefresh"); } if (group_right_1) { PyErr_SetString(PyExc_TypeError, @@ -2105,7 +2139,7 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) Py_BEGIN_ALLOW_THREADS rtn = wnoutrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); + return PyCursesCheckERR_ForWin(self, rtn, "wnoutrefresh"); } /*[clinic input] @@ -2147,11 +2181,11 @@ _curses_window_overlay_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, TRUE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR_ForWin(self, rtn, "copywin"); } else { rtn = overlay(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overlay"); + return PyCursesCheckERR_ForWin(self, rtn, "overlay"); } } @@ -2195,11 +2229,11 @@ _curses_window_overwrite_impl(PyCursesWindowObject *self, if (group_right_1) { rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, FALSE); - return PyCursesCheckERR(rtn, "copywin"); + return PyCursesCheckERR_ForWin(self, rtn, "copywin"); } else { rtn = overwrite(self->win, destwin->win); - return PyCursesCheckERR(rtn, "overwrite"); + return PyCursesCheckERR_ForWin(self, rtn, "overwrite"); } } @@ -2228,7 +2262,7 @@ _curses_window_putwin(PyCursesWindowObject *self, PyObject *file) return PyErr_SetFromErrno(PyExc_OSError); if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) goto exit; - res = PyCursesCheckERR(putwin(self->win, fp), "putwin"); + res = PyCursesCheckERR_ForWin(self, putwin(self->win, fp), "putwin"); if (res == NULL) goto exit; fseek(fp, 0, 0); @@ -2267,7 +2301,7 @@ static PyObject * _curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) /*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ { - return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); + return PyCursesCheckERR_ForWin(self, wredrawln(self->win,beg,num), "redrawln"); } /*[clinic input] @@ -2317,7 +2351,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, rtn = prefresh(self->win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR_ForWin(self, rtn, "prefresh"); } #endif if (group_right_1) { @@ -2328,7 +2362,7 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, Py_BEGIN_ALLOW_THREADS rtn = wrefresh(self->win); Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); + return PyCursesCheckERR_ForWin(self, rtn, "prefresh"); } /*[clinic input] @@ -2350,7 +2384,7 @@ _curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, int bottom) /*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ { - return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg"); + return PyCursesCheckERR_ForWin(self, wsetscrreg(self->win, top, bottom), "wsetscrreg"); } /*[clinic input] @@ -2418,10 +2452,10 @@ _curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, /*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/ { if (!group_right_1) { - return PyCursesCheckERR(scroll(self->win), "scroll"); + return PyCursesCheckERR_ForWin(self, scroll(self->win), "scroll"); } else { - return PyCursesCheckERR(wscrl(self->win, lines), "scroll"); + return PyCursesCheckERR_ForWin(self, wscrl(self->win, lines), "scroll"); } } @@ -2447,10 +2481,10 @@ _curses_window_touchline_impl(PyCursesWindowObject *self, int start, /*[clinic end generated code: output=65d05b3f7438c61d input=a98aa4f79b6be845]*/ { if (!group_right_1) { - return PyCursesCheckERR(touchline(self->win, start, count), "touchline"); + return PyCursesCheckERR_ForWin(self, touchline(self->win, start, count), "touchline"); } else { - return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline"); + return PyCursesCheckERR_ForWin(self, wtouchln(self->win, start, count, changed), "touchline"); } } @@ -2490,9 +2524,9 @@ _curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, return NULL; if (group_left_1) { if (wmove(self->win, y, x) == ERR) - return PyCursesCheckERR(ERR, "wmove"); + return PyCursesCheckERR_ForWin(self, ERR, "wmove"); } - return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline"); + return PyCursesCheckERR_ForWin(self, wvline(self->win, ch_ | (attr_t)attr, n), "vline"); } static PyObject * @@ -2676,15 +2710,15 @@ PyTypeObject PyCursesWindow_Type = { #define NoArgNoReturnFunctionBody(X) \ { \ PyCursesStatefulInitialised(module); \ - return PyCursesCheckERR(X(), # X); } + return PyCursesCheckERR(module, X(), # X); } #define NoArgOrFlagNoReturnFunctionBody(X, flag) \ { \ PyCursesStatefulInitialised(module); \ if (flag) \ - return PyCursesCheckERR(X(), # X); \ + return PyCursesCheckERR(module, X(), # X); \ else \ - return PyCursesCheckERR(no ## X(), # X); \ + return PyCursesCheckERR(module, no ## X(), # X); \ } #define NoArgReturnIntFunctionBody(X) \ @@ -2863,7 +2897,7 @@ _curses_curs_set_impl(PyObject *module, int visibility) PyCursesStatefulInitialised(module); erg = curs_set(visibility); - if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); + if (erg == ERR) return PyCursesCheckERR(module, erg, "curs_set"); return PyLong_FromLong((long) erg); } @@ -2914,7 +2948,7 @@ _curses_delay_output_impl(PyObject *module, int ms) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(delay_output(ms), "delay_output"); + return PyCursesCheckERR(module, delay_output(ms), "delay_output"); } /*[clinic input] @@ -3086,7 +3120,7 @@ _curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, event.y = y; event.z = z; event.bstate = bstate; - return PyCursesCheckERR(ungetmouse(&event), "ungetmouse"); + return PyCursesCheckERR(module, ungetmouse(&event), "ungetmouse"); } #endif @@ -3171,7 +3205,7 @@ _curses_halfdelay_impl(PyObject *module, unsigned char tenths) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); + return PyCursesCheckERR(module, halfdelay(tenths), "halfdelay"); } /*[clinic input] @@ -3256,7 +3290,8 @@ _curses_init_color_impl(PyObject *module, int color_number, short r, short g, PyCursesStatefulInitialised(module); PyCursesStatefulInitialisedColor(module); - return PyCursesCheckERR(_CURSES_INIT_COLOR_FUNC(color_number, r, g, b), + return PyCursesCheckERR(module, + _CURSES_INIT_COLOR_FUNC(color_number, r, g, b), Py_STRINGIFY(_CURSES_INIT_COLOR_FUNC)); } @@ -3525,7 +3560,7 @@ _curses_set_escdelay_impl(PyObject *module, int ms) return NULL; } - return PyCursesCheckERR(set_escdelay(ms), "set_escdelay"); + return PyCursesCheckERR(module, set_escdelay(ms), "set_escdelay"); } /*[clinic input] @@ -3564,7 +3599,7 @@ _curses_set_tabsize_impl(PyObject *module, int size) return NULL; } - return PyCursesCheckERR(set_tabsize(size), "set_tabsize"); + return PyCursesCheckERR(module, set_tabsize(size), "set_tabsize"); } #endif @@ -3582,7 +3617,7 @@ _curses_intrflush_impl(PyObject *module, int flag) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); + return PyCursesCheckERR(module, intrflush(NULL, flag), "intrflush"); } /*[clinic input] @@ -3695,7 +3730,7 @@ _curses_meta_impl(PyObject *module, int yes) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(meta(stdscr, yes), "meta"); + return PyCursesCheckERR(module, meta(stdscr, yes), "meta"); } #ifdef NCURSES_MOUSE_VERSION @@ -3719,7 +3754,7 @@ _curses_mouseinterval_impl(PyObject *module, int interval) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); + return PyCursesCheckERR(module, mouseinterval(interval), "mouseinterval"); } /*[clinic input] @@ -3997,7 +4032,7 @@ static PyObject * _curses_putp_impl(PyObject *module, const char *string) /*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - return PyCursesCheckERR(putp(string), "putp"); + return PyCursesCheckERR(module, putp(string), "putp"); } /*[clinic input] @@ -4174,7 +4209,7 @@ _curses_resizeterm_impl(PyObject *module, int nlines, int ncols) PyCursesStatefulInitialised(module); - result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); + result = PyCursesCheckERR(module, resizeterm(nlines, ncols), "resizeterm"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4213,7 +4248,7 @@ _curses_resize_term_impl(PyObject *module, int nlines, int ncols) PyCursesStatefulInitialised(module); - result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); + result = PyCursesCheckERR(module, resize_term(nlines, ncols), "resize_term"); if (!result) return NULL; if (!update_lines_cols(module)) { @@ -4462,7 +4497,7 @@ _curses_typeahead_impl(PyObject *module, int fd) { PyCursesStatefulInitialised(module); - return PyCursesCheckERR(typeahead( fd ), "typeahead"); + return PyCursesCheckERR(module, typeahead( fd ), "typeahead"); } #endif @@ -4512,7 +4547,7 @@ _curses_ungetch(PyObject *module, PyObject *ch) if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyCursesCheckERR(ungetch(ch_), "ungetch"); + return PyCursesCheckERR(module, ungetch(ch_), "ungetch"); } #ifdef HAVE_NCURSESW @@ -4582,7 +4617,7 @@ _curses_unget_wch(PyObject *module, PyObject *ch) if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; - return PyCursesCheckERR(unget_wch(wch), "unget_wch"); + return PyCursesCheckERR(module, unget_wch(wch), "unget_wch"); } #endif From e8d9d665c23060aec075d33ef827e24bf9e2d24d 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, 29 Sep 2024 14:30:06 +0200 Subject: [PATCH 35/38] Make use of module's state whenever possible. --- Modules/_cursesmodule.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index adee475c13cfdb..4e4e28e8c912d1 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1396,7 +1396,8 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - PyErr_SetString(curses_global_state.error, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, catchall_NULL); return NULL; } @@ -1547,8 +1548,10 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, if (rtn == ERR) { /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); - if (!PyErr_Occurred()) - PyErr_SetString(curses_global_state.error, "no input"); + if (!PyErr_Occurred()) { + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, "no input"); + } return NULL; } else if (rtn <= 255) { #ifdef NCURSES_VERSION_MAJOR @@ -1606,7 +1609,8 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - PyErr_SetString(curses_global_state.error, "no input"); + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -2119,7 +2123,8 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(curses_global_state.error, + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2343,7 +2348,8 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - PyErr_SetString(curses_global_state.error, + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2425,7 +2431,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - PyErr_SetString(curses_global_state.error, catchall_NULL); + _cursesmodule_state *st = get_cursesmodule_state_by_win(self); + PyErr_SetString(st->error, catchall_NULL); return NULL; } From b02e8603838e0ca2b013ee5a8ccb9d77e15f33d7 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, 29 Sep 2024 14:53:32 +0200 Subject: [PATCH 36/38] remove unused function for now --- Modules/_cursesmodule.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 4e4e28e8c912d1..ad56861c03c361 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -173,12 +173,6 @@ get_cursesmodule_state(PyObject *Py_UNUSED(module)) return &curses_global_state; } -static inline _cursesmodule_state * -get_cursesmodule_state_by_cls(PyObject *Py_UNUSED(cls)) -{ - return &curses_global_state; -} - static inline _cursesmodule_state * get_cursesmodule_state_by_win(PyCursesWindowObject *Py_UNUSED(win)) { From 439a63fa48cf46908d8736049a57ea8e64291542 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, 29 Sep 2024 16:50:25 +0200 Subject: [PATCH 37/38] address Victor's review --- Modules/_cursesmodule.c | 224 +++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 105 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index ad56861c03c361..e6d2f926bc04c3 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -196,84 +196,101 @@ static int curses_start_color_called = FALSE; static const char *curses_screen_encoding = NULL; -/* Utility Macros */ +/* Utility Checking Procedures */ /* - * Macro to check that FUNC_NAME has been called by testing - * the CALLED boolean. If an error occurs, a PyCursesError - * is raised. + * Function to check that 'funcname' has been called by testing + * the 'called' boolean. If an error occurs, a PyCursesError is + * set and this returns 0. Otherwise, this returns 1. * - * Since these macros can be called in functions that do not + * Since this function can be called in functions that do not * have a direct access to the module's state, the exception - * type is imported on demand as well. + * type is directly taken from the global state for now. */ -#define _PyCursesCheckFunction(CALLED, FUNC_NAME) \ - do { \ - if ((CALLED) != TRUE) { \ - PyObject *exc = _PyImport_GetModuleAttrString("_curses", \ - "error"); \ - if (exc == NULL) { \ - return 0; \ - } \ - PyErr_SetString(exc, "must call " # FUNC_NAME "() first"); \ - Py_DECREF(exc); \ - return 0; \ - } \ - } while (0) +static inline int +_PyCursesCheckFunction(int called, const char *funcname) +{ + if (called == TRUE) { + return 1; + } + PyErr_Format(curses_global_state.error, "must call %s() first", funcname); + return 0; +} /* - * Macro to check that FUNC_NAME has been called by testing - * the CALLED boolean. If an error occurs, a PyCursesError - * is raised. The exception type is obtained from the module - * state. + * Function to check that 'funcname' has been called by testing + * the 'called'' boolean. If an error occurs, a PyCursesError is + * set and this returns 0. Otherwise this returns 1. + * + * The exception type is obtained from the 'module' state. */ -#define _PyCursesStatefulCheckFunction(CALLED, FUNC_NAME, MODULE) \ +static inline int +_PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcname) +{ + if (called == TRUE) { + return 1; + } + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_Format(state->error, "must call %s() first", funcname); + return 0; +} + +#define PyCursesStatefulSetupTermCalled(MODULE) \ + do { \ + if (_PyCursesStatefulCheckFunction(MODULE, \ + curses_setupterm_called, \ + "setupterm")) \ + { \ + return 0; \ + } \ + } while (0) + +#define PyCursesStatefulInitialised(MODULE) \ + do { \ + if (_PyCursesStatefulCheckFunction(MODULE, \ + curses_initscr_called, \ + "initscr")) \ + { \ + return 0; \ + } \ + } while (0) + +#define PyCursesStatefulInitialisedColor(MODULE) \ do { \ - if ((CALLED) != TRUE) { \ - _cursesmodule_state *st = get_cursesmodule_state((MODULE)); \ - PyErr_SetString(st->error, \ - "must call " # FUNC_NAME "() first"); \ + if (_PyCursesStatefulCheckFunction(MODULE, \ + curses_start_color_called, \ + "start_color")) \ + { \ return 0; \ } \ } while (0) -#define PyCursesStatefulSetupTermCalled(MODULE) \ - _PyCursesStatefulCheckFunction(curses_setupterm_called, \ - "setupterm", (MODULE)) -#define PyCursesStatefulInitialised(MODULE) \ - _PyCursesStatefulCheckFunction(curses_initscr_called, \ - "initscr", (MODULE)) -#define PyCursesStatefulInitialisedColor(MODULE) \ - _PyCursesStatefulCheckFunction(curses_start_color_called, \ - "start_color", (MODULE)) - /* Utility Functions */ +static inline void +_PyCursesSetError(_cursesmodule_state *state, const char *funcname) +{ + if (funcname == NULL) { + PyErr_SetString(state->error, catchall_ERR); + } + else { + PyErr_Format(state->error, "%s() returned ERR", funcname); + } +} + /* * Check the return code from a curses function and return None - * or raise an exception as appropriate. These are exported using the - * capsule API. + * or raise an exception as appropriate. */ -#define _PyCursesSetError(MODULE_STATE, FUNCNAME) \ - do { \ - if ((FUNCNAME) == NULL) { \ - PyErr_SetString((MODULE_STATE)->error, catchall_ERR); \ - } \ - else { \ - PyErr_Format((MODULE_STATE)->error, \ - "%s() returned ERR", (FUNCNAME)); \ - } \ - } while (0) - static PyObject * PyCursesCheckERR(PyObject *module, int code, const char *fname) { if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *st = get_cursesmodule_state(module); - _PyCursesSetError(st, fname); + _cursesmodule_state *state = get_cursesmodule_state(module); + _PyCursesSetError(state, fname); return NULL; } } @@ -284,8 +301,8 @@ PyCursesCheckERR_ForWin(PyCursesWindowObject *win, int code, const char *fname) if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *st = get_cursesmodule_state_by_win(win); - _PyCursesSetError(st, fname); + _cursesmodule_state *state = get_cursesmodule_state_by_win(win); + _PyCursesSetError(state, fname); return NULL; } } @@ -614,20 +631,17 @@ class component_converter(CConverter): static int func_PyCursesSetupTermCalled(void) { - _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); - return 1; + return _PyCursesCheckFunction(curses_setupterm_called, "setupterm"); } static int func_PyCursesInitialised(void) { - _PyCursesCheckFunction(curses_initscr_called, "initscr"); - return 1; + return _PyCursesCheckFunction(curses_initscr_called, "initscr"); } static int func_PyCursesInitialisedColor(void) { - _PyCursesCheckFunction(curses_start_color_called, "start_color");; - return 1; + return _PyCursesCheckFunction(curses_start_color_called, "start_color"); } /***************************************************************************** @@ -1390,8 +1404,8 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, win = derwin(self->win,nlines,ncols,begin_y,begin_x); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -1543,8 +1557,8 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); if (!PyErr_Occurred()) { - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, "no input"); + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, "no input"); } return NULL; } else if (rtn <= 255) { @@ -1603,8 +1617,8 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, return NULL; /* get_wch() returns ERR in nodelay mode */ - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, "no input"); + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, "no input"); return NULL; } if (ct == KEY_CODE_YES) @@ -2117,8 +2131,8 @@ _curses_window_noutrefresh_impl(PyCursesWindowObject *self) #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, "noutrefresh() called for a pad " "requires 6 arguments"); return NULL; @@ -2342,8 +2356,8 @@ _curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, #ifdef py_is_pad if (py_is_pad(self->win)) { if (!group_right_1) { - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, "refresh() for a pad requires 6 arguments"); return NULL; } @@ -2425,8 +2439,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, win = subwin(self->win, nlines, ncols, begin_y, begin_x); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state_by_win(self); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state_by_win(self); + PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -2842,8 +2856,8 @@ _curses_color_content_impl(PyObject *module, int color_number) PyCursesStatefulInitialisedColor(module); if (_COLOR_CONTENT_FUNC(color_number, &r, &g, &b) == ERR) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->error, "%s() returned ERR", + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_COLOR_CONTENT_FUNC)); return NULL; } @@ -3082,8 +3096,8 @@ _curses_getmouse_impl(PyObject *module) rtn = getmouse( &event ); if (rtn == ERR) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, "getmouse() returned ERR"); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "getmouse() returned ERR"); return NULL; } return Py_BuildValue("(hiiik)", @@ -3177,8 +3191,8 @@ _curses_getwin(PyObject *module, PyObject *file) fseek(fp, 0, 0); win = getwin(fp); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, catchall_NULL); goto error; } res = PyCursesWindow_New(win, NULL); @@ -3327,8 +3341,8 @@ _curses_init_pair_impl(PyObject *module, int pair_number, int fg, int bg) COLOR_PAIRS - 1); } else { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->error, "%s() returned ERR", + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_INIT_PAIR_FUNC)); } return NULL; @@ -3359,8 +3373,8 @@ _curses_initscr_impl(PyObject *module) win = initscr(); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -3489,8 +3503,8 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) sys_stdout = PySys_GetObject("stdout"); if (sys_stdout == NULL || sys_stdout == Py_None) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, "lost sys.stdout"); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "lost sys.stdout"); return NULL; } @@ -3510,8 +3524,8 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd) s = "setupterm: could not find terminfo database"; } - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, s); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, s); return NULL; } @@ -3828,8 +3842,8 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols) win = newpad(nlines, ncols); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -3868,8 +3882,8 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols, win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, catchall_NULL); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, catchall_NULL); return NULL; } @@ -3987,8 +4001,8 @@ _curses_pair_content_impl(PyObject *module, int pair_number) COLOR_PAIRS - 1); } else { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_Format(st->error, "%s() returned ERR", + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_Format(state->error, "%s() returned ERR", Py_STRINGIFY(_CURSES_PAIR_CONTENT_FUNC)); } return NULL; @@ -4318,8 +4332,8 @@ _curses_start_color_impl(PyObject *module) PyCursesStatefulInitialised(module); if (start_color() == ERR) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, "start_color() returned ERR"); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "start_color() returned ERR"); return NULL; } @@ -4471,8 +4485,8 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, result = tparm((char *)str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, "tparm() returned NULL"); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "tparm() returned NULL"); return NULL; } @@ -4673,8 +4687,8 @@ _curses_use_default_colors_impl(PyObject *module) if (code != ERR) { Py_RETURN_NONE; } else { - _cursesmodule_state *st = get_cursesmodule_state(module); - PyErr_SetString(st->error, "use_default_colors() returned ERR"); + _cursesmodule_state *state = get_cursesmodule_state(module); + PyErr_SetString(state->error, "use_default_colors() returned ERR"); return NULL; } } @@ -4865,7 +4879,7 @@ curses_destructor(PyObject *op) static int cursesmodule_exec(PyObject *module) { - _cursesmodule_state *st = get_cursesmodule_state(module); + _cursesmodule_state *state = get_cursesmodule_state(module); /* Initialize object type */ if (PyType_Ready(&PyCursesWindow_Type) < 0) { return -1; @@ -4873,7 +4887,7 @@ cursesmodule_exec(PyObject *module) if (PyModule_AddType(module, &PyCursesWindow_Type) < 0) { return -1; } - st->window_type = &PyCursesWindow_Type; + state->window_type = &PyCursesWindow_Type; /* Add some symbolic constants to the module */ PyObject *module_dict = PyModule_GetDict(module); @@ -4907,12 +4921,12 @@ cursesmodule_exec(PyObject *module) } /* For exception curses.error */ - st->error = PyErr_NewException("_curses.error", NULL, NULL); - if (st->error == NULL) { + state->error = PyErr_NewException("_curses.error", NULL, NULL); + if (state->error == NULL) { return -1; } - rc = PyDict_SetItemString(module_dict, "error", st->error); - Py_DECREF(st->error); + rc = PyDict_SetItemString(module_dict, "error", state->error); + Py_DECREF(state->error); if (rc < 0) { return -1; } From 3936143d9b0b357b251c9073b43502f2554b0d01 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, 29 Sep 2024 16:51:46 +0200 Subject: [PATCH 38/38] fix test --- Modules/_cursesmodule.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index e6d2f926bc04c3..a3de86f18ad191 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -235,21 +235,21 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam return 0; } -#define PyCursesStatefulSetupTermCalled(MODULE) \ - do { \ - if (_PyCursesStatefulCheckFunction(MODULE, \ - curses_setupterm_called, \ - "setupterm")) \ - { \ - return 0; \ - } \ +#define PyCursesStatefulSetupTermCalled(MODULE) \ + do { \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_setupterm_called, \ + "setupterm")) \ + { \ + return 0; \ + } \ } while (0) #define PyCursesStatefulInitialised(MODULE) \ do { \ - if (_PyCursesStatefulCheckFunction(MODULE, \ - curses_initscr_called, \ - "initscr")) \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_initscr_called, \ + "initscr")) \ { \ return 0; \ } \ @@ -257,9 +257,9 @@ _PyCursesStatefulCheckFunction(PyObject *module, int called, const char *funcnam #define PyCursesStatefulInitialisedColor(MODULE) \ do { \ - if (_PyCursesStatefulCheckFunction(MODULE, \ - curses_start_color_called, \ - "start_color")) \ + if (!_PyCursesStatefulCheckFunction(MODULE, \ + curses_start_color_called, \ + "start_color")) \ { \ return 0; \ } \