1# Copyright 2007 Google, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3
4"""Fixer that changes filter(F, X) into list(filter(F, X)).
5
6We avoid the transformation if the filter() call is directly contained
7in iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or
8for V in <>:.
9
10NOTE: This is still not correct if the original code was depending on
11filter(F, X) to return a string if X is a string and a tuple if X is a
12tuple.  That would require type inference, which we don't do.  Let
13Python 2.6 figure it out.
14"""
15
16# Local imports
17from ..pgen2 import token
18from .. import fixer_base
19from ..fixer_util import Name, Call, ListComp, in_special_context
20
21class FixFilter(fixer_base.ConditionalFix):
22    BM_compatible = True
23
24    PATTERN = """
25    filter_lambda=power<
26        'filter'
27        trailer<
28            '('
29            arglist<
30                lambdef< 'lambda'
31                         (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any
32                >
33                ','
34                it=any
35            >
36            ')'
37        >
38    >
39    |
40    power<
41        'filter'
42        trailer< '(' arglist< none='None' ',' seq=any > ')' >
43    >
44    |
45    power<
46        'filter'
47        args=trailer< '(' [any] ')' >
48    >
49    """
50
51    skip_on = "future_builtins.filter"
52
53    def transform(self, node, results):
54        if self.should_skip(node):
55            return
56
57        if "filter_lambda" in results:
58            new = ListComp(results.get("fp").clone(),
59                           results.get("fp").clone(),
60                           results.get("it").clone(),
61                           results.get("xp").clone())
62
63        elif "none" in results:
64            new = ListComp(Name(u"_f"),
65                           Name(u"_f"),
66                           results["seq"].clone(),
67                           Name(u"_f"))
68
69        else:
70            if in_special_context(node):
71                return None
72            new = node.clone()
73            new.prefix = u""
74            new = Call(Name(u"list"), [new])
75        new.prefix = node.prefix
76        return new
77