1 # Copyright 2006 Google, Inc. All Rights Reserved.
2 # Licensed to PSF under a Contributor Agreement.
3
4 """Fixer for has_key().
5
6 Calls to .has_key() methods are expressed in terms of the 'in'
7 operator:
8
9 d.has_key(k) -> k in d
10
11 CAVEATS:
12 1) While the primary target of this fixer is dict.has_key(), the
13 fixer will change any has_key() method call, regardless of its
14 class.
15
16 2) Cases like this will not be converted:
17
18 m = d.has_key
19 if m(k):
20 ...
21
22 Only *calls* to has_key() are converted. While it is possible to
23 convert the above to something like
24
25 m = d.__contains__
26 if m(k):
27 ...
28
29 this is currently not done.
30 """
31
32 # Local imports
33 from .. import pytree
34 from .. import fixer_base
35 from ..fixer_util import Name, parenthesize
36
37
38 class ESC[4;38;5;81mFixHasKey(ESC[4;38;5;149mfixer_baseESC[4;38;5;149m.ESC[4;38;5;149mBaseFix):
39 BM_compatible = True
40
41 PATTERN = """
42 anchor=power<
43 before=any+
44 trailer< '.' 'has_key' >
45 trailer<
46 '('
47 ( not(arglist | argument<any '=' any>) arg=any
48 | arglist<(not argument<any '=' any>) arg=any ','>
49 )
50 ')'
51 >
52 after=any*
53 >
54 |
55 negation=not_test<
56 'not'
57 anchor=power<
58 before=any+
59 trailer< '.' 'has_key' >
60 trailer<
61 '('
62 ( not(arglist | argument<any '=' any>) arg=any
63 | arglist<(not argument<any '=' any>) arg=any ','>
64 )
65 ')'
66 >
67 >
68 >
69 """
70
71 def transform(self, node, results):
72 assert results
73 syms = self.syms
74 if (node.parent.type == syms.not_test and
75 self.pattern.match(node.parent)):
76 # Don't transform a node matching the first alternative of the
77 # pattern when its parent matches the second alternative
78 return None
79 negation = results.get("negation")
80 anchor = results["anchor"]
81 prefix = node.prefix
82 before = [n.clone() for n in results["before"]]
83 arg = results["arg"].clone()
84 after = results.get("after")
85 if after:
86 after = [n.clone() for n in after]
87 if arg.type in (syms.comparison, syms.not_test, syms.and_test,
88 syms.or_test, syms.test, syms.lambdef, syms.argument):
89 arg = parenthesize(arg)
90 if len(before) == 1:
91 before = before[0]
92 else:
93 before = pytree.Node(syms.power, before)
94 before.prefix = " "
95 n_op = Name("in", prefix=" ")
96 if negation:
97 n_not = Name("not", prefix=" ")
98 n_op = pytree.Node(syms.comp_op, (n_not, n_op))
99 new = pytree.Node(syms.comparison, (arg, n_op, before))
100 if after:
101 new = parenthesize(new)
102 new = pytree.Node(syms.power, (new,) + tuple(after))
103 if node.parent.type in (syms.comparison, syms.expr, syms.xor_expr,
104 syms.and_expr, syms.shift_expr,
105 syms.arith_expr, syms.term,
106 syms.factor, syms.power):
107 new = parenthesize(new)
108 new.prefix = prefix
109 return new