symbian-qemu-0.9.1-12/python-2.6.1/Lib/lib2to3/fixes/fix_dict.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 # Copyright 2007 Google, Inc. All Rights Reserved.
       
     2 # Licensed to PSF under a Contributor Agreement.
       
     3 
       
     4 """Fixer for dict methods.
       
     5 
       
     6 d.keys() -> list(d.keys())
       
     7 d.items() -> list(d.items())
       
     8 d.values() -> list(d.values())
       
     9 
       
    10 d.iterkeys() -> iter(d.keys())
       
    11 d.iteritems() -> iter(d.items())
       
    12 d.itervalues() -> iter(d.values())
       
    13 
       
    14 Except in certain very specific contexts: the iter() can be dropped
       
    15 when the context is list(), sorted(), iter() or for...in; the list()
       
    16 can be dropped when the context is list() or sorted() (but not iter()
       
    17 or for...in!). Special contexts that apply to both: list(), sorted(), tuple()
       
    18 set(), any(), all(), sum().
       
    19 
       
    20 Note: iter(d.keys()) could be written as iter(d) but since the
       
    21 original d.iterkeys() was also redundant we don't fix this.  And there
       
    22 are (rare) contexts where it makes a difference (e.g. when passing it
       
    23 as an argument to a function that introspects the argument).
       
    24 """
       
    25 
       
    26 # Local imports
       
    27 from .. import pytree
       
    28 from .. import patcomp
       
    29 from ..pgen2 import token
       
    30 from .. import fixer_base
       
    31 from ..fixer_util import Name, Call, LParen, RParen, ArgList, Dot
       
    32 from .. import fixer_util
       
    33 
       
    34 
       
    35 iter_exempt = fixer_util.consuming_calls | set(["iter"])
       
    36 
       
    37 
       
    38 class FixDict(fixer_base.BaseFix):
       
    39     PATTERN = """
       
    40     power< head=any+
       
    41          trailer< '.' method=('keys'|'items'|'values'|
       
    42                               'iterkeys'|'iteritems'|'itervalues') >
       
    43          parens=trailer< '(' ')' >
       
    44          tail=any*
       
    45     >
       
    46     """
       
    47 
       
    48     def transform(self, node, results):
       
    49         head = results["head"]
       
    50         method = results["method"][0] # Extract node for method name
       
    51         tail = results["tail"]
       
    52         syms = self.syms
       
    53         method_name = method.value
       
    54         isiter = method_name.startswith("iter")
       
    55         if isiter:
       
    56             method_name = method_name[4:]
       
    57         assert method_name in ("keys", "items", "values"), repr(method)
       
    58         head = [n.clone() for n in head]
       
    59         tail = [n.clone() for n in tail]
       
    60         special = not tail and self.in_special_context(node, isiter)
       
    61         args = head + [pytree.Node(syms.trailer,
       
    62                                    [Dot(),
       
    63                                     Name(method_name,
       
    64                                          prefix=method.get_prefix())]),
       
    65                        results["parens"].clone()]
       
    66         new = pytree.Node(syms.power, args)
       
    67         if not special:
       
    68             new.set_prefix("")
       
    69             new = Call(Name(isiter and "iter" or "list"), [new])
       
    70         if tail:
       
    71             new = pytree.Node(syms.power, [new] + tail)
       
    72         new.set_prefix(node.get_prefix())
       
    73         return new
       
    74 
       
    75     P1 = "power< func=NAME trailer< '(' node=any ')' > any* >"
       
    76     p1 = patcomp.compile_pattern(P1)
       
    77 
       
    78     P2 = """for_stmt< 'for' any 'in' node=any ':' any* >
       
    79             | comp_for< 'for' any 'in' node=any any* >
       
    80          """
       
    81     p2 = patcomp.compile_pattern(P2)
       
    82 
       
    83     def in_special_context(self, node, isiter):
       
    84         if node.parent is None:
       
    85             return False
       
    86         results = {}
       
    87         if (node.parent.parent is not None and
       
    88                self.p1.match(node.parent.parent, results) and
       
    89                results["node"] is node):
       
    90             if isiter:
       
    91                 # iter(d.iterkeys()) -> iter(d.keys()), etc.
       
    92                 return results["func"].value in iter_exempt
       
    93             else:
       
    94                 # list(d.keys()) -> list(d.keys()), etc.
       
    95                 return results["func"].value in fixer_util.consuming_calls
       
    96         if not isiter:
       
    97             return False
       
    98         # for ... in d.iterkeys() -> for ... in d.keys(), etc.
       
    99         return self.p2.match(node.parent, results) and results["node"] is node