15e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Copyright 2006 Google, Inc. All Rights Reserved. 25e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Licensed to PSF under a Contributor Agreement. 35e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 45e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis"""Fixer for apply(). 55e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 65e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. LöwisThis converts apply(func, v, k) into (func)(*v, **k).""" 75e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 85e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis# Local imports 95e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom .. import pytree 105e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwisfrom ..pgen2 import token 11e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonfrom .. import fixer_base 1243caaa09ea364aab6cbd7ede2aa9c3d004a129a5Benjamin Petersonfrom ..fixer_util import Call, Comma, parenthesize 135e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 14e607823af57c176c3be23985f5bbf9260f6bd836Benjamin Petersonclass FixApply(fixer_base.BaseFix): 15a81eae1fd71eed670d1c28bf940ea99b4bfa2335Benjamin Peterson BM_compatible = True 165e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 175e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis PATTERN = """ 185e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis power< 'apply' 195e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis trailer< 205e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis '(' 215e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis arglist< 225e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis (not argument<NAME '=' any>) func=any ',' 235e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis (not argument<NAME '=' any>) args=any [',' 245e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis (not argument<NAME '=' any>) kwds=any] [','] 255e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis > 265e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis ')' 275e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis > 285e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis > 295e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis """ 305e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis 315e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis def transform(self, node, results): 325e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis syms = self.syms 335e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis assert results 345e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis func = results["func"] 355e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis args = results["args"] 365e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis kwds = results.get("kwds") 3788c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% # I feel like we should be able to express this logic in the 3888c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% # PATTERN above but I don't know how to do it so... 3988c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% if args: 4088c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% if args.type == self.syms.star_expr: 4188c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% return # Make no change. 4288c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% if (args.type == self.syms.argument and 4388c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% args.children[0].value == '**'): 4488c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% return # Make no change. 4588c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% if kwds and (kwds.type == self.syms.argument and 4688c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% kwds.children[0].value == '**'): 4788c00132ccdced2645e78e0059eab93590adecbdGregory P. Smith ext:(% return # Make no change. 486118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson prefix = node.prefix 495e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis func = func.clone() 505e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis if (func.type not in (token.NAME, syms.atom) and 515e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis (func.type != syms.power or 525e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis func.children[-2].type == token.DOUBLESTAR)): 535e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis # Need to parenthesize 5443caaa09ea364aab6cbd7ede2aa9c3d004a129a5Benjamin Peterson func = parenthesize(func) 556118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson func.prefix = "" 565e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis args = args.clone() 576118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson args.prefix = "" 585e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis if kwds is not None: 595e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis kwds = kwds.clone() 606118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson kwds.prefix = "" 6184ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson l_newargs = [pytree.Leaf(token.STAR, u"*"), args] 625e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis if kwds is not None: 635e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis l_newargs.extend([Comma(), 6484ad84e0bb15e7c64109e88060afdcb60ae7b740Benjamin Peterson pytree.Leaf(token.DOUBLESTAR, u"**"), 655e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis kwds]) 666118040b7aee905bcddcb949c6815dc19ca23070Benjamin Peterson l_newargs[-2].prefix = u" " # that's the ** token 675e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t) 685e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis # can be translated into f(x, y, *t) instead of f(*(x, y) + t) 695e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis #new = pytree.Node(syms.power, (func, ArgList(l_newargs))) 705e37baea8007cb64b65a180e4d6c80de292a8a4aMartin v. Löwis return Call(func, l_newargs, prefix=prefix) 71