• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // clinic/exceptions.c.h uses internal pycore_modsupport.h API
2 #define PYTESTCAPI_NEED_INTERNAL_API
3 
4 #include "parts.h"
5 #include "util.h"
6 #include "clinic/exceptions.c.h"
7 
8 
9 /*[clinic input]
10 module _testcapi
11 [clinic start generated code]*/
12 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/
13 
14 /*[clinic input]
15 _testcapi.err_set_raised
16     exception as exc: object
17     /
18 [clinic start generated code]*/
19 
20 static PyObject *
_testcapi_err_set_raised(PyObject * module,PyObject * exc)21 _testcapi_err_set_raised(PyObject *module, PyObject *exc)
22 /*[clinic end generated code: output=0a0c7743961fcae5 input=c5f7331864a94df9]*/
23 {
24     Py_INCREF(exc);
25     PyErr_SetRaisedException(exc);
26     assert(PyErr_Occurred());
27     return NULL;
28 }
29 
30 static PyObject *
err_restore(PyObject * self,PyObject * args)31 err_restore(PyObject *self, PyObject *args) {
32     PyObject *type = NULL, *value = NULL, *traceback = NULL;
33     switch(PyTuple_Size(args)) {
34         case 3:
35             traceback = PyTuple_GetItem(args, 2);
36             Py_INCREF(traceback);
37             /* fall through */
38         case 2:
39             value = PyTuple_GetItem(args, 1);
40             Py_INCREF(value);
41             /* fall through */
42         case 1:
43             type = PyTuple_GetItem(args, 0);
44             Py_INCREF(type);
45             break;
46         default:
47             PyErr_SetString(PyExc_TypeError,
48                         "wrong number of arguments");
49             return NULL;
50     }
51     PyErr_Restore(type, value, traceback);
52     assert(PyErr_Occurred());
53     return NULL;
54 }
55 
56 /*[clinic input]
57 _testcapi.exception_print
58     exception as exc: object
59     legacy: bool = False
60     /
61 
62 To test the format of exceptions as printed out.
63 [clinic start generated code]*/
64 
65 static PyObject *
_testcapi_exception_print_impl(PyObject * module,PyObject * exc,int legacy)66 _testcapi_exception_print_impl(PyObject *module, PyObject *exc, int legacy)
67 /*[clinic end generated code: output=3f04fe0c18412ae0 input=c76f42cb94136dbf]*/
68 {
69     if (legacy) {
70         PyObject *tb = NULL;
71         if (PyExceptionInstance_Check(exc)) {
72             tb = PyException_GetTraceback(exc);
73         }
74         PyErr_Display((PyObject *) Py_TYPE(exc), exc, tb);
75         Py_XDECREF(tb);
76     }
77     else {
78         PyErr_DisplayException(exc);
79     }
80     Py_RETURN_NONE;
81 }
82 
83 /*[clinic input]
84 _testcapi.make_exception_with_doc
85     name: str
86     doc: str = NULL
87     base: object = NULL
88     dict: object = NULL
89 
90 Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). Run via Lib/test/test_exceptions.py
91 [clinic start generated code]*/
92 
93 static PyObject *
_testcapi_make_exception_with_doc_impl(PyObject * module,const char * name,const char * doc,PyObject * base,PyObject * dict)94 _testcapi_make_exception_with_doc_impl(PyObject *module, const char *name,
95                                        const char *doc, PyObject *base,
96                                        PyObject *dict)
97 /*[clinic end generated code: output=439f0d963c1ce2c4 input=23a73013f8a8795a]*/
98 {
99     return PyErr_NewExceptionWithDoc(name, doc, base, dict);
100 }
101 
102 /*[clinic input]
103 _testcapi.exc_set_object
104     exception as exc: object
105     obj: object
106     /
107 [clinic start generated code]*/
108 
109 static PyObject *
_testcapi_exc_set_object_impl(PyObject * module,PyObject * exc,PyObject * obj)110 _testcapi_exc_set_object_impl(PyObject *module, PyObject *exc, PyObject *obj)
111 /*[clinic end generated code: output=34c8c7c83e5c8463 input=fc530aafb1b0a360]*/
112 {
113     PyErr_SetObject(exc, obj);
114     return NULL;
115 }
116 
117 /*[clinic input]
118 _testcapi.exc_set_object_fetch = _testcapi.exc_set_object
119 [clinic start generated code]*/
120 
121 static PyObject *
_testcapi_exc_set_object_fetch_impl(PyObject * module,PyObject * exc,PyObject * obj)122 _testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc,
123                                     PyObject *obj)
124 /*[clinic end generated code: output=7a5ff5f6d3cf687f input=77ec686f1f95fa38]*/
125 {
126     PyObject *type = UNINITIALIZED_PTR;
127     PyObject *value = UNINITIALIZED_PTR;
128     PyObject *tb = UNINITIALIZED_PTR;
129 
130     PyErr_SetObject(exc, obj);
131     PyErr_Fetch(&type, &value, &tb);
132     assert(type != UNINITIALIZED_PTR);
133     assert(value != UNINITIALIZED_PTR);
134     assert(tb != UNINITIALIZED_PTR);
135     Py_XDECREF(type);
136     Py_XDECREF(tb);
137     return value;
138 }
139 
140 /*[clinic input]
141 _testcapi.err_setstring
142     exc: object
143     value: str(zeroes=True, accept={robuffer, str, NoneType})
144     /
145 [clinic start generated code]*/
146 
147 static PyObject *
_testcapi_err_setstring_impl(PyObject * module,PyObject * exc,const char * value,Py_ssize_t value_length)148 _testcapi_err_setstring_impl(PyObject *module, PyObject *exc,
149                              const char *value, Py_ssize_t value_length)
150 /*[clinic end generated code: output=fba8705e5703dd3f input=e8a95fad66d9004b]*/
151 {
152     NULLABLE(exc);
153     PyErr_SetString(exc, value);
154     return NULL;
155 }
156 
157 /*[clinic input]
158 _testcapi.err_setfromerrnowithfilename
159     error: int
160     exc: object
161     value: str(zeroes=True, accept={robuffer, str, NoneType})
162     /
163 [clinic start generated code]*/
164 
165 static PyObject *
_testcapi_err_setfromerrnowithfilename_impl(PyObject * module,int error,PyObject * exc,const char * value,Py_ssize_t value_length)166 _testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error,
167                                             PyObject *exc, const char *value,
168                                             Py_ssize_t value_length)
169 /*[clinic end generated code: output=d02df5749a01850e input=ff7c384234bf097f]*/
170 {
171     NULLABLE(exc);
172     errno = error;
173     PyErr_SetFromErrnoWithFilename(exc, value);
174     return NULL;
175 }
176 
177 /*[clinic input]
178 _testcapi.raise_exception
179     exception as exc: object
180     num_args: int
181     /
182 [clinic start generated code]*/
183 
184 static PyObject *
_testcapi_raise_exception_impl(PyObject * module,PyObject * exc,int num_args)185 _testcapi_raise_exception_impl(PyObject *module, PyObject *exc, int num_args)
186 /*[clinic end generated code: output=eb0a9c5d69e0542d input=83d6262c3829d088]*/
187 {
188     PyObject *exc_args = PyTuple_New(num_args);
189     if (exc_args == NULL) {
190         return NULL;
191     }
192     for (int i = 0; i < num_args; ++i) {
193         PyObject *v = PyLong_FromLong(i);
194         if (v == NULL) {
195             Py_DECREF(exc_args);
196             return NULL;
197         }
198         PyTuple_SET_ITEM(exc_args, i, v);
199     }
200     PyErr_SetObject(exc, exc_args);
201     Py_DECREF(exc_args);
202     return NULL;
203 }
204 
205 /*[clinic input]
206 _testcapi.raise_memoryerror
207 [clinic start generated code]*/
208 
209 static PyObject *
_testcapi_raise_memoryerror_impl(PyObject * module)210 _testcapi_raise_memoryerror_impl(PyObject *module)
211 /*[clinic end generated code: output=dd057803fb0131e6 input=6ca521bd07fb73cb]*/
212 {
213     return PyErr_NoMemory();
214 }
215 
216 /*[clinic input]
217 _testcapi.fatal_error
218     message: str(accept={robuffer})
219     release_gil: bool = False
220     /
221 [clinic start generated code]*/
222 
223 static PyObject *
_testcapi_fatal_error_impl(PyObject * module,const char * message,int release_gil)224 _testcapi_fatal_error_impl(PyObject *module, const char *message,
225                            int release_gil)
226 /*[clinic end generated code: output=9c3237116e6a03e8 input=1be357a2ccb04c8c]*/
227 {
228     if (release_gil) {
229         Py_BEGIN_ALLOW_THREADS
230         Py_FatalError(message);
231         Py_END_ALLOW_THREADS
232     }
233     else {
234         Py_FatalError(message);
235     }
236     // Py_FatalError() does not return, but exits the process.
237     Py_RETURN_NONE;
238 }
239 
240 /*[clinic input]
241 _testcapi.set_exc_info
242     new_type: object
243     new_value: object
244     new_tb: object
245     /
246 [clinic start generated code]*/
247 
248 static PyObject *
_testcapi_set_exc_info_impl(PyObject * module,PyObject * new_type,PyObject * new_value,PyObject * new_tb)249 _testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type,
250                             PyObject *new_value, PyObject *new_tb)
251 /*[clinic end generated code: output=b55fa35dec31300e input=ea9f19e0f55fe5b3]*/
252 {
253     PyObject *type = UNINITIALIZED_PTR, *value = UNINITIALIZED_PTR, *tb = UNINITIALIZED_PTR;
254     PyErr_GetExcInfo(&type, &value, &tb);
255 
256     Py_INCREF(new_type);
257     Py_INCREF(new_value);
258     Py_INCREF(new_tb);
259     PyErr_SetExcInfo(new_type, new_value, new_tb);
260 
261     PyObject *orig_exc = PyTuple_Pack(3,
262             type  ? type  : Py_None,
263             value ? value : Py_None,
264             tb    ? tb    : Py_None);
265     Py_XDECREF(type);
266     Py_XDECREF(value);
267     Py_XDECREF(tb);
268     return orig_exc;
269 }
270 
271 /*[clinic input]
272 _testcapi.set_exception
273     new_exc: object
274     /
275 [clinic start generated code]*/
276 
277 static PyObject *
_testcapi_set_exception(PyObject * module,PyObject * new_exc)278 _testcapi_set_exception(PyObject *module, PyObject *new_exc)
279 /*[clinic end generated code: output=8b969b35d029e96d input=c89d4ca966c69738]*/
280 {
281     PyObject *exc = PyErr_GetHandledException();
282     assert(PyExceptionInstance_Check(exc) || exc == NULL);
283     PyErr_SetHandledException(new_exc);
284     return exc;
285 }
286 
287 /*[clinic input]
288 _testcapi.traceback_print
289     traceback: object
290     file: object
291     /
292 To test the format of tracebacks as printed out.
293 [clinic start generated code]*/
294 
295 static PyObject *
_testcapi_traceback_print_impl(PyObject * module,PyObject * traceback,PyObject * file)296 _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
297                                PyObject *file)
298 /*[clinic end generated code: output=17074ecf9d95cf30 input=9423f2857b008ca8]*/
299 {
300     if (PyTraceBack_Print(traceback, file) < 0) {
301         return NULL;
302     }
303     Py_RETURN_NONE;
304 }
305 
306 static PyObject *
err_writeunraisable(PyObject * Py_UNUSED (module),PyObject * args)307 err_writeunraisable(PyObject *Py_UNUSED(module), PyObject *args)
308 {
309     PyObject *exc, *obj;
310     if (!PyArg_ParseTuple(args, "OO", &exc, &obj)) {
311         return NULL;
312     }
313     NULLABLE(exc);
314     NULLABLE(obj);
315     if (exc) {
316         PyErr_SetRaisedException(Py_NewRef(exc));
317     }
318     PyErr_WriteUnraisable(obj);
319     Py_RETURN_NONE;
320 }
321 
322 static PyObject *
err_formatunraisable(PyObject * Py_UNUSED (module),PyObject * args)323 err_formatunraisable(PyObject *Py_UNUSED(module), PyObject *args)
324 {
325     PyObject *exc;
326     const char *fmt;
327     Py_ssize_t fmtlen;
328     PyObject *objs[10] = {NULL};
329 
330     if (!PyArg_ParseTuple(args, "Oz#|OOOOOOOOOO", &exc, &fmt, &fmtlen,
331             &objs[0], &objs[1], &objs[2], &objs[3], &objs[4],
332             &objs[5], &objs[6], &objs[7], &objs[8], &objs[9]))
333     {
334         return NULL;
335     }
336     NULLABLE(exc);
337     if (exc) {
338         PyErr_SetRaisedException(Py_NewRef(exc));
339     }
340     PyErr_FormatUnraisable(fmt,
341             objs[0], objs[1], objs[2], objs[3], objs[4],
342             objs[5], objs[6], objs[7], objs[8], objs[9]);
343     Py_RETURN_NONE;
344 }
345 
346 /*[clinic input]
347 _testcapi.unstable_exc_prep_reraise_star
348     orig: object
349     excs: object
350     /
351 To test PyUnstable_Exc_PrepReraiseStar.
352 [clinic start generated code]*/
353 
354 static PyObject *
_testcapi_unstable_exc_prep_reraise_star_impl(PyObject * module,PyObject * orig,PyObject * excs)355 _testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
356                                               PyObject *orig, PyObject *excs)
357 /*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
358 {
359     return PyUnstable_Exc_PrepReraiseStar(orig, excs);
360 }
361 
362 
363 /*
364  * Define the PyRecurdingInfinitelyError_Type
365  */
366 
367 static PyTypeObject PyRecursingInfinitelyError_Type;
368 
369 static int
recurse_infinitely_error_init(PyObject * self,PyObject * args,PyObject * kwds)370 recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
371 {
372     PyObject *type = (PyObject *)&PyRecursingInfinitelyError_Type;
373 
374     /* Instantiating this exception starts infinite recursion. */
375     Py_INCREF(type);
376     PyErr_SetObject(type, NULL);
377     return -1;
378 }
379 
380 static PyTypeObject PyRecursingInfinitelyError_Type = {
381     .tp_name = "RecursingInfinitelyError",
382     .tp_basicsize = sizeof(PyBaseExceptionObject),
383     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
384     .tp_doc = PyDoc_STR("Instantiating this exception starts infinite recursion."),
385     .tp_init = (initproc)recurse_infinitely_error_init,
386 };
387 
388 static PyMethodDef test_methods[] = {
389     {"err_restore",             err_restore,                     METH_VARARGS},
390     {"err_writeunraisable",     err_writeunraisable,             METH_VARARGS},
391     {"err_formatunraisable",    err_formatunraisable,            METH_VARARGS},
392     _TESTCAPI_ERR_SET_RAISED_METHODDEF
393     _TESTCAPI_EXCEPTION_PRINT_METHODDEF
394     _TESTCAPI_FATAL_ERROR_METHODDEF
395     _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF
396     _TESTCAPI_EXC_SET_OBJECT_METHODDEF
397     _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF
398     _TESTCAPI_ERR_SETSTRING_METHODDEF
399     _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF
400     _TESTCAPI_RAISE_EXCEPTION_METHODDEF
401     _TESTCAPI_RAISE_MEMORYERROR_METHODDEF
402     _TESTCAPI_SET_EXC_INFO_METHODDEF
403     _TESTCAPI_SET_EXCEPTION_METHODDEF
404     _TESTCAPI_TRACEBACK_PRINT_METHODDEF
405     _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
406     {NULL},
407 };
408 
409 int
_PyTestCapi_Init_Exceptions(PyObject * mod)410 _PyTestCapi_Init_Exceptions(PyObject *mod)
411 {
412     PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
413     if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
414         return -1;
415     }
416     if (PyModule_AddObjectRef(mod, "RecursingInfinitelyError",
417                               (PyObject *)&PyRecursingInfinitelyError_Type) < 0)
418     {
419         return -1;
420     }
421 
422     if (PyModule_AddFunctions(mod, test_methods) < 0) {
423         return -1;
424     }
425 
426     return 0;
427 }
428