PyObject* PyCodec_StrictErrors(PyObject* exc) noexcept { if (PyExceptionInstance_Check(exc)) PyErr_SetObject(PyExceptionInstance_Class(exc), exc); else PyErr_SetString(PyExc_TypeError, "codec must pass exception instance"); return NULL; }
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_IMPLICIT( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb ) { CHECK_OBJECT( *exception_type ); CHECK_OBJECT( *exception_value ); *exception_tb = NULL; // Non-empty tuple exceptions are the first element. while (unlikely( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 )) { *exception_type = PyTuple_GET_ITEM( *exception_type, 0 ); } if ( PyExceptionClass_Check( *exception_type ) ) { return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); return; } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
int PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) { if (err == NULL || exc == NULL) { /* maybe caused by "import exceptions" that failed early on */ return 0; } if (PyTuple_Check(exc)) { Py_ssize_t i, n; n = PyTuple_Size(exc); for (i = 0; i < n; i++) { /* Test recursively */ if (PyErr_GivenExceptionMatches( err, PyTuple_GET_ITEM(exc, i))) { return 1; } } return 0; } /* err might be an instance, so check its class. */ if (PyExceptionInstance_Check(err)) err = PyExceptionInstance_Class(err); if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { return PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc); } return err == exc; }
int PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) { if (err == NULL || exc == NULL) { /* maybe caused by "import exceptions" that failed early on */ return 0; } if (PyTuple_Check(exc)) { Py_ssize_t i, n; n = PyTuple_Size(exc); for (i = 0; i < n; i++) { /* Test recursively */ if (PyErr_GivenExceptionMatches( err, PyTuple_GET_ITEM(exc, i))) { return 1; } } return 0; } /* err might be an instance, so check its class. */ if (PyExceptionInstance_Check(err)) err = PyExceptionInstance_Class(err); if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { /* problems here!? not sure PyObject_IsSubclass expects to be called with an exception pending... */ return PyObject_IsSubclass(err, exc); } return err == exc; }
static PyObject * gen_throw(PyGenObject *gen, PyObject *typ, PyObject *val, PyObject *tb) { /* First, check the traceback argument, replacing None with NULL. */ if (tb == Py_None) tb = NULL; else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format(PyExc_TypeError, "exceptions must be classes, or instances, not %s", typ->ob_type->tp_name); goto failed_throw; } PyErr_Restore(typ, val, tb); return gen_send_ex(gen, Py_None, 1); failed_throw: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
// takes the three arguments of a `raise' and produces the ExcInfo to throw ExcInfo excInfoForRaise(Box* type, Box* value, Box* tb) { assert(type && value && tb); // use None for default behavior, not nullptr // TODO switch this to PyErr_Normalize if (tb == None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { raiseExcHelper(TypeError, "raise: arg 3 must be a traceback or None"); } /* Next, repeatedly, replace a tuple exception with its first item */ while (PyTuple_Check(type) && PyTuple_Size(type) > 0) { PyObject* tmp = type; type = PyTuple_GET_ITEM(type, 0); Py_INCREF(type); Py_DECREF(tmp); } if (PyExceptionClass_Check(type)) { PyErr_NormalizeException(&type, &value, &tb); if (!PyExceptionInstance_Check(value)) { raiseExcHelper(TypeError, "calling %s() should have returned an instance of " "BaseException, not '%s'", ((PyTypeObject*)type)->tp_name, Py_TYPE(value)->tp_name); } } else if (PyExceptionInstance_Check(type)) { /* Raising an instance. The value should be a dummy. */ if (value != Py_None) { raiseExcHelper(TypeError, "instance exception may not have a separate value"); } else { /* Normalize to raise <class>, <instance> */ Py_DECREF(value); value = type; type = PyExceptionInstance_Class(type); Py_INCREF(type); } } else { /* Not something you can raise. You get an exception anyway, just not what you specified :-) */ raiseExcHelper(TypeError, "exceptions must be old-style classes or " "derived from BaseException, not %s", type->cls->tp_name); } assert(PyExceptionClass_Check(type)); if (tb == NULL) { tb = None; } return ExcInfo(type, value, tb); }
static PyObject* compose_throw(PyComposeObject* self, PyObject* arg) { PyObject* exc_type = NULL, *exc_value = NULL, *exc_tb = NULL; if(!PyArg_ParseTuple(arg, "O|OO", &exc_type, &exc_value, &exc_tb)) //borrowed refs return NULL; if(PyExceptionInstance_Check(exc_type)) { // e.g. throw(Exception()) exc_value = exc_type; exc_type = PyExceptionInstance_Class(exc_type); // borrowed ref } return _compose_go_with_frame(self, exc_type, exc_value, exc_tb); }
int PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) { if (err == NULL || exc == NULL) { /* maybe caused by "import exceptions" that failed early on */ return 0; } if (PyTuple_Check(exc)) { Py_ssize_t i, n; n = PyTuple_Size(exc); for (i = 0; i < n; i++) { /* Test recursively */ if (PyErr_GivenExceptionMatches( err, PyTuple_GET_ITEM(exc, i))) { return 1; } } return 0; } /* err might be an instance, so check its class. */ if (PyExceptionInstance_Check(err)) err = PyExceptionInstance_Class(err); if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { int res = 0, reclimit; PyObject *exception, *value, *tb; PyErr_Fetch(&exception, &value, &tb); /* Temporarily bump the recursion limit, so that in the most common case PyObject_IsSubclass will not raise a recursion error we have to ignore anyway. Don't do it when the limit is already insanely high, to avoid overflow */ reclimit = Py_GetRecursionLimit(); if (reclimit < (1 << 30)) Py_SetRecursionLimit(reclimit + 5); res = PyObject_IsSubclass(err, exc); Py_SetRecursionLimit(reclimit); /* This function must not fail, so print the error here */ if (res == -1) { PyErr_WriteUnraisable(err); res = 0; } PyErr_Restore(exception, value, tb); return res; } return err == exc; }
NUITKA_MAY_BE_UNUSED static bool EXCEPTION_MATCH_GENERATOR( PyObject *exception_value ) { CHECK_OBJECT( exception_value ); // We need to check the class. if ( PyExceptionInstance_Check( exception_value ) ) { exception_value = PyExceptionInstance_Class( exception_value ); } // Lets be optimistic. If it matches, we would be wasting our time. if ( exception_value == PyExc_GeneratorExit || exception_value == PyExc_StopIteration ) { return true; } if ( PyExceptionClass_Check( exception_value ) ) { // Save the current exception, if any, we must preserve it. PyObject *save_exception_type, *save_exception_value; PyTracebackObject *save_exception_tb; FETCH_ERROR_OCCURRED( &save_exception_type, &save_exception_value, &save_exception_tb ); int res = PyObject_IsSubclass( exception_value, PyExc_GeneratorExit ); // This function must not fail, so print the error here */ if (unlikely( res == -1 )) { PyErr_WriteUnraisable( exception_value ); } if (res == 1) return true; res = PyObject_IsSubclass( exception_value, PyExc_StopIteration ); // This function must not fail, so print the error here */ if (unlikely( res == -1 )) { PyErr_WriteUnraisable( exception_value ); } RESTORE_ERROR_OCCURRED( save_exception_type, save_exception_value, save_exception_tb ); return res == 1; } return false; }
int PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc) { if (err == NULL || exc == NULL) { /* maybe caused by "import exceptions" that failed early on */ return 0; } if (PyTuple_Check(exc)) { Py_ssize_t i, n; n = PyTuple_Size(exc); for (i = 0; i < n; i++) { /* Test recursively */ if (PyErr_GivenExceptionMatches( err, PyTuple_GET_ITEM(exc, i))) { return 1; } } return 0; } /* err might be an instance, so check its class. */ if (PyExceptionInstance_Check(err)) err = PyExceptionInstance_Class(err); if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) { int res = 0; PyObject *exception, *value, *tb; PyErr_Fetch(&exception, &value, &tb); /* PyObject_IsSubclass() can recurse and therefore is not safe (see test_bad_getattr in test.pickletester). */ res = PyType_IsSubtype((PyTypeObject *)err, (PyTypeObject *)exc); /* This function must not fail, so print the error here */ if (res == -1) { PyErr_WriteUnraisable(err); res = 0; } PyErr_Restore(exception, value, tb); return res; } return err == exc; }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_VALUE_NO_NORMALIZE( PyObject *exception_type, PyObject *value, PyObject *tb ) { PyTracebackObject *traceback = (PyTracebackObject *)tb; assertObject( exception_type ); assert( !PyTuple_Check( exception_type ) ); if ( PyExceptionClass_Check( exception_type ) ) { throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT_X( traceback ) ); } else if ( PyExceptionInstance_Check( exception_type ) ) { assert ( value == NULL || value == Py_None ); // The type is rather a value, so we are overriding it here. value = exception_type; exception_type = PyExceptionInstance_Class( exception_type ); throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT_X( traceback ) ); } else { assert( false ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); throw PythonException(); } }
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb ) { *exception_value = NULL; *exception_tb = NULL; #if PYTHON_VERSION < 300 // Next, repeatedly, replace a tuple exception with its first item while( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 ) { PyObject *tmp = *exception_type; *exception_type = PyTuple_GET_ITEM( *exception_type, 0 ); Py_INCREF( *exception_type ); Py_DECREF( tmp ); } #endif if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)*exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); Py_DECREF( *exception_type ); Py_DECREF( *exception_value ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } #endif #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_type, *exception_value ); #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_type, *exception_value ); // TODO: Ever true? if ( *exception_tb ) { PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( *exception_value ); if ( prev != NULL ) { assert( (*exception_tb)->tb_next == NULL ); (*exception_tb)->tb_next = prev; } PyException_SetTraceback( *exception_value, (PyObject *)(*exception_tb ? *exception_tb : (PyTracebackObject *)Py_None ) ); } *exception_tb = (PyTracebackObject *)PyException_GetTraceback( *exception_value ); #endif return; } else { Py_DECREF( *exception_type ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( *exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
NUITKA_MAY_BE_UNUSED static inline void RAISE_EXCEPTION_WITH_TRACEBACK( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb ) { CHECK_OBJECT( *exception_type ); CHECK_OBJECT( *exception_value ); if ( *exception_tb == (PyTracebackObject *)Py_None ) { Py_DECREF( *exception_tb ); *exception_tb = NULL; } // Non-empty tuple exceptions are the first element. while (unlikely( PyTuple_Check( *exception_type ) && PyTuple_Size( *exception_type ) > 0 )) { *exception_type = PyTuple_GET_ITEM( *exception_type, 0 ); } if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)*exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); } #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { if (unlikely( *exception_value != NULL && *exception_value != Py_None )) { PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } // The type is rather a value, so we are overriding it here. *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); return; } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject **exception_type, PyObject **exception_value, PyTracebackObject **exception_tb, PyObject *exception_cause ) { CHECK_OBJECT( *exception_type ); CHECK_OBJECT( exception_cause ); *exception_value = NULL; *exception_tb = NULL; #if PYTHON_VERSION >= 330 // None is not a cause. if ( exception_cause == Py_None ) { Py_DECREF( exception_cause ); exception_cause = NULL; } else #endif if ( PyExceptionClass_Check( exception_cause ) ) { PyObject *old_exception_cause = exception_cause; exception_cause = PyObject_CallObject( exception_cause, NULL ); Py_DECREF( old_exception_cause ); if (unlikely( exception_cause == NULL )) { Py_DECREF( *exception_type ); Py_XDECREF( *exception_tb ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } } #if PYTHON_VERSION >= 330 if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) )) #else if (unlikely( !PyExceptionInstance_Check( exception_cause ) )) #endif { Py_DECREF( *exception_type ); Py_XDECREF( *exception_tb ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } if ( PyExceptionClass_Check( *exception_type ) ) { NORMALIZE_EXCEPTION( exception_type, exception_value, exception_tb ); if (unlikely( !PyExceptionInstance_Check( *exception_value ) )) { Py_DECREF( *exception_type ); Py_XDECREF( *exception_value ); Py_DECREF( *exception_tb ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( *exception_value )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } PyException_SetCause( *exception_value, exception_cause ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_type, *exception_value ); #endif return; } else if ( PyExceptionInstance_Check( *exception_type ) ) { *exception_value = *exception_type; *exception_type = PyExceptionInstance_Class( *exception_type ); Py_INCREF( *exception_type ); PyException_SetCause( *exception_value, exception_cause ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( *exception_type, *exception_value ); #endif return; } else { Py_DECREF( *exception_type ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); FETCH_ERROR_OCCURRED( exception_type, exception_value, exception_tb ); return; } }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() XXX: should PyErr_NormalizeException() also call PyException_SetTraceback() with the resulting value and tb? */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { int recursion_depth = 0; PyObject *type, *value, *initial_tb; restart: type = *exc; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } value = *val; /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { PyObject *inclass = NULL; int is_subclass = 0; if (PyExceptionInstance_Check(value)) { inclass = PyExceptionInstance_Class(value); is_subclass = PyObject_IsSubclass(inclass, type); if (is_subclass < 0) { goto error; } } /* If the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!is_subclass) { PyObject *fixed_value = _PyErr_CreateException(type, value); if (fixed_value == NULL) { goto error; } Py_DECREF(value); value = fixed_value; } /* If the class of the instance doesn't exactly match the class of the type, believe the instance. */ else if (inclass != type) { Py_INCREF(inclass); Py_DECREF(type); type = inclass; } } *exc = type; *val = value; return; error: Py_DECREF(type); Py_DECREF(value); recursion_depth++; if (recursion_depth == Py_NORMALIZE_RECURSION_LIMIT) { PyErr_SetString(PyExc_RecursionError, "maximum recursion depth " "exceeded while normalizing an exception"); } /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); assert(*exc != NULL); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* Abort when Py_NORMALIZE_RECURSION_LIMIT has been exceeded, and the corresponding RecursionError could not be normalized, and the MemoryError raised when normalize this RecursionError could not be normalized. */ if (recursion_depth >= Py_NORMALIZE_RECURSION_LIMIT + 2) { if (PyErr_GivenExceptionMatches(*exc, PyExc_MemoryError)) { Py_FatalError("Cannot recover from MemoryErrors " "while normalizing exceptions."); } else { Py_FatalError("Cannot recover from the recursive normalization " "of an exception."); } } goto restart; }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_CAUSE( PyObject *exception_type, PyObject *exception_cause, PyObject *exception_tb ) { PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; assertObject( exception_type ); assertObject( exception_cause ); #if PYTHON_VERSION >= 330 // None is not a cause. if ( exception_cause == Py_None ) { exception_cause = NULL; } else #endif if ( PyExceptionClass_Check( exception_cause ) ) { exception_cause = PyObject_CallObject( exception_cause, NULL ); if (unlikely( exception_cause == NULL )) { throw PythonException(); } } else { Py_INCREF( exception_cause ); } #if PYTHON_VERSION >= 330 if (unlikely( exception_cause != NULL && !PyExceptionInstance_Check( exception_cause ) )) #else if (unlikely( !PyExceptionInstance_Check( exception_cause ) )) #endif { Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "exception causes must derive from BaseException" ); throw PythonException(); } if ( PyExceptionClass_Check( exception_type ) ) { PyObject *value = NULL; Py_INCREF( exception_type ); Py_INCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); if (unlikely( !PyExceptionInstance_Check( value ) )) { Py_DECREF( exception_type ); Py_XDECREF( value ); Py_DECREF( traceback ); Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); throw PythonException(); } PythonException to_throw( exception_type, value, traceback ); to_throw.setCause( exception_cause ); throw to_throw; } else if ( PyExceptionInstance_Check( exception_type ) ) { Py_XDECREF( exception_cause ); throw PythonException( INCREASE_REFCOUNT( PyExceptionInstance_Class( exception_type ) ), INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( traceback ) ); } else { Py_XDECREF( exception_cause ); PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); PythonException to_throw; to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) ); throw to_throw; } }
static PyObject * Fiber_func_throw(Fiber *self, PyObject *args) { Fiber *current; PyObject *typ, *val, *tb; val = tb = NULL; if (!PyArg_ParseTuple(args, "O|OO:throw", &typ, &val, &tb)) { return NULL; } /* First, check the traceback argument, replacing None, with NULL */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exceptions cannot have a separate value"); goto error; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format(PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(typ)->tp_name); goto error; } if (!CHECK_STATE) { goto error; } current = _global_state.current; if (self == current) { PyErr_SetString(PyExc_FiberError, "cannot throw from a Fiber to itself"); goto error; } if (self->stacklet_h == EMPTY_STACKLET_HANDLE) { PyErr_SetString(PyExc_FiberError, "Fiber has ended"); goto error; } if (self->thread_h != current->thread_h) { PyErr_SetString(PyExc_FiberError, "cannot switch to a Fiber on a different thread"); return NULL; } /* set error and do a switch with NULL as the value */ PyErr_Restore(typ, val, tb); return do_switch(self, NULL); error: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_VALUE( PyObject *exception_type, PyObject *value, PyObject *exception_tb ) { assertObject( exception_type ); PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; // Non-empty tuple exceptions are the first element. while (unlikely( PyTuple_Check( exception_type ) && PyTuple_Size( exception_type ) > 0 )) { exception_type = PyTuple_GET_ITEM( exception_type, 0 ); } if ( PyExceptionClass_Check( exception_type ) ) { Py_INCREF( exception_type ); Py_XINCREF( value ); Py_XINCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( value ) )) { PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); Py_DECREF( exception_type ); Py_XDECREF( value ); Py_XDECREF( traceback ); throw PythonException(); } #endif throw PythonException( exception_type, value, traceback ); } else if ( PyExceptionInstance_Check( exception_type ) ) { if (unlikely( value != NULL && value != Py_None )) { PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); throw PythonException(); } // The type is rather a value, so we are overriding it here. value = exception_type; exception_type = PyExceptionInstance_Class( exception_type ); throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT_X( traceback ) ); } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); throw PythonException(); } }
static PyObject * gen_throw(PyGenObject *gen, PyObject *args) { PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL; PyObject *yf = _PyGen_yf(gen); _Py_IDENTIFIER(throw); if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) return NULL; if (yf) { PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) { gen->gi_running = 1; err = gen_close_iter(yf); gen->gi_running = 0; Py_DECREF(yf); if (err < 0) return gen_send_ex(gen, Py_None, 1, 0); goto throw_here; } if (PyGen_CheckExact(yf)) { gen->gi_running = 1; ret = gen_throw((PyGenObject *)yf, args); gen->gi_running = 0; } else { PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw); if (meth == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { Py_DECREF(yf); return NULL; } PyErr_Clear(); Py_DECREF(yf); goto throw_here; } gen->gi_running = 1; ret = PyObject_CallObject(meth, args); gen->gi_running = 0; Py_DECREF(meth); } Py_DECREF(yf); if (!ret) { PyObject *val; /* Pop subiterator from stack */ ret = *(--gen->gi_frame->f_stacktop); assert(ret == yf); Py_DECREF(ret); /* Termination repetition of YIELD_FROM */ gen->gi_frame->f_lasti += 2; if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send_ex(gen, val, 0, 0); Py_DECREF(val); } else { ret = gen_send_ex(gen, Py_None, 1, 0); } } return ret; } throw_here: /* First, check the traceback argument, replacing None with NULL. */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) PyErr_NormalizeException(&typ, &val, &tb); else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); if (tb == NULL) /* Returns NULL if there's no traceback */ tb = PyException_GetTraceback(val); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format(PyExc_TypeError, "exceptions must be classes or instances " "deriving from BaseException, not %s", Py_TYPE(typ)->tp_name); goto failed_throw; } PyErr_Restore(typ, val, tb); return gen_send_ex(gen, Py_None, 1, 0); failed_throw: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() XXX: should PyErr_NormalizeException() also call PyException_SetTraceback() with the resulting value and tb? */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { PyObject *type = *exc; PyObject *value = *val; PyObject *inclass = NULL; PyObject *initial_tb = NULL; PyThreadState *tstate = NULL; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } if (PyExceptionInstance_Check(value)) inclass = PyExceptionInstance_Class(value); /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { int is_subclass; if (inclass) { is_subclass = PyObject_IsSubclass(inclass, type); if (is_subclass < 0) goto finally; } else is_subclass = 0; /* if the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!inclass || !is_subclass) { PyObject *fixed_value; fixed_value = _PyErr_CreateException(type, value); if (fixed_value == NULL) { goto finally; } Py_DECREF(value); value = fixed_value; } /* if the class of the instance doesn't exactly match the class of the type, believe the instance */ else if (inclass != type) { Py_DECREF(type); type = inclass; Py_INCREF(type); } } *exc = type; *val = value; return; finally: Py_DECREF(type); Py_DECREF(value); /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* normalize recursively */ tstate = PyThreadState_GET(); if (++tstate->recursion_depth > Py_GetRecursionLimit()) { --tstate->recursion_depth; /* throw away the old exception and use the recursion error instead */ Py_INCREF(PyExc_RecursionError); Py_SETREF(*exc, PyExc_RecursionError); Py_INCREF(PyExc_RecursionErrorInst); Py_SETREF(*val, PyExc_RecursionErrorInst); /* just keeping the old traceback */ return; } PyErr_NormalizeException(exc, val, tb); --tstate->recursion_depth; }
/* Used in many places to normalize a raised exception, including in eval_code2(), do_raise(), and PyErr_Print() */ void PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb) { PyObject *type = *exc; PyObject *value = *val; PyObject *inclass = NULL; PyObject *initial_tb = NULL; if (type == NULL) { /* There was no exception, so nothing to do. */ return; } /* If PyErr_SetNone() was used, the value will have been actually set to NULL. */ if (!value) { value = Py_None; Py_INCREF(value); } if (PyExceptionInstance_Check(value)) inclass = PyExceptionInstance_Class(value); /* Normalize the exception so that if the type is a class, the value will be an instance. */ if (PyExceptionClass_Check(type)) { /* if the value was not an instance, or is not an instance whose class is (or is derived from) type, then use the value as an argument to instantiation of the type class. */ if (!inclass || !PyObject_IsSubclass(inclass, type)) { PyObject *args, *res; if (value == Py_None) args = PyTuple_New(0); else if (PyTuple_Check(value)) { Py_INCREF(value); args = value; } else args = PyTuple_Pack(1, value); if (args == NULL) goto finally; res = PyEval_CallObject(type, args); Py_DECREF(args); if (res == NULL) goto finally; Py_DECREF(value); value = res; } /* if the class of the instance doesn't exactly match the class of the type, believe the instance */ else if (inclass != type) { Py_DECREF(type); type = inclass; Py_INCREF(type); } } *exc = type; *val = value; return; finally: Py_DECREF(type); Py_DECREF(value); /* If the new exception doesn't set a traceback and the old exception had a traceback, use the old traceback for the new exception. It's better than nothing. */ initial_tb = *tb; PyErr_Fetch(exc, val, tb); if (initial_tb != NULL) { if (*tb == NULL) *tb = initial_tb; else Py_DECREF(initial_tb); } /* normalize recursively */ PyErr_NormalizeException(exc, val, tb); }
NUITKA_NO_RETURN NUITKA_MAY_BE_UNUSED static void RAISE_EXCEPTION_WITH_TYPE( PyObject *exception_type, PyObject *exception_tb ) { PyTracebackObject *traceback = (PyTracebackObject *)exception_tb; assertObject( traceback ); assert( PyTraceBack_Check( traceback ) ); assertObject( exception_type ); if ( PyExceptionClass_Check( exception_type ) ) { PyObject *value = NULL; Py_INCREF( exception_type ); Py_XINCREF( traceback ); NORMALIZE_EXCEPTION( &exception_type, &value, &traceback ); #if PYTHON_VERSION >= 270 if (unlikely( !PyExceptionInstance_Check( value ) )) { Py_DECREF( exception_type ); Py_DECREF( value ); Py_XDECREF( traceback ); PyErr_Format( PyExc_TypeError, "calling %s() should have returned an instance of BaseException, not '%s'", ((PyTypeObject *)exception_type)->tp_name, Py_TYPE( value )->tp_name ); throw PythonException(); } #endif #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( exception_type, value ); #endif throw PythonException( exception_type, value, traceback ); } else if ( PyExceptionInstance_Check( exception_type ) ) { PyObject *value = exception_type; exception_type = PyExceptionInstance_Class( exception_type ); #if PYTHON_VERSION >= 300 CHAIN_EXCEPTION( exception_type, value ); PyTracebackObject *prev = (PyTracebackObject *)PyException_GetTraceback( value ); if ( prev != NULL ) { assert( traceback->tb_next == NULL ); traceback->tb_next = prev; } PyException_SetTraceback( value, (PyObject *)traceback ); #endif throw PythonException( INCREASE_REFCOUNT( exception_type ), INCREASE_REFCOUNT( value ), INCREASE_REFCOUNT( traceback ) ); } else { PyErr_Format( PyExc_TypeError, WRONG_EXCEPTION_TYPE_ERROR_MESSAGE, Py_TYPE( exception_type )->tp_name ); PythonException to_throw; to_throw.setTraceback( INCREASE_REFCOUNT( traceback ) ); throw to_throw; } }
static PyObject * green_throw(PyGreenlet *self, PyObject *args) { PyObject *typ = PyExc_GreenletExit; PyObject *val = NULL; PyObject *tb = NULL; if (!PyArg_ParseTuple(args, "|OOO:throw", &typ, &val, &tb)) { return NULL; } /* First, check the traceback argument, replacing None, with NULL */ if (tb == Py_None) { tb = NULL; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString( PyExc_TypeError, "throw() third argument must be a traceback object"); return NULL; } Py_INCREF(typ); Py_XINCREF(val); Py_XINCREF(tb); if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString( PyExc_TypeError, "instance exception may not have a separate value"); goto failed_throw; } else { /* Normalize to raise <class>, <instance> */ Py_XDECREF(val); val = typ; typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } else { /* Not something you can raise. throw() fails. */ PyErr_Format( PyExc_TypeError, "exceptions must be classes, or instances, not %s", Py_TYPE(typ)->tp_name); goto failed_throw; } return throw_greenlet(self, typ, val, tb); failed_throw: /* Didn't use our arguments, so restore their original refcounts */ Py_DECREF(typ); Py_XDECREF(val); Py_XDECREF(tb); return NULL; }
static PyObject *Nuitka_Generator_throw( struct Nuitka_GeneratorObject *generator, PyObject *args ) { assert( generator->m_exception_type == NULL ); assert( generator->m_exception_value == NULL ); assert( generator->m_exception_tb == NULL ); int res = PyArg_UnpackTuple( args, "throw", 1, 3, &generator->m_exception_type, &generator->m_exception_value, (PyObject **)&generator->m_exception_tb ); if (unlikely( res == 0 )) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } if ( (PyObject *)generator->m_exception_tb == Py_None ) { generator->m_exception_tb = NULL; } else if ( generator->m_exception_tb != NULL && !PyTraceBack_Check( generator->m_exception_tb ) ) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" ); return NULL; } if ( PyExceptionClass_Check( generator->m_exception_type )) { Py_INCREF( generator->m_exception_type ); Py_XINCREF( generator->m_exception_value ); Py_XINCREF( generator->m_exception_tb ); NORMALIZE_EXCEPTION( &generator->m_exception_type, &generator->m_exception_value, &generator->m_exception_tb ); } else if ( PyExceptionInstance_Check( generator->m_exception_type ) ) { if ( generator->m_exception_value && generator->m_exception_value != Py_None ) { generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; PyErr_Format( PyExc_TypeError, "instance exception may not have a separate value" ); return NULL; } generator->m_exception_value = generator->m_exception_type; Py_INCREF( generator->m_exception_value ); generator->m_exception_type = PyExceptionInstance_Class( generator->m_exception_type ); Py_INCREF( generator->m_exception_type ); Py_XINCREF( generator->m_exception_tb ); } else { PyErr_Format( PyExc_TypeError, #if PYTHON_VERSION < 300 "exceptions must be classes, or instances, not %s", #else "exceptions must be classes or instances deriving from BaseException, not %s", #endif Py_TYPE( generator->m_exception_type )->tp_name ); generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } if ( ( generator->m_exception_tb != NULL ) && ( (PyObject *)generator->m_exception_tb != Py_None ) && ( !PyTraceBack_Check( generator->m_exception_tb ) ) ) { PyErr_Format( PyExc_TypeError, "throw() third argument must be a traceback object" ); return NULL; } if ( generator->m_status != status_Finished ) { PyObject *result = Nuitka_Generator_send( generator, Py_None ); return result; } else { RESTORE_ERROR_OCCURRED( generator->m_exception_type, generator->m_exception_value, generator->m_exception_tb ); generator->m_exception_type = NULL; generator->m_exception_value = NULL; generator->m_exception_tb = NULL; return NULL; } }