Index: Python/codecs.c =================================================================== --- Python/codecs.c (revision 41614) +++ Python/codecs.c (working copy) @@ -448,9 +448,8 @@ PyObject *PyCodec_StrictErrors(PyObject *exc) { - if (PyInstance_Check(exc)) - PyErr_SetObject((PyObject*)((PyInstanceObject*)exc)->in_class, - exc); + if (PyExceptionInstance_Check(exc)) + PyErr_SetObject(PyExceptionInstance_Class(exc), exc); else PyErr_SetString(PyExc_TypeError, "codec must pass exception instance"); return NULL; Index: Python/errors.c =================================================================== --- Python/errors.c (revision 41614) +++ Python/errors.c (working copy) @@ -96,11 +96,14 @@ return 0; } /* err might be an instance, so check its class. */ - if (PyInstance_Check(err)) - err = (PyObject*)((PyInstanceObject*)err)->in_class; + if (PyExceptionInstance_Check(err)) + err = PyExceptionInstance_Class(err); - if (PyClass_Check(err) && PyClass_Check(exc)) - return PyClass_IsSubclass(err, exc); + 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; } @@ -137,19 +140,19 @@ Py_INCREF(value); } - if (PyInstance_Check(value)) - inclass = (PyObject*)((PyInstanceObject*)value)->in_class; + 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 (PyClass_Check(type)) { + 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 || !PyClass_IsSubclass(inclass, type)) { + if (!inclass || !PyObject_IsSubclass(inclass, type)) { PyObject *args, *res; if (value == Py_None) @@ -281,7 +284,7 @@ { /* Note that the Win32 errors do not lineup with the errno error. So if the error is in the MSVC error - table, we use it, otherwise we assume it really _is_ + table, we use it, otherwise we assume it really _is_ a Win32 error code */ if (i > 0 && i < _sys_nerr) { @@ -301,7 +304,7 @@ 0, /* size not used */ NULL); /* no args */ if (len==0) { - /* Only ever seen this in out-of-mem + /* Only ever seen this in out-of-mem situations */ sprintf(s_small_buf, "Windows Error 0x%X", i); s = s_small_buf; @@ -344,8 +347,8 @@ PyObject * PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, Py_UNICODE *filename) { - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name); Py_XDECREF(name); @@ -359,7 +362,7 @@ return PyErr_SetFromErrnoWithFilenameObject(exc, NULL); } -#ifdef MS_WINDOWS +#ifdef MS_WINDOWS /* Windows specific error code handling */ PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject( PyObject *exc, @@ -414,8 +417,8 @@ const char *filename) { PyObject *name = filename ? PyString_FromString(filename) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, name); Py_XDECREF(name); return ret; @@ -427,11 +430,11 @@ int ierr, const Py_UNICODE *filename) { - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; - PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, - ierr, + PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc, + ierr, name); Py_XDECREF(name); return ret; @@ -465,8 +468,8 @@ int ierr, const Py_UNICODE *filename) { - PyObject *name = filename ? - PyUnicode_FromUnicode(filename, wcslen(filename)) : + PyObject *name = filename ? + PyUnicode_FromUnicode(filename, wcslen(filename)) : NULL; PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject( PyExc_WindowsError, @@ -573,7 +576,24 @@ if (f != NULL) { PyFile_WriteString("Exception ", f); if (t) { - PyFile_WriteObject(t, f, Py_PRINT_RAW); + char* className = PyExceptionClass_Name(t); + PyObject* moduleName = + PyObject_GetAttrString(t, "__module__"); + + if (moduleName == NULL) + PyFile_WriteString("", f); + else { + char* modstr = PyString_AsString(moduleName); + if (modstr) + { + PyFile_WriteString(modstr, f); + PyFile_WriteString(".", f); + } + } + if (className == NULL) + PyFile_WriteString("", f); + else + PyFile_WriteString(className, f); if (v && v != Py_None) { PyFile_WriteString(": ", f); PyFile_WriteObject(v, f, 0); @@ -725,7 +745,7 @@ /* com_fetch_program_text will attempt to load the line of text that the exception refers to. If it fails, it will return NULL but will - not set an exception. + not set an exception. XXX The functionality of this function is quite similar to the functionality in tb_displayline() in traceback.c. Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 41614) +++ Python/ceval.c (working copy) @@ -1683,7 +1683,7 @@ why == WHY_CONTINUE) retval = POP(); } - else if (PyClass_Check(v) || PyString_Check(v)) { + else if (PyExceptionClass_Check(v) || PyString_Check(v)) { w = POP(); u = POP(); PyErr_Restore(v, w, u); @@ -2962,13 +2962,13 @@ /* Raising builtin string is deprecated but still allowed -- * do nothing. Raising an instance of a new-style str * subclass is right out. */ - PyErr_Warn(PyExc_PendingDeprecationWarning, + PyErr_Warn(PyExc_DeprecationWarning, "raising a string exception is deprecated"); - else if (PyClass_Check(type)) + else if (PyExceptionClass_Check(type)) PyErr_NormalizeException(&type, &value, &tb); - else if (PyInstance_Check(type)) { + else if (PyExceptionInstance_Check(type)) { /* Raising an instance. The value should be a dummy. */ if (value != Py_None) { PyErr_SetString(PyExc_TypeError, @@ -2979,7 +2979,7 @@ /* Normalize to raise , */ Py_DECREF(value); value = type; - type = (PyObject*) ((PyInstanceObject*)type)->in_class; + type = PyExceptionInstance_Class(type); Py_INCREF(type); } } Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (revision 41614) +++ Python/pythonrun.c (working copy) @@ -968,7 +968,7 @@ fflush(stdout); if (value == NULL || value == Py_None) goto done; - if (PyInstance_Check(value)) { + if (PyExceptionInstance_Check(value)) { /* The error code should be in the `code' attribute. */ PyObject *code = PyObject_GetAttrString(value, "code"); if (code) { @@ -1098,11 +1098,10 @@ if (err) { /* Don't do anything else */ } - else if (PyClass_Check(exception)) { - PyClassObject* exc = (PyClassObject*)exception; - PyObject* className = exc->cl_name; + else if (PyExceptionClass_Check(exception)) { + char* className = PyExceptionClass_Name(exception); PyObject* moduleName = - PyDict_GetItemString(exc->cl_dict, "__module__"); + PyObject_GetAttrString(exception, "__module__"); if (moduleName == NULL) err = PyFile_WriteString("", f); @@ -1118,8 +1117,7 @@ if (className == NULL) err = PyFile_WriteString("", f); else - err = PyFile_WriteObject(className, f, - Py_PRINT_RAW); + err = PyFile_WriteString(className, f); } } else Index: Python/Python-ast.c =================================================================== --- Python/Python-ast.c (revision 41614) +++ Python/Python-ast.c (working copy) @@ -1,4 +1,4 @@ -/* File automatically generated by ./Parser/asdl_c.py */ +/* File automatically generated by ../Parser/asdl_c.py */ #include "Python.h" #include "Python-ast.h" Index: Python/exceptions.c =================================================================== --- Python/exceptions.c (revision 41614) +++ Python/exceptions.c (working copy) @@ -125,7 +125,7 @@ /* Helper function for populating a dictionary with method wrappers. */ static int -populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods) +populate_methods(PyObject *klass, PyMethodDef *methods) { PyObject *module; int status = -1; @@ -151,7 +151,7 @@ } /* add method to dictionary */ - status = PyDict_SetItemString(dict, methods->ml_name, meth); + status = PyObject_SetAttrString(klass, methods->ml_name, meth); Py_DECREF(meth); Py_DECREF(func); @@ -196,7 +196,7 @@ if (!(*klass = PyErr_NewException(name, base, dict))) goto finally; - if (populate_methods(*klass, dict, methods)) { + if (populate_methods(*klass, methods)) { Py_DECREF(*klass); *klass = NULL; goto finally; @@ -346,6 +346,8 @@ PyObject *dict = PyDict_New(); PyObject *str = NULL; PyObject *name = NULL; + PyObject *emptytuple = NULL; + PyObject *argstuple = NULL; int status = -1; if (!dict) @@ -360,6 +362,7 @@ if (PyDict_SetItemString(dict, "__module__", str)) goto finally; Py_DECREF(str); + if (!(str = PyString_FromString(Exception__doc__))) goto finally; if (PyDict_SetItemString(dict, "__doc__", str)) @@ -368,11 +371,17 @@ if (!(name = PyString_FromString("Exception"))) goto finally; - if (!(PyExc_Exception = PyClass_New(NULL, dict, name))) + if (!(emptytuple = PyTuple_New(0))) goto finally; + + if (!(argstuple = PyTuple_Pack(3, name, emptytuple, dict))) + goto finally; + + if (!(PyExc_Exception = PyType_Type.tp_new(&PyType_Type, argstuple, NULL))) + goto finally; /* Now populate the dictionary with the method suite */ - if (populate_methods(PyExc_Exception, dict, Exception_methods)) + if (populate_methods(PyExc_Exception, Exception_methods)) /* Don't need to reclaim PyExc_Exception here because that'll * happen during interpreter shutdown. */ @@ -384,6 +393,8 @@ Py_XDECREF(dict); Py_XDECREF(str); Py_XDECREF(name); + Py_XDECREF(emptytuple); + Py_XDECREF(argstuple); return status; } Index: Include/Python-ast.h =================================================================== --- Include/Python-ast.h (revision 41614) +++ Include/Python-ast.h (working copy) @@ -1,4 +1,4 @@ -/* File automatically generated by ./Parser/asdl_c.py */ +/* File automatically generated by ../Parser/asdl_c.py */ #include "asdl.h" Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (revision 41614) +++ Include/pyerrors.h (working copy) @@ -26,7 +26,31 @@ PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *); PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**); +/* */ +#define PyExceptionClass_Check(x) \ + (PyClass_Check((x)) \ + || (PyType_Check((x)) && PyType_IsSubtype( \ + (PyTypeObject*)(x), (PyTypeObject*)PyExc_Exception))) + + +#define PyExceptionInstance_Check(x) \ + (PyInstance_Check((x)) || \ + (PyType_IsSubtype((x)->ob_type, (PyTypeObject*)PyExc_Exception))) + +#define PyExceptionClass_Name(x) \ + (PyClass_Check((x)) \ + ? PyString_AS_STRING(((PyClassObject*)(x))->cl_name) \ + : ((PyTypeObject*)(x))->tp_name) + +#define PyExceptionInstance_Class(x) \ + ((PyInstance_Check((x)) \ + ? (PyObject*)((PyInstanceObject*)(x))->in_class \ + : (PyObject*)((x)->ob_type))) + + + + /* Predefined exceptions */ PyAPI_DATA(PyObject *) PyExc_Exception; Index: Objects/genobject.c =================================================================== --- Objects/genobject.c (revision 41614) +++ Objects/genobject.c (working copy) @@ -224,11 +224,11 @@ Py_XINCREF(val); Py_XINCREF(tb); - if (PyClass_Check(typ)) { + if (PyExceptionClass_Check(typ)) { PyErr_NormalizeException(&typ, &val, &tb); } - else if (PyInstance_Check(typ)) { + else if (PyExceptionInstance_Check(typ)) { /* Raising an instance. The value should be a dummy. */ if (val && val != Py_None) { PyErr_SetString(PyExc_TypeError, @@ -238,7 +238,7 @@ else { /* Normalize to raise , */ val = typ; - typ = (PyObject*) ((PyInstanceObject*)typ)->in_class; + typ = PyExceptionInstance_Class(typ); Py_INCREF(typ); } } Index: Lib/warnings.py =================================================================== --- Lib/warnings.py (revision 41614) +++ Lib/warnings.py (working copy) @@ -145,7 +145,8 @@ assert action in ("error", "ignore", "always", "default", "module", "once"), "invalid action: %r" % (action,) assert isinstance(message, basestring), "message must be a string" - assert isinstance(category, types.ClassType), "category must be a class" + assert isinstance(category, (type, types.ClassType)), \ + "category must be a class" assert issubclass(category, Warning), "category must be a Warning subclass" assert isinstance(module, basestring), "module must be a string" assert isinstance(lineno, int) and lineno >= 0, \ Index: Lib/traceback.py =================================================================== --- Lib/traceback.py (revision 41614) +++ Lib/traceback.py (working copy) @@ -157,7 +157,8 @@ which exception occurred is the always last string in the list. """ list = [] - if type(etype) == types.ClassType: + if (type(etype) == types.ClassType + or (isinstance(etype, type) and issubclass(etype, Exception))): stype = etype.__name__ else: stype = etype Index: Lib/test/test_exceptions.py =================================================================== --- Lib/test/test_exceptions.py (revision 41614) +++ Lib/test/test_exceptions.py (working copy) @@ -29,10 +29,7 @@ def r(thing): test_raise_catch(thing) - if isinstance(thing, ClassType): - print thing.__name__ - else: - print thing + print getattr(thing, '__name__', thing) r(AttributeError) import sys Index: Lib/test/test_coercion.py =================================================================== --- Lib/test/test_coercion.py (revision 41614) +++ Lib/test/test_coercion.py (working copy) @@ -96,7 +96,7 @@ x = eval('a %s b' % op) except: error = sys.exc_info()[:2] - print '... %s' % error[0] + print '... %s.%s' % (error[0].__module__, error[0].__name__) else: print '=', format_result(x) try: @@ -108,7 +108,7 @@ exec('z %s= b' % op) except: error = sys.exc_info()[:2] - print '... %s' % error[0] + print '... %s.%s' % (error[0].__module__, error[0].__name__) else: print '=>', format_result(z) @@ -121,7 +121,7 @@ x = eval('%s(a, b)' % op) except: error = sys.exc_info()[:2] - print '... %s' % error[0] + print '... %s.%s' % (error[0].__module__, error[0].__name__) else: print '=', format_result(x)