17db96d56Sopenharmony_ci"""Fixer for 'raise E, V, T' 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ciraise -> raise 47db96d56Sopenharmony_ciraise E -> raise E 57db96d56Sopenharmony_ciraise E, V -> raise E(V) 67db96d56Sopenharmony_ciraise E, V, T -> raise E(V).with_traceback(T) 77db96d56Sopenharmony_ciraise E, None, T -> raise E.with_traceback(T) 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ciraise (((E, E'), E''), E'''), V -> raise E(V) 107db96d56Sopenharmony_ciraise "foo", V, T -> warns about string exceptions 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ciCAVEATS: 147db96d56Sopenharmony_ci1) "raise E, V" will be incorrectly translated if V is an exception 157db96d56Sopenharmony_ci instance. The correct Python 3 idiom is 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci raise E from V 187db96d56Sopenharmony_ci 197db96d56Sopenharmony_ci but since we can't detect instance-hood by syntax alone and since 207db96d56Sopenharmony_ci any client code would have to be changed as well, we don't automate 217db96d56Sopenharmony_ci this. 227db96d56Sopenharmony_ci""" 237db96d56Sopenharmony_ci# Author: Collin Winter 247db96d56Sopenharmony_ci 257db96d56Sopenharmony_ci# Local imports 267db96d56Sopenharmony_cifrom .. import pytree 277db96d56Sopenharmony_cifrom ..pgen2 import token 287db96d56Sopenharmony_cifrom .. import fixer_base 297db96d56Sopenharmony_cifrom ..fixer_util import Name, Call, Attr, ArgList, is_tuple 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ciclass FixRaise(fixer_base.BaseFix): 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci BM_compatible = True 347db96d56Sopenharmony_ci PATTERN = """ 357db96d56Sopenharmony_ci raise_stmt< 'raise' exc=any [',' val=any [',' tb=any]] > 367db96d56Sopenharmony_ci """ 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci def transform(self, node, results): 397db96d56Sopenharmony_ci syms = self.syms 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_ci exc = results["exc"].clone() 427db96d56Sopenharmony_ci if exc.type == token.STRING: 437db96d56Sopenharmony_ci msg = "Python 3 does not support string exceptions" 447db96d56Sopenharmony_ci self.cannot_convert(node, msg) 457db96d56Sopenharmony_ci return 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci # Python 2 supports 487db96d56Sopenharmony_ci # raise ((((E1, E2), E3), E4), E5), V 497db96d56Sopenharmony_ci # as a synonym for 507db96d56Sopenharmony_ci # raise E1, V 517db96d56Sopenharmony_ci # Since Python 3 will not support this, we recurse down any tuple 527db96d56Sopenharmony_ci # literals, always taking the first element. 537db96d56Sopenharmony_ci if is_tuple(exc): 547db96d56Sopenharmony_ci while is_tuple(exc): 557db96d56Sopenharmony_ci # exc.children[1:-1] is the unparenthesized tuple 567db96d56Sopenharmony_ci # exc.children[1].children[0] is the first element of the tuple 577db96d56Sopenharmony_ci exc = exc.children[1].children[0].clone() 587db96d56Sopenharmony_ci exc.prefix = " " 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci if "val" not in results: 617db96d56Sopenharmony_ci # One-argument raise 627db96d56Sopenharmony_ci new = pytree.Node(syms.raise_stmt, [Name("raise"), exc]) 637db96d56Sopenharmony_ci new.prefix = node.prefix 647db96d56Sopenharmony_ci return new 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci val = results["val"].clone() 677db96d56Sopenharmony_ci if is_tuple(val): 687db96d56Sopenharmony_ci args = [c.clone() for c in val.children[1:-1]] 697db96d56Sopenharmony_ci else: 707db96d56Sopenharmony_ci val.prefix = "" 717db96d56Sopenharmony_ci args = [val] 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci if "tb" in results: 747db96d56Sopenharmony_ci tb = results["tb"].clone() 757db96d56Sopenharmony_ci tb.prefix = "" 767db96d56Sopenharmony_ci 777db96d56Sopenharmony_ci e = exc 787db96d56Sopenharmony_ci # If there's a traceback and None is passed as the value, then don't 797db96d56Sopenharmony_ci # add a call, since the user probably just wants to add a 807db96d56Sopenharmony_ci # traceback. See issue #9661. 817db96d56Sopenharmony_ci if val.type != token.NAME or val.value != "None": 827db96d56Sopenharmony_ci e = Call(exc, args) 837db96d56Sopenharmony_ci with_tb = Attr(e, Name('with_traceback')) + [ArgList([tb])] 847db96d56Sopenharmony_ci new = pytree.Node(syms.simple_stmt, [Name("raise")] + with_tb) 857db96d56Sopenharmony_ci new.prefix = node.prefix 867db96d56Sopenharmony_ci return new 877db96d56Sopenharmony_ci else: 887db96d56Sopenharmony_ci return pytree.Node(syms.raise_stmt, 897db96d56Sopenharmony_ci [Name("raise"), Call(exc, args)], 907db96d56Sopenharmony_ci prefix=node.prefix) 91