17db96d56Sopenharmony_ci# Copyright 2007 Google, Inc. All Rights Reserved. 27db96d56Sopenharmony_ci# Licensed to PSF under a Contributor Agreement. 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci"""Fixer that changes map(F, ...) into list(map(F, ...)) unless there 57db96d56Sopenharmony_ciexists a 'from future_builtins import map' statement in the top-level 67db96d56Sopenharmony_cinamespace. 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ciAs a special case, map(None, X) is changed into list(X). (This is 97db96d56Sopenharmony_cinecessary because the semantics are changed in this case -- the new 107db96d56Sopenharmony_cimap(None, X) is equivalent to [(x,) for x in X].) 117db96d56Sopenharmony_ci 127db96d56Sopenharmony_ciWe avoid the transformation (except for the special case mentioned 137db96d56Sopenharmony_ciabove) if the map() call is directly contained in iter(<>), list(<>), 147db96d56Sopenharmony_cituple(<>), sorted(<>), ...join(<>), or for V in <>:. 157db96d56Sopenharmony_ci 167db96d56Sopenharmony_ciNOTE: This is still not correct if the original code was depending on 177db96d56Sopenharmony_cimap(F, X, Y, ...) to go on until the longest argument is exhausted, 187db96d56Sopenharmony_cisubstituting None for missing values -- like zip(), it now stops as 197db96d56Sopenharmony_cisoon as the shortest argument is exhausted. 207db96d56Sopenharmony_ci""" 217db96d56Sopenharmony_ci 227db96d56Sopenharmony_ci# Local imports 237db96d56Sopenharmony_cifrom ..pgen2 import token 247db96d56Sopenharmony_cifrom .. import fixer_base 257db96d56Sopenharmony_cifrom ..fixer_util import Name, ArgList, Call, ListComp, in_special_context 267db96d56Sopenharmony_cifrom ..pygram import python_symbols as syms 277db96d56Sopenharmony_cifrom ..pytree import Node 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ciclass FixMap(fixer_base.ConditionalFix): 317db96d56Sopenharmony_ci BM_compatible = True 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci PATTERN = """ 347db96d56Sopenharmony_ci map_none=power< 357db96d56Sopenharmony_ci 'map' 367db96d56Sopenharmony_ci trailer< '(' arglist< 'None' ',' arg=any [','] > ')' > 377db96d56Sopenharmony_ci [extra_trailers=trailer*] 387db96d56Sopenharmony_ci > 397db96d56Sopenharmony_ci | 407db96d56Sopenharmony_ci map_lambda=power< 417db96d56Sopenharmony_ci 'map' 427db96d56Sopenharmony_ci trailer< 437db96d56Sopenharmony_ci '(' 447db96d56Sopenharmony_ci arglist< 457db96d56Sopenharmony_ci lambdef< 'lambda' 467db96d56Sopenharmony_ci (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any 477db96d56Sopenharmony_ci > 487db96d56Sopenharmony_ci ',' 497db96d56Sopenharmony_ci it=any 507db96d56Sopenharmony_ci > 517db96d56Sopenharmony_ci ')' 527db96d56Sopenharmony_ci > 537db96d56Sopenharmony_ci [extra_trailers=trailer*] 547db96d56Sopenharmony_ci > 557db96d56Sopenharmony_ci | 567db96d56Sopenharmony_ci power< 577db96d56Sopenharmony_ci 'map' args=trailer< '(' [any] ')' > 587db96d56Sopenharmony_ci [extra_trailers=trailer*] 597db96d56Sopenharmony_ci > 607db96d56Sopenharmony_ci """ 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci skip_on = 'future_builtins.map' 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci def transform(self, node, results): 657db96d56Sopenharmony_ci if self.should_skip(node): 667db96d56Sopenharmony_ci return 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci trailers = [] 697db96d56Sopenharmony_ci if 'extra_trailers' in results: 707db96d56Sopenharmony_ci for t in results['extra_trailers']: 717db96d56Sopenharmony_ci trailers.append(t.clone()) 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_ci if node.parent.type == syms.simple_stmt: 747db96d56Sopenharmony_ci self.warning(node, "You should use a for loop here") 757db96d56Sopenharmony_ci new = node.clone() 767db96d56Sopenharmony_ci new.prefix = "" 777db96d56Sopenharmony_ci new = Call(Name("list"), [new]) 787db96d56Sopenharmony_ci elif "map_lambda" in results: 797db96d56Sopenharmony_ci new = ListComp(results["xp"].clone(), 807db96d56Sopenharmony_ci results["fp"].clone(), 817db96d56Sopenharmony_ci results["it"].clone()) 827db96d56Sopenharmony_ci new = Node(syms.power, [new] + trailers, prefix="") 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci else: 857db96d56Sopenharmony_ci if "map_none" in results: 867db96d56Sopenharmony_ci new = results["arg"].clone() 877db96d56Sopenharmony_ci new.prefix = "" 887db96d56Sopenharmony_ci else: 897db96d56Sopenharmony_ci if "args" in results: 907db96d56Sopenharmony_ci args = results["args"] 917db96d56Sopenharmony_ci if args.type == syms.trailer and \ 927db96d56Sopenharmony_ci args.children[1].type == syms.arglist and \ 937db96d56Sopenharmony_ci args.children[1].children[0].type == token.NAME and \ 947db96d56Sopenharmony_ci args.children[1].children[0].value == "None": 957db96d56Sopenharmony_ci self.warning(node, "cannot convert map(None, ...) " 967db96d56Sopenharmony_ci "with multiple arguments because map() " 977db96d56Sopenharmony_ci "now truncates to the shortest sequence") 987db96d56Sopenharmony_ci return 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci new = Node(syms.power, [Name("map"), args.clone()]) 1017db96d56Sopenharmony_ci new.prefix = "" 1027db96d56Sopenharmony_ci 1037db96d56Sopenharmony_ci if in_special_context(node): 1047db96d56Sopenharmony_ci return None 1057db96d56Sopenharmony_ci 1067db96d56Sopenharmony_ci new = Node(syms.power, [Name("list"), ArgList([new])] + trailers) 1077db96d56Sopenharmony_ci new.prefix = "" 1087db96d56Sopenharmony_ci 1097db96d56Sopenharmony_ci new.prefix = node.prefix 1107db96d56Sopenharmony_ci return new 111