|
Re: Pyrex exception type checking broken under Python 2.5 (and earlier): msg#00043python.pyrex
Hi Greg, Greg Ewing wrote: > Stefan Behnel wrote: >> Pyrex uses this code in __Pyx_Raise() to check if an exception object >> has the right type for being raised: >> >> The problem is that exceptions in Py2.5 have become new-style classes >> which no longer fall under any of the above checks. >> >> Also, support for string exceptions is deprecated and supposed to be >> removed in later Python versions. I therefore propose to actually >> remove the above check from Pyrex completely. > > What I'd really like is an API call for raising an exception that > does all the same things as the Python raise statement. There > didn't seem to be such a call at the time I wrote that code. There still doesn't seem to be a function that checks the argument types. > I'd be wary about removing the checks altogether, because I > wouldn't be surprised if you could cause a crash by stuffing > arbitrary values into the exception variables. I don't quite buy that argument - it's unlikely that it crashes, at least, and having the Python interpreter raise exceptions for wrong arguments should be fine. But since 2.5's interpreter actually checks for exception inheritance in do_raise(), Pyrex can well do that, too. Ok, so the only new thing is that instances of new-style classes are 'objects', just as new-style classes themselves. What Python 2.5 does is check that they inherit from BaseException. Since that's not available in earlier versions, what about checking that raised new-style objects (which are not currently allowed at all in Pyrex) inherit from PyErr_Exception? I find that a reasonable restriction. The following is based on do_raise() in Py2.5. You can remove string support completely by simply dropping the "if (PyString_CheckExact(type)) { } else" part, however, Py*_CheckExact tends to be pretty fast, so there's not much you loose by printing a warning as Py2.5 does. I couldn't test it on earlier Python versions than 2.4, BTW, but it 'should' work on 2.2. Stefan static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb) { Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); /* First, check the traceback argument, replacing None with NULL. */ if (tb == Py_None) { Py_DECREF(tb); tb = 0; } else if (tb != NULL && !PyTraceBack_Check(tb)) { PyErr_SetString(PyExc_TypeError, "raise: arg 3 must be a traceback or None"); goto raise_error; } /* Next, replace a missing value with None */ if (value == NULL) { value = Py_None; Py_INCREF(value); } /* 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 (PyString_CheckExact(type)) { /* Raising builtin string is deprecated but still allowed -- * do nothing. Raising an instance of a new-style str * subclass is right out. */ if (PyErr_Warn(PyExc_DeprecationWarning, "raising a string exception is deprecated")) goto raise_error; } else if (PyType_Check(type) || PyClass_Check(type)) ; /* PyErr_NormalizeException(&type, &value, &tb); */ else if (PyInstance_Check(type)) { /* Raising an instance. The value should be a dummy. */ if (value != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } else { /* Normalize to raise <class>, <instance> */ Py_DECREF(value); value = type; type = (PyObject*) ((PyInstanceObject*)type)->in_class; Py_INCREF(type); } } else if (PyType_IsSubtype(type->ob_type, (PyTypeObject*)PyExc_Exception)){ /* Raising a new-style object (in Py2.5). The value should be a dummy. */ if (value != Py_None) { PyErr_SetString(PyExc_TypeError, "instance exception may not have a separate value"); goto raise_error; } else { /* Normalize to raise <class>, <instance> */ Py_DECREF(value); value = type; type = type->ob_type; Py_INCREF(type); } } else { /* Not something you can raise. You get an exception anyway, just not what you specified :-) */ PyErr_Format(PyExc_TypeError, "exceptions must be classes, instances, or " "strings (deprecated), not %s", type->ob_type->tp_name); goto raise_error; } PyErr_Restore(type, value, tb); return; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(tb); return; } |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: Pyrex exception type checking broken under Python 2.5 (and earlier): 00043, Greg Ewing |
|---|---|
| Next by Date: | Re: Pyrex exception type checking broken under Python 2.5 (and earlier): 00043, Greg Ewing |
| Previous by Thread: | Re: Pyrex exception type checking broken under Python 2.5 (and earlier)i: 00043, Greg Ewing |
| Next by Thread: | Re: Pyrex exception type checking broken under Python 2.5 (and earlier): 00043, Greg Ewing |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |