[Python-checkins] r61598 - in sandbox/trunk/2to3/lib2to3: fixes/fix_map.py fixes/fix_zip.py fixes/util.py tests/test_fixers.py

david.wolever python-checkins at python.org
Wed Mar 19 05:58:34 CET 2008


Author: david.wolever
Date: Wed Mar 19 05:58:33 2008
New Revision: 61598

Added:
   sandbox/trunk/2to3/lib2to3/fixes/fix_zip.py
Modified:
   sandbox/trunk/2to3/lib2to3/fixes/fix_map.py
   sandbox/trunk/2to3/lib2to3/fixes/util.py
   sandbox/trunk/2to3/lib2to3/tests/test_fixers.py
Log:
Added fixer for zip, and refactored a bit of code in the process.  Closing #2171.

Modified: sandbox/trunk/2to3/lib2to3/fixes/fix_map.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/fixes/fix_map.py	(original)
+++ sandbox/trunk/2to3/lib2to3/fixes/fix_map.py	Wed Mar 19 05:58:33 2008
@@ -20,11 +20,9 @@
 """
 
 # Local imports
-from .. import pytree
-from .. import patcomp
 from ..pgen2 import token
 from . import basefix
-from .util import Name, Call, ListComp, attr_chain, does_tree_import
+from .util import Name, Call, ListComp, does_tree_import, in_special_context
 from ..pygram import python_symbols as syms
 
 class FixMap(basefix.BaseFix):
@@ -92,35 +90,3 @@
             new = Call(Name("list"), [new])
         new.set_prefix(node.get_prefix())
         return new
-
-P0 = """for_stmt< 'for' any 'in' node=any ':' any* >
-        | comp_for< 'for' any 'in' node=any any* >
-     """
-p0 = patcomp.compile_pattern(P0)
-
-P1 = """
-power<
-    ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' |
-      'any' | 'all' | (any* trailer< '.' 'join' >) )
-    trailer< '(' node=any ')' >
-    any*
->
-"""
-p1 = patcomp.compile_pattern(P1)
-
-P2 = """
-power<
-    'sorted'
-    trailer< '(' arglist<node=any any*> ')' >
-    any*
->
-"""
-p2 = patcomp.compile_pattern(P2)
-
-def in_special_context(node):
-    patterns = [p0, p1, p2]
-    for pattern, parent in zip(patterns, attr_chain(node, "parent")):
-        results = {}
-        if pattern.match(parent, results) and results["node"] is node:
-            return True
-    return False

Added: sandbox/trunk/2to3/lib2to3/fixes/fix_zip.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/lib2to3/fixes/fix_zip.py	Wed Mar 19 05:58:33 2008
@@ -0,0 +1,43 @@
+"""
+Fixer that changes zip(seq0, seq1, ...) into list(zip(seq0, seq1, ...)
+unless there exists a 'from future_builtins import zip' statement in the
+top-level namespace.
+
+We avoid the transformation if the zip() call is directly contained in
+iter(<>), list(<>), tuple(<>), sorted(<>), ...join(<>), or for V in <>:.
+"""
+
+# Local imports
+from . import basefix
+from .util import Name, Call, does_tree_import, in_special_context
+
+class FixZip(basefix.BaseFix):
+
+    PATTERN = """
+    power< 'zip' args=trailer< '(' [any] ')' >
+    >
+    """
+
+    def start_tree(self, *args):
+        super(FixZip, self).start_tree(*args)
+        self._future_zip_found = None
+
+    def has_future_zip(self, node):
+        if self._future_zip_found is not None:
+            return self._future_zip_found
+        self._future_zip_found = does_tree_import('future_builtins', 'zip', node)
+        return self._future_zip_found
+
+    def transform(self, node, results):
+        if self.has_future_zip(node):
+            # If a future zip has been imported for this file, we won't
+            # be making any modifications
+            return
+            
+        if in_special_context(node):
+            return None
+        new = node.clone()
+        new.set_prefix("")
+        new = Call(Name("list"), [new])
+        new.set_prefix(node.get_prefix())
+        return new

Modified: sandbox/trunk/2to3/lib2to3/fixes/util.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/fixes/util.py	(original)
+++ sandbox/trunk/2to3/lib2to3/fixes/util.py	Wed Mar 19 05:58:33 2008
@@ -5,6 +5,7 @@
 from ..pgen2 import token
 from ..pytree import Leaf, Node
 from ..pygram import python_symbols as syms
+from .. import patcomp
 
 
 ###########################################################
@@ -180,6 +181,44 @@
         yield next
         next = getattr(next, attr)
 
+p0 = """for_stmt< 'for' any 'in' node=any ':' any* >
+        | comp_for< 'for' any 'in' node=any any* >
+     """
+p1 = """
+power<
+    ( 'iter' | 'list' | 'tuple' | 'sorted' | 'set' | 'sum' |
+      'any' | 'all' | (any* trailer< '.' 'join' >) )
+    trailer< '(' node=any ')' >
+    any*
+>
+"""
+p2 = """
+power<
+    'sorted'
+    trailer< '(' arglist<node=any any*> ')' >
+    any*
+>
+"""
+pats_built = False
+def in_special_context(node):
+    """ Returns true if node is in an environment where all that is required
+        of it is being itterable (ie, it doesn't matter if it returns a list
+        or an itterator).
+        See test_map_nochange in test_fixers.py for some examples and tests.
+        """
+    global p0, p1, p2, pats_built
+    if not pats_built:
+        p1 = patcomp.compile_pattern(p1)
+        p0 = patcomp.compile_pattern(p0)
+        p2 = patcomp.compile_pattern(p2)
+        pats_built = True
+    patterns = [p0, p1, p2]
+    for pattern, parent in zip(patterns, attr_chain(node, "parent")):
+        results = {}
+        if pattern.match(parent, results) and results["node"] is node:
+            return True
+    return False
+
 ###########################################################
 ### The following functions are to find bindings in a suite
 ###########################################################

Modified: sandbox/trunk/2to3/lib2to3/tests/test_fixers.py
==============================================================================
--- sandbox/trunk/2to3/lib2to3/tests/test_fixers.py	(original)
+++ sandbox/trunk/2to3/lib2to3/tests/test_fixers.py	Wed Mar 19 05:58:33 2008
@@ -2493,6 +2493,69 @@
         a = "from future_builtins import *; map(f, 'ham')"
         self.unchanged(a)
 
+class Test_zip(FixerTestCase):
+    fixer = "zip"
+
+    def check(self, b, a):
+        self.unchanged("from future_builtins import zip; " + b, a)
+        FixerTestCase.check(self, b, a)
+
+    def test_zip_basic(self):
+        b = """x = zip(a, b, c)"""
+        a = """x = list(zip(a, b, c))"""
+        self.check(b, a)
+
+        b = """x = len(zip(a, b))"""
+        a = """x = len(list(zip(a, b)))"""
+        self.check(b, a)
+
+    def test_zip_nochange(self):
+        a = """b.join(zip(a, b))"""
+        self.unchanged(a)
+        a = """(a + foo(5)).join(zip(a, b))"""
+        self.unchanged(a)
+        a = """iter(zip(a, b))"""
+        self.unchanged(a)
+        a = """list(zip(a, b))"""
+        self.unchanged(a)
+        a = """list(zip(a, b))[0]"""
+        self.unchanged(a)
+        a = """set(zip(a, b))"""
+        self.unchanged(a)
+        a = """set(zip(a, b)).pop()"""
+        self.unchanged(a)
+        a = """tuple(zip(a, b))"""
+        self.unchanged(a)
+        a = """any(zip(a, b))"""
+        self.unchanged(a)
+        a = """all(zip(a, b))"""
+        self.unchanged(a)
+        a = """sum(zip(a, b))"""
+        self.unchanged(a)
+        a = """sorted(zip(a, b))"""
+        self.unchanged(a)
+        a = """sorted(zip(a, b), key=blah)"""
+        self.unchanged(a)
+        a = """sorted(zip(a, b), key=blah)[0]"""
+        self.unchanged(a)
+        a = """for i in zip(a, b): pass"""
+        self.unchanged(a)
+        a = """[x for x in zip(a, b)]"""
+        self.unchanged(a)
+        a = """(x for x in zip(a, b))"""
+        self.unchanged(a)
+
+    def test_future_builtins(self):
+        a = "from future_builtins import spam, zip, eggs; zip(a, b)"
+        self.unchanged(a)
+
+        b = """from future_builtins import spam, eggs; x = zip(a, b)"""
+        a = """from future_builtins import spam, eggs; x = list(zip(a, b))"""
+        self.check(b, a)
+
+        a = "from future_builtins import *; zip(a, b)"
+        self.unchanged(a)
+
 class Test_standarderror(FixerTestCase):
     fixer = "standarderror"
 


More information about the Python-checkins mailing list