1"""Fixer for generator.throw(E, V, T).
2
3g.throw(E)       -> g.throw(E)
4g.throw(E, V)    -> g.throw(E(V))
5g.throw(E, V, T) -> g.throw(E(V).with_traceback(T))
6
7g.throw("foo"[, V[, T]]) will warn about string exceptions."""
8# Author: Collin Winter
9
10# Local imports
11from .. import pytree
12from ..pgen2 import token
13from .. import fixer_base
14from ..fixer_util import Name, Call, ArgList, Attr, is_tuple
15
16class FixThrow(fixer_base.BaseFix):
17    BM_compatible = True
18    PATTERN = """
19    power< any trailer< '.' 'throw' >
20           trailer< '(' args=arglist< exc=any ',' val=any [',' tb=any] > ')' >
21    >
22    |
23    power< any trailer< '.' 'throw' > trailer< '(' exc=any ')' > >
24    """
25
26    def transform(self, node, results):
27        syms = self.syms
28
29        exc = results["exc"].clone()
30        if exc.type is token.STRING:
31            self.cannot_convert(node, "Python 3 does not support string exceptions")
32            return
33
34        # Leave "g.throw(E)" alone
35        val = results.get("val")
36        if val is None:
37            return
38
39        val = val.clone()
40        if is_tuple(val):
41            args = [c.clone() for c in val.children[1:-1]]
42        else:
43            val.prefix = ""
44            args = [val]
45
46        throw_args = results["args"]
47
48        if "tb" in results:
49            tb = results["tb"].clone()
50            tb.prefix = ""
51
52            e = Call(exc, args)
53            with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])]
54            throw_args.replace(pytree.Node(syms.power, with_tb))
55        else:
56            throw_args.replace(Call(exc, args))
57