fix_raise.py revision ab41b370a3eb1444b8ada38311a1bb498575a81c
15e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""Fixer for 'raise E, V, T'
25e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
35e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise         -> raise
45e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise E       -> raise E
55e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise E, V    -> raise E(V)
65e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise E, V, T -> raise E(V).with_traceback(T)
75e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
85e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise (((E, E'), E''), E'''), V -> raise E(V)
95e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisraise "foo", V, T               -> warns about string exceptions
105e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
115e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
125e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. LöwisCAVEATS:
135e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis1) "raise E, V" will be incorrectly translated if V is an exception
145e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis   instance. The correct Python 3 idiom is
15ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis
165e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        raise E from V
17ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis
185e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis   but since we can't detect instance-hood by syntax alone and since
195e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis   any client code would have to be changed as well, we don't automate
205e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis   this.
215e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""
225e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Author: Collin Winter
235e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
245e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Local imports
255e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom .. import pytree
265e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom ..pgen2 import token
275e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom .import basefix
285e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom .util import Name, Call, Attr, ArgList, is_tuple
295e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
305e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisclass FixRaise(basefix.BaseFix):
315e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
325e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    PATTERN = """
335e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] >
345e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    """
355e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
365e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis    def transform(self, node, results):
375e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        syms = self.syms
385e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
395e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        exc = results["exc"].clone()
405e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if exc.type is token.STRING:
415e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            self.cannot_convert(node, "Python 3 does not support string exceptions")
425e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            return
435e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
445e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # Python 2 supports
455e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        #  raise ((((E1, E2), E3), E4), E5), V
465e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # as a synonym for
475e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        #  raise E1, V
485e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # Since Python 3 will not support this, we recurse down any tuple
495e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        # literals, always taking the first element.
505e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if is_tuple(exc):
51ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis            while is_tuple(exc):
52ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis                # exc.children[1:-1] is the unparenthesized tuple
53ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis                # exc.children[1].children[0] is the first element of the tuple
54ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis                exc = exc.children[1].children[0].clone()
55ab41b370a3eb1444b8ada38311a1bb498575a81cMartin v. Löwis            exc.set_prefix(" ")
565e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
575e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if "val" not in results:
585e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            # One-argument raise
595e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            new = pytree.Node(syms.raise_stmt, [Name("raise"), exc])
605e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            new.set_prefix(node.get_prefix())
615e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            return new
625e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
635e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        val = results["val"].clone()
645e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if is_tuple(val):
655e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            args = [c.clone() for c in val.children[1:-1]]
665e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        else:
675e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            val.set_prefix("")
685e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            args = [val]
695e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
705e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        if "tb" in results:
715e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            tb = results["tb"].clone()
725e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            tb.set_prefix("")
735e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis
745e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            e = Call(exc, args)
755e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])]
765e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb)
775e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            new.set_prefix(node.get_prefix())
785e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            return new
795e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis        else:
805e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis            return pytree.Node(syms.raise_stmt,
815e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                               [Name("raise"), Call(exc, args)],
825e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis                               prefix=node.get_prefix())
83