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 .. import fixer_base 18from ..pytree import Node 19from ..pygram import python_symbols as syms 20from ..fixer_util import Name, ArgList, ListComp, in_special_context, parenthesize 21 22 23class FixFilter(fixer_base.ConditionalFix): 24 BM_compatible = True 25 26 PATTERN = """ 27 filter_lambda=power< 28 'filter' 29 trailer< 30 '(' 31 arglist< 32 lambdef< 'lambda' 33 (fp=NAME | vfpdef< '(' fp=NAME ')'> ) ':' xp=any 34 > 35 ',' 36 it=any 37 > 38 ')' 39 > 40 [extra_trailers=trailer*] 41 > 42 | 43 power< 44 'filter' 45 trailer< '(' arglist< none='None' ',' seq=any > ')' > 46 [extra_trailers=trailer*] 47 > 48 | 49 power< 50 'filter' 51 args=trailer< '(' [any] ')' > 52 [extra_trailers=trailer*] 53 > 54 """ 55 56 skip_on = "future_builtins.filter" 57 58 def transform(self, node, results): 59 if self.should_skip(node): 60 return 61 62 trailers = [] 63 if 'extra_trailers' in results: 64 for t in results['extra_trailers']: 65 trailers.append(t.clone()) 66 67 if "filter_lambda" in results: 68 xp = results.get("xp").clone() 69 if xp.type == syms.test: 70 xp.prefix = "" 71 xp = parenthesize(xp) 72 73 new = ListComp(results.get("fp").clone(), 74 results.get("fp").clone(), 75 results.get("it").clone(), xp) 76 new = Node(syms.power, [new] + trailers, prefix="") 77 78 elif "none" in results: 79 new = ListComp(Name("_f"), 80 Name("_f"), 81 results["seq"].clone(), 82 Name("_f")) 83 new = Node(syms.power, [new] + trailers, prefix="") 84 85 else: 86 if in_special_context(node): 87 return None 88 89 args = results['args'].clone() 90 new = Node(syms.power, [Name("filter"), args], prefix="") 91 new = Node(syms.power, [Name("list"), ArgList([new])] + trailers) 92 new.prefix = "" 93 new.prefix = node.prefix 94 return new 95