|
1 """Fixer for 'raise E, V, T' |
|
2 |
|
3 raise -> raise |
|
4 raise E -> raise E |
|
5 raise E, V -> raise E(V) |
|
6 raise E, V, T -> raise E(V).with_traceback(T) |
|
7 |
|
8 raise (((E, E'), E''), E'''), V -> raise E(V) |
|
9 raise "foo", V, T -> warns about string exceptions |
|
10 |
|
11 |
|
12 CAVEATS: |
|
13 1) "raise E, V" will be incorrectly translated if V is an exception |
|
14 instance. The correct Python 3 idiom is |
|
15 |
|
16 raise E from V |
|
17 |
|
18 but since we can't detect instance-hood by syntax alone and since |
|
19 any client code would have to be changed as well, we don't automate |
|
20 this. |
|
21 """ |
|
22 # Author: Collin Winter |
|
23 |
|
24 # Local imports |
|
25 from .. import pytree |
|
26 from ..pgen2 import token |
|
27 from .. import fixer_base |
|
28 from ..fixer_util import Name, Call, Attr, ArgList, is_tuple |
|
29 |
|
30 class FixRaise(fixer_base.BaseFix): |
|
31 |
|
32 PATTERN = """ |
|
33 raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] > |
|
34 """ |
|
35 |
|
36 def transform(self, node, results): |
|
37 syms = self.syms |
|
38 |
|
39 exc = results["exc"].clone() |
|
40 if exc.type is token.STRING: |
|
41 self.cannot_convert(node, "Python 3 does not support string exceptions") |
|
42 return |
|
43 |
|
44 # Python 2 supports |
|
45 # raise ((((E1, E2), E3), E4), E5), V |
|
46 # as a synonym for |
|
47 # raise E1, V |
|
48 # Since Python 3 will not support this, we recurse down any tuple |
|
49 # literals, always taking the first element. |
|
50 if is_tuple(exc): |
|
51 while is_tuple(exc): |
|
52 # exc.children[1:-1] is the unparenthesized tuple |
|
53 # exc.children[1].children[0] is the first element of the tuple |
|
54 exc = exc.children[1].children[0].clone() |
|
55 exc.set_prefix(" ") |
|
56 |
|
57 if "val" not in results: |
|
58 # One-argument raise |
|
59 new = pytree.Node(syms.raise_stmt, [Name("raise"), exc]) |
|
60 new.set_prefix(node.get_prefix()) |
|
61 return new |
|
62 |
|
63 val = results["val"].clone() |
|
64 if is_tuple(val): |
|
65 args = [c.clone() for c in val.children[1:-1]] |
|
66 else: |
|
67 val.set_prefix("") |
|
68 args = [val] |
|
69 |
|
70 if "tb" in results: |
|
71 tb = results["tb"].clone() |
|
72 tb.set_prefix("") |
|
73 |
|
74 e = Call(exc, args) |
|
75 with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] |
|
76 new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb) |
|
77 new.set_prefix(node.get_prefix()) |
|
78 return new |
|
79 else: |
|
80 return pytree.Node(syms.raise_stmt, |
|
81 [Name("raise"), Call(exc, args)], |
|
82 prefix=node.get_prefix()) |