]> granicus.if.org Git - python/commitdiff
PEP 352 implementation. Creates a new base class, BaseException, which has an
authorBrett Cannon <bcannon@gmail.com>
Wed, 1 Mar 2006 04:25:17 +0000 (04:25 +0000)
committerBrett Cannon <bcannon@gmail.com>
Wed, 1 Mar 2006 04:25:17 +0000 (04:25 +0000)
added message attribute compared to the previous version of Exception.  It is
also a new-style class, making all exceptions now new-style.  KeyboardInterrupt
and SystemExit inherit from BaseException directly.  String exceptions now
raise DeprecationWarning.

Applies patch 1104669, and closes bugs 1012952 and 518846.

16 files changed:
Include/pyerrors.h
Lib/test/exception_hierarchy.txt [new file with mode: 0644]
Lib/test/output/test_logging
Lib/test/test_coercion.py
Lib/test/test_descr.py
Lib/test/test_exceptions.py
Lib/test/test_pep352.py [new file with mode: 0644]
Lib/traceback.py
Lib/warnings.py
Misc/NEWS
Objects/genobject.c
Python/ceval.c
Python/codecs.c
Python/errors.c
Python/exceptions.c
Python/pythonrun.c

index 330a35c1d70493cb623de21abd3c6b7dfcf6be67..1fe2e4541e3289925b629568074da7a97ce9d123 100644 (file)
@@ -26,9 +26,32 @@ PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
 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_BaseException)))
