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