2147 lines · 58.3 KB · C
RawDownload
/* * New exceptions.c written in Iceland by Richard Jones and Georg Brandl. * * Thanks go to Tim Peters and Michael Hudson for debugging. */ #define PY_SSIZE_T_CLEAN#include <Python.h>#include "structmember.h"#include "osdefs.h" #define MAKE_IT_NONE(x) (x) = Py_None; Py_INCREF(Py_None);#define EXC_MODULE_NAME "exceptions." /* NOTE: If the exception class hierarchy changes, don't forget to update * Lib/test/exception_hierarchy.txt */ PyDoc_STRVAR(exceptions_doc, "Python's standard exception class hierarchy.\n\\n\Exceptions found here are defined both in the exceptions module and the\n\built-in namespace.  It is recommended that user-defined exceptions\n\inherit from Exception.  See the documentation for the exception\n\inheritance hierarchy.\n\"); /* *    BaseException */static PyObject *BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds){    PyBaseExceptionObject *self;     self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);    /* the dict is created on the fly in PyObject_GenericSetAttr */    self->message = self->dict = NULL;     self->args = PyTuple_New(0);    if (!self->args) {        Py_DECREF(self);        return NULL;    }     self->message = PyString_FromString("");    if (!self->message) {        Py_DECREF(self);        return NULL;    }     return (PyObject *)self;} static intBaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds){    if (!_PyArg_NoKeywords(self->ob_type->tp_name, kwds))        return -1;     Py_DECREF(self->args);    self->args = args;    Py_INCREF(self->args);     if (PyTuple_GET_SIZE(self->args) == 1) {        Py_CLEAR(self->message);        self->message = PyTuple_GET_ITEM(self->args, 0);        Py_INCREF(self->message);    }    return 0;} static intBaseException_clear(PyBaseExceptionObject *self){    Py_CLEAR(self->dict);    Py_CLEAR(self->args);    Py_CLEAR(self->message);    return 0;} static voidBaseException_dealloc(PyBaseExceptionObject *self){    _PyObject_GC_UNTRACK(self);    BaseException_clear(self);    self->ob_type->tp_free((PyObject *)self);} static intBaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg){    Py_VISIT(self->dict);    Py_VISIT(self->args);    Py_VISIT(self->message);    return 0;} static PyObject *BaseException_str(PyBaseExceptionObject *self){    PyObject *out;     switch (PyTuple_GET_SIZE(self->args)) {    case 0:        out = PyString_FromString("");        break;    case 1:        out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));        break;    default:        out = PyObject_Str(self->args);        break;    }     return out;} static PyObject *BaseException_repr(PyBaseExceptionObject *self){    PyObject *repr_suffix;    PyObject *repr;    char *name;    char *dot;     repr_suffix = PyObject_Repr(self->args);    if (!repr_suffix)        return NULL;     name = (char *)self->ob_type->tp_name;    dot = strrchr(name, '.');    if (dot != NULL) name = dot+1;     repr = PyString_FromString(name);    if (!repr) {        Py_DECREF(repr_suffix);        return NULL;    }     PyString_ConcatAndDel(&repr, repr_suffix);    return repr;} /* Pickling support */static PyObject *BaseException_reduce(PyBaseExceptionObject *self){    if (self->args && self->dict)        return PyTuple_Pack(3, self->ob_type, self->args, self->dict);    else        return PyTuple_Pack(2, self->ob_type, self->args);} /* * Needed for backward compatibility, since exceptions used to store * all their attributes in the __dict__. Code is taken from cPickle's * load_build function. */static PyObject *BaseException_setstate(PyObject *self, PyObject *state){    PyObject *d_key, *d_value;    Py_ssize_t i = 0;     if (state != Py_None) {        if (!PyDict_Check(state)) {            PyErr_SetString(PyExc_TypeError, "state is not a dictionary");            return NULL;        }        while (PyDict_Next(state, &i, &d_key, &d_value)) {            if (PyObject_SetAttr(self, d_key, d_value) < 0)                return NULL;        }    }    Py_RETURN_NONE;}  static PyMethodDef BaseException_methods[] = {   {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },   {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },   {NULL, NULL, 0, NULL},};   static PyObject *BaseException_getitem(PyBaseExceptionObject *self, Py_ssize_t index){    return PySequence_GetItem(self->args, index);} static PyObject *BaseException_getslice(PyBaseExceptionObject *self,			Py_ssize_t start, Py_ssize_t stop){    return PySequence_GetSlice(self->args, start, stop);} static PySequenceMethods BaseException_as_sequence = {    0,                      /* sq_length; */    0,                      /* sq_concat; */    0,                      /* sq_repeat; */    (ssizeargfunc)BaseException_getitem,  /* sq_item; */    (ssizessizeargfunc)BaseException_getslice,  /* sq_slice; */    0,                      /* sq_ass_item; */    0,                      /* sq_ass_slice; */    0,                      /* sq_contains; */    0,                      /* sq_inplace_concat; */    0                       /* sq_inplace_repeat; */}; static PyMemberDef BaseException_members[] = {    {"message", T_OBJECT, offsetof(PyBaseExceptionObject, message), 0,        PyDoc_STR("exception message")},    {NULL}  /* Sentinel */};  static PyObject *BaseException_get_dict(PyBaseExceptionObject *self){    if (self->dict == NULL) {        self->dict = PyDict_New();        if (!self->dict)            return NULL;    }    Py_INCREF(self->dict);    return self->dict;} static intBaseException_set_dict(PyBaseExceptionObject *self, PyObject *val){    if (val == NULL) {        PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");        return -1;    }    if (!PyDict_Check(val)) {        PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");        return -1;    }    Py_CLEAR(self->dict);    Py_INCREF(val);    self->dict = val;    return 0;} static PyObject *BaseException_get_args(PyBaseExceptionObject *self){    if (self->args == NULL) {        Py_INCREF(Py_None);        return Py_None;    }    Py_INCREF(self->args);    return self->args;} static intBaseException_set_args(PyBaseExceptionObject *self, PyObject *val){    PyObject *seq;    if (val == NULL) {        PyErr_SetString(PyExc_TypeError, "args may not be deleted");        return -1;    }    seq = PySequence_Tuple(val);    if (!seq) return -1;    Py_CLEAR(self->args);    self->args = seq;    return 0;} static PyGetSetDef BaseException_getset[] = {    {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict},    {"args", (getter)BaseException_get_args, (setter)BaseException_set_args},    {NULL},};  static PyTypeObject _PyExc_BaseException = {    PyObject_HEAD_INIT(NULL)    0,                          /*ob_size*/    EXC_MODULE_NAME "BaseException", /*tp_name*/    sizeof(PyBaseExceptionObject), /*tp_basicsize*/    0,                          /*tp_itemsize*/    (destructor)BaseException_dealloc, /*tp_dealloc*/    0,                          /*tp_print*/    0,                          /*tp_getattr*/    0,                          /*tp_setattr*/    0,                          /* tp_compare; */    (reprfunc)BaseException_repr, /*tp_repr*/    0,                          /*tp_as_number*/    &BaseException_as_sequence, /*tp_as_sequence*/    0,                          /*tp_as_mapping*/    0,                          /*tp_hash */    0,                          /*tp_call*/    (reprfunc)BaseException_str,  /*tp_str*/    PyObject_GenericGetAttr,    /*tp_getattro*/    PyObject_GenericSetAttr,    /*tp_setattro*/    0,                          /*tp_as_buffer*/    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,  /*tp_flags*/    PyDoc_STR("Common base class for all exceptions"), /* tp_doc */    (traverseproc)BaseException_traverse, /* tp_traverse */    (inquiry)BaseException_clear, /* tp_clear */    0,                          /* tp_richcompare */    0,                          /* tp_weaklistoffset */    0,                          /* tp_iter */    0,                          /* tp_iternext */    BaseException_methods,      /* tp_methods */    BaseException_members,      /* tp_members */    BaseException_getset,       /* tp_getset */    0,                          /* tp_base */    0,                          /* tp_dict */    0,                          /* tp_descr_get */    0,                          /* tp_descr_set */    offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */    (initproc)BaseException_init, /* tp_init */    0,                          /* tp_alloc */    BaseException_new,          /* tp_new */};/* the CPython API expects exceptions to be (PyObject *) - both a hold-overfrom the previous implmentation and also allowing Python objects to be usedin the API */PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException; /* note these macros omit the last semicolon so the macro invocation may * include it and not look strange. */#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \static PyTypeObject _PyExc_ ## EXCNAME = { \    PyObject_HEAD_INIT(NULL) \    0, \    EXC_MODULE_NAME # EXCNAME, \    sizeof(PyBaseExceptionObject), \    0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \    0, 0, 0, 0, 0, 0, 0, \    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \    PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \    (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \    0, 0, 0, offsetof(PyBaseExceptionObject, dict), \    (initproc)BaseException_init, 0, BaseException_new,\}; \PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME #define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \static PyTypeObject _PyExc_ ## EXCNAME = { \    PyObject_HEAD_INIT(NULL) \    0, \    EXC_MODULE_NAME # EXCNAME, \    sizeof(Py ## EXCSTORE ## Object), \    0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \    0, 0, 0, 0, 0, \    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \    (initproc)EXCSTORE ## _init, 0, BaseException_new,\}; \PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME #define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDEALLOC, EXCMETHODS, EXCMEMBERS, EXCSTR, EXCDOC) \static PyTypeObject _PyExc_ ## EXCNAME = { \    PyObject_HEAD_INIT(NULL) \    0, \    EXC_MODULE_NAME # EXCNAME, \    sizeof(Py ## EXCSTORE ## Object), 0, \    (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \    (reprfunc)EXCSTR, 0, 0, 0, \    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \    PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \    (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \    EXCMEMBERS, 0, &_ ## EXCBASE, \    0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \    (initproc)EXCSTORE ## _init, 0, BaseException_new,\}; \PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME  /* *    Exception extends BaseException */SimpleExtendsException(PyExc_BaseException, Exception,                       "Common base class for all non-exit exceptions.");  /* *    StandardError extends Exception */SimpleExtendsException(PyExc_Exception, StandardError,    "Base class for all standard Python exceptions that do not represent\n"    "interpreter exiting.");  /* *    TypeError extends StandardError */SimpleExtendsException(PyExc_StandardError, TypeError,                       "Inappropriate argument type.");  /* *    StopIteration extends Exception */SimpleExtendsException(PyExc_Exception, StopIteration,                       "Signal the end from iterator.next().");  /* *    GeneratorExit extends Exception */SimpleExtendsException(PyExc_Exception, GeneratorExit,                       "Request that a generator exit.");  /* *    SystemExit extends BaseException */ static intSystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds){    Py_ssize_t size = PyTuple_GET_SIZE(args);     if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)        return -1;     if (size == 0)        return 0;    Py_CLEAR(self->code);    if (size == 1)        self->code = PyTuple_GET_ITEM(args, 0);    else if (size > 1)        self->code = args;    Py_INCREF(self->code);    return 0;} static intSystemExit_clear(PySystemExitObject *self){    Py_CLEAR(self->code);    return BaseException_clear((PyBaseExceptionObject *)self);} static voidSystemExit_dealloc(PySystemExitObject *self){    _PyObject_GC_UNTRACK(self);    SystemExit_clear(self);    self->ob_type->tp_free((PyObject *)self);} static intSystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg){    Py_VISIT(self->code);    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);} static PyMemberDef SystemExit_members[] = {    {"message", T_OBJECT, offsetof(PySystemExitObject, message), 0,        PyDoc_STR("exception message")},    {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0,        PyDoc_STR("exception code")},    {NULL}  /* Sentinel */}; ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,                        SystemExit_dealloc, 0, SystemExit_members, 0,                        "Request to exit from the interpreter."); /* *    KeyboardInterrupt extends BaseException */SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,                       "Program interrupted by user.");  /* *    ImportError extends StandardError */SimpleExtendsException(PyExc_StandardError, ImportError,          "Import can't find module, or can't find name in module.");  /* *    EnvironmentError extends StandardError */ /* Where a function has a single filename, such as open() or some * of the os module functions, PyErr_SetFromErrnoWithFilename() is * called, giving a third argument which is the filename.  But, so * that old code using in-place unpacking doesn't break, e.g.: * * except IOError, (errno, strerror): * * we hack args so that it only contains two items.  This also * means we need our own __str__() which prints out the filename

Lines 1–500 of 2147.