@@ -194,9 +194,8 @@ get_cursesmodule_state_by_win(PyCursesWindowObject *win)
194194/*[clinic input]
195195module _curses
196196class _curses.window "PyCursesWindowObject *" "clinic_state()->window_type"
197- class _curses.error "PyCursesErrorObject *" "clinic_state()->error"
198197[clinic start generated code]*/
199- /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a6b4ac3824e7c5c3 ]*/
198+ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=ae6cb623018f2cbc ]*/
200199
201200/* Indicate whether the module has already been loaded or not. */
202201static int curses_module_loaded = 0 ;
@@ -214,110 +213,14 @@ static const char *curses_screen_encoding = NULL;
214213
215214/* Error type */
216215
217- #define CURSES_ERROR_FORMAT "%s() returned ERR"
218- #define CURSES_ERROR_NULL_FORMAT "%s() returned NULL"
219- #define CURSES_ERROR_MUST_CALL_FORMAT "must call %s() first"
220-
221- typedef struct {
222- PyException_HEAD
223- /* The name of the curses function that triggered the error. */
224- PyObject * funcname ;
225- } PyCursesErrorObject ;
226-
227- #define _PyCursesErrorObject_CAST (PTR ) ((PyCursesErrorObject *)(PTR))
228-
229- static int
230- PyCursesError_clear (PyObject * self )
231- {
232- PyCursesErrorObject * exc = _PyCursesErrorObject_CAST (self );
233- Py_CLEAR (exc -> funcname );
234- return _PyType_CAST (PyExc_Exception )-> tp_clear (self );
235- }
236-
237- static void
238- PyCursesError_dealloc (PyObject * self )
239- {
240- PyTypeObject * tp = Py_TYPE (self );
241- PyObject_GC_UnTrack (self );
242- (void )PyCursesError_clear (self );
243- tp -> tp_free (self );
244- Py_DECREF (tp );
245- }
246-
247- static int
248- PyCursesError_traverse (PyObject * self , visitproc visit , void * arg )
249- {
250- Py_VISIT (Py_TYPE (self ));
251- PyCursesErrorObject * exc = _PyCursesErrorObject_CAST (self );
252- Py_VISIT (exc -> funcname );
253- return _PyType_CAST (PyExc_Exception )-> tp_traverse (self , visit , arg );
254- }
255-
256- /*[clinic input]
257- @getter
258- _curses.error.funcname
259- [clinic start generated code]*/
260-
261- static PyObject *
262- _curses_error_funcname_get_impl (PyCursesErrorObject * self )
263- /*[clinic end generated code: output=bddac78d045d9e92 input=a0ed7b814bba25e9]*/
264- {
265- PyObject * res = self -> funcname ;
266- return res == NULL ? Py_None : Py_NewRef (res );
267- }
268-
269- /*[clinic input]
270- @setter
271- _curses.error.funcname
272- [clinic start generated code]*/
273-
274- static int
275- _curses_error_funcname_set_impl (PyCursesErrorObject * self , PyObject * value )
276- /*[clinic end generated code: output=1320e03bf8c27ca8 input=e7ad8f11456a402e]*/
277- {
278- if (PyUnicode_Check (value ) || Py_IsNone (value )) {
279- Py_XSETREF (self -> funcname , Py_NewRef (value ));
280- return 0 ;
281- }
282- PyErr_Format (PyExc_TypeError , "expecting a str or None, got %T" , value );
283- return -1 ;
284- }
216+ #define CURSES_ERROR_FORMAT "%s() returned ERR"
217+ #define CURSES_ERROR_VERBOSE_FORMAT "%s() (called by %s()) returned ERR"
218+ #define CURSES_ERROR_NULL_FORMAT "%s() returned NULL"
219+ #define CURSES_ERROR_NULL_VERBOSE_FORMAT "%s() (called by %s()) returned NULL"
220+ #define CURSES_ERROR_MUST_CALL_FORMAT "must call %s() first"
285221
286222/* Utility Error Procedures */
287223
288- static inline void
289- PyCursesError_SetImplementation (
290- #ifndef NDEBUG
291- cursesmodule_state * state ,
292- #else
293- cursesmodule_state * Py_UNUSED (state ),
294- #endif
295- const char * funcname )
296- {
297- assert (funcname != NULL );
298- PyObject * exc = PyErr_GetRaisedException ();
299- assert (PyErr_GivenExceptionMatches (exc , state -> error ));
300- PyObject * p_funcname = PyUnicode_FromString (funcname );
301- if (p_funcname == NULL ) {
302- goto error ;
303- }
304- int rc = PyObject_SetAttrString (exc , "funcname" , p_funcname );
305- Py_DECREF (p_funcname );
306- if (rc < 0 ) {
307- goto error ;
308- }
309-
310- restore :
311- PyErr_SetRaisedException (exc );
312- return ;
313-
314- error :
315- // The curses exception is likely more important than the
316- // exceptions that we get if we fail to set the attribute.
317- PyErr_Clear ();
318- goto restore ;
319- }
320-
321224/*
322225 * Format a curses error.
323226 *
@@ -335,10 +238,18 @@ _PyCursesSetError(cursesmodule_state *state,
335238 return ;
336239 }
337240 if (simple_funcname == NULL ) {
338- simple_funcname = curses_funcname ;
241+ PyErr_Format (state -> error , CURSES_ERROR_FORMAT , curses_funcname );
242+ }
243+ else if (curses_funcname == NULL ) {
244+ PyErr_Format (state -> error , CURSES_ERROR_FORMAT , simple_funcname );
245+ }
246+ else if (strcmp (simple_funcname , curses_funcname ) == 0 ) {
247+ PyErr_Format (state -> error , CURSES_ERROR_FORMAT , simple_funcname );
248+ }
249+ else {
250+ PyErr_Format (state -> error , CURSES_ERROR_VERBOSE_FORMAT ,
251+ curses_funcname , simple_funcname );
339252 }
340- PyErr_Format (state -> error , CURSES_ERROR_FORMAT , simple_funcname );
341- PyCursesError_SetImplementation (state , curses_funcname );
342253}
343254
344255static void
@@ -1673,7 +1584,6 @@ _curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1,
16731584 if (win == NULL ) {
16741585 cursesmodule_state * state = get_cursesmodule_state_by_win (self );
16751586 PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "derwin" );
1676- PyCursesError_SetImplementation (state , "derwin" );
16771587 return NULL ;
16781588 }
16791589
@@ -1830,9 +1740,8 @@ _curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1,
18301740 PyErr_CheckSignals ();
18311741 if (!PyErr_Occurred ()) {
18321742 cursesmodule_state * state = get_cursesmodule_state_by_win (self );
1833- PyErr_SetString (state -> error , "no input" );
18341743 const char * funcname = group_right_1 ? "mvwgetch" : "wgetch" ;
1835- PyCursesError_SetImplementation (state , funcname );
1744+ PyErr_Format (state -> error , "getkey(): %s(): no input" , funcname );
18361745 }
18371746 return NULL ;
18381747 } else if (rtn <= 255 ) {
@@ -1894,7 +1803,7 @@ _curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1,
18941803 cursesmodule_state * state = get_cursesmodule_state_by_win (self );
18951804 PyErr_SetString (state -> error , "no input" );
18961805 const char * funcname = group_right_1 ? "mvwget_wch" : "wget_wch" ;
1897- PyCursesError_SetImplementation (state , funcname );
1806+ PyErr_Format (state -> error , "get_wch(): %s(): no input" , funcname );
18981807 return NULL ;
18991808 }
19001809 if (ct == KEY_CODE_YES )
@@ -2752,8 +2661,8 @@ _curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1,
27522661
27532662 if (win == NULL ) {
27542663 cursesmodule_state * state = get_cursesmodule_state_by_win (self );
2755- PyErr_SetString (state -> error , catchall_NULL );
2756- PyCursesError_SetImplementation ( state , curses_funcname );
2664+ PyErr_Format (state -> error , CURSES_ERROR_NULL_VERBOSE_FORMAT ,
2665+ curses_funcname , "subwin" );
27572666 return NULL ;
27582667 }
27592668
@@ -2916,29 +2825,6 @@ PyCursesWindow_set_encoding(PyObject *op, PyObject *value, void *Py_UNUSED(ignor
29162825#include "clinic/_cursesmodule.c.h"
29172826#undef clinic_state
29182827
2919- static PyGetSetDef PyCursesError_Type_getsets [] = {
2920- _CURSES_ERROR_FUNCNAME_GETSETDEF
2921- {NULL }
2922- };
2923-
2924- static PyType_Slot PyCursesError_Type_slots [] = {
2925- {Py_tp_getset , PyCursesError_Type_getsets },
2926- {Py_tp_dealloc , PyCursesError_dealloc },
2927- {Py_tp_traverse , PyCursesError_traverse },
2928- {Py_tp_clear , PyCursesError_clear },
2929- {0 , NULL },
2930- };
2931-
2932- static PyType_Spec PyCursesError_Type_spec = {
2933- .name = "_curses.error" ,
2934- .basicsize = sizeof (PyCursesErrorObject ),
2935- .flags = Py_TPFLAGS_DEFAULT
2936- | Py_TPFLAGS_BASETYPE
2937- | Py_TPFLAGS_IMMUTABLETYPE
2938- | Py_TPFLAGS_HAVE_GC ,
2939- .slots = PyCursesError_Type_slots ,
2940- };
2941-
29422828static PyMethodDef PyCursesWindow_methods [] = {
29432829 _CURSES_WINDOW_ADDCH_METHODDEF
29442830 _CURSES_WINDOW_ADDNSTR_METHODDEF
@@ -3547,8 +3433,7 @@ _curses_getwin(PyObject *module, PyObject *file)
35473433 win = getwin (fp );
35483434 if (win == NULL ) {
35493435 cursesmodule_state * state = get_cursesmodule_state (module );
3550- PyErr_SetString (state -> error , catchall_NULL );
3551- PyCursesError_SetImplementation (state , "getwin" );
3436+ PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "getwin" );
35523437 goto error ;
35533438 }
35543439 cursesmodule_state * state = get_cursesmodule_state (module );
@@ -3730,8 +3615,7 @@ _curses_initscr_impl(PyObject *module)
37303615
37313616 if (win == NULL ) {
37323617 cursesmodule_state * state = get_cursesmodule_state (module );
3733- PyErr_SetString (state -> error , catchall_NULL );
3734- PyCursesError_SetImplementation (state , "initscr" );
3618+ PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "initscr" );
37353619 return NULL ;
37363620 }
37373621
@@ -3891,7 +3775,6 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd)
38913775
38923776 cursesmodule_state * state = get_cursesmodule_state (module );
38933777 PyErr_SetString (state -> error , s );
3894- PyCursesError_SetImplementation (state , "setupterm" );
38953778 return NULL ;
38963779 }
38973780
@@ -4212,8 +4095,7 @@ _curses_newpad_impl(PyObject *module, int nlines, int ncols)
42124095
42134096 if (win == NULL ) {
42144097 cursesmodule_state * state = get_cursesmodule_state (module );
4215- PyErr_SetString (state -> error , catchall_NULL );
4216- PyCursesError_SetImplementation (state , "newpad" );
4098+ PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "newpad" );
42174099 return NULL ;
42184100 }
42194101
@@ -4254,8 +4136,7 @@ _curses_newwin_impl(PyObject *module, int nlines, int ncols,
42544136 win = newwin (nlines ,ncols ,begin_y ,begin_x );
42554137 if (win == NULL ) {
42564138 cursesmodule_state * state = get_cursesmodule_state (module );
4257- PyErr_SetString (state -> error , catchall_NULL );
4258- PyCursesError_SetImplementation (state , "newwin" );
4139+ PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "newwin" );
42594140 return NULL ;
42604141 }
42614142
@@ -4857,7 +4738,6 @@ _curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3,
48574738 if (!result ) {
48584739 cursesmodule_state * state = get_cursesmodule_state (module );
48594740 PyErr_Format (state -> error , CURSES_ERROR_NULL_FORMAT , "tparm" );
4860- PyCursesError_SetImplementation (state , "tparm" );
48614741 return NULL ;
48624742 }
48634743
@@ -5348,22 +5228,7 @@ cursesmodule_exec(PyObject *module)
53485228 curses_module_loaded = 1 ;
53495229
53505230 cursesmodule_state * state = get_cursesmodule_state (module );
5351- /* Initialize error type */
5352- PyObject * bases = PyTuple_Pack (1 , PyExc_Exception );
5353- if (bases == NULL ) {
5354- return -1 ;
5355- }
5356- state -> error = PyType_FromModuleAndSpec (module , & PyCursesError_Type_spec ,
5357- bases );
5358- Py_DECREF (bases );
5359- if (state -> error == NULL ) {
5360- return -1 ;
5361- }
5362- if (PyModule_AddType (module , _PyType_CAST (state -> error )) < 0 ) {
5363- return -1 ;
5364- }
5365-
5366- /* Initialize window type */
5231+ /* Initialize object type */
53675232 state -> window_type = (PyTypeObject * )PyType_FromModuleAndSpec (
53685233 module , & PyCursesWindow_Type_spec , NULL );
53695234 if (state -> window_type == NULL ) {
@@ -5396,6 +5261,16 @@ cursesmodule_exec(PyObject *module)
53965261 return -1 ;
53975262 }
53985263
5264+ /* For exception curses.error */
5265+ state -> error = PyErr_NewException ("_curses.error" , NULL , NULL );
5266+ if (state -> error == NULL ) {
5267+ return -1 ;
5268+ }
5269+ rc = PyDict_SetItemString (module_dict , "error" , state -> error );
5270+ if (rc < 0 ) {
5271+ return -1 ;
5272+ }
5273+
53995274 /* Make the version available */
54005275 PyObject * curses_version = PyBytes_FromString (PyCursesVersion );
54015276 if (curses_version == NULL ) {
0 commit comments