Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 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 | ... |
Martin v. Löwis | f733c60 | 2008-03-19 05:26:18 +0000 | [diff] [blame] | 21 | |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 22 | Only *calls* to has_key() are converted. While it is possible to |
| 23 | convert the above to something like |
Martin v. Löwis | f733c60 | 2008-03-19 05:26:18 +0000 | [diff] [blame] | 24 | |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 25 | m = d.__contains__ |
| 26 | if m(k): |
| 27 | ... |
Martin v. Löwis | f733c60 | 2008-03-19 05:26:18 +0000 | [diff] [blame] | 28 | |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 29 | this is currently not done. |
| 30 | """ |
| 31 | |
| 32 | # Local imports |
| 33 | from .. import pytree |
| 34 | from ..pgen2 import token |
Benjamin Peterson | df6dc8f | 2008-06-15 02:57:40 +0000 | [diff] [blame] | 35 | from .. import fixer_base |
Benjamin Peterson | 0b24b3d | 2008-12-16 03:57:54 +0000 | [diff] [blame] | 36 | from ..fixer_util import Name, parenthesize |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 37 | |
| 38 | |
Benjamin Peterson | df6dc8f | 2008-06-15 02:57:40 +0000 | [diff] [blame] | 39 | class FixHasKey(fixer_base.BaseFix): |
Benjamin Peterson | f37eb3a | 2010-10-14 23:00:04 +0000 | [diff] [blame] | 40 | BM_compatible = True |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 41 | |
| 42 | PATTERN = """ |
| 43 | anchor=power< |
| 44 | before=any+ |
| 45 | trailer< '.' 'has_key' > |
| 46 | trailer< |
| 47 | '(' |
| 48 | ( not(arglist | argument<any '=' any>) arg=any |
| 49 | | arglist<(not argument<any '=' any>) arg=any ','> |
| 50 | ) |
| 51 | ')' |
| 52 | > |
| 53 | after=any* |
| 54 | > |
| 55 | | |
| 56 | negation=not_test< |
| 57 | 'not' |
| 58 | anchor=power< |
| 59 | before=any+ |
| 60 | trailer< '.' 'has_key' > |
| 61 | trailer< |
| 62 | '(' |
| 63 | ( not(arglist | argument<any '=' any>) arg=any |
| 64 | | arglist<(not argument<any '=' any>) arg=any ','> |
| 65 | ) |
| 66 | ')' |
| 67 | > |
| 68 | > |
| 69 | > |
| 70 | """ |
| 71 | |
| 72 | def transform(self, node, results): |
| 73 | assert results |
| 74 | syms = self.syms |
| 75 | if (node.parent.type == syms.not_test and |
| 76 | self.pattern.match(node.parent)): |
| 77 | # Don't transform a node matching the first alternative of the |
| 78 | # pattern when its parent matches the second alternative |
| 79 | return None |
| 80 | negation = results.get("negation") |
| 81 | anchor = results["anchor"] |
Benjamin Peterson | 2c3ac6b | 2009-06-11 23:47:38 +0000 | [diff] [blame] | 82 | prefix = node.prefix |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 83 | before = [n.clone() for n in results["before"]] |
| 84 | arg = results["arg"].clone() |
| 85 | after = results.get("after") |
| 86 | if after: |
| 87 | after = [n.clone() for n in after] |
| 88 | if arg.type in (syms.comparison, syms.not_test, syms.and_test, |
| 89 | syms.or_test, syms.test, syms.lambdef, syms.argument): |
Benjamin Peterson | 0b24b3d | 2008-12-16 03:57:54 +0000 | [diff] [blame] | 90 | arg = parenthesize(arg) |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 91 | if len(before) == 1: |
| 92 | before = before[0] |
| 93 | else: |
| 94 | before = pytree.Node(syms.power, before) |
Benjamin Peterson | 2c3ac6b | 2009-06-11 23:47:38 +0000 | [diff] [blame] | 95 | before.prefix = " " |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 96 | n_op = Name("in", prefix=" ") |
| 97 | if negation: |
| 98 | n_not = Name("not", prefix=" ") |
| 99 | n_op = pytree.Node(syms.comp_op, (n_not, n_op)) |
| 100 | new = pytree.Node(syms.comparison, (arg, n_op, before)) |
| 101 | if after: |
Benjamin Peterson | 0b24b3d | 2008-12-16 03:57:54 +0000 | [diff] [blame] | 102 | new = parenthesize(new) |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 103 | new = pytree.Node(syms.power, (new,) + tuple(after)) |
| 104 | if node.parent.type in (syms.comparison, syms.expr, syms.xor_expr, |
| 105 | syms.and_expr, syms.shift_expr, |
| 106 | syms.arith_expr, syms.term, |
| 107 | syms.factor, syms.power): |
Benjamin Peterson | 0b24b3d | 2008-12-16 03:57:54 +0000 | [diff] [blame] | 108 | new = parenthesize(new) |
Benjamin Peterson | 2c3ac6b | 2009-06-11 23:47:38 +0000 | [diff] [blame] | 109 | new.prefix = prefix |
Martin v. Löwis | ef04c44 | 2008-03-19 05:04:44 +0000 | [diff] [blame] | 110 | return new |