diff options
Diffstat (limited to 'Objects/exceptions.c')
-rw-r--r-- | Objects/exceptions.c | 98 |
1 files changed, 97 insertions, 1 deletions
diff --git a/Objects/exceptions.c b/Objects/exceptions.c index e900243..cbc41e8 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -28,6 +28,7 @@ BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; /* the dict is created on the fly in PyObject_GenericSetAttr */ self->dict = NULL; + self->traceback = NULL; self->args = PyTuple_New(0); if (!self->args) { @@ -56,6 +57,7 @@ BaseException_clear(PyBaseExceptionObject *self) { Py_CLEAR(self->dict); Py_CLEAR(self->args); + Py_CLEAR(self->traceback); return 0; } @@ -72,6 +74,7 @@ BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg) { Py_VISIT(self->dict); Py_VISIT(self->args); + Py_VISIT(self->traceback); return 0; } @@ -135,10 +138,20 @@ BaseException_setstate(PyObject *self, PyObject *state) Py_RETURN_NONE; } +static PyObject * +BaseException_with_traceback(PyObject *self, PyObject *tb) { + if (PyException_SetTraceback(self, tb)) + return NULL; + + Py_INCREF(self); + return self; +} + static PyMethodDef BaseException_methods[] = { {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS }, {"__setstate__", (PyCFunction)BaseException_setstate, METH_O }, + {"with_traceback", (PyCFunction)BaseException_with_traceback, METH_O }, {NULL, NULL, 0, NULL}, }; @@ -198,14 +211,97 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val) return 0; } +static PyObject * +BaseException_get_tb(PyBaseExceptionObject *self) +{ + if (self->traceback == NULL) { + Py_INCREF(Py_None); + return Py_None; + } + Py_INCREF(self->traceback); + return self->traceback; +} + +static int +BaseException_set_tb(PyBaseExceptionObject *self, PyObject *tb) +{ + if (tb == NULL) { + PyErr_SetString(PyExc_TypeError, "__traceback__ may not be deleted"); + return -1; + } + else if (!(tb == Py_None || PyTraceBack_Check(tb))) { + PyErr_SetString(PyExc_TypeError, + "__traceback__ must be a traceback or None"); + return -1; + } + + Py_XINCREF(tb); + Py_XDECREF(self->traceback); + self->traceback = tb; + return 0; +} + static PyGetSetDef BaseException_getset[] = { {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict}, {"args", (getter)BaseException_get_args, (setter)BaseException_set_args}, + {"__traceback__", (getter)BaseException_get_tb, (setter)BaseException_set_tb}, {NULL}, }; +PyObject * +PyException_GetTraceback(PyObject *self) { + PyBaseExceptionObject *base_self = (PyBaseExceptionObject *)self; + Py_XINCREF(base_self->traceback); + return base_self->traceback; +} + + +int +PyException_SetTraceback(PyObject *self, PyObject *tb) { + return BaseException_set_tb((PyBaseExceptionObject *)self, tb); +} + +PyObject * +PyException_GetCause(PyObject *self) { + PyObject *cause = ((PyBaseExceptionObject *)self)->cause; + Py_XINCREF(cause); + return cause; +} + +/* Steals a reference to cause */ +void +PyException_SetCause(PyObject *self, PyObject *cause) { + PyObject *old_cause = ((PyBaseExceptionObject *)self)->cause; + ((PyBaseExceptionObject *)self)->cause = cause; + Py_XDECREF(old_cause); +} + +PyObject * +PyException_GetContext(PyObject *self) { + PyObject *context = ((PyBaseExceptionObject *)self)->context; + Py_XINCREF(context); + return context; +} + +/* Steals a reference to context */ +void +PyException_SetContext(PyObject *self, PyObject *context) { + PyObject *old_context = ((PyBaseExceptionObject *)self)->context; + ((PyBaseExceptionObject *)self)->context = context; + Py_XDECREF(old_context); +} + + +static PyMemberDef BaseException_members[] = { + {"__context__", T_OBJECT, offsetof(PyBaseExceptionObject, context), 0, + PyDoc_STR("exception context")}, + {"__cause__", T_OBJECT, offsetof(PyBaseExceptionObject, cause), 0, + PyDoc_STR("exception cause")}, + {NULL} /* Sentinel */ +}; + static PyTypeObject _PyExc_BaseException = { PyVarObject_HEAD_INIT(NULL, 0) "BaseException", /*tp_name*/ @@ -236,7 +332,7 @@ static PyTypeObject _PyExc_BaseException = { 0, /* tp_iter */ 0, /* tp_iternext */ BaseException_methods, /* tp_methods */ - 0, /* tp_members */ + BaseException_members, /* tp_members */ BaseException_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ |