Commits

Joe Amenta committed 7a4a804

Adding more support and output regarding exceptions using with_traceback

Comments (0)

Files changed (4)

lib3to2/fixes/feature_base.py

 
 pattern_unformatted = "%s=%s" # name=pattern, for dict lookups
 message_unformatted = """
-feature %s is only supported in Python %s and above."""
+%s is only supported in Python %s and above."""
 
 class Feature(object):
     """

lib3to2/fixes/fix_features.py

         "global_stmt< 'nonlocal' any* >",
      "3.0",
     ),
+    ("with_traceback",
+        "trailer< '.' 'with_traceback' >",
+     "3.0",
+    ),
 ]
 
 class FixFeatures(fixer_base.BaseFix):
 
+    run_order = 9 # Wait until all other fixers have run to check for these
+
     # To avoid spamming, we only want to warn for each feature once.
     features_warned = set()
 

lib3to2/fixes/fix_raise.py

 """Fixer for 'raise E(V).with_traceback(T)' -> 'raise E, V, T'"""
 
 from lib2to3 import fixer_base
-from lib2to3.pytree import Node, Leaf
-from lib2to3.pgen2 import token
-from lib2to3.fixer_util import Comma
+from ..fixer_util import Comma, Node, Leaf, token, syms
 
 class FixRaise(fixer_base.BaseFix):
 
     PATTERN = """
-    raise_stmt< 'raise' power< exc=any trailer< '(' val=any* ')' >
-        trailer< '.' 'with_traceback' > trailer< '(' trc=any ')' > > ['from' any] >"""
+    raise_stmt< 'raise' (power< name=any [trailer< '(' val=any* ')' >]
+        [trailer< '.' 'with_traceback' > trailer< '(' trc=any ')' >] > | any) ['from' chain=any] >"""
 
     def transform(self, node, results):
-        syms = self.syms
-        exc, val, trc = (results["exc"], results["val"], results["trc"])
-        val = val[0] if val else Leaf(token.NAME, "None")
-        val.prefix = trc.prefix = " "
-        kids = [Leaf(token.NAME, "raise"), exc.clone(), Comma(),
-                val.clone(), Comma(), trc.clone()]
-        raise_stmt = Node(syms.raise_stmt, kids)
-        return raise_stmt
+        name, val, trc = (results.get("name"), results.get("val"), results.get("trc"))
+        chain = results.get("chain")
+        if chain is not None:
+            self.warning(node, "explicit exception chaining is not supported in Python 2")
+            chain.prev_sibling.remove()
+            chain.remove()
+        if trc is not None:
+            val = val[0] if val else Leaf(token.NAME, "None")
+            val.prefix = trc.prefix = " "
+            kids = [Leaf(token.NAME, "raise"), name.clone(), Comma(),
+                    val.clone(), Comma(), trc.clone()]
+            raise_stmt = Node(syms.raise_stmt, kids)
+            node.replace(raise_stmt)

lib3to2/tests/test_raise.py

         b = """raise E("Sorry, you cannot do that.").with_traceback(T)"""
         a = """raise E, "Sorry, you cannot do that.", T"""
         self.check(b, a)
+
+    def test_chain(self):
+        b = "raise E(V).with_traceback(t) from exc"
+        a = "raise E, V, t"
+        self.check(b, a, ignore_warnings=True)
+
+        b = "raise E(V) from exc"
+        a = "raise E(V)"
+        self.check(b, a, ignore_warnings=True)
+
+        b = "raise eBob.exception from exc"
+        a = "raise eBob.exception"
+        self.check(b, a, ignore_warnings=True)
+