[Python-checkins] r53681 - in sandbox/trunk/2to3: example.py fixes/fix_dict.py

guido.van.rossum python-checkins at python.org
Fri Feb 9 02:27:50 CET 2007


Author: guido.van.rossum
Date: Fri Feb  9 02:27:49 2007
New Revision: 53681

Added:
   sandbox/trunk/2to3/fixes/fix_dict.py   (contents, props changed)
Modified:
   sandbox/trunk/2to3/example.py
Log:
Work checkpoint: convert d.keys(), d.iterkeys() etc.


Modified: sandbox/trunk/2to3/example.py
==============================================================================
--- sandbox/trunk/2to3/example.py	(original)
+++ sandbox/trunk/2to3/example.py	Fri Feb  9 02:27:49 2007
@@ -243,5 +243,36 @@
     b = 0x12
     c = 3.14
 
+def dict_examples():
+    #
+    # Plain method calls
+    #
+    print d.keys()
+    print d.items()
+    print d.values()
+    #
+    # Plain method calls in special contexts
+    #
+    print list(e.keys())
+    print sorted(e.keys())
+    print iter(e.keys())
+    for i in e.keys(): print i
+    #
+    # Iterator method calls
+    #
+    print d.iterkeys()
+    print d.iteritems()
+    print d.itervalues()
+    #
+    # Iterator method calls in special contexts
+    #
+    print list(e.iterkeys())
+    print sorted(e.iterkeys())
+    print iter(e.iterkeys())
+    for i in e.iterkeys(): print i
+    #
+    # This should be left unchanged but trigger a warning:
+    #
+    print d.keys()[0]
 
 # This is the last line.

Added: sandbox/trunk/2to3/fixes/fix_dict.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/fixes/fix_dict.py	Fri Feb  9 02:27:49 2007
@@ -0,0 +1,90 @@
+# Copyright 2007 Google, Inc. All Rights Reserved.
+
+"""Fixer for dict methods.
+
+d.keys() -> list(d.keys())
+d.items() -> list(d.items())
+d.values() -> list(d.values())
+
+d.iterkeys() -> iter(d.keys())
+d.iteritems() -> iter(d.items())
+d.itervalues() -> iter(d.values())
+
+Except in certain very specific contexts: the iter() can be dropped
+when the context is list(), sorted(), iter() or for...in; the list()
+can be dropped when the context is list() or sorted() (but not iter()
+or for...in!).
+
+Note: iter(d.keys()) could be written as iter(d) but since the
+original d.iterkeys() was also redundant we don't fix this.  And there
+are (rare) contexts where it makes a difference (e.g. when passing it
+as an argument to a function that introspects the argument).
+"""
+
+# Python imports
+import token
+
+# Local imports
+import pytree
+import patcomp
+from fixes import basefix
+from fixes import macros
+
+class FixDict(basefix.BaseFix):
+
+  PATTERN = """
+  power< prefix=any+
+         trailer< '.' method=('keys'|'items'|'values'|
+                              'iterkeys'|'iteritems'|'itervalues') >
+         trailer< '(' ')' >
+         tail=any*
+  >
+  """
+
+  def transform(self, node):
+    results = self.match(node)
+    prefix = results["prefix"]
+    method = results["method"][0].value # Extract method name
+    tail = results["tail"]
+    if tail:
+      return self.cannot_convert(node,
+                                 "stuff after .[iter]keys() etc. unsupported")
+    syms = self.syms
+    isiter = method.startswith("iter")
+    if isiter:
+      method = method[4:]
+    assert method in ("keys", "items", "values"), repr(method)
+    prefix = [n.clone() for n in prefix]
+    new = pytree.Node(syms.power,
+                      prefix + [pytree.Node(syms.trailer,
+                                            [pytree.Leaf(token.DOT, '.'),
+                                             macros.Name(method)]),
+                                pytree.Node(syms.trailer,
+                                            [macros.lparen_leaf.clone(),
+                                             macros.rparen_leaf.clone()])])
+    if not self.in_special_context(node, isiter):
+      new.set_prefix("")
+      new = macros.Call(macros.Name(isiter and "iter" or "list"), [new])
+    new.set_prefix(node.get_prefix())
+    return new
+
+  P1 = "trailer< '(' node=any ')' >"
+  p1 = patcomp.PatternCompiler().compile_pattern(P1)
+
+  P2 = "power< func=NAME trailer< '(' node=any ')' > any* >"
+  p2 = patcomp.PatternCompiler().compile_pattern(P2)
+
+  def in_special_context(self, node, isiter):
+    results = {}
+    if not (self.p1.match(node.parent, results) and
+            results["node"] is node):
+      return False
+    results = {}
+    if not (self.p2.match(node.parent.parent, results) and
+            results["node"] is node):
+      return False
+    if isiter:
+      return results["func"].value == ("iter", "list", "sorted")
+    else:
+      return results["func"].value in ("list", "sorted")
+    # XXX TODO: for...in context.


More information about the Python-checkins mailing list