|
1 # Copyright 2007 Google, Inc. All Rights Reserved. |
|
2 # Licensed to PSF under a Contributor Agreement. |
|
3 |
|
4 """Fixer that changes map(F, ...) into list(map(F, ...)) unless there |
|
5 exists a 'from future_builtins import map' statement in the top-level |
|
6 namespace. |
|
7 |
|
8 As a special case, map(None, X) is changed into list(X). (This is |
|
9 necessary because the semantics are changed in this case -- the new |
|
10 map(None, X) is equivalent to [(x,) for x in X].) |
|
11 |
|
12 We avoid the transformation (except for the special case mentioned |
|
13 above) if the map() call is directly contained in iter(<>), list(<>), |
|
14 tuple(<>), sorted(<>), ...join(<>), or for V in <>:. |
|
15 |
|
16 NOTE: This is still not correct if the original code was depending on |
|
17 map(F, X, Y, ...) to go on until the longest argument is exhausted, |
|
18 substituting None for missing values -- like zip(), it now stops as |
|
19 soon as the shortest argument is exhausted. |
|
20 """ |
|
21 |
|
22 # Local imports |
|
23 from ..pgen2 import token |
|
24 from .. import fixer_base |
|
25 from ..fixer_util import Name, Call, ListComp, in_special_context |
|
26 from ..pygram import python_symbols as syms |
|
27 |
|
28 class FixMap(fixer_base.ConditionalFix): |
|
29 |
|
30 PATTERN = """ |
|
31 map_none=power< |
|
32 'map' |
|
33 trailer< '(' arglist< 'None' ',' arg=any [','] > ')' > |
|
34 > |
|
35 | |
|
36 map_lambda=power< |
|
37 'map' |
|
38 trailer< |
|
39 '(' |
|
40 arglist< |
|
41 lambdef< 'lambda' |
|
42 (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any |
|
43 > |
|
44 ',' |
|
45 it=any |
|
46 > |
|
47 ')' |
|
48 > |
|
49 > |
|
50 | |
|
51 power< |
|
52 'map' |
|
53 args=trailer< '(' [any] ')' > |
|
54 > |
|
55 """ |
|
56 |
|
57 skip_on = 'future_builtins.map' |
|
58 |
|
59 def transform(self, node, results): |
|
60 if self.should_skip(node): |
|
61 return |
|
62 |
|
63 if node.parent.type == syms.simple_stmt: |
|
64 self.warning(node, "You should use a for loop here") |
|
65 new = node.clone() |
|
66 new.set_prefix("") |
|
67 new = Call(Name("list"), [new]) |
|
68 elif "map_lambda" in results: |
|
69 new = ListComp(results.get("xp").clone(), |
|
70 results.get("fp").clone(), |
|
71 results.get("it").clone()) |
|
72 else: |
|
73 if "map_none" in results: |
|
74 new = results["arg"].clone() |
|
75 else: |
|
76 if in_special_context(node): |
|
77 return None |
|
78 new = node.clone() |
|
79 new.set_prefix("") |
|
80 new = Call(Name("list"), [new]) |
|
81 new.set_prefix(node.get_prefix()) |
|
82 return new |