[Python-checkins] r54447 - in sandbox/trunk/2to3: README fixes/fix_tuple_params.py tests/test_fixers.py
collin.winter
python-checkins at python.org
Mon Mar 19 22:46:06 CET 2007
Author: collin.winter
Date: Mon Mar 19 22:46:01 2007
New Revision: 54447
Modified:
sandbox/trunk/2to3/README
sandbox/trunk/2to3/fixes/fix_tuple_params.py
sandbox/trunk/2to3/tests/test_fixers.py
Log:
Add lambda support to fix_tuple_params.
Modified: sandbox/trunk/2to3/README
==============================================================================
--- sandbox/trunk/2to3/README (original)
+++ sandbox/trunk/2to3/README Mon Mar 19 22:46:01 2007
@@ -65,8 +65,8 @@
* **fix_throw** - fix generator.throw() calls to be 3.0-compliant (PEP 3109).
-* **fix_tuple_params** - remove tuple parameters from function and method
- declarations (PEP 3113).
+* **fix_tuple_params** - remove tuple parameters from function, method and
+ lambda declarations (PEP 3113).
* **fix_xrange** - "xrange()" -> "range()".
Modified: sandbox/trunk/2to3/fixes/fix_tuple_params.py
==============================================================================
--- sandbox/trunk/2to3/fixes/fix_tuple_params.py (original)
+++ sandbox/trunk/2to3/fixes/fix_tuple_params.py Mon Mar 19 22:46:01 2007
@@ -8,28 +8,38 @@
def func(x, d):
((a, b), c) = x
...
+
+It will also support lambdas:
+
+ lambda (x, y): x + y -> lambda: t: t[0] + t[1]
"""
# Author: Collin Winter
# Local imports
import pytree
from pgen2 import token
+from pygram import python_symbols as syms
from fixes import basefix
-from fixes.macros import Assign, Name, Newline
+from fixes.macros import Assign, Name, Newline, Number, Subscript
def is_docstring(stmt):
return isinstance(stmt, pytree.Node) and \
stmt.children[0].type == token.STRING
class FixTupleParams(basefix.BaseFix):
- PATTERN = """funcdef< 'def' any parameters< '(' args=any ')' >
- ['->' any] ':' suite=any+ >"""
+ PATTERN = """
+ funcdef< 'def' any parameters< '(' args=any ')' >
+ ['->' any] ':' suite=any+ >
+ |
+ lambda=lambdef< 'lambda' args=vfpdef< any+ > ':' body=any >"""
def transform(self, node):
- syms = self.syms
results = self.match(node)
assert results
+ if "lambda" in results:
+ return self.transform_lambda(node)
+
new_lines = []
suite = results["suite"]
args = results["args"]
@@ -85,3 +95,54 @@
children[i].set_prefix(indent)
suite[0].children = tuple(children)
suite[0].changed()
+
+ def transform_lambda(self, node):
+ results = self.match(node)
+ assert results
+ args = results["args"]
+ body = results["body"]
+
+ params = find_params(args)
+ to_index = map_to_index(params)
+ tup_name = self.new_name(tuple_name(params))
+
+ new_param = Name(tup_name)
+ new_param.set_prefix(args.get_prefix())
+ args.replace(new_param.clone())
+ for n in body.post_order():
+ if n.type == token.NAME and n.value in to_index:
+ subscripts = [c.clone() for c in to_index[n.value]]
+ new = pytree.Node(syms.power,
+ [new_param.clone()] + subscripts)
+ new.set_prefix(n.get_prefix())
+ n.replace(new)
+
+
+### Helper functions for transform_lambda()
+
+def find_params(node):
+ if node.type == syms.vfpdef:
+ return find_params(node.children[1])
+ elif node.type == token.NAME:
+ return node.value
+ return [find_params(c) for c in node.children if c.type != token.COMMA]
+
+def map_to_index(param_list, prefix=[], d=None):
+ if d is None:
+ d = {}
+ for i, obj in enumerate(param_list):
+ trailer = [Subscript(Number(i))]
+ if isinstance(obj, list):
+ map_to_index(obj, trailer, d=d)
+ else:
+ d[obj] = prefix + trailer
+ return d
+
+def tuple_name(param_list):
+ l = []
+ for obj in param_list:
+ if isinstance(obj, list):
+ l.append(tuple_name(obj))
+ else:
+ l.append(obj)
+ return "_".join(l)
Modified: sandbox/trunk/2to3/tests/test_fixers.py
==============================================================================
--- sandbox/trunk/2to3/tests/test_fixers.py (original)
+++ sandbox/trunk/2to3/tests/test_fixers.py Mon Mar 19 22:46:01 2007
@@ -1229,6 +1229,35 @@
x = 5"""
self.check(b, a)
+ def test_lambda_no_change(self):
+ s = """lambda x: x + 5"""
+ self.check(s, s)
+
+ def test_lambda_simple(self):
+ b = """lambda (x, y): x + f(y)"""
+ a = """lambda x_y: x_y[0] + f(x_y[1])"""
+ self.check(b, a)
+
+ def test_lambda_simple_multi_use(self):
+ b = """lambda (x, y): x + x + f(x) + x"""
+ a = """lambda x_y: x_y[0] + x_y[0] + f(x_y[0]) + x_y[0]"""
+ self.check(b, a)
+
+ def test_lambda_simple_reverse(self):
+ b = """lambda (x, y): y + x"""
+ a = """lambda x_y: x_y[1] + x_y[0]"""
+ self.check(b, a)
+
+ def test_lambda_nested(self):
+ b = """lambda (x, (y, z)): x + y + z"""
+ a = """lambda x_y_z: x_y_z[0] + x_y_z[1][0] + x_y_z[1][1]"""
+ self.check(b, a)
+
+ def test_lambda_nested_multi_use(self):
+ b = """lambda (x, (y, z)): x + y + f(y)"""
+ a = """lambda x_y_z: x_y_z[0] + x_y_z[1][0] + f(x_y_z[1][0])"""
+ self.check(b, a)
+
class Test_next(FixerTestCase):
fixer = "next"
More information about the Python-checkins
mailing list