From 757af0e7bb7c7d56670fbc84f1f5b0182a54e3d5 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 29 Aug 1997 22:13:51 +0000 Subject: Removed obsolete exception PyExc_AccessError. Added PyErr_MemoryErrorInst to hold the pre-instantiated instance when using class based exceptions. Simplified the creation of all built-in exceptions, both class based and string based. Actually, for class based exceptions, the string ones are still created just in case there's a problem creating the class based ones (so you still get *some* exception handling!). Now the init and fini functions run through a list of structure elements, creating the strings (and optionally classes) for every entry. initerrors(): the new base class exceptions StandardError, LookupError, and NumberError are initialized when using string exceptions, to tuples containing the list of derived string exceptions. This GvR trick enables forward compatibility! One bit of nastiness is that the C code has to know the inheritance tree embodied in exceptions.py. Added the two phase init and fini functions. --- Python/bltinmodule.c | 214 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 171 insertions(+), 43 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index a89b3fc..358b6f1 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1724,7 +1724,10 @@ static PyMethodDef builtin_methods[] = { /* Predefined exceptions */ -PyObject *PyExc_AccessError; +PyObject *PyExc_StandardError; +PyObject *PyExc_NumberError; +PyObject *PyExc_LookupError; + PyObject *PyExc_AssertionError; PyObject *PyExc_AttributeError; PyObject *PyExc_EOFError; @@ -1745,6 +1748,108 @@ PyObject *PyExc_TypeError; PyObject *PyExc_ValueError; PyObject *PyExc_ZeroDivisionError; +PyObject *PyExc_MemoryErrorInst; + +static struct +{ + char* name; + PyObject** exc; + int leaf_exc; +} +bltin_exc[] = { + {"StandardError", &PyExc_StandardError, 0}, + {"NumberError", &PyExc_NumberError, 0}, + {"LookupError", &PyExc_LookupError, 0}, + {"AssertionError", &PyExc_AssertionError, 1}, + {"AttributeError", &PyExc_AttributeError, 1}, + {"EOFError", &PyExc_EOFError, 1}, + {"FloatingPointError", &PyExc_FloatingPointError, 1}, + {"IOError", &PyExc_IOError, 1}, + {"ImportError", &PyExc_ImportError, 1}, + {"IndexError", &PyExc_IndexError, 1}, + {"KeyError", &PyExc_KeyError, 1}, + {"KeyboardInterrupt", &PyExc_KeyboardInterrupt, 1}, + {"MemoryError", &PyExc_MemoryError, 1}, + {"NameError", &PyExc_NameError, 1}, + {"OverflowError", &PyExc_OverflowError, 1}, + {"RuntimeError", &PyExc_RuntimeError, 1}, + {"SyntaxError", &PyExc_SyntaxError, 1}, + {"SystemError", &PyExc_SystemError, 1}, + {"SystemExit", &PyExc_SystemExit, 1}, + {"TypeError", &PyExc_TypeError, 1}, + {"ValueError", &PyExc_ValueError, 1}, + {"ZeroDivisionError", &PyExc_ZeroDivisionError, 1}, + {NULL, NULL} +}; + + +/* import exceptions module to extract class exceptions */ +static void +init_class_exc(dict) + PyObject *dict; +{ + int i; + PyObject *m = PyImport_ImportModule("exceptions"); + PyObject *d; + PyObject *args; + + if (m == NULL || + (d = PyModule_GetDict(m)) == NULL) + { + PyObject *f = PySys_GetObject("stderr"); + if (Py_VerboseFlag) { + PyFile_WriteString( + "'import exceptions' failed; traceback:\n", f); + PyErr_Print(); + } + else { + PyFile_WriteString( + "'import exceptions' failed; use -v for traceback\n", f); + PyErr_Clear(); + } + PyFile_WriteString("defaulting to old style exceptions\n", f); + return; + } + for (i = 0; bltin_exc[i].name; i++) { + /* dig the exception out of the module */ + PyObject *exc = PyDict_GetItemString(d, bltin_exc[i].name); + if (!exc) + Py_FatalError("built-in exception cannot be initialized"); + + Py_XDECREF(*bltin_exc[i].exc); + + /* squirrel away a pointer to the exception */ + Py_INCREF(exc); + *bltin_exc[i].exc = exc; + + /* and insert the name in the __builtin__ module */ + PyDict_SetItemString(dict, bltin_exc[i].name, exc); + } + + /* we need one pre-allocated instance */ + args = Py_BuildValue("()"); + if (args) { + PyExc_MemoryErrorInst = + PyEval_CallObject(PyExc_MemoryError, args); + Py_DECREF(args); + } + + /* we're done with the exceptions module */ + Py_DECREF(m); + + if (PyErr_Occurred()) + Py_FatalError("can't instantiate standard exceptions"); +} + + +static void +fini_instances() +{ + Py_XDECREF(PyExc_MemoryErrorInst); + PyExc_MemoryErrorInst = NULL; +} + + static PyObject * newstdexception(dict, name) PyObject *dict; @@ -1760,55 +1865,60 @@ static void initerrors(dict) PyObject *dict; { - PyExc_AccessError = newstdexception(dict, "AccessError"); - PyExc_AssertionError = newstdexception(dict, "AssertionError"); - PyExc_AttributeError = newstdexception(dict, "AttributeError"); - PyExc_EOFError = newstdexception(dict, "EOFError"); - PyExc_FloatingPointError = newstdexception(dict, "FloatingPointError"); - PyExc_IOError = newstdexception(dict, "IOError"); - PyExc_ImportError = newstdexception(dict, "ImportError"); - PyExc_IndexError = newstdexception(dict, "IndexError"); - PyExc_KeyError = newstdexception(dict, "KeyError"); - PyExc_KeyboardInterrupt = newstdexception(dict, "KeyboardInterrupt"); - PyExc_MemoryError = newstdexception(dict, "MemoryError"); - PyExc_NameError = newstdexception(dict, "NameError"); - PyExc_OverflowError = newstdexception(dict, "OverflowError"); - PyExc_RuntimeError = newstdexception(dict, "RuntimeError"); - PyExc_SyntaxError = newstdexception(dict, "SyntaxError"); - PyExc_SystemError = newstdexception(dict, "SystemError"); - PyExc_SystemExit = newstdexception(dict, "SystemExit"); - PyExc_TypeError = newstdexception(dict, "TypeError"); - PyExc_ValueError = newstdexception(dict, "ValueError"); - PyExc_ZeroDivisionError = newstdexception(dict, "ZeroDivisionError"); + int i; + int exccnt = 0; + for (i = 0; bltin_exc[i].name; i++, exccnt++) { + if (bltin_exc[i].leaf_exc) + *bltin_exc[i].exc = + newstdexception(dict, bltin_exc[i].name); + } + + /* This is kind of bogus because we special case the three new + exceptions to be nearly forward compatible. But this means we + hard code knowledge about exceptions.py into C here. I don't + have a better solution, though + */ + PyExc_LookupError = PyTuple_New(2); + Py_INCREF(PyExc_IndexError); + PyTuple_SET_ITEM(PyExc_LookupError, 0, PyExc_IndexError); + Py_INCREF(PyExc_KeyError); + PyTuple_SET_ITEM(PyExc_LookupError, 1, PyExc_KeyError); + PyDict_SetItemString(dict, "LookupError", PyExc_LookupError); + + PyExc_NumberError = PyTuple_New(3); + Py_INCREF(PyExc_OverflowError); + PyTuple_SET_ITEM(PyExc_NumberError, 0, PyExc_OverflowError); + Py_INCREF(PyExc_ZeroDivisionError); + PyTuple_SET_ITEM(PyExc_NumberError, 1, PyExc_ZeroDivisionError); + Py_INCREF(PyExc_FloatingPointError); + PyTuple_SET_ITEM(PyExc_NumberError, 2, PyExc_FloatingPointError); + PyDict_SetItemString(dict, "NumberError", PyExc_NumberError); + + PyExc_StandardError = PyTuple_New(exccnt-1); + for (i = 1; bltin_exc[i].name; i++) { + PyObject *exc = *bltin_exc[i].exc; + Py_INCREF(exc); + PyTuple_SET_ITEM(PyExc_StandardError, i-1, exc); + } + PyDict_SetItemString(dict, "StandardError", PyExc_StandardError); + + if (PyErr_Occurred()) + Py_FatalError("Could not initialize built-in string exceptions"); } static void finierrors() { - Py_XDECREF(PyExc_AccessError); PyExc_AccessError = NULL; - Py_XDECREF(PyExc_AssertionError); PyExc_AssertionError = NULL; - Py_XDECREF(PyExc_AttributeError); PyExc_AttributeError = NULL; - Py_XDECREF(PyExc_EOFError); PyExc_EOFError = NULL; - Py_XDECREF(PyExc_FloatingPointError); PyExc_FloatingPointError = NULL; - Py_XDECREF(PyExc_IOError); PyExc_IOError = NULL; - Py_XDECREF(PyExc_ImportError); PyExc_ImportError = NULL; - Py_XDECREF(PyExc_IndexError); PyExc_IndexError = NULL; - Py_XDECREF(PyExc_KeyError); PyExc_KeyError = NULL; - Py_XDECREF(PyExc_KeyboardInterrupt); PyExc_KeyboardInterrupt = NULL; - Py_XDECREF(PyExc_MemoryError); PyExc_MemoryError = NULL; - Py_XDECREF(PyExc_NameError); PyExc_NameError = NULL; - Py_XDECREF(PyExc_OverflowError); PyExc_OverflowError = NULL; - Py_XDECREF(PyExc_RuntimeError); PyExc_RuntimeError = NULL; - Py_XDECREF(PyExc_SyntaxError); PyExc_SyntaxError = NULL; - Py_XDECREF(PyExc_SystemError); PyExc_SystemError = NULL; - Py_XDECREF(PyExc_SystemExit); PyExc_SystemExit = NULL; - Py_XDECREF(PyExc_TypeError); PyExc_TypeError = NULL; - Py_XDECREF(PyExc_ValueError); PyExc_ValueError = NULL; - Py_XDECREF(PyExc_ZeroDivisionError); PyExc_ZeroDivisionError = NULL; + int i; + for (i = 0; bltin_exc[i].name; i++) { + PyObject *exc = *bltin_exc[i].exc; + Py_XDECREF(exc); + *bltin_exc[i].exc = NULL; + } } PyObject * -_PyBuiltin_Init() +_PyBuiltin_Init_1() { PyObject *mod, *dict; mod = Py_InitModule("__builtin__", builtin_methods); @@ -1823,11 +1933,29 @@ _PyBuiltin_Init() if (PyDict_SetItemString(dict, "__debug__", PyInt_FromLong(Py_OptimizeFlag == 0)) < 0) return NULL; + return mod; } void -_PyBuiltin_Fini() +_PyBuiltin_Init_2(dict) + PyObject *dict; +{ + /* if Python was started with -X, initialize the class exceptions */ + if (Py_UseClassExceptionsFlag) + init_class_exc(dict); +} + + +void +_PyBuiltin_Fini_1() +{ + fini_instances(); +} + + +void +_PyBuiltin_Fini_2() { finierrors(); } -- cgit v0.12