Merged revisions 61598-61599,61601 via svnmerge from
svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3

........
  r61598 | david.wolever | 2008-03-18 23:58:33 -0500 (Di, 18 Mär 2008) | 1 line

  Added fixer for zip, and refactored a bit of code in the process.  Closing #2171.
........
  r61599 | david.wolever | 2008-03-19 00:04:26 -0500 (Mi, 19 Mär 2008) | 3 lines

  Removed a bunch of duplicate code -- it's in util now.
........
  r61601 | martin.v.loewis | 2008-03-19 00:21:12 -0500 (Mi, 19 Mär 2008) | 2 lines

  Fix whitespace.
........
diff --git a/Lib/lib2to3/fixes/util.py b/Lib/lib2to3/fixes/util.py
index 8b7ad9f..ef809af 100644
--- a/Lib/lib2to3/fixes/util.py
+++ b/Lib/lib2to3/fixes/util.py
@@ -5,6 +5,7 @@
 from ..pgen2 import token
 from ..pytree import Leaf, Node
 from ..pygram import python_symbols as syms
+from .. import patcomp
 
 
 ###########################################################
@@ -163,15 +164,15 @@
 
 def attr_chain(obj, attr):
     """Follow an attribute chain.
-    
+
     If you have a chain of objects where a.foo -> b, b.foo-> c, etc,
     use this to iterate over all objects in the chain. Iteration is
     terminated by getattr(x, attr) is None.
-    
+
     Args:
         obj: the starting object
         attr: the name of the chaining attribute
-    
+
     Yields:
         Each successive object in the chain.
     """
@@ -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
 ###########################################################
@@ -240,8 +279,8 @@
         elif child.type == syms.simple_stmt:
             ret = find_binding(name, child, package)
         elif child.type == syms.expr_stmt:
-                if _find(name, child.children[0]):
-                    ret = child
+            if _find(name, child.children[0]):
+                ret = child
 
         if ret:
             if not package: