PageRenderTime 13ms CodeModel.GetById 1ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/lib2to3/fixes/fix_has_key.py

http://unladen-swallow.googlecode.com/
Python | 109 lines | 103 code | 1 blank | 5 comment | 12 complexity | 1b88e2b6b4c60df9b85a168a07e13fa7 MD5 | raw file
  1# Copyright 2006 Google, Inc. All Rights Reserved.
  2# Licensed to PSF under a Contributor Agreement.
  3
  4"""Fixer for has_key().
  5
  6Calls to .has_key() methods are expressed in terms of the 'in'
  7operator:
  8
  9    d.has_key(k) -> k in d
 10
 11CAVEATS:
 121) 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
 162) 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
 33from .. import pytree
 34from ..pgen2 import token
 35from .. import fixer_base
 36from ..fixer_util import Name, parenthesize
 37
 38
 39class FixHasKey(fixer_base.BaseFix):
 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.get_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.set_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.set_prefix(prefix)
109        return new