mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			402 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // clinic/exceptions.c.h uses internal pycore_modsupport.h API
 | |
| #define PYTESTCAPI_NEED_INTERNAL_API
 | |
| 
 | |
| #include "parts.h"
 | |
| #include "util.h"
 | |
| #include "clinic/exceptions.c.h"
 | |
| 
 | |
| 
 | |
| /*[clinic input]
 | |
| module _testcapi
 | |
| [clinic start generated code]*/
 | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.err_set_raised
 | |
|     exception as exc: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_err_set_raised(PyObject *module, PyObject *exc)
 | |
| /*[clinic end generated code: output=0a0c7743961fcae5 input=c5f7331864a94df9]*/
 | |
| {
 | |
|     Py_INCREF(exc);
 | |
|     PyErr_SetRaisedException(exc);
 | |
|     assert(PyErr_Occurred());
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| err_restore(PyObject *self, PyObject *args) {
 | |
|     PyObject *type = NULL, *value = NULL, *traceback = NULL;
 | |
|     switch(PyTuple_Size(args)) {
 | |
|         case 3:
 | |
|             traceback = PyTuple_GetItem(args, 2);
 | |
|             Py_INCREF(traceback);
 | |
|             /* fall through */
 | |
|         case 2:
 | |
|             value = PyTuple_GetItem(args, 1);
 | |
|             Py_INCREF(value);
 | |
|             /* fall through */
 | |
|         case 1:
 | |
|             type = PyTuple_GetItem(args, 0);
 | |
|             Py_INCREF(type);
 | |
|             break;
 | |
|         default:
 | |
|             PyErr_SetString(PyExc_TypeError,
 | |
|                         "wrong number of arguments");
 | |
|             return NULL;
 | |
|     }
 | |
|     PyErr_Restore(type, value, traceback);
 | |
|     assert(PyErr_Occurred());
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.exception_print
 | |
|     exception as exc: object
 | |
|     legacy: bool = False
 | |
|     /
 | |
| 
 | |
| To test the format of exceptions as printed out.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_exception_print_impl(PyObject *module, PyObject *exc, int legacy)
 | |
| /*[clinic end generated code: output=3f04fe0c18412ae0 input=c76f42cb94136dbf]*/
 | |
| {
 | |
|     if (legacy) {
 | |
|         PyObject *tb = NULL;
 | |
|         if (PyExceptionInstance_Check(exc)) {
 | |
|             tb = PyException_GetTraceback(exc);
 | |
|         }
 | |
|         PyErr_Display((PyObject *) Py_TYPE(exc), exc, tb);
 | |
|         Py_XDECREF(tb);
 | |
|     }
 | |
|     else {
 | |
|         PyErr_DisplayException(exc);
 | |
|     }
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.make_exception_with_doc
 | |
|     name: str
 | |
|     doc: str = NULL
 | |
|     base: object = NULL
 | |
|     dict: object = NULL
 | |
| 
 | |
| Test PyErr_NewExceptionWithDoc (also exercise PyErr_NewException). Run via Lib/test/test_exceptions.py
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_make_exception_with_doc_impl(PyObject *module, const char *name,
 | |
|                                        const char *doc, PyObject *base,
 | |
|                                        PyObject *dict)
 | |
| /*[clinic end generated code: output=439f0d963c1ce2c4 input=23a73013f8a8795a]*/
 | |
| {
 | |
|     return PyErr_NewExceptionWithDoc(name, doc, base, dict);
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.exc_set_object
 | |
|     exception as exc: object
 | |
|     obj: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_exc_set_object_impl(PyObject *module, PyObject *exc, PyObject *obj)
 | |
| /*[clinic end generated code: output=34c8c7c83e5c8463 input=fc530aafb1b0a360]*/
 | |
| {
 | |
|     PyErr_SetObject(exc, obj);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.exc_set_object_fetch = _testcapi.exc_set_object
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_exc_set_object_fetch_impl(PyObject *module, PyObject *exc,
 | |
|                                     PyObject *obj)
 | |
| /*[clinic end generated code: output=7a5ff5f6d3cf687f input=77ec686f1f95fa38]*/
 | |
| {
 | |
|     PyObject *type = UNINITIALIZED_PTR;
 | |
|     PyObject *value = UNINITIALIZED_PTR;
 | |
|     PyObject *tb = UNINITIALIZED_PTR;
 | |
| 
 | |
|     PyErr_SetObject(exc, obj);
 | |
|     PyErr_Fetch(&type, &value, &tb);
 | |
|     assert(type != UNINITIALIZED_PTR);
 | |
|     assert(value != UNINITIALIZED_PTR);
 | |
|     assert(tb != UNINITIALIZED_PTR);
 | |
|     Py_XDECREF(type);
 | |
|     Py_XDECREF(tb);
 | |
|     return value;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.err_setstring
 | |
|     exc: object
 | |
|     value: str(zeroes=True, accept={robuffer, str, NoneType})
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_err_setstring_impl(PyObject *module, PyObject *exc,
 | |
|                              const char *value, Py_ssize_t value_length)
 | |
| /*[clinic end generated code: output=fba8705e5703dd3f input=e8a95fad66d9004b]*/
 | |
| {
 | |
|     NULLABLE(exc);
 | |
|     PyErr_SetString(exc, value);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.err_setfromerrnowithfilename
 | |
|     error: int
 | |
|     exc: object
 | |
|     value: str(zeroes=True, accept={robuffer, str, NoneType})
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_err_setfromerrnowithfilename_impl(PyObject *module, int error,
 | |
|                                             PyObject *exc, const char *value,
 | |
|                                             Py_ssize_t value_length)
 | |
| /*[clinic end generated code: output=d02df5749a01850e input=ff7c384234bf097f]*/
 | |
| {
 | |
|     NULLABLE(exc);
 | |
|     errno = error;
 | |
|     PyErr_SetFromErrnoWithFilename(exc, value);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.raise_exception
 | |
|     exception as exc: object
 | |
|     num_args: int
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_raise_exception_impl(PyObject *module, PyObject *exc, int num_args)
 | |
| /*[clinic end generated code: output=eb0a9c5d69e0542d input=83d6262c3829d088]*/
 | |
| {
 | |
|     PyObject *exc_args = PyTuple_New(num_args);
 | |
|     if (exc_args == NULL) {
 | |
|         return NULL;
 | |
|     }
 | |
|     for (int i = 0; i < num_args; ++i) {
 | |
|         PyObject *v = PyLong_FromLong(i);
 | |
|         if (v == NULL) {
 | |
|             Py_DECREF(exc_args);
 | |
|             return NULL;
 | |
|         }
 | |
|         PyTuple_SET_ITEM(exc_args, i, v);
 | |
|     }
 | |
|     PyErr_SetObject(exc, exc_args);
 | |
|     Py_DECREF(exc_args);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.raise_memoryerror
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_raise_memoryerror_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=dd057803fb0131e6 input=6ca521bd07fb73cb]*/
 | |
| {
 | |
|     return PyErr_NoMemory();
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.fatal_error
 | |
|     message: str(accept={robuffer})
 | |
|     release_gil: bool = False
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_fatal_error_impl(PyObject *module, const char *message,
 | |
|                            int release_gil)
 | |
| /*[clinic end generated code: output=9c3237116e6a03e8 input=1be357a2ccb04c8c]*/
 | |
| {
 | |
|     if (release_gil) {
 | |
|         Py_BEGIN_ALLOW_THREADS
 | |
|         Py_FatalError(message);
 | |
|         Py_END_ALLOW_THREADS
 | |
|     }
 | |
|     else {
 | |
|         Py_FatalError(message);
 | |
|     }
 | |
|     // Py_FatalError() does not return, but exits the process.
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.set_exc_info
 | |
|     new_type: object
 | |
|     new_value: object
 | |
|     new_tb: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_set_exc_info_impl(PyObject *module, PyObject *new_type,
 | |
|                             PyObject *new_value, PyObject *new_tb)
 | |
| /*[clinic end generated code: output=b55fa35dec31300e input=ea9f19e0f55fe5b3]*/
 | |
| {
 | |
|     PyObject *type = UNINITIALIZED_PTR, *value = UNINITIALIZED_PTR, *tb = UNINITIALIZED_PTR;
 | |
|     PyErr_GetExcInfo(&type, &value, &tb);
 | |
| 
 | |
|     Py_INCREF(new_type);
 | |
|     Py_INCREF(new_value);
 | |
|     Py_INCREF(new_tb);
 | |
|     PyErr_SetExcInfo(new_type, new_value, new_tb);
 | |
| 
 | |
|     PyObject *orig_exc = PyTuple_Pack(3,
 | |
|             type  ? type  : Py_None,
 | |
|             value ? value : Py_None,
 | |
|             tb    ? tb    : Py_None);
 | |
|     Py_XDECREF(type);
 | |
|     Py_XDECREF(value);
 | |
|     Py_XDECREF(tb);
 | |
|     return orig_exc;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.set_exception
 | |
|     new_exc: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_set_exception(PyObject *module, PyObject *new_exc)
 | |
| /*[clinic end generated code: output=8b969b35d029e96d input=c89d4ca966c69738]*/
 | |
| {
 | |
|     PyObject *exc = PyErr_GetHandledException();
 | |
|     assert(PyExceptionInstance_Check(exc) || exc == NULL);
 | |
|     PyErr_SetHandledException(new_exc);
 | |
|     return exc;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.traceback_print
 | |
|     traceback: object
 | |
|     file: object
 | |
|     /
 | |
| To test the format of tracebacks as printed out.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_traceback_print_impl(PyObject *module, PyObject *traceback,
 | |
|                                PyObject *file)
 | |
| /*[clinic end generated code: output=17074ecf9d95cf30 input=9423f2857b008ca8]*/
 | |
| {
 | |
|     if (PyTraceBack_Print(traceback, file) < 0) {
 | |
|         return NULL;
 | |
|     }
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| err_writeunraisable(PyObject *Py_UNUSED(module), PyObject *args)
 | |
| {
 | |
|     PyObject *exc, *obj;
 | |
|     if (!PyArg_ParseTuple(args, "OO", &exc, &obj)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     NULLABLE(exc);
 | |
|     NULLABLE(obj);
 | |
|     if (exc) {
 | |
|         PyErr_SetRaisedException(Py_NewRef(exc));
 | |
|     }
 | |
|     PyErr_WriteUnraisable(obj);
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.unstable_exc_prep_reraise_star
 | |
|     orig: object
 | |
|     excs: object
 | |
|     /
 | |
| To test PyUnstable_Exc_PrepReraiseStar.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_unstable_exc_prep_reraise_star_impl(PyObject *module,
 | |
|                                               PyObject *orig, PyObject *excs)
 | |
| /*[clinic end generated code: output=850cf008e0563c77 input=27fbcda2203eb301]*/
 | |
| {
 | |
|     return PyUnstable_Exc_PrepReraiseStar(orig, excs);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Define the PyRecurdingInfinitelyError_Type
 | |
|  */
 | |
| 
 | |
| static PyTypeObject PyRecursingInfinitelyError_Type;
 | |
| 
 | |
| static int
 | |
| recurse_infinitely_error_init(PyObject *self, PyObject *args, PyObject *kwds)
 | |
| {
 | |
|     PyObject *type = (PyObject *)&PyRecursingInfinitelyError_Type;
 | |
| 
 | |
|     /* Instantiating this exception starts infinite recursion. */
 | |
|     Py_INCREF(type);
 | |
|     PyErr_SetObject(type, NULL);
 | |
|     return -1;
 | |
| }
 | |
| 
 | |
| static PyTypeObject PyRecursingInfinitelyError_Type = {
 | |
|     .tp_name = "RecursingInfinitelyError",
 | |
|     .tp_basicsize = sizeof(PyBaseExceptionObject),
 | |
|     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
 | |
|     .tp_doc = PyDoc_STR("Instantiating this exception starts infinite recursion."),
 | |
|     .tp_init = (initproc)recurse_infinitely_error_init,
 | |
| };
 | |
| 
 | |
| static PyMethodDef test_methods[] = {
 | |
|     {"err_restore",             err_restore,                     METH_VARARGS},
 | |
|     {"err_writeunraisable",     err_writeunraisable,             METH_VARARGS},
 | |
|     _TESTCAPI_ERR_SET_RAISED_METHODDEF
 | |
|     _TESTCAPI_EXCEPTION_PRINT_METHODDEF
 | |
|     _TESTCAPI_FATAL_ERROR_METHODDEF
 | |
|     _TESTCAPI_MAKE_EXCEPTION_WITH_DOC_METHODDEF
 | |
|     _TESTCAPI_EXC_SET_OBJECT_METHODDEF
 | |
|     _TESTCAPI_EXC_SET_OBJECT_FETCH_METHODDEF
 | |
|     _TESTCAPI_ERR_SETSTRING_METHODDEF
 | |
|     _TESTCAPI_ERR_SETFROMERRNOWITHFILENAME_METHODDEF
 | |
|     _TESTCAPI_RAISE_EXCEPTION_METHODDEF
 | |
|     _TESTCAPI_RAISE_MEMORYERROR_METHODDEF
 | |
|     _TESTCAPI_SET_EXC_INFO_METHODDEF
 | |
|     _TESTCAPI_SET_EXCEPTION_METHODDEF
 | |
|     _TESTCAPI_TRACEBACK_PRINT_METHODDEF
 | |
|     _TESTCAPI_UNSTABLE_EXC_PREP_RERAISE_STAR_METHODDEF
 | |
|     {NULL},
 | |
| };
 | |
| 
 | |
| int
 | |
| _PyTestCapi_Init_Exceptions(PyObject *mod)
 | |
| {
 | |
|     PyRecursingInfinitelyError_Type.tp_base = (PyTypeObject *)PyExc_Exception;
 | |
|     if (PyType_Ready(&PyRecursingInfinitelyError_Type) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
|     if (PyModule_AddObjectRef(mod, "RecursingInfinitelyError",
 | |
|                               (PyObject *)&PyRecursingInfinitelyError_Type) < 0)
 | |
|     {
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     if (PyModule_AddFunctions(mod, test_methods) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | 