+
+
+#define PyExceptionInstance_Check(x)                   \
+       (PyInstance_Check((x)) ||                       \
+        (PyType_IsSubtype((x)->ob_type, (PyTypeObject*)PyExc_BaseException)))
+
+#define PyExceptionClass_Name(x)                                  \
+       (PyClass_Check((x))                                        \
+        ? PyString_AS_STRING(((PyClassObject*)(x))->cl_name)      \
+        : (char *)(((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_BaseException;
 PyAPI_DATA(PyObject *) PyExc_Exception;
 PyAPI_DATA(PyObject *) PyExc_StopIteration;
 PyAPI_DATA(PyObject *) PyExc_GeneratorExit;
diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt
new file mode 100644 (file)
index 0000000..9ed92d0
--- /dev/null
@@ -0,0 +1,46 @@
+BaseException
+ +-- SystemExit
+ +-- KeyboardInterrupt
+ +-- Exception
+      +-- GeneratorExit
+      +-- StopIteration
+      +-- StandardError
+      |    +-- ArithmeticError
+      |    |    +-- FloatingPointError
+      |    |    +-- OverflowError
+      |    |    +-- ZeroDivisionError
+      |    +-- AssertionError
+      |    +-- AttributeError
+      |    +-- EnvironmentError
+      |    |    +-- IOError
+      |    |    +-- OSError
+      |    |         +-- WindowsError (Windows)
+      |    +-- EOFError
+      |    +-- ImportError
+      |    +-- LookupError
+      |    |    +-- IndexError
+      |    |    +-- KeyError
+      |    +-- MemoryError
+      |    +-- NameError
+      |    |    +-- UnboundLocalError
+      |    +-- ReferenceError
+      |    +-- RuntimeError
+      |    |    +-- NotImplementedError
+      |    +-- SyntaxError
+      |    |    +-- IndentationError
+      |    |         +-- TabError
+      |    +-- SystemError
+      |    +-- TypeError
+      |    +-- ValueError
+      |    |    +-- UnicodeError
+      |    |         +-- UnicodeDecodeError
+      |    |         +-- UnicodeEncodeError
+      |    |         +-- UnicodeTranslateError
+      +-- Warning
+           +-- DeprecationWarning
+           +-- PendingDeprecationWarning
+           +-- RuntimeWarning
+           +-- SyntaxWarning
+           +-- UserWarning
+           +-- FutureWarning
+          +-- OverflowWarning [not generated by the interpreter]
index cedd2977dfb957b597554474836fa94f83e1cc24..7be3a3e8ae211a45f6cfcd4c0ba23341b640a494 100644 (file)
@@ -488,12 +488,12 @@ INFO:a.b.c.d:Info 5
 -- log_test4  begin  ---------------------------------------------------
 config0: ok.
 config1: ok.
-config2: exceptions.AttributeError
-config3: exceptions.KeyError
+config2: <class 'exceptions.AttributeError'>
+config3: <class 'exceptions.KeyError'>
 -- log_test4  end    ---------------------------------------------------
 -- log_test5  begin  ---------------------------------------------------
 ERROR:root:just testing
-exceptions.KeyError... Don't panic!
+<class 'exceptions.KeyError'>... Don't panic!
 -- log_test5  end    ---------------------------------------------------
 -- logrecv output begin  ---------------------------------------------------
 ERR -> CRITICAL: Message 0 (via logrecv.tcp.ERR)
index 37d735b3ba5bfb64206e129f683b4db885dfca5c..ceea17b461312d7f1103421becec50caff28a911 100644 (file)
@@ -96,7 +96,7 @@ def do_infix_binops():
                     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 @@ def do_infix_binops():
                     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 @@ def do_prefix_binops():
                     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)
 
index 2f12e96bf41e7096f22740b4fca47fa760ce5b02..68a11facdc12dcc9ceb47c0714de7c73821e79ed 100644 (file)
@@ -3355,31 +3355,6 @@ def docdescriptor():
     vereq(NewClass.__doc__, 'object=None; type=NewClass')
     vereq(NewClass().__doc__, 'object=NewClass instance; type=NewClass')
 
-def string_exceptions():
-    if verbose:
-        print "Testing string exceptions ..."
-
-    # Ensure builtin strings work OK as exceptions.
-    astring = "An exception string."
-    try:
-        raise astring
-    except astring:
-        pass
-    else:
-        raise TestFailed, "builtin string not usable as exception"
-
-    # Ensure string subclass instances do not.
-    class MyStr(str):
-        pass
-
-    newstring = MyStr("oops -- shouldn't work")
-    try:
-        raise newstring
-    except TypeError:
-        pass
-    except:
-        raise TestFailed, "string subclass allowed as exception"
-
 def copy_setstate():
     if verbose:
         print "Testing that copy.*copy() correctly uses __setstate__..."
@@ -4172,7 +4147,6 @@ def test_main():
     funnynew()
     imulbug()
     docdescriptor()
-    string_exceptions()
     copy_setstate()
     slices()
     subtype_resurrection()
index c157122b5b0c668f5d685ccbf836f2de9fd81ea9..fdef876879b2498f8d8655bf33688df60887024e 100644 (file)
@@ -29,10 +29,7 @@ def test_raise_catch(exc):
 
 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
diff --git a/Lib/test/test_pep352.py b/Lib/test/test_pep352.py
new file mode 100644 (file)
index 0000000..234d671
--- /dev/null
@@ -0,0 +1,182 @@
+import unittest
+import __builtin__
+import exceptions
+import warnings
+from test.test_support import run_unittest
+import os
+from platform import system as platform_system
+
+class ExceptionClassTests(unittest.TestCase):
+
+    """Tests for anything relating to exception objects themselves (e.g.,
+    inheritance hierarchy)"""
+
+    def test_builtins_new_style(self):
+        self.failUnless(issubclass(Exception, object))
+
+    def verify_instance_interface(self, ins):
+        for attr in ("args", "message", "__str__", "__unicode__", "__repr__",
+                "__getitem__"):
+            self.failUnless(hasattr(ins, attr), "%s missing %s attribute" %
+                    (ins.__class__.__name__, attr))
+
+    def test_inheritance(self):
+        # Make sure the inheritance hierarchy matches the documentation
+        exc_set = set(x for x in dir(exceptions) if not x.startswith('_'))
+        inheritance_tree = open(os.path.join(os.path.split(__file__)[0],
+                                                'exception_hierarchy.txt'))
+        try:
+            superclass_name = inheritance_tree.readline().rstrip()
+            try:
+                last_exc = getattr(__builtin__, superclass_name)
+            except AttributeError:
+                self.fail("base class %s not a built-in" % superclass_name)
+            self.failUnless(superclass_name in exc_set)
+            exc_set.discard(superclass_name)
+            superclasses = []  # Loop will insert base exception
+            last_depth = 0
+            for exc_line in inheritance_tree:
+                exc_line = exc_line.rstrip()
+                depth = exc_line.rindex('-')
+                exc_name = exc_line[depth+2:]  # Slice past space
+                if '(' in exc_name:
+                    paren_index = exc_name.index('(')
+                    platform_name = exc_name[paren_index+1:-1]
+                    if platform_system() != platform_name:
+                        exc_set.discard(exc_name)
+                        continue
+                if '[' in exc_name:
+                    left_bracket = exc_name.index('[')
+                    exc_name = exc_name[:left_bracket-1]  # cover space
+                try:
+                    exc = getattr(__builtin__, exc_name)
+                except AttributeError:
+                    self.fail("%s not a built-in exception" % exc_name)
+                if last_depth < depth:
+                    superclasses.append((last_depth, last_exc))
+                elif last_depth > depth:
+                    while superclasses[-1][0] >= depth:
+                        superclasses.pop()
+                self.failUnless(issubclass(exc, superclasses[-1][1]),
+                "%s is not a subclass of %s" % (exc.__name__,
+                    superclasses[-1][1].__name__))
+                try:  # Some exceptions require arguments; just skip them
+                    self.verify_instance_interface(exc())
+                except TypeError:
+                    pass
+                self.failUnless(exc_name in exc_set)
+                exc_set.discard(exc_name)
+                last_exc = exc
+                last_depth = depth
+        finally:
+            inheritance_tree.close()
+        self.failUnlessEqual(len(exc_set), 0, "%s not accounted for" % exc_set)
+
+    interface_tests = ("length", "args", "message", "str", "unicode", "repr",
+            "indexing")
+
+    def interface_test_driver(self, results):
+        for test_name, (given, expected) in zip(self.interface_tests, results):
+            self.failUnlessEqual(given, expected, "%s: %s != %s" % (test_name,
+                given, expected))
+
+    def test_interface_single_arg(self):
+        # Make sure interface works properly when given a single argument
+        arg = "spam"
+        exc = Exception(arg)
+        results = ([len(exc.args), 1], [exc.args[0], arg], [exc.message, arg],
+                [str(exc), str(arg)], [unicode(exc), unicode(arg)],
+            [repr(exc), exc.__class__.__name__ + repr(exc.args)], [exc[0], arg])
+        self.interface_test_driver(results)
+
+    def test_interface_multi_arg(self):
+        # Make sure interface correct when multiple arguments given
+        arg_count = 3
+        args = tuple(range(arg_count))
+        exc = Exception(*args)
+        results = ([len(exc.args), arg_count], [exc.args, args],
+                [exc.message, ''], [str(exc), str(args)],
+                [unicode(exc), unicode(args)],
+                [repr(exc), exc.__class__.__name__ + repr(exc.args)],
+                [exc[-1], args[-1]])
+        self.interface_test_driver(results)
+
+    def test_interface_no_arg(self):
+        # Make sure that with no args that interface is correct
+        exc = Exception()
+        results = ([len(exc.args), 0], [exc.args, tuple()], [exc.message, ''],
+                [str(exc), ''], [unicode(exc), u''],
+                [repr(exc), exc.__class__.__name__ + '()'], [True, True])
+        self.interface_test_driver(results)
+
+class UsageTests(unittest.TestCase):
+
+    """Test usage of exceptions"""
+
+    def setUp(self):
+        self._filters = warnings.filters[:]
+
+    def tearDown(self):
+        warnings.filters = self._filters[:]
+
+    def test_raise_classic(self):
+        class ClassicClass:
+            pass
+        try:
+            raise ClassicClass
+        except ClassicClass:
+            pass
+        except:
+            self.fail("unable to raise classic class")
+        try:
+            raise ClassicClass()
+        except ClassicClass:
+            pass
+        except:
+            self.fail("unable to raise class class instance")
+
+    def test_raise_new_style_non_exception(self):
+        class NewStyleClass(object):
+            pass
+        try:
+            raise NewStyleClass
+        except TypeError:
+            pass
+        except:
+            self.fail("unable to raise new-style class")
+        try:
+            raise NewStyleClass()
+        except TypeError:
+            pass
+        except:
+            self.fail("unable to raise new-style class instance")
+
+    def test_raise_string(self):
+        warnings.resetwarnings()
+        warnings.filterwarnings("error")
+        try:
+            raise "spam"
+        except DeprecationWarning:
+            pass
+        except:
+            self.fail("raising a string did not cause a DeprecationWarning")
+
+    def test_catch_string(self):
+        # Test will be pertinent when catching exceptions raises a
+        #   DeprecationWarning
+        warnings.filterwarnings("ignore", "raising")
+        str_exc = "spam"
+        try:
+            raise str_exc
+        except str_exc:
+            pass
+        except:
+            self.fail("catching a string exception failed")
+
+def test_main():
+    run_unittest(ExceptionClassTests, UsageTests)
+
+
+
+if __name__ == '__main__':
+    test_main()
index 95cde2bd75ca792c6a54bda38c64cfcfe0dd1262..d4a40114ea199eca544fc8680d61d26dd110660a 100644 (file)
@@ -157,7 +157,8 @@ def format_exception_only(etype, value):
     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 8baac479cd2be83e432d8a3017a360e8b69cd097..e622b9acab489730a77df0af643faa6dd326e218 100644 (file)
@@ -145,7 +145,8 @@ def filterwarnings(action, message="", category=Warning, module="", lineno=0,
     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 51e0aefc4176a75f5e271739aed22ba590d6ce7a..63c2874c3779004a415cc077a47a310421e32a1c 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 2.5 alpha 1?
 Core and builtins
 -----------------
 
+- PEP 352, patch #1104669: Make exceptions new-style objects.  Introduced the
+  new exception base class, BaseException, which has a new message attribute.
+  KeyboardInterrupt and SystemExit to directly inherit from BaseException now.
+  Raising a string exception now raises a DeprecationWarning.
+
 - Patch #1438387, PEP 328: relative and absolute imports. Imports can now be
   explicitly relative, using 'from .module import name' to mean 'from the same
   package as this module is in. Imports without dots still default to the
index 8b84e2e41aedf74a6f891a520261f28d1521cce3..c24c3ce7ab5565db5a3791cb0d4d6fcd2ed02b8d 100644 (file)
@@ -230,11 +230,11 @@ gen_throw(PyGenObject *gen, PyObject *args)
        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,
@@ -245,7 +245,7 @@ gen_throw(PyGenObject *gen, PyObject *args)
                        /* Normalize to raise <class>, <instance> */
                        Py_XDECREF(val);
                        val = typ;
-                       typ = (PyObject*) ((PyInstanceObject*)typ)->in_class;
+                       typ = PyExceptionInstance_Class(typ);
                        Py_INCREF(typ);
                }
        }
index 3ef853ea1b2f9ae9ba533c38e41205ba1db1d243..8d0f7e6ce2f662a8f1cb0e9d2b4dc0c462c4b205 100644 (file)
@@ -1685,7 +1685,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
                                    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);
@@ -3026,14 +3026,14 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
                /* Raising builtin string is deprecated but still allowed --
                 * do nothing.  Raising an instance of a new-style str
                 * subclass is right out. */
-               if (-1 == PyErr_Warn(PyExc_PendingDeprecationWarning,
+               if (PyErr_Warn(PyExc_DeprecationWarning,
                           "raising a string exception is deprecated"))
                        goto raise_error;
        }
-       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,
@@ -3044,7 +3044,7 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
                        /* Normalize to raise <class>, <instance> */
                        Py_DECREF(value);
                        value = type;
-                       type = (PyObject*) ((PyInstanceObject*)type)->in_class;
+                       type = PyExceptionInstance_Class(type);
                        Py_INCREF(type);
                }
        }
index cd31e1c9fcbb0c5c44129abdb2ad9519dcc308d1..253bc393260d385af191d697ba417e1f710fda6f 100644 (file)
@@ -448,9 +448,8 @@ static void wrong_exception_type(PyObject *exc)
 
 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 c33bd13bde600005a32e71e615aa5710b21a6a52..7fc4c97c825d106c2865a3e025f0dac61bbccfd3 100644 (file)
@@ -97,11 +97,14 @@ PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)
                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;
 }
@@ -138,19 +141,19 @@ PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
                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)
@@ -282,7 +285,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
        {
                /* 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) {
@@ -302,7 +305,7 @@ PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
                                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;
@@ -345,8 +348,8 @@ PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename)
 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);
@@ -360,7 +363,7 @@ PyErr_SetFromErrno(PyObject *exc)
        return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
 }
 
-#ifdef MS_WINDOWS 
+#ifdef MS_WINDOWS
 /* Windows specific error code handling */
 PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(
        PyObject *exc,
@@ -415,8 +418,8 @@ PyObject *PyErr_SetExcFromWindowsErrWithFilename(
        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;
@@ -428,11 +431,11 @@ PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
        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;
@@ -466,8 +469,8 @@ PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(
        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,
@@ -574,7 +577,24 @@ PyErr_WriteUnraisable(PyObject *obj)
        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("<unknown>", f);
+                       else {
+                               char* modstr = PyString_AsString(moduleName);
+                               if (modstr)
+                               {
+                                       PyFile_WriteString(modstr, f);
+                                       PyFile_WriteString(".", f);
+                               }
+                       }
+                       if (className == NULL)
+                               PyFile_WriteString("<unknown>", f);
+                       else
+                               PyFile_WriteString(className, f);
                        if (v && v != Py_None) {
                                PyFile_WriteString(": ", f);
                                PyFile_WriteObject(v, f, 0);
@@ -726,7 +746,7 @@ PyErr_SyntaxLocation(const char *filename, int lineno)
 
 /* 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 c9e516f598db2c096d99baebc8f3a47129b39c99..59f209176675593f257d4378a19fada837cfd230 100644 (file)
@@ -11,6 +11,7 @@
  * 98-08-19    fl   created (for pyexe)
  * 00-02-08    fl   updated for 1.5.2
  * 26-May-2000 baw  vetted for Python 1.6
+ * XXX
  *
  * written by Fredrik Lundh
  * modifications, additions, cleanups, and proofreading by Barry Warsaw
 PyDoc_STRVAR(module__doc__,
 "Python's standard exception class hierarchy.\n\
 \n\
-Before Python 1.5, the standard exceptions were all simple string objects.\n\
-In Python 1.5, the standard exceptions were converted to classes organized\n\
-into a relatively flat hierarchy.  String-based standard exceptions were\n\
-optional, or used as a fallback if some problem occurred while importing\n\
-the exception module.  With Python 1.6, optional string-based standard\n\
-exceptions were removed (along with the -X command line flag).\n\
-\n\
-The class exceptions were implemented in such a way as to be almost\n\
-completely backward compatible.  Some tricky uses of IOError could\n\
-potentially have broken, but by Python 1.6, all of these should have\n\
-been fixed.  As of Python 1.6, the class-based standard exceptions are\n\
-now implemented in C, and are guaranteed to exist in the Python\n\
-interpreter.\n\
-\n\
-Here is a rundown of the class hierarchy.  The classes found here are\n\
-inserted into both the exceptions module and the `built-in' module.  It is\n\
-recommended that user defined class based exceptions be derived from the\n\
-`Exception' class, although this is currently not enforced.\n"
+Exceptions found here are defined both in the exceptions module and the \n\
+built-in namespace.  It is recommended that user-defined exceptions inherit \n\
+from Exception.\n\
+"
+
        /* keep string pieces "small" */
-"\n\
-Exception\n\
- |\n\
- +-- SystemExit\n\
- +-- StopIteration\n\
- +-- GeneratorExit\n\
- +-- StandardError\n\
- |    |\n\
- |    +-- KeyboardInterrupt\n\
- |    +-- ImportError\n\
- |    +-- EnvironmentError\n\
- |    |    |\n\
- |    |    +-- IOError\n\
- |    |    +-- OSError\n\
- |    |         |\n\
- |    |         +-- WindowsError\n\
- |    |         +-- VMSError\n\
- |    |\n\
- |    +-- EOFError\n\
- |    +-- RuntimeError\n\
- |    |    |\n\
- |    |    +-- NotImplementedError\n\
- |    |\n\
- |    +-- NameError\n\
- |    |    |\n\
- |    |    +-- UnboundLocalError\n\
- |    |\n\
- |    +-- AttributeError\n\
- |    +-- SyntaxError\n\
- |    |    |\n\
- |    |    +-- IndentationError\n\
- |    |         |\n\
- |    |         +-- TabError\n\
- |    |\n\
- |    +-- TypeError\n\
- |    +-- AssertionError\n\
- |    +-- LookupError\n\
- |    |    |\n\
- |    |    +-- IndexError\n\
- |    |    +-- KeyError\n\
- |    |\n\
- |    +-- ArithmeticError\n\
- |    |    |\n\
- |    |    +-- OverflowError\n\
- |    |    +-- ZeroDivisionError\n\
- |    |    +-- FloatingPointError\n\
- |    |\n\
- |    +-- ValueError\n\
- |    |    |\n\
- |    |    +-- UnicodeError\n\
- |    |        |\n\
- |    |        +-- UnicodeEncodeError\n\
- |    |        +-- UnicodeDecodeError\n\
- |    |        +-- UnicodeTranslateError\n\
- |    |\n\
- |    +-- ReferenceError\n\
- |    +-- SystemError\n\
- |    +-- MemoryError\n\
- |\n\
- +---Warning\n\
-      |\n\
-      +-- UserWarning\n\
-      +-- DeprecationWarning\n\
-      +-- PendingDeprecationWarning\n\
-      +-- SyntaxWarning\n\
-      +-- OverflowWarning\n\
-      +-- RuntimeWarning\n\
-      +-- FutureWarning"
+/* XXX exception hierarchy from Lib/test/exception_hierarchy.txt */
 );
 
 \f
 /* 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 +72,7 @@ populate_methods(PyObject *klass, PyObject *dict, PyMethodDef *methods)
        }
 
        /* 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 +117,7 @@ make_class(PyObject **klass, PyObject *base,
     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;
@@ -232,47 +153,81 @@ get_self(PyObject *args)
 /* Notes on bootstrapping the exception classes.
  *
  * First thing we create is the base class for all exceptions, called
- * appropriately enough: Exception.  Creation of this class makes no
+ * appropriately BaseException.  Creation of this class makes no
  * assumptions about the existence of any other exception class -- except
  * for TypeError, which can conditionally exist.
  *
- * Next, StandardError is created (which is quite simple) followed by
+ * Next, Exception is created since it is the common subclass for the rest of
+ * the needed exceptions for this bootstrapping to work.  StandardError is
+ * created (which is quite simple) followed by
  * TypeError, because the instantiation of other exceptions can potentially
  * throw a TypeError.  Once these exceptions are created, all the others
  * can be created in any order.  See the static exctable below for the
  * explicit bootstrap order.
  *
- * All classes after Exception can be created using PyErr_NewException().
+ * All classes after BaseException can be created using PyErr_NewException().
  */
 
-PyDoc_STRVAR(Exception__doc__, "Common base class for all exceptions.");
+PyDoc_STRVAR(BaseException__doc__, "Common base class for all exceptions");
 
+/*
+   Set args and message attributes.
 
-static PyObject *
-Exception__init__(PyObject *self, PyObject *args)
+   Assumes self and args have already been set properly with set_self, etc.
+*/
+static int
+set_args_and_message(PyObject *self, PyObject *args)
 {
-    int status;
+    PyObject *message_val;
+    Py_ssize_t args_len = PySequence_Length(args);
+
+    if (args_len < 0)
+           return 0;
+
+    /* set args */
+    if (PyObject_SetAttrString(self, "args", args) < 0)
+           return 0;
+
+    /* set message */
+    if (args_len == 1)
+           message_val = PySequence_GetItem(args, 0);
+    else
+           message_val = PyString_FromString("");
+    if (!message_val)
+           return 0;
+
+    if (PyObject_SetAttrString(self, "message", message_val) < 0) {
+            Py_DECREF(message_val);
+            return 0;
+    }
+
+    Py_DECREF(message_val);
+    return 1;
+}
 
+static PyObject *
+BaseException__init__(PyObject *self, PyObject *args)
+{
     if (!(self = get_self(args)))
        return NULL;
 
-    /* set args attribute */
-    /* XXX size is only a hint */
-    args = PySequence_GetSlice(args, 1, PySequence_Size(args));
+    /* set args and message attribute */
+    args = PySequence_GetSlice(args, 1, PySequence_Length(args));
     if (!args)
         return NULL;
-    status = PyObject_SetAttrString(self, "args", args);
-    Py_DECREF(args);
-    if (status < 0)
-        return NULL;
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
+    }
+
+    Py_DECREF(args);
+    Py_RETURN_NONE;
 }
 
 
 static PyObject *
-Exception__str__(PyObject *self, PyObject *args)
+BaseException__str__(PyObject *self, PyObject *args)
 {
     PyObject *out;
 
@@ -310,9 +265,116 @@ Exception__str__(PyObject *self, PyObject *args)
     return out;
 }
 
+#ifdef Py_USING_UNICODE
+static PyObject *
+BaseException__unicode__(PyObject *self, PyObject *args)
+{
+       Py_ssize_t args_len;
+
+       if (!PyArg_ParseTuple(args, "O:__unicode__", &self))
+               return NULL;
+
+       args = PyObject_GetAttrString(self, "args");
+       if (!args)
+               return NULL;
+
+       args_len = PySequence_Size(args);
+       if (args_len < 0) {
+               Py_DECREF(args);
+               return NULL;
+       }
+
+       if (args_len == 0) {
+               Py_DECREF(args);
+               return PyUnicode_FromUnicode(NULL, 0);
+       }
+       else if (args_len == 1) {
+               PyObject *temp = PySequence_GetItem(args, 0);
+               if (!temp) {
+                       Py_DECREF(args);
+                       return NULL;
+               }
+               Py_DECREF(args);
+               return PyObject_Unicode(temp);
+       }
+       else {
+               Py_DECREF(args);
+               return PyObject_Unicode(args);
+       }
+}
+#endif /* Py_USING_UNICODE */
+
+static PyObject *
+BaseException__repr__(PyObject *self, PyObject *args)
+{
+       PyObject *args_attr;
+       Py_ssize_t args_len;
+       PyObject *repr_suffix;
+       PyObject *repr;
+       
+       if (!PyArg_ParseTuple(args, "O:__repr__", &self))
+               return NULL;
+
+       args_attr = PyObject_GetAttrString(self, "args");
+       if (!args_attr)
+               return NULL;
+
+       args_len = PySequence_Length(args_attr);
+       if (args_len < 0) {
+               Py_DECREF(args_attr);
+               return NULL;
+       }
+
+       if (args_len == 0) {
+               Py_DECREF(args_attr);
+               repr_suffix = PyString_FromString("()");
+               if (!repr_suffix)
+                       return NULL;
+       }
+       else {
+               PyObject *args_repr;
+               /*PyObject *right_paren;
+
+               repr_suffix = PyString_FromString("(*");
+               if (!repr_suffix) {
+                       Py_DECREF(args_attr);
+                       return NULL;
+               }*/
+
+               args_repr = PyObject_Repr(args_attr);
+               Py_DECREF(args_attr);
+               if (!args_repr)
+                       return NULL;
+
+               repr_suffix = args_repr;
+
+               /*PyString_ConcatAndDel(&repr_suffix, args_repr);
+               if (!repr_suffix)
+                       return NULL;
+
+               right_paren = PyString_FromString(")");
+               if (!right_paren) {
+                       Py_DECREF(repr_suffix);
+                       return NULL;
+               }
+
+               PyString_ConcatAndDel(&repr_suffix, right_paren);
+               if (!repr_suffix)
+                       return NULL;*/
+       }
+
+       repr = PyString_FromString(self->ob_type->tp_name);
+       if (!repr) {
+               Py_DECREF(repr_suffix);
+               return NULL;
+       }
+
+       PyString_ConcatAndDel(&repr, repr_suffix);
+       return repr;
+}
 
 static PyObject *
-Exception__getitem__(PyObject *self, PyObject *args)
+BaseException__getitem__(PyObject *self, PyObject *args)
 {
     PyObject *out;
     PyObject *index;
@@ -331,21 +393,27 @@ Exception__getitem__(PyObject *self, PyObject *args)
 
 
 static PyMethodDef
-Exception_methods[] = {
-    /* methods for the Exception class */
-    { "__getitem__", Exception__getitem__, METH_VARARGS},
-    { "__str__",     Exception__str__, METH_VARARGS},
-    { "__init__",    Exception__init__, METH_VARARGS},
-    { NULL, NULL }
+BaseException_methods[] = {
+    /* methods for the BaseException class */
+    {"__getitem__", BaseException__getitem__, METH_VARARGS},
+    {"__repr__", BaseException__repr__, METH_VARARGS},
+    {"__str__",     BaseException__str__, METH_VARARGS},
+#ifdef Py_USING_UNICODE
+    {"__unicode__",  BaseException__unicode__, METH_VARARGS},
+#endif /* Py_USING_UNICODE */
+    {"__init__",    BaseException__init__, METH_VARARGS},
+    {NULL, NULL }
 };
 
 
 static int
-make_Exception(char *modulename)
+make_BaseException(char *modulename)
 {
     PyObject *dict = PyDict_New();
     PyObject *str = NULL;
     PyObject *name = NULL;
+    PyObject *emptytuple = NULL;
+    PyObject *argstuple = NULL;
     int status = -1;
 
     if (!dict)
@@ -360,20 +428,28 @@ make_Exception(char *modulename)
     if (PyDict_SetItemString(dict, "__module__", str))
        goto finally;
     Py_DECREF(str);
-    if (!(str = PyString_FromString(Exception__doc__)))
+
+    if (!(str = PyString_FromString(BaseException__doc__)))
        goto finally;
     if (PyDict_SetItemString(dict, "__doc__", str))
        goto finally;
 
-    if (!(name = PyString_FromString("Exception")))
+    if (!(name = PyString_FromString("BaseException")))
        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_BaseException = 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))
-       /* Don't need to reclaim PyExc_Exception here because that'll
+    if (populate_methods(PyExc_BaseException, BaseException_methods))
+       /* Don't need to reclaim PyExc_BaseException here because that'll
         * happen during interpreter shutdown.
         */
        goto finally;
@@ -384,13 +460,18 @@ make_Exception(char *modulename)
     Py_XDECREF(dict);
     Py_XDECREF(str);
     Py_XDECREF(name);
+    Py_XDECREF(emptytuple);
+    Py_XDECREF(argstuple);
     return status;
 }
 
 
 \f
+PyDoc_STRVAR(Exception__doc__, "Common base class for all non-exit exceptions.");
+
 PyDoc_STRVAR(StandardError__doc__,
-"Base class for all standard Python exceptions.");
+"Base class for all standard Python exceptions that do not represent"
+"interpreter exiting.");
 
 PyDoc_STRVAR(TypeError__doc__, "Inappropriate argument type.");
 
@@ -411,14 +492,12 @@ SystemExit__init__(PyObject *self, PyObject *args)
     if (!(self = get_self(args)))
        return NULL;
 
-    /* Set args attribute. */
     if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
         return NULL;
 
-    status = PyObject_SetAttrString(self, "args", args);
-    if (status < 0) {
-       Py_DECREF(args);
-        return NULL;
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
     }
 
     /* set code attribute */
@@ -445,8 +524,7 @@ SystemExit__init__(PyObject *self, PyObject *args)
     if (status < 0)
         return NULL;
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 
@@ -482,8 +560,12 @@ EnvironmentError__init__(PyObject *self, PyObject *args)
     if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
        return NULL;
 
-    if (PyObject_SetAttrString(self, "args", args) ||
-       PyObject_SetAttrString(self, "errno", Py_None) ||
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
+    }
+
+    if (PyObject_SetAttrString(self, "errno", Py_None) ||
        PyObject_SetAttrString(self, "strerror", Py_None) ||
        PyObject_SetAttrString(self, "filename", Py_None))
     {
@@ -624,9 +706,9 @@ EnvironmentError__str__(PyObject *self, PyObject *args)
         *   return StandardError.__str__(self)
         *
         * but there is no StandardError__str__() function; we happen to
-        * know that's just a pass through to Exception__str__().
+        * know that's just a pass through to BaseException__str__().
         */
-       rtnval = Exception__str__(originalself, args);
+       rtnval = BaseException__str__(originalself, args);
 
   finally:
     Py_XDECREF(filename);
@@ -712,8 +794,10 @@ SyntaxError__init__(PyObject *self, PyObject *args)
     if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
        return NULL;
 
-    if (PyObject_SetAttrString(self, "args", args))
-       goto finally;
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
+    }
 
     lenargs = PySequence_Size(args);
     if (lenargs >= 1) {
@@ -879,8 +963,9 @@ KeyError__str__(PyObject *self, PyObject *args)
     if (!PyArg_ParseTuple(args, "O:__str__", &self))
        return NULL;
 
-    if (!(argsattr = PyObject_GetAttrString(self, "args")))
-       return NULL;
+    argsattr = PyObject_GetAttrString(self, "args");
+    if (!argsattr)
+           return NULL;
 
     /* If args is a tuple of exactly one item, apply repr to args[0].
        This is done so that e.g. the exception raised by {}[''] prints
@@ -889,14 +974,14 @@ KeyError__str__(PyObject *self, PyObject *args)
          KeyError
        alone.  The downside is that if KeyError is raised with an explanatory
        string, that string will be displayed in quotes.  Too bad.
-       If args is anything else, use the default Exception__str__().
+       If args is anything else, use the default BaseException__str__().
     */
     if (PyTuple_Check(argsattr) && PyTuple_GET_SIZE(argsattr) == 1) {
        PyObject *key = PyTuple_GET_ITEM(argsattr, 0);
        result = PyObject_Repr(key);
     }
     else
-       result = Exception__str__(self, args);
+       result = BaseException__str__(self, args);
 
     Py_DECREF(argsattr);
     return result;
@@ -1193,6 +1278,11 @@ UnicodeError__init__(PyObject *self, PyObject *args, PyTypeObject *objecttype)
     if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
        return NULL;
 
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
+    }
+
     if (!PyArg_ParseTuple(args, "O!O!O!O!O!",
        &PyString_Type, &encoding,
        objecttype, &object,
@@ -1201,9 +1291,6 @@ UnicodeError__init__(PyObject *self, PyObject *args, PyTypeObject *objecttype)
        &PyString_Type, &reason))
        goto finally;
 
-    if (PyObject_SetAttrString(self, "args", args))
-       goto finally;
-
     if (PyObject_SetAttrString(self, "encoding", encoding))
        goto finally;
     if (PyObject_SetAttrString(self, "object", object))
@@ -1405,6 +1492,11 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
     if (!(args = PySequence_GetSlice(args, 1, PySequence_Size(args))))
        return NULL;
 
+    if (!set_args_and_message(self, args)) {
+           Py_DECREF(args);
+           return NULL;
+    }
+
     if (!PyArg_ParseTuple(args, "O!O!O!O!",
        &PyUnicode_Type, &object,
        &PyInt_Type, &start,
@@ -1412,9 +1504,6 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
        &PyString_Type, &reason))
        goto finally;
 
-    if (PyObject_SetAttrString(self, "args", args))
-       goto finally;
-
     if (PyObject_SetAttrString(self, "object", object))
        goto finally;
     if (PyObject_SetAttrString(self, "start", start))
@@ -1424,8 +1513,8 @@ UnicodeTranslateError__init__(PyObject *self, PyObject *args)
     if (PyObject_SetAttrString(self, "reason", reason))
        goto finally;
 
-    Py_INCREF(Py_None);
     rtnval = Py_None;
+    Py_INCREF(rtnval);
 
   finally:
     Py_DECREF(args);
@@ -1591,6 +1680,7 @@ static PyMethodDef functions[] = {
 \f
 /* Global C API defined exceptions */
 
+PyObject *PyExc_BaseException;
 PyObject *PyExc_Exception;
 PyObject *PyExc_StopIteration;
 PyObject *PyExc_GeneratorExit;
@@ -1636,7 +1726,7 @@ PyObject *PyExc_VMSError;
 #endif
 
 /* Pre-computed MemoryError instance.  Best to create this as early as
- * possibly and not wait until a MemoryError is actually raised!
+ * possible and not wait until a MemoryError is actually raised!
  */
 PyObject *PyExc_MemoryErrorInst;
 
@@ -1663,9 +1753,10 @@ static struct {
     int (*classinit)(PyObject *);
 } exctable[] = {
  /*
-  * The first three classes MUST appear in exactly this order
+  * The first four classes MUST appear in exactly this order
   */
- {"Exception", &PyExc_Exception},
+ {"BaseException", &PyExc_BaseException},
+ {"Exception", &PyExc_Exception, &PyExc_BaseException, Exception__doc__},
  {"StopIteration", &PyExc_StopIteration, &PyExc_Exception,
   StopIteration__doc__},
  {"GeneratorExit", &PyExc_GeneratorExit, &PyExc_Exception,
@@ -1676,9 +1767,10 @@ static struct {
  /*
   * The rest appear in depth-first order of the hierarchy
   */
- {"SystemExit", &PyExc_SystemExit, &PyExc_Exception, SystemExit__doc__,
+ {"SystemExit", &PyExc_SystemExit, &PyExc_BaseException, SystemExit__doc__,
   SystemExit_methods},
- {"KeyboardInterrupt",  &PyExc_KeyboardInterrupt, 0, KeyboardInterrupt__doc__},
+ {"KeyboardInterrupt",  &PyExc_KeyboardInterrupt, &PyExc_BaseException,
+        KeyboardInterrupt__doc__},
  {"ImportError",        &PyExc_ImportError,       0, ImportError__doc__},
  {"EnvironmentError",   &PyExc_EnvironmentError,  0, EnvironmentError__doc__,
   EnvironmentError_methods},
@@ -1786,11 +1878,11 @@ _PyExc_Init(void)
     }
 
     /* This is the base class of all exceptions, so make it first. */
-    if (make_Exception(modulename) ||
-       PyDict_SetItemString(mydict, "Exception", PyExc_Exception) ||
-       PyDict_SetItemString(bdict, "Exception", PyExc_Exception))
+    if (make_BaseException(modulename) ||
+       PyDict_SetItemString(mydict, "BaseException", PyExc_BaseException) ||
+       PyDict_SetItemString(bdict, "BaseException", PyExc_BaseException))
     {
-       Py_FatalError("Base class `Exception' could not be created.");
+       Py_FatalError("Base class `BaseException' could not be created.");
     }
 
     /* Now we can programmatically create all the remaining exceptions.
index d5c86f2a1f6cd04bcb9e4bac39c063e073a5c3c0..bbe935297d92318b75c679f2763372521c96b1cb 100644 (file)
@@ -976,7 +976,7 @@ handle_system_exit(void)
        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) {
@@ -1106,11 +1106,10 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
                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("<unknown>", f);
@@ -1126,8 +1125,7 @@ void PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
                                if (className == NULL)
                                      err = PyFile_WriteString("<unknown>", f);
                                else
-                                     err = PyFile_WriteObject(className, f,
-                                                              Py_PRINT_RAW);
+                                     err = PyFile_WriteString(className, f);
                        }
                }
                else