]> granicus.if.org Git - python/commitdiff
Issue #1066: implement PEP 3109, 2/3 of PEP 3134.
authorCollin Winter <collinw@gmail.com>
Fri, 31 Aug 2007 00:04:24 +0000 (00:04 +0000)
committerCollin Winter <collinw@gmail.com>
Fri, 31 Aug 2007 00:04:24 +0000 (00:04 +0000)
32 files changed:
Grammar/Grammar
Include/Python-ast.h
Include/pyerrors.h
Lib/contextlib.py
Lib/doctest.py
Lib/os.py
Lib/test/test_ast.py
Lib/test/test_exceptions.py
Lib/test/test_grammar.py
Lib/test/test_opcodes.py
Lib/test/test_raise.py [new file with mode: 0644]
Lib/test/test_syntax.py
Lib/test/test_sys.py
Lib/test/test_with.py
Lib/test/test_zipimport.py
Lib/urllib.py
Lib/urllib2.py
Lib/wsgiref/handlers.py
Mac/BuildScript/build-installer.py
Mac/Tools/Doc/setup.py
Mac/scripts/buildpkg.py
Mac/scripts/mkestrres.py
Objects/exceptions.c
Parser/Python.asdl
Python/Python-ast.c
Python/ast.c
Python/ceval.c
Python/compile.c
Python/graminit.c
Python/import.c
Python/symtable.c
Tools/webchecker/webchecker.py

index 17a01483e8c077226462a15fbdf41a9fdb3549e5..6111fae79b80e72e6af8d7c522b272c20bf57772 100644 (file)
@@ -49,7 +49,7 @@ break_stmt: 'break'
 continue_stmt: 'continue'
 return_stmt: 'return' [testlist]
 yield_stmt: yield_expr
-raise_stmt: 'raise' [test [',' test [',' test]]]
+raise_stmt: 'raise' [test ['from' test]]
 import_stmt: import_name | import_from
 import_name: 'import' dotted_as_names
 # note below: the ('.' | '...') is necessary because '...' is tokenized as ELLIPSIS
index 174a8412c4960d52d5cefff1cbc393bf09f8afce..51e52986ee55a105824ff3e7aceecdc755d30dd1 100644 (file)
@@ -134,9 +134,8 @@ struct _stmt {
                 } With;
                 
                 struct {
-                        expr_ty type;
-                        expr_ty inst;
-                        expr_ty tback;
+                        expr_ty exc;
+                        expr_ty cause;
                 } Raise;
                 
                 struct {
@@ -418,9 +417,9 @@ stmt_ty _Py_If(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno,
 #define With(a0, a1, a2, a3, a4, a5) _Py_With(a0, a1, a2, a3, a4, a5)
 stmt_ty _Py_With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body,
                  int lineno, int col_offset, PyArena *arena);
-#define Raise(a0, a1, a2, a3, a4, a5) _Py_Raise(a0, a1, a2, a3, a4, a5)
-stmt_ty _Py_Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int
-                  col_offset, PyArena *arena);
+#define Raise(a0, a1, a2, a3, a4) _Py_Raise(a0, a1, a2, a3, a4)
+stmt_ty _Py_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset,
+                  PyArena *arena);
 #define TryExcept(a0, a1, a2, a3, a4, a5) _Py_TryExcept(a0, a1, a2, a3, a4, a5)
 stmt_ty _Py_TryExcept(asdl_seq * body, asdl_seq * handlers, asdl_seq * orelse,
                       int lineno, int col_offset, PyArena *arena);
index ca187e4876a6a910612151d42c8b7c462cc0a5c5..8d676d9ed4b3bfbf62a19a457c7c05a9bb1ce6e6 100644 (file)
@@ -6,16 +6,17 @@ extern "C" {
 
 /* Error objects */
 
+/* PyException_HEAD defines the initial segment of every exception class. */
+#define PyException_HEAD PyObject_HEAD; PyObject *dict;\
+                         PyObject *args; PyObject *traceback;\
+                         PyObject *context; PyObject *cause;
+
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
 } PyBaseExceptionObject;
 
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
     PyObject *msg;
     PyObject *filename;
     PyObject *lineno;
@@ -25,9 +26,7 @@ typedef struct {
 } PySyntaxErrorObject;
 
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
     PyObject *encoding;
     PyObject *object;
     Py_ssize_t start;
@@ -36,16 +35,12 @@ typedef struct {
 } PyUnicodeErrorObject;
 
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
     PyObject *code;
 } PySystemExitObject;
 
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
     PyObject *myerrno;
     PyObject *strerror;
     PyObject *filename;
@@ -53,9 +48,7 @@ typedef struct {
 
 #ifdef MS_WINDOWS
 typedef struct {
-    PyObject_HEAD
-    PyObject *dict;
-    PyObject *args;
+    PyException_HEAD
     PyObject *myerrno;
     PyObject *strerror;
     PyObject *filename;
@@ -84,6 +77,19 @@ PyAPI_FUNC(int) PyErr_GivenExceptionMatches(PyObject *, PyObject *);
 PyAPI_FUNC(int) PyErr_ExceptionMatches(PyObject *);
 PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
 
+/* Traceback manipulation (PEP 3134) */
+PyAPI_FUNC(int) PyException_SetTraceback(PyObject *, PyObject *);
+PyAPI_FUNC(PyObject *) PyException_GetTraceback(PyObject *);
+
+/* Cause manipulation (PEP 3134) */
+PyAPI_FUNC(PyObject *) PyException_GetCause(PyObject *);
+PyAPI_FUNC(void) PyException_SetCause(PyObject *, PyObject *);
+
+/* Context manipulation (PEP 3134) */
+PyAPI_FUNC(PyObject *) PyException_GetContext(PyObject *);
+PyAPI_FUNC(void) PyException_SetContext(PyObject *, PyObject *);
+
+
 /* */
 
 #define PyExceptionClass_Check(x)                                      \
@@ -98,7 +104,7 @@ PyAPI_FUNC(void) PyErr_NormalizeException(PyObject**, PyObject**, PyObject**);
 
 #define PyExceptionInstance_Class(x) ((PyObject*)((x)->ob_type))
 
-       
+
 /* Predefined exceptions */
 
 PyAPI_DATA(PyObject *) PyExc_BaseException;
@@ -212,7 +218,7 @@ PyAPI_FUNC(void) PyErr_WriteUnraisable(PyObject *);
 PyAPI_FUNC(int) PyErr_WarnEx(PyObject *category, const char *msg,
                             Py_ssize_t stack_level);
 PyAPI_FUNC(int) PyErr_WarnExplicit(PyObject *, const char *,
-                                  const char *, int, 
+                                  const char *, int,
                                   const char *, PyObject *);
 
 /* In sigcheck.c or signalmodule.c */
index bc810b0bc83e04c8c1eda941b50951647f0a92da..38ec5775988e5c03cbc79f57c1c3c4d5aac2fba1 100644 (file)
@@ -125,7 +125,7 @@ def nested(*managers):
             # Don't rely on sys.exc_info() still containing
             # the right information. Another exception may
             # have been raised and caught by an exit method
-            raise exc[0], exc[1], exc[2]
+            raise exc[0](exc[1]).with_traceback(exc[2])
 
 
 class closing(object):
index 2374d44f5d813eb30cf568d844e5700ab7263b55..395f8b6369c486547c18ca44e15d098e08cdf6bb 100644 (file)
@@ -1608,7 +1608,7 @@ class DebugRunner(DocTestRunner):
          '42\n'
 
          >>> exc_info = failure.exc_info
-         >>> raise exc_info[0], exc_info[1], exc_info[2]
+         >>> raise exc_info[1] # Already has the traceback
          Traceback (most recent call last):
          ...
          KeyError
@@ -2146,7 +2146,7 @@ class DocTestCase(unittest.TestCase):
              '42\n'
 
              >>> exc_info = failure.exc_info
-             >>> raise exc_info[0], exc_info[1], exc_info[2]
+             >>> raise exc_info[1] # Already has the traceback
              Traceback (most recent call last):
              ...
              KeyError
index b8d7a0f828a6a0611059854a60b6c9d764db0fc5..727d0cb27c2afa9bbed3e0f419a485bd88ff6a82 100644 (file)
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -113,7 +113,7 @@ elif 'ce' in _names:
     del ce
 
 else:
-    raise ImportError, 'no os specific module found'
+    raise ImportError('no os specific module found')
 
 sys.modules['os.path'] = path
 from os.path import curdir, pardir, sep, pathsep, defpath, altsep, devnull
@@ -386,8 +386,8 @@ def _execvpe(file, args, env=None):
                 saved_exc = e
                 saved_tb = tb
     if saved_exc:
-        raise error, saved_exc, saved_tb
-    raise error, last_exc, tb
+        raise error(saved_exc).with_traceback(saved_tb)
+    raise error(last_exc).with_traceback(tb)
 
 
 # Change environ to automatically call putenv(), unsetenv if they exist.
@@ -492,7 +492,7 @@ if _exists("fork") and not _exists("spawnv") and _exists("execv"):
                 elif WIFEXITED(sts):
                     return WEXITSTATUS(sts)
                 else:
-                    raise error, "Not stopped, signaled or exited???"
+                    raise error("Not stopped, signaled or exited???")
 
     def spawnv(mode, file, args):
         """spawnv(mode, file, args) -> integer
index b8c1ed9d4d8932270e8aaf7426a770e0a76b5f79..629912355d6c801492476a76be76b3b2ec39a4da 100644 (file)
@@ -37,7 +37,7 @@ exec_tests = [
     # If
     "if v:pass",
     # Raise
-    "raise Exception, 'string'",
+    "raise Exception('string')",
     # TryExcept
     "try:\n  pass\nexcept Exception:\n  pass",
     # TryFinally
@@ -160,7 +160,7 @@ exec_results = [
 ('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]),
 ('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]),
 ('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]),
-('Module', [('Raise', (1, 0), ('Name', (1, 6), 'Exception', ('Load',)), ('Str', (1, 17), 'string'), None)]),
+('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], [], None, None), None)]),
 ('Module', [('TryExcept', (1, 0), [('Pass', (2, 2))], [('excepthandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))], 3, 0)], [])]),
 ('Module', [('TryFinally', (1, 0), [('Pass', (2, 2))], [('Pass', (4, 2))])]),
 ('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]),
index 90f6ae7d8b95f673a085621f99913e71166c53c4..d2a21913a46e0935d5ba10d7646cd0efa1189678 100644 (file)
@@ -13,7 +13,7 @@ class ExceptionTests(unittest.TestCase):
 
     def raise_catch(self, exc, excname):
         try:
-            raise exc, "spam"
+            raise exc("spam")
         except exc as err:
             buf1 = str(err)
         try:
@@ -141,7 +141,7 @@ class ExceptionTests(unittest.TestCase):
 
         class BadException(Exception):
             def __init__(self_):
-                raise RuntimeError, "can't instantiate BadException"
+                raise RuntimeError("can't instantiate BadException")
 
         class InvalidException:
             pass
@@ -305,6 +305,62 @@ class ExceptionTests(unittest.TestCase):
                                               'pickled "%r", attribute "%s' %
                                               (e, checkArgName))
 
+    def testWithTraceback(self):
+        try:
+            raise IndexError(4)
+        except:
+            tb = sys.exc_info()[2]
+
+        e = BaseException().with_traceback(tb)
+        self.failUnless(isinstance(e, BaseException))
+        self.assertEqual(e.__traceback__, tb)
+
+        e = IndexError(5).with_traceback(tb)
+        self.failUnless(isinstance(e, IndexError))
+        self.assertEqual(e.__traceback__, tb)
+
+        class MyException(Exception):
+            pass
+
+        e = MyException().with_traceback(tb)
+        self.failUnless(isinstance(e, MyException))
+        self.assertEqual(e.__traceback__, tb)
+
+    def testInvalidTraceback(self):
+        try:
+            Exception().__traceback__ = 5
+        except TypeError as e:
+            self.failUnless("__traceback__ must be a traceback" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def testNoneClearsTracebackAttr(self):
+        try:
+            raise IndexError(4)
+        except:
+            tb = sys.exc_info()[2]
+
+        e = Exception()
+        e.__traceback__ = tb
+        e.__traceback__ = None
+        self.assertEqual(e.__traceback__, None)
+
+    def testChainingAttrs(self):
+        e = Exception()
+        self.assertEqual(e.__context__, None)
+        self.assertEqual(e.__cause__, None)
+
+        e = TypeError()
+        self.assertEqual(e.__context__, None)
+        self.assertEqual(e.__cause__, None)
+
+        class MyException(EnvironmentError):
+            pass
+
+        e = MyException()
+        self.assertEqual(e.__context__, None)
+        self.assertEqual(e.__cause__, None)
+
     def testKeywordArgs(self):
         # test that builtin exception don't take keyword args,
         # but user-defined subclasses can if they want
index bfc77feccfc5d72556a57b5a8b109c67a5ad8359..ee3ffc7e2e0f8ed2457ce301e3148f3b6ca615f4 100644 (file)
@@ -438,7 +438,7 @@ class GrammarTests(unittest.TestCase):
 
     def testRaise(self):
         # 'raise' test [',' test]
-        try: raise RuntimeError, 'just testing'
+        try: raise RuntimeError('just testing')
         except RuntimeError: pass
         try: raise KeyboardInterrupt
         except KeyboardInterrupt: pass
index 0ee51a83059aa82c311825e4708aa16debe25966..d65c5cca53fa63d963b87620fe275854a7c04e66 100644 (file)
@@ -46,14 +46,10 @@ class OpcodeTest(unittest.TestCase):
         a = AClass()
         b = BClass()
 
-        try: raise AClass, b
-        except BClass as v:
-            if v != b: self.fail("v!=b")
-        else: self.fail("no exception")
-
-        try: raise b
+        try:
+            raise b
         except AClass as v:
-            if v != b: self.fail("v!=b AClass")
+            self.assertEqual(v, b)
         else:
             self.fail("no exception")
 
@@ -62,7 +58,7 @@ class OpcodeTest(unittest.TestCase):
         ##except TypeError: pass
         ##else: self.fail("no exception")
 
-        try:  raise DClass, a
+        try:  raise DClass(a)
         except DClass as v:
             self.assert_(isinstance(v, DClass))
         else:
diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py
new file mode 100644 (file)
index 0000000..ac0a32b
--- /dev/null
@@ -0,0 +1,417 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+    try:
+        raise OSError()
+    except:
+        return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+    def test_invalid_reraise(self):
+        try:
+            raise
+        except RuntimeError as e:
+            self.failUnless("No active exception" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_reraise(self):
+        try:
+            try:
+                raise IndexError()
+            except IndexError as e:
+                exc1 = e
+                raise
+        except IndexError as exc2:
+            self.failUnless(exc1 is exc2)
+        else:
+            self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+    def test_invalid_cause(self):
+        try:
+            raise IndexError from 5
+        except TypeError as e:
+            self.failUnless("exception cause" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_class_cause(self):
+        try:
+            raise IndexError from KeyError
+        except IndexError as e:
+            self.failUnless(isinstance(e.__cause__, KeyError))
+        else:
+            self.fail("No exception raised")
+
+    def test_instance_cause(self):
+        cause = KeyError()
+        try:
+            raise IndexError from cause
+        except IndexError as e:
+            self.failUnless(e.__cause__ is cause)
+        else:
+            self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+    def test_sets_traceback(self):
+        try:
+            raise IndexError()
+        except IndexError as e:
+            self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+        else:
+            self.fail("No exception raised")
+
+    def test_accepts_traceback(self):
+        tb = get_tb()
+        try:
+            raise IndexError().with_traceback(tb)
+        except IndexError as e:
+            self.assertNotEqual(e.__traceback__, tb)
+            self.assertEqual(e.__traceback__.tb_next, tb)
+        else:
+            self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+#     def test_instance_context_bare_raise(self):
+#         context = IndexError()
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertEqual(e.__context__, context)
+#         else:
+#             self.fail("No exception raised")
+#
+#     def test_class_context_bare_raise(self):
+#         context = IndexError
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertNotEqual(e.__context__, context)
+#             self.failUnless(isinstance(e.__context__, context))
+#         else:
+#             self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+    def test_tuples(self):
+        try:
+            raise (IndexError, KeyError) # This should be a tuple!
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+    def test_strings(self):
+        try:
+            raise "foo"
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+
+def test_main():
+    test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+    unittest.main()
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+    try:
+        raise OSError()
+    except:
+        return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+    def test_invalid_reraise(self):
+        try:
+            raise
+        except RuntimeError as e:
+            self.failUnless("No active exception" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_reraise(self):
+        try:
+            try:
+                raise IndexError()
+            except IndexError as e:
+                exc1 = e
+                raise
+        except IndexError as exc2:
+            self.failUnless(exc1 is exc2)
+        else:
+            self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+    def test_invalid_cause(self):
+        try:
+            raise IndexError from 5
+        except TypeError as e:
+            self.failUnless("exception cause" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_class_cause(self):
+        try:
+            raise IndexError from KeyError
+        except IndexError as e:
+            self.failUnless(isinstance(e.__cause__, KeyError))
+        else:
+            self.fail("No exception raised")
+
+    def test_instance_cause(self):
+        cause = KeyError()
+        try:
+            raise IndexError from cause
+        except IndexError as e:
+            self.failUnless(e.__cause__ is cause)
+        else:
+            self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+    def test_sets_traceback(self):
+        try:
+            raise IndexError()
+        except IndexError as e:
+            self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+        else:
+            self.fail("No exception raised")
+
+    def test_accepts_traceback(self):
+        tb = get_tb()
+        try:
+            raise IndexError().with_traceback(tb)
+        except IndexError as e:
+            self.assertNotEqual(e.__traceback__, tb)
+            self.assertEqual(e.__traceback__.tb_next, tb)
+        else:
+            self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+#     def test_instance_context_bare_raise(self):
+#         context = IndexError()
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertEqual(e.__context__, context)
+#         else:
+#             self.fail("No exception raised")
+#
+#     def test_class_context_bare_raise(self):
+#         context = IndexError
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertNotEqual(e.__context__, context)
+#             self.failUnless(isinstance(e.__context__, context))
+#         else:
+#             self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+    def test_tuples(self):
+        try:
+            raise (IndexError, KeyError) # This should be a tuple!
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+    def test_strings(self):
+        try:
+            raise "foo"
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+
+def test_main():
+    test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+    unittest.main()
+# Copyright 2007 Google, Inc. All Rights Reserved.
+# Licensed to PSF under a Contributor Agreement.
+
+"""Tests for the raise statement."""
+
+from test import test_support
+import sys
+import types
+import unittest
+
+
+def get_tb():
+    try:
+        raise OSError()
+    except:
+        return sys.exc_info()[2]
+
+
+class TestRaise(unittest.TestCase):
+    def test_invalid_reraise(self):
+        try:
+            raise
+        except RuntimeError as e:
+            self.failUnless("No active exception" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_reraise(self):
+        try:
+            try:
+                raise IndexError()
+            except IndexError as e:
+                exc1 = e
+                raise
+        except IndexError as exc2:
+            self.failUnless(exc1 is exc2)
+        else:
+            self.fail("No exception raised")
+
+
+class TestCause(unittest.TestCase):
+    def test_invalid_cause(self):
+        try:
+            raise IndexError from 5
+        except TypeError as e:
+            self.failUnless("exception cause" in str(e))
+        else:
+            self.fail("No exception raised")
+
+    def test_class_cause(self):
+        try:
+            raise IndexError from KeyError
+        except IndexError as e:
+            self.failUnless(isinstance(e.__cause__, KeyError))
+        else:
+            self.fail("No exception raised")
+
+    def test_instance_cause(self):
+        cause = KeyError()
+        try:
+            raise IndexError from cause
+        except IndexError as e:
+            self.failUnless(e.__cause__ is cause)
+        else:
+            self.fail("No exception raised")
+
+
+class TestTraceback(unittest.TestCase):
+    def test_sets_traceback(self):
+        try:
+            raise IndexError()
+        except IndexError as e:
+            self.failUnless(isinstance(e.__traceback__, types.TracebackType))
+        else:
+            self.fail("No exception raised")
+
+    def test_accepts_traceback(self):
+        tb = get_tb()
+        try:
+            raise IndexError().with_traceback(tb)
+        except IndexError as e:
+            self.assertNotEqual(e.__traceback__, tb)
+            self.assertEqual(e.__traceback__.tb_next, tb)
+        else:
+            self.fail("No exception raised")
+
+
+# Disabled until context is implemented
+# class TestContext(object):
+#     def test_instance_context_bare_raise(self):
+#         context = IndexError()
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertEqual(e.__context__, context)
+#         else:
+#             self.fail("No exception raised")
+#
+#     def test_class_context_bare_raise(self):
+#         context = IndexError
+#         try:
+#             try:
+#                 raise context
+#             except:
+#                 raise OSError()
+#         except OSError as e:
+#             self.assertNotEqual(e.__context__, context)
+#             self.failUnless(isinstance(e.__context__, context))
+#         else:
+#             self.fail("No exception raised")
+
+
+class TestRemovedFunctionality(unittest.TestCase):
+    def test_tuples(self):
+        try:
+            raise (IndexError, KeyError) # This should be a tuple!
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+    def test_strings(self):
+        try:
+            raise "foo"
+        except TypeError:
+            pass
+        else:
+            self.fail("No exception raised")
+
+
+def test_main():
+    test_support.run_unittest(__name__)
+
+
+if __name__ == "__main__":
+    unittest.main()
index 4297d22c3c356f49866753e776f2febaba886247..546f7a8626ca0d294625cbc201ba736d075fbf8f 100644 (file)
@@ -460,6 +460,16 @@ leading to spurious errors.
      ...
    SyntaxError: can't assign to function call
 
+Make sure that the old "raise X, Y[, Z]" form is gone:
+   >>> raise X, Y
+   Traceback (most recent call last):
+     ...
+   SyntaxError: invalid syntax
+   >>> raise X, Y, Z
+   Traceback (most recent call last):
+     ...
+   SyntaxError: invalid syntax
+
 """
 
 import re
index d9adf029a769261a9b4e80f1f51d10f135629902..e7370471b568ded80965a588ff6b918786b729ac 100644 (file)
@@ -119,11 +119,6 @@ class SysModuleTest(unittest.TestCase):
 
         # test that the exit machinery handles SystemExits properly
         import subprocess
-        # both unnormalized...
-        rc = subprocess.call([sys.executable, "-c",
-                              "raise SystemExit, 46"])
-        self.assertEqual(rc, 46)
-        # ... and normalized
         rc = subprocess.call([sys.executable, "-c",
                               "raise SystemExit(47)"])
         self.assertEqual(rc, 47)
index 3f1d3582cb166156798491168a802c87d6722966..4fc8fe9fca514f3b7881d62f473a1fb242f3d8bd 100644 (file)
@@ -87,7 +87,7 @@ class Nested(object):
                 ex = sys.exc_info()
         self.entered = None
         if ex is not exc_info:
-            raise ex[0], ex[1], ex[2]
+            raise ex[0](ex[1]).with_traceback(ex[2])
 
 
 class MockNested(Nested):
index f38983fce989f0290d5ad899f42b21608b769627..58935b7f0312daf7b9adea0f03aacd46e923d8e5 100644 (file)
@@ -244,7 +244,7 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
         def get_file():
             return __file__
         if __loader__.get_data("some.data") != b"some data":
-            raise AssertionError, "bad data"\n"""
+            raise AssertionError("bad data")\n"""
         pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
         files = {TESTMOD + pyc_ext: (NOW, pyc),
                  "some.data": (NOW, "some data")}
index 67f457d55995d146dbd1b19941e0f535b35728a0..a1e26f04d220fc38f382767c3e38e54da300f64e 100644 (file)
@@ -199,7 +199,7 @@ class URLopener:
             else:
                 return getattr(self, name)(url, data)
         except socket.error as msg:
-            raise IOError, ('socket error', msg), sys.exc_info()[2]
+            raise IOError('socket error', msg).with_traceback(sys.exc_info()[2])
 
     def open_unknown(self, fullurl, data=None):
         """Overridable interface to open unknown URL type."""
@@ -498,7 +498,7 @@ class URLopener:
             headers = mimetools.Message(StringIO(headers))
             return addinfourl(fp, headers, "ftp:" + url)
         except ftperrors() as msg:
-            raise IOError, ('ftp error', msg), sys.exc_info()[2]
+            raise IOError('ftp error', msg).with_traceback(sys.exc_info()[2])
 
     def open_data(self, url, data=None):
         """Use "data" URL."""
@@ -809,7 +809,7 @@ class ftpwrapper:
                 conn = self.ftp.ntransfercmd(cmd)
             except ftplib.error_perm as reason:
                 if str(reason)[:3] != '550':
-                    raise IOError, ('ftp error', reason), sys.exc_info()[2]
+                    raise IOError('ftp error', reason).with_traceback(sys.exc_info()[2])
         if not conn:
             # Set transfer mode to ASCII!
             self.ftp.voidcmd('TYPE A')
@@ -1186,7 +1186,7 @@ def urlencode(query,doseq=0):
             # preserved for consistency
         except TypeError:
             ty,va,tb = sys.exc_info()
-            raise TypeError, "not a valid non-string sequence or mapping object", tb
+            raise TypeError("not a valid non-string sequence or mapping object").with_traceback(tb)
 
     l = []
     if not doseq:
index 72e2899aba977e9ddae14edd37265631b51144bf..58e01533034e0a8a3ba0b5191c1baa2e21a3992a 100644 (file)
@@ -1286,7 +1286,7 @@ class FTPHandler(BaseHandler):
             headers = mimetools.Message(sf)
             return addinfourl(fp, headers, req.get_full_url())
         except ftplib.all_errors as msg:
-            raise IOError, ('ftp error', msg), sys.exc_info()[2]
+            raise IOError('ftp error', msg).with_traceback(sys.exc_info()[2])
 
     def connect_ftp(self, user, passwd, host, port, dirs, timeout):
         fw = ftpwrapper(user, passwd, host, port, dirs, timeout)
index d9347e55a6e7f5d7fe3a287c7c7fc4f856ca931e..8231620499cced0b069834248b72d6566870fb59 100644 (file)
@@ -151,7 +151,7 @@ class BaseHandler:
             try:
                 if self.headers_sent:
                     # Re-raise original exception if headers sent
-                    raise exc_info[0], exc_info[1], exc_info[2]
+                    raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
             finally:
                 exc_info = None        # avoid dangling circular ref
         elif self.headers is not None:
index c7ebce81d19dc0a068325ee3bffacd346156ebe2..0b62ea60162728657a8da83e6f9485c91d24c69c 100755 (executable)
@@ -54,7 +54,7 @@ def getFullVersion():
         if 'PY_VERSION' in ln:
             return ln.split()[-1][1:-1]
 
-    raise RuntimeError, "Cannot find full version??"
+    raise RuntimeError("Cannot find full version??")
 
 # The directory we'll use to create the build (will be erased and recreated)
 WORKDIR = "/tmp/_py"
@@ -291,7 +291,7 @@ def runCommand(commandline):
     xit = fd.close()
     if xit != None:
         sys.stdout.write(data)
-        raise RuntimeError, "command failed: %s"%(commandline,)
+        raise RuntimeError("command failed: %s"%(commandline,))
 
     if VERBOSE:
         sys.stdout.write(data); sys.stdout.flush()
@@ -302,7 +302,7 @@ def captureCommand(commandline):
     xit = fd.close()
     if xit != None:
         sys.stdout.write(data)
-        raise RuntimeError, "command failed: %s"%(commandline,)
+        raise RuntimeError("command failed: %s"%(commandline,))
 
     return data
 
@@ -361,7 +361,7 @@ def parseOptions(args=None):
             SRCDIR=v
 
         else:
-            raise NotImplementedError, k
+            raise NotImplementedError(k)
 
     SRCDIR=os.path.abspath(SRCDIR)
     WORKDIR=os.path.abspath(WORKDIR)
@@ -418,7 +418,7 @@ def extractArchive(builddir, archiveName):
         xit = fp.close()
         if xit is not None:
             sys.stdout.write(data)
-            raise RuntimeError, "Cannot extract %s"%(archiveName,)
+            raise RuntimeError("Cannot extract %s"%(archiveName,))
 
         return os.path.join(builddir, retval)
 
index 5f60c5184d33fe3211265193cc00b5647f6378db..e1d8fb189132dcdecd38a09cfe9b9579f968c64d 100644 (file)
@@ -59,7 +59,7 @@ class DocBuild(build):
         dirname = 'Python-Docs-%s' % self.doc_version
 
         if os.path.exists(self.build_html):
-            raise RuntimeError, '%s: already exists, please remove and try again' % self.build_html
+            raise RuntimeError('%s: already exists, please remove and try again' % self.build_html)
         os.chdir(self.build_base)
         self.spawn('curl','-O', url)
         self.spawn('tar', '-xjf', tarfile)
@@ -146,8 +146,7 @@ class DocBuild(build):
         self.mkpath(self.build_base)
         self.ensureHtml()
         if not os.path.isdir(self.build_html):
-            raise RuntimeError, \
-            "Can't find source folder for documentation."
+            raise RuntimeError("Can't find source folder for documentation.")
         self.mkpath(self.build_dest)
         if dep_util.newer(os.path.join(self.build_html,'index.html'), os.path.join(self.build_dest,'index.html')):
             self.mkpath(self.build_dest)
index 73dd4b6dfca6b4aa0141cbc09abe55c0cb328e64..ad0afe46c545d18a1491afcf10e0bc27752b1b4d 100644 (file)
@@ -194,7 +194,7 @@ class PackageMaker:
             if k in fields:
                 self.packageInfo[k] = v
             elif not k in ["OutputDir"]:
-                raise Error, "Unknown package option: %s" % k
+                raise Error("Unknown package option: %s" % k)
 
         # Check where we should leave the output. Default is current directory
         outputdir = options.get("OutputDir", os.getcwd())
index d4238922c2f2e5262b3f332fc51d350cec5ab682..93af56e1b45c7a26473d86a9f67806d414696bb4 100644 (file)
@@ -33,7 +33,7 @@ ERRORS_PROG_2="[ \t]*" \
 
 def Pstring(str):
     if len(str) > 255:
-        raise ValueError, 'String too large'
+        raise ValueError('String too large')
     return chr(len(str))+str
 
 def writeestr(dst, edict):
index e900243448fdd8e34c0b337f4cacecae7891df02..cbc41e8ba2393e46e73f106b50768f23b41153d8 100644 (file)
@@ -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 */
index ea9f5020ff0a42557015595280b80ababf695d67..8686709b9b1d8451612a0a4d4fd081782ad135fb 100644 (file)
@@ -30,8 +30,7 @@ module Python version "$Revision$"
              | If(expr test, stmt* body, stmt* orelse)
              | With(expr context_expr, expr? optional_vars, stmt* body)
 
-             -- 'type' is a bad name
-             | Raise(expr? type, expr? inst, expr? tback)
+             | Raise(expr? exc, expr? cause)
              | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
              | TryFinally(stmt* body, stmt* finalbody)
              | Assert(expr test, expr? msg)
index 605a152ca9702c4f09ff4c18bd32b171c05915bb..9089b9a3d17a2c004ea80a52fdcec04a6738f497 100644 (file)
@@ -2,7 +2,7 @@
 
 
 /*
-   __version__ 56266.
+   __version__ 465.
 
    This module must be committed separately after each AST grammar change;
    The __version__ number is set to the revision number of the commit
@@ -101,9 +101,8 @@ static char *With_fields[]={
 };
 static PyTypeObject *Raise_type;
 static char *Raise_fields[]={
-        "type",
-        "inst",
-        "tback",
+        "exc",
+        "cause",
 };
 static PyTypeObject *TryExcept_type;
 static char *TryExcept_fields[]={
@@ -510,7 +509,7 @@ static int init_types(void)
         if (!If_type) return 0;
         With_type = make_type("With", stmt_type, With_fields, 3);
         if (!With_type) return 0;
-        Raise_type = make_type("Raise", stmt_type, Raise_fields, 3);
+        Raise_type = make_type("Raise", stmt_type, Raise_fields, 2);
         if (!Raise_type) return 0;
         TryExcept_type = make_type("TryExcept", stmt_type, TryExcept_fields, 3);
         if (!TryExcept_type) return 0;
@@ -1052,17 +1051,15 @@ With(expr_ty context_expr, expr_ty optional_vars, asdl_seq * body, int lineno,
 }
 
 stmt_ty
-Raise(expr_ty type, expr_ty inst, expr_ty tback, int lineno, int col_offset,
-      PyArena *arena)
+Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena)
 {
         stmt_ty p;
         p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
         if (!p)
                 return NULL;
         p->kind = Raise_kind;
-        p->v.Raise.type = type;
-        p->v.Raise.inst = inst;
-        p->v.Raise.tback = tback;
+        p->v.Raise.exc = exc;
+        p->v.Raise.cause = cause;
         p->lineno = lineno;
         p->col_offset = col_offset;
         return p;
@@ -2221,19 +2218,14 @@ ast2obj_stmt(void* _o)
         case Raise_kind:
                 result = PyType_GenericNew(Raise_type, NULL, NULL);
                 if (!result) goto failed;
-                value = ast2obj_expr(o->v.Raise.type);
-                if (!value) goto failed;
-                if (PyObject_SetAttrString(result, "type", value) == -1)
-                        goto failed;
-                Py_DECREF(value);
-                value = ast2obj_expr(o->v.Raise.inst);
+                value = ast2obj_expr(o->v.Raise.exc);
                 if (!value) goto failed;
-                if (PyObject_SetAttrString(result, "inst", value) == -1)
+                if (PyObject_SetAttrString(result, "exc", value) == -1)
                         goto failed;
                 Py_DECREF(value);
-                value = ast2obj_expr(o->v.Raise.tback);
+                value = ast2obj_expr(o->v.Raise.cause);
                 if (!value) goto failed;
-                if (PyObject_SetAttrString(result, "tback", value) == -1)
+                if (PyObject_SetAttrString(result, "cause", value) == -1)
                         goto failed;
                 Py_DECREF(value);
                 break;
@@ -3179,7 +3171,7 @@ init_ast(void)
         if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return;
         if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0)
                 return;
-        if (PyModule_AddStringConstant(m, "__version__", "56266") < 0)
+        if (PyModule_AddStringConstant(m, "__version__", "465") < 0)
                 return;
         if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return;
         if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0)
index c13d093a29155ee97dec78206857545e9ee39b66..8dd3c4ab061cc2b01d17095720af8cd37d05d160 100644 (file)
@@ -2199,39 +2199,18 @@ ast_for_flow_stmt(struct compiling *c, const node *n)
             }
         case raise_stmt:
             if (NCH(ch) == 1)
-                return Raise(NULL, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
-            else if (NCH(ch) == 2) {
+                return Raise(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
+            else if (NCH(ch) >= 2) {
+                expr_ty cause = NULL;
                 expr_ty expression = ast_for_expr(c, CHILD(ch, 1));
                 if (!expression)
                     return NULL;
-                return Raise(expression, NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena);
-            }
-            else if (NCH(ch) == 4) {
-                expr_ty expr1, expr2;
-
-                expr1 = ast_for_expr(c, CHILD(ch, 1));
-                if (!expr1)
-                    return NULL;
-                expr2 = ast_for_expr(c, CHILD(ch, 3));
-                if (!expr2)
-                    return NULL;
-
-                return Raise(expr1, expr2, NULL, LINENO(n), n->n_col_offset, c->c_arena);
-            }
-            else if (NCH(ch) == 6) {
-                expr_ty expr1, expr2, expr3;
-
-                expr1 = ast_for_expr(c, CHILD(ch, 1));
-                if (!expr1)
-                    return NULL;
-                expr2 = ast_for_expr(c, CHILD(ch, 3));
-                if (!expr2)
-                    return NULL;
-                expr3 = ast_for_expr(c, CHILD(ch, 5));
-                if (!expr3)
-                    return NULL;
-                    
-                return Raise(expr1, expr2, expr3, LINENO(n), n->n_col_offset, c->c_arena);
+                if (NCH(ch) == 4) {
+                    cause = ast_for_expr(c, CHILD(ch, 3));
+                    if (!cause)
+                        return NULL;
+                }
+                return Raise(expression, cause, LINENO(n), n->n_col_offset, c->c_arena);
             }
         default:
             PyErr_Format(PyExc_SystemError,
index be804ad3d0a93a525d4835248d309dfbe0376c1b..24d4dec277c769d6b1293acc12ec52ec5bf0dbc1 100644 (file)
@@ -484,7 +484,7 @@ enum why_code {
                WHY_YIELD =     0x0040  /* 'yield' operator */
 };
 
-static enum why_code do_raise(PyObject *, PyObject *, PyObject *);
+static enum why_code do_raise(PyObject *, PyObject *);
 static int unpack_iterable(PyObject *, int, int, PyObject **);
 
 /* for manipulating the thread switch and periodic "stuff" - used to be
@@ -1465,18 +1465,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
                default: switch (opcode) {
 #endif
                case RAISE_VARARGS:
-                       u = v = w = NULL;
+                       v = w = NULL;
                        switch (oparg) {
-                       case 3:
-                               u = POP(); /* traceback */
-                               /* Fallthrough */
-                       case 2:
-                               v = POP(); /* value */
-                               /* Fallthrough */
+            case 2:
+                v = POP(); /* cause */
                        case 1:
                                w = POP(); /* exc */
                        case 0: /* Fallthrough */
-                               why = do_raise(w, v, u);
+                               why = do_raise(w, v);
                                break;
                        default:
                                PyErr_SetString(PyExc_SystemError,
@@ -2880,6 +2876,7 @@ set_exc_info(PyThreadState *tstate,
        tstate->exc_type = type;
        tstate->exc_value = value;
        tstate->exc_traceback = tb;
+    PyException_SetTraceback(value, tb);
        Py_XDECREF(tmp_type);
        Py_XDECREF(tmp_value);
        Py_XDECREF(tmp_tb);
@@ -2928,95 +2925,78 @@ reset_exc_info(PyThreadState *tstate)
 /* Logic for the raise statement (too complicated for inlining).
    This *consumes* a reference count to each of its arguments. */
 static enum why_code
-do_raise(PyObject *type, PyObject *value, PyObject *tb)
+do_raise(PyObject *exc, PyObject *cause)
 {
-       if (type == NULL) {
+    PyObject *type = NULL, *value = NULL, *tb = NULL;
+
+       if (exc == NULL) {
                /* Reraise */
                PyThreadState *tstate = PyThreadState_GET();
-               type = tstate->exc_type == NULL ? Py_None : tstate->exc_type;
+               type = tstate->exc_type;
                value = tstate->exc_value;
                tb = tstate->exc_traceback;
-               Py_XINCREF(type);
+        if (type == Py_None) {
+            PyErr_SetString(PyExc_RuntimeError,
+                                    "No active exception to reraise");
+            return WHY_EXCEPTION;
+        }
+        Py_XINCREF(type);
                Py_XINCREF(value);
                Py_XINCREF(tb);
+        PyErr_Restore(type, value, tb);
+        return WHY_RERAISE;
        }
 
        /* We support the following forms of raise:
-          raise <class>, <classinstance>
-          raise <class>, <argument tuple>
-          raise <class>, None
-          raise <class>, <argument>
-          raise <classinstance>, None
-          raise <string>, <object>
-          raise <string>, None
-
-          An omitted second argument is the same as None.
-
-          In addition, raise <tuple>, <anything> is the same as
-          raising the tuple's first item (and it better have one!);
-          this rule is applied recursively.
-
-          Finally, an optional third argument can be supplied, which
-          gives the traceback to be substituted (useful when
-          re-raising an exception after examining it).  */
-
-       /* First, check the traceback argument, replacing None with
-          NULL. */
-       if (tb == Py_None) {
-               Py_DECREF(tb);
-               tb = NULL;
-       }
-       else if (tb != NULL && !PyTraceBack_Check(tb)) {
-               PyErr_SetString(PyExc_TypeError,
-                          "raise: arg 3 must be a traceback or None");
-               goto raise_error;
-       }
-
-       /* Next, replace a missing value with None */
-       if (value == NULL) {
-               value = Py_None;
-               Py_INCREF(value);
-       }
+          raise
+       raise <instance>
+       raise <type> */
 
-       /* Next, repeatedly, replace a tuple exception with its first item */
-       while (PyTuple_Check(type) && PyTuple_Size(type) > 0) {
-               PyObject *tmp = type;
-               type = PyTuple_GET_ITEM(type, 0);
+       if (PyExceptionClass_Check(exc)) {
+        type = exc;
+        value = PyObject_CallObject(exc, NULL);
+               if (value == NULL)
+            goto raise_error;
+    }
+       else if (PyExceptionInstance_Check(exc)) {
+               value = exc;
+               type = PyExceptionInstance_Class(exc);
                Py_INCREF(type);
-               Py_DECREF(tmp);
-       }
-
-       if (PyExceptionClass_Check(type))
-               PyErr_NormalizeException(&type, &value, &tb);
-
-       else if (PyExceptionInstance_Check(type)) {
-               /* Raising an instance.  The value should be a dummy. */
-               if (value != Py_None) {
-                       PyErr_SetString(PyExc_TypeError,
-                         "instance exception may not have a separate value");
-                       goto raise_error;
-               }
-               else {
-                       /* Normalize to raise <class>, <instance> */
-                       Py_DECREF(value);
-                       value = type;
-                       type = PyExceptionInstance_Class(type);
-                       Py_INCREF(type);
-               }
        }
        else {
                /* Not something you can raise.  You get an exception
                   anyway, just not what you specified :-) */
+        Py_DECREF(exc);
+        Py_XDECREF(cause);
                PyErr_SetString(PyExc_TypeError,
                                 "exceptions must derive from BaseException");
                goto raise_error;
        }
+
+    tb = PyException_GetTraceback(value);
+    if (cause) {
+        PyObject *fixed_cause;
+        if (PyExceptionClass_Check(cause)) {
+            fixed_cause = PyObject_CallObject(cause, NULL);
+            if (fixed_cause == NULL)
+                goto raise_error;
+        }
+        else if (PyExceptionInstance_Check(cause)) {
+            fixed_cause = cause;
+        }
+        else {
+            Py_DECREF(cause);
+            PyErr_SetString(PyExc_TypeError,
+                            "exception causes must derive from BaseException");
+            goto raise_error;
+        }
+        PyException_SetCause(value, fixed_cause);
+    }
+
        PyErr_Restore(type, value, tb);
-       if (tb == NULL)
-               return WHY_EXCEPTION;
-       else
-               return WHY_RERAISE;
- raise_error:
+       return WHY_EXCEPTION;
+
+raise_error:
        Py_XDECREF(value);
        Py_XDECREF(type);
        Py_XDECREF(tb);
index 3a211277bf3b56a69370eb5a7ef3744ccf4b2249..e569102f3b54edf4555047eead21889a4dee9ce3 100644 (file)
@@ -2187,11 +2187,9 @@ compiler_assert(struct compiler *c, stmt_ty s)
        ADDOP_O(c, LOAD_GLOBAL, assertion_error, names);
        if (s->v.Assert.msg) {
                VISIT(c, expr, s->v.Assert.msg);
-               ADDOP_I(c, RAISE_VARARGS, 2);
-       }
-       else {
-               ADDOP_I(c, RAISE_VARARGS, 1);
+               ADDOP_I(c, CALL_FUNCTION, 1);
        }
+       ADDOP_I(c, RAISE_VARARGS, 1);
        compiler_use_next_block(c, end);
        ADDOP(c, POP_TOP);
        return 1;
@@ -2244,17 +2242,13 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
                return compiler_if(c, s);
        case Raise_kind:
                n = 0;
-               if (s->v.Raise.type) {
-                       VISIT(c, expr, s->v.Raise.type);
+               if (s->v.Raise.exc) {
+                       VISIT(c, expr, s->v.Raise.exc);
                        n++;
-                       if (s->v.Raise.inst) {
-                               VISIT(c, expr, s->v.Raise.inst);
-                               n++;
-                               if (s->v.Raise.tback) {
-                                       VISIT(c, expr, s->v.Raise.tback);
-                                       n++;
-                               }
-                       }
+            if (s->v.Raise.cause) {
+                VISIT(c, expr, s->v.Raise.cause);
+                n++;
+            }
                }
                ADDOP_I(c, RAISE_VARARGS, n);
                break;
index 95905d7f59374fd5542371b1f6873e981e42308b..081a072966f33105e5c59372defa29eff65c39e5 100644 (file)
@@ -503,34 +503,25 @@ static arc arcs_24_1[2] = {
        {0, 1},
 };
 static arc arcs_24_2[2] = {
-       {30, 3},
+       {71, 3},
        {0, 2},
 };
 static arc arcs_24_3[1] = {
        {24, 4},
 };
-static arc arcs_24_4[2] = {
-       {30, 5},
+static arc arcs_24_4[1] = {
        {0, 4},
 };
-static arc arcs_24_5[1] = {
-       {24, 6},
-};
-static arc arcs_24_6[1] = {
-       {0, 6},
-};
-static state states_24[7] = {
+static state states_24[5] = {
        {1, arcs_24_0},
        {2, arcs_24_1},
        {2, arcs_24_2},
        {1, arcs_24_3},
-       {2, arcs_24_4},
-       {1, arcs_24_5},
-       {1, arcs_24_6},
+       {1, arcs_24_4},
 };
 static arc arcs_25_0[2] = {
-       {71, 1},
        {72, 1},
+       {73, 1},
 };
 static arc arcs_25_1[1] = {
        {0, 1},
@@ -540,10 +531,10 @@ static state states_25[2] = {
        {1, arcs_25_1},
 };
 static arc arcs_26_0[1] = {
-       {73, 1},
+       {74, 1},
 };
 static arc arcs_26_1[1] = {
-       {74, 2},
+       {75, 2},
 };
 static arc arcs_26_2[1] = {
        {0, 2},
@@ -554,7 +545,7 @@ static state states_26[3] = {
        {1, arcs_26_2},
 };
 static arc arcs_27_0[1] = {
-       {75, 1},
+       {71, 1},
 };
 static arc arcs_27_1[3] = {
        {76, 2},
@@ -565,10 +556,10 @@ static arc arcs_27_2[4] = {
        {76, 2},
        {77, 2},
        {12, 3},
-       {73, 4},
+       {74, 4},
 };
 static arc arcs_27_3[1] = {
-       {73, 4},
+       {74, 4},
 };
 static arc arcs_27_4[3] = {
        {31, 5},
@@ -1733,9 +1724,9 @@ static state states_80[3] = {
 };
 static dfa dfas[81] = {
        {256, "single_input", 0, 3, states_0,
-        "\004\050\060\200\000\000\000\050\170\052\034\144\011\040\004\000\200\041\224\017\101"},
+        "\004\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\200\041\224\017\101"},
        {257, "file_input", 0, 2, states_1,
-        "\204\050\060\200\000\000\000\050\170\052\034\144\011\040\004\000\200\041\224\017\101"},
+        "\204\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\200\041\224\017\101"},
        {258, "eval_input", 0, 3, states_2,
         "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\200\041\224\017\000"},
        {259, "decorator", 0, 7, states_3,
@@ -1757,11 +1748,11 @@ static dfa dfas[81] = {
        {267, "vfpdef", 0, 2, states_11,
         "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
        {268, "stmt", 0, 2, states_12,
-        "\000\050\060\200\000\000\000\050\170\052\034\144\011\040\004\000\200\041\224\017\101"},
+        "\000\050\060\200\000\000\000\050\370\044\034\144\011\040\004\000\200\041\224\017\101"},
        {269, "simple_stmt", 0, 4, states_13,
-        "\000\040\040\200\000\000\000\050\170\052\034\000\000\040\004\000\200\041\224\017\100"},
+        "\000\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\200\041\224\017\100"},
        {270, "small_stmt", 0, 2, states_14,
-        "\000\040\040\200\000\000\000\050\170\052\034\000\000\040\004\000\200\041\224\017\100"},
+        "\000\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\200\041\224\017\100"},
        {271, "expr_stmt", 0, 6, states_15,
         "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\200\041\224\017\000"},
        {272, "augassign", 0, 2, states_16,
@@ -1780,14 +1771,14 @@ static dfa dfas[81] = {
         "\000\000\000\000\000\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000"},
        {279, "yield_stmt", 0, 2, states_23,
         "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\100"},
-       {280, "raise_stmt", 0, 7, states_24,
+       {280, "raise_stmt", 0, 5, states_24,
         "\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000\000\000\000\000"},
        {281, "import_stmt", 0, 2, states_25,
-        "\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000"},
+        "\000\000\000\000\000\000\000\000\200\004\000\000\000\000\000\000\000\000\000\000\000"},
        {282, "import_name", 0, 3, states_26,
-        "\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000"},
+        "\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000"},
        {283, "import_from", 0, 8, states_27,
-        "\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000"},
+        "\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000"},
        {284, "import_as_name", 0, 4, states_28,
         "\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"},
        {285, "dotted_as_name", 0, 4, states_29,
@@ -1821,7 +1812,7 @@ static dfa dfas[81] = {
        {299, "except_clause", 0, 5, states_43,
         "\000\000\000\000\000\000\000\000\000\000\000\000\100\000\000\000\000\000\000\000\000"},
        {300, "suite", 0, 5, states_44,
-        "\004\040\040\200\000\000\000\050\170\052\034\000\000\040\004\000\200\041\224\017\100"},
+        "\004\040\040\200\000\000\000\050\370\044\034\000\000\040\004\000\200\041\224\017\100"},
        {301, "test", 0, 6, states_45,
         "\000\040\040\200\000\000\000\000\000\040\000\000\000\040\004\000\200\041\224\017\000"},
        {302, "test_nocond", 0, 2, states_46,
@@ -1967,11 +1958,11 @@ static label labels[167] = {
        {1, "continue"},
        {1, "return"},
        {1, "raise"},
+       {1, "from"},
        {282, 0},
        {283, 0},
        {1, "import"},
        {287, 0},
-       {1, "from"},
        {23, 0},
        {52, 0},
        {286, 0},
index 2ef6aec9416e80f13bba419c8e07b63118996a86..33cafd02b6995d3728389297e07132d3479c9ae8 100644 (file)
@@ -74,6 +74,7 @@ extern time_t PyOS_GetLastModificationTime(char *, FILE *);
                      3040 (added signature annotations)
                      3050 (print becomes a function)
                      3060 (PEP 3115 metaclass syntax)
+          3070 (PEP 3109 raise changes)
 .
 */
 #define MAGIC (3060 | ((long)'\r'<<16) | ((long)'\n'<<24))
index 59eef02c74781ad124de67eaf38f5ea2542039d5..83e571e6747118085480b5607f514af54bd1488d 100644 (file)
@@ -1101,13 +1101,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
                        VISIT_SEQ(st, stmt, s->v.If.orelse);
                break;
         case Raise_kind:
-               if (s->v.Raise.type) {
-                       VISIT(st, expr, s->v.Raise.type);
-                       if (s->v.Raise.inst) {
-                               VISIT(st, expr, s->v.Raise.inst);
-                               if (s->v.Raise.tback)
-                                       VISIT(st, expr, s->v.Raise.tback);
-                       }
+               if (s->v.Raise.exc) {
+                       VISIT(st, expr, s->v.Raise.exc);
+            if (s->v.Raise.cause) {
+                VISIT(st, expr, s->v.Raise.cause);
+            }
                }
                break;
         case TryExcept_kind:
index 5b978512bfd77feb6ade1e4b78b9a0ac48f2ef05..6ad92b275a5dc711f763a68646cf9b0b291046c3 100755 (executable)
@@ -267,7 +267,7 @@ class Checker:
     def setflags(self, **kw):
         for key in kw.keys():
             if key not in self.validflags:
-                raise NameError, "invalid keyword argument: %s" % str(key)
+                raise NameError("invalid keyword argument: %s" % str(key))
         for key, value in kw.items():
             setattr(self, key, value)
 
@@ -761,7 +761,7 @@ class MyURLopener(urllib.FancyURLopener):
                 names = os.listdir(path)
             except os.error as msg:
                 exc_type, exc_value, exc_tb = sys.exc_info()
-                raise IOError, msg, exc_tb
+                raise IOError(msg).with_traceback(exc_tb)
             names.sort()
             s = MyStringIO("file:"+url, {'content-type': 'text/html'})
             s.write('<BASE HREF="file:%s">\n' %