[pypy-svn] r75538 - in pypy/branch/fast-forward/pypy/interpreter: astcompiler astcompiler/test pyparser/data test

benjamin at codespeak.net benjamin at codespeak.net
Wed Jun 23 22:03:17 CEST 2010


Author: benjamin
Date: Wed Jun 23 22:03:16 2010
New Revision: 75538

Modified:
   pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py
   pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py
   pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7
   pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py
Log:
implement multi-with statements

Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/astbuilder.py	Wed Jun 23 22:03:16 2010
@@ -436,15 +436,23 @@
                               try_node.column)
 
     def handle_with_stmt(self, with_node):
-        test = self.handle_expr(with_node.children[1])
         body = self.handle_suite(with_node.children[-1])
-        if len(with_node.children) == 5:
-            target_node = with_node.children[2]
-            target = self.handle_expr(target_node.children[1])
-            self.set_context(target, ast.Store)
-        else:
-            target = None
-        return ast.With(test, target, body, with_node.lineno, with_node.column)
+        i = len(with_node.children) - 1
+        while True:
+            i -= 2
+            item = with_node.children[i]
+            test = self.handle_expr(item.children[0])
+            if len(item.children) == 3:
+                target = self.handle_expr(item.children[2])
+                self.set_context(target, ast.Store)
+            else:
+                target = None
+            wi = ast.With(test, target, body, with_node.lineno,
+                          with_node.column)
+            if i == 1:
+                break
+            body = [wi]
+        return wi
 
     def handle_classdef(self, classdef_node, decorators=None):
         name_node = classdef_node.children[1]

Modified: pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/astcompiler/test/test_astbuilder.py	Wed Jun 23 22:03:16 2010
@@ -455,6 +455,20 @@
         assert wi.optional_vars.elts[0].ctx == ast.Store
         input = "with x hi y: pass"
         exc = py.test.raises(SyntaxError, self.get_ast, input).value
+        wi = self.get_first_stmt("with x as y, b: pass")
+        assert isinstance(wi, ast.With)
+        assert isinstance(wi.context_expr, ast.Name)
+        assert wi.context_expr.id == "x"
+        assert isinstance(wi.optional_vars, ast.Name)
+        assert wi.optional_vars.id == "y"
+        assert len(wi.body) == 1
+        wi = wi.body[0]
+        assert isinstance(wi, ast.With)
+        assert isinstance(wi.context_expr, ast.Name)
+        assert wi.context_expr.id == "b"
+        assert wi.optional_vars is None
+        assert len(wi.body) == 1
+        assert isinstance(wi.body[0], ast.Pass)
 
     def test_class(self):
         for input in ("class X: pass", "class X(): pass"):

Modified: pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/pyparser/data/Grammar2.7	Wed Jun 23 22:03:16 2010
@@ -71,8 +71,8 @@
 	    ['else' ':' suite]
 	    ['finally' ':' suite] |
 	   'finally' ':' suite))
-with_stmt: 'with' test [ with_var ] ':' suite
-with_var: 'as' expr
+with_stmt: 'with' with_item (',' with_item)*  ':' suite
+with_item: test ['as' expr]
 # NB compile.c makes sure that the default except clause is last
 except_clause: 'except' [test [('as' | ',') test]]
 suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

Modified: pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py
==============================================================================
--- pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py	(original)
+++ pypy/branch/fast-forward/pypy/interpreter/test/test_syntax.py	Wed Jun 23 22:03:16 2010
@@ -390,6 +390,30 @@
 
         assert acontext.calls == '__enter__ __exit__'.split()
 
+    def test_compound_with(self):
+        s = """class Context:
+    def __init__(self, var):
+        self.record = []
+        self.var = a
+    def __enter__(self):
+        self.record.append(("__enter__", self.var))
+        return self.var
+    def __exit__(self):
+        self.record.append(("__exit__", self.var))
+c1 = Context("blah")
+c2 = Context("bling")
+with c1 as v1, c2 as v2:
+    pass
+    """
+        ns = {}
+        exec s in ns
+        assert ns["v1"] == "blah"
+        assert ns["v2"] == "bling"
+        assert ns["c1"].record == [("__enter__", "blah"), ("__exit__", "blah")]
+        assert ns["c2"].record == [("__exit___", "bling"),
+                                   ("__exit__", "bling")]
+
+
     def test_start_with_blank_line(self):
         s = """
 if 1:



More information about the Pypy-commit mailing list