17db96d56Sopenharmony_ci# Copyright 2006 Google, Inc. All Rights Reserved. 27db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci"""Fixer for apply(). 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ciThis converts apply(func, v, k) into (func)(*v, **k).""" 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci# Local imports 97db96d56Sopenharmony_cifrom .. import pytree 107db96d56Sopenharmony_cifrom ..pgen2 import token 117db96d56Sopenharmony_cifrom .. import fixer_base 127db96d56Sopenharmony_cifrom ..fixer_util import Call, Comma, parenthesize 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ciclass FixApply(fixer_base.BaseFix): 157db96d56Sopenharmony_ci BM_compatible = True 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci PATTERN = """ 187db96d56Sopenharmony_ci power< 'apply' 197db96d56Sopenharmony_ci trailer< 207db96d56Sopenharmony_ci '(' 217db96d56Sopenharmony_ci arglist< 227db96d56Sopenharmony_ci (not argument<NAME '=' any>) func=any ',' 237db96d56Sopenharmony_ci (not argument<NAME '=' any>) args=any [',' 247db96d56Sopenharmony_ci (not argument<NAME '=' any>) kwds=any] [','] 257db96d56Sopenharmony_ci > 267db96d56Sopenharmony_ci ')' 277db96d56Sopenharmony_ci > 287db96d56Sopenharmony_ci > 297db96d56Sopenharmony_ci """ 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci def transform(self, node, results): 327db96d56Sopenharmony_ci syms = self.syms 337db96d56Sopenharmony_ci assert results 347db96d56Sopenharmony_ci func = results["func"] 357db96d56Sopenharmony_ci args = results["args"] 367db96d56Sopenharmony_ci kwds = results.get("kwds") 377db96d56Sopenharmony_ci # I feel like we should be able to express this logic in the 387db96d56Sopenharmony_ci # PATTERN above but I don't know how to do it so... 397db96d56Sopenharmony_ci if args: 407db96d56Sopenharmony_ci if (args.type == self.syms.argument and 417db96d56Sopenharmony_ci args.children[0].value in {'**', '*'}): 427db96d56Sopenharmony_ci return # Make no change. 437db96d56Sopenharmony_ci if kwds and (kwds.type == self.syms.argument and 447db96d56Sopenharmony_ci kwds.children[0].value == '**'): 457db96d56Sopenharmony_ci return # Make no change. 467db96d56Sopenharmony_ci prefix = node.prefix 477db96d56Sopenharmony_ci func = func.clone() 487db96d56Sopenharmony_ci if (func.type not in (token.NAME, syms.atom) and 497db96d56Sopenharmony_ci (func.type != syms.power or 507db96d56Sopenharmony_ci func.children[-2].type == token.DOUBLESTAR)): 517db96d56Sopenharmony_ci # Need to parenthesize 527db96d56Sopenharmony_ci func = parenthesize(func) 537db96d56Sopenharmony_ci func.prefix = "" 547db96d56Sopenharmony_ci args = args.clone() 557db96d56Sopenharmony_ci args.prefix = "" 567db96d56Sopenharmony_ci if kwds is not None: 577db96d56Sopenharmony_ci kwds = kwds.clone() 587db96d56Sopenharmony_ci kwds.prefix = "" 597db96d56Sopenharmony_ci l_newargs = [pytree.Leaf(token.STAR, "*"), args] 607db96d56Sopenharmony_ci if kwds is not None: 617db96d56Sopenharmony_ci l_newargs.extend([Comma(), 627db96d56Sopenharmony_ci pytree.Leaf(token.DOUBLESTAR, "**"), 637db96d56Sopenharmony_ci kwds]) 647db96d56Sopenharmony_ci l_newargs[-2].prefix = " " # that's the ** token 657db96d56Sopenharmony_ci # XXX Sometimes we could be cleverer, e.g. apply(f, (x, y) + t) 667db96d56Sopenharmony_ci # can be translated into f(x, y, *t) instead of f(*(x, y) + t) 677db96d56Sopenharmony_ci #new = pytree.Node(syms.power, (func, ArgList(l_newargs))) 687db96d56Sopenharmony_ci return Call(func, l_newargs, prefix=prefix) 69