[Python-checkins] r54104 - in sandbox/trunk/2to3: fixes/fix_arg_tuples.py tests/test_fixers.py

collin.winter python-checkins at python.org
Sat Mar 3 05:03:51 CET 2007


Author: collin.winter
Date: Sat Mar  3 05:03:44 2007
New Revision: 54104

Added:
   sandbox/trunk/2to3/fixes/fix_arg_tuples.py   (contents, props changed)
Modified:
   sandbox/trunk/2to3/tests/test_fixers.py
Log:
Add a fixer for tuple parameters (per PEP 3113).

Added: sandbox/trunk/2to3/fixes/fix_arg_tuples.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/2to3/fixes/fix_arg_tuples.py	Sat Mar  3 05:03:44 2007
@@ -0,0 +1,86 @@
+"""Fixer for function definitions with tuple parameters.
+
+def func(((a, b), c), d):
+    ...
+    
+    ->
+
+def func(x, d):
+    ((a, b), c) = x
+    ...
+"""
+# Author: Collin Winter
+
+# Local imports
+import pytree
+from pgen2 import token
+from fixes import basefix
+from fixes.macros import Assign, Name, Newline
+
+def is_docstring(stmt):
+    return isinstance(stmt, pytree.Node) and \
+           stmt.children[0].type == token.STRING
+
+class FixArgTuples(basefix.BaseFix):
+    PATTERN = """funcdef< 'def' any parameters< '(' args=any ')' >
+                                                ['->' any] ':' suite=any+ >"""
+
+    def transform(self, node):
+        syms = self.syms
+        results = self.match(node)
+        assert results
+        
+        new_lines = []
+        suite = results["suite"]
+        args = results["args"]
+        # This crap is so "def foo(...): x = 5; y = 7" is handled correctly.
+        if suite[0].children[1].type == token.INDENT:
+            start = 2
+            indent = suite[0].children[1].value
+            end = Newline()
+        else:
+            start = 0
+            indent = "; "
+            end = pytree.Leaf(token.INDENT, "")
+        
+        # We need access to self for new_name(), and making this a method
+        #  doesn't feel right. Closing over self and new_lines makes the
+        #  code below cleaner.
+        def handle_tuple(tuple_arg, add_prefix=False):
+            n = Name(self.new_name())
+            arg = tuple_arg.clone()
+            arg.set_prefix("")
+            stmt = Assign(arg, n.clone())
+            if add_prefix:
+                n.set_prefix(" ")
+            tuple_arg.replace(n)
+            new_lines.append(pytree.Node(syms.simple_stmt, [stmt, end.clone()]))
+        
+        if args.type == syms.tfpdef:
+            handle_tuple(args)
+        elif args.type == syms.typedargslist:
+            for i, arg in enumerate(args.children):
+                if arg.type == syms.tfpdef:
+                    # Without add_prefix, the emitted code is correct,
+                    #  just ugly.
+                    handle_tuple(arg, add_prefix=(i > 0))
+                    
+        if not new_lines:
+            return node
+        
+        # This isn't strictly necessary, but it plays nicely with other fixers.
+        for line in new_lines:
+            line.parent = suite[0]
+            
+        after = start
+        if start == 0:
+            new_lines[0].set_prefix(" ")
+        elif is_docstring(suite[0].children[start]):
+            new_lines[0].set_prefix(indent)
+            after = start + 1
+            
+        children = list(suite[0].children)    
+        children[after:after] = new_lines
+        for i in range(after+1, after+len(new_lines)+1):
+            children[i].set_prefix(indent)
+        suite[0].children = tuple(children)

Modified: sandbox/trunk/2to3/tests/test_fixers.py
==============================================================================
--- sandbox/trunk/2to3/tests/test_fixers.py	(original)
+++ sandbox/trunk/2to3/tests/test_fixers.py	Sat Mar  3 05:03:44 2007
@@ -496,8 +496,8 @@
             def foo():
                 try:
                     pass
-                except Exception as xxx_todo_changeme:
-                    (f, e) = xxx_todo_changeme.message
+                except Exception as xxx_todo_changeme12:
+                    (f, e) = xxx_todo_changeme12.message
                     pass
                 except ImportError as e:
                     pass"""
@@ -527,8 +527,8 @@
         a = """
             try:
                 pass
-            except Exception as xxx_todo_changeme1:
-                (a, b) = xxx_todo_changeme1.message
+            except Exception as xxx_todo_changeme13:
+                (a, b) = xxx_todo_changeme13.message
                 pass"""
         self.check(b, a)
 
@@ -542,8 +542,8 @@
         a = """
             try:
                 pass
-            except Exception as xxx_todo_changeme2:
-                d[5] = xxx_todo_changeme2
+            except Exception as xxx_todo_changeme14:
+                d[5] = xxx_todo_changeme14
                 pass"""
         self.check(b, a)
 
@@ -557,8 +557,8 @@
         a = """
             try:
                 pass
-            except Exception as xxx_todo_changeme3:
-                a.foo = xxx_todo_changeme3
+            except Exception as xxx_todo_changeme15:
+                a.foo = xxx_todo_changeme15
                 pass"""
         self.check(b, a)
 
@@ -572,8 +572,8 @@
         a = """
             try:
                 pass
-            except Exception as xxx_todo_changeme4:
-                a().foo = xxx_todo_changeme4
+            except Exception as xxx_todo_changeme16:
+                a().foo = xxx_todo_changeme16
                 pass"""
         self.check(b, a)
 
@@ -1111,6 +1111,123 @@
         b = """x = input('prompt')"""
         a = """x = eval(input('prompt'))"""
         self.check(b, a)
+        
+        
+class Test_arg_tuples(FixerTestCase):
+    fixer = "arg_tuples"
+    
+    def test_unchanged_1(self):
+        s = """def foo(): pass"""
+        self.check(s, s)
+    
+    def test_unchanged_2(self):
+        s = """def foo(a, b, c): pass"""
+        self.check(s, s)
+    
+    def test_unchanged_3(self):
+        s = """def foo(a=3, b=4, c=5): pass"""
+        self.check(s, s)
+        
+    def test_1(self):
+        b = """
+            def foo(((a, b), c)):
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme):
+                ((a, b), c) = xxx_todo_changeme
+                x = 5"""
+        self.check(b, a)
+        
+    def test_2(self):
+        b = """
+            def foo(((a, b), c), d):
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme1, d):
+                ((a, b), c) = xxx_todo_changeme1
+                x = 5"""
+        self.check(b, a)
+        
+    def test_3(self):
+        b = """
+            def foo(((a, b), c), d) -> e:
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme2, d) -> e:
+                ((a, b), c) = xxx_todo_changeme2
+                x = 5"""
+        self.check(b, a)
+        
+    def test_semicolon(self):
+        b = """
+            def foo(((a, b), c)): x = 5; y = 7"""
+                
+        a = """
+            def foo(xxx_todo_changeme10): ((a, b), c) = xxx_todo_changeme10; x = 5; y = 7"""
+        self.check(b, a)
+        
+    def test_keywords(self):
+        b = """
+            def foo(((a, b), c), d, e=5) -> z:
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme5, d, e=5) -> z:
+                ((a, b), c) = xxx_todo_changeme5
+                x = 5"""
+        self.check(b, a)
+        
+    def test_varargs(self):
+        b = """
+            def foo(((a, b), c), d, *vargs, **kwargs) -> z:
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme11, d, *vargs, **kwargs) -> z:
+                ((a, b), c) = xxx_todo_changeme11
+                x = 5"""
+        self.check(b, a)
+        
+    def test_multi_1(self):
+        b = """
+            def foo(((a, b), c), (d, e, f)) -> z:
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme6, xxx_todo_changeme7) -> z:
+                ((a, b), c) = xxx_todo_changeme6
+                (d, e, f) = xxx_todo_changeme7
+                x = 5"""
+        self.check(b, a)
+        
+    def test_multi_2(self):
+        b = """
+            def foo(x, ((a, b), c), d, (e, f, g), y) -> z:
+                x = 5"""
+                
+        a = """
+            def foo(x, xxx_todo_changeme8, d, xxx_todo_changeme9, y) -> z:
+                ((a, b), c) = xxx_todo_changeme8
+                (e, f, g) = xxx_todo_changeme9
+                x = 5"""
+        self.check(b, a)
+        
+    def test_docstring(self):
+        b = """
+            def foo(((a, b), c), (d, e, f)) -> z:
+                "foo foo foo foo"
+                x = 5"""
+                
+        a = """
+            def foo(xxx_todo_changeme3, xxx_todo_changeme4) -> z:
+                "foo foo foo foo"
+                ((a, b), c) = xxx_todo_changeme3
+                (d, e, f) = xxx_todo_changeme4
+                x = 5"""
+        self.check(b, a)
 
 
 if __name__ == "__main__":


More information about the Python-checkins mailing list