[pypy-commit] pypy py3.5: Add another test for 'async with', and fix for 'with' or 'async with':

arigo pypy.commits at gmail.com
Sun Jul 1 16:51:21 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r94795:0a4016e8a6bc
Date: 2018-07-01 22:50 +0200
http://bitbucket.org/pypy/pypy/changeset/0a4016e8a6bc/

Log:	Add another test for 'async with', and fix for 'with' or 'async
	with': if they call '__exit__' or '__aexit__' and this returns True,
	we must ignore that if we're processing a return/break/continue
	instead of a real exception.

diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1260,9 +1260,11 @@
 
     def WITH_CLEANUP_FINISH(self, oparg, next_instr):
         w_suppress = self.popvalue()
-        if self.space.is_true(w_suppress):
-            # __exit__() returned True -> Swallow the exception.
-            self.settopvalue(self.space.w_None)
+        w_unroller = self.peekvalue()
+        if isinstance(w_unroller, SApplicationException):
+            if self.space.is_true(w_suppress):
+                # __exit__() returned True -> Swallow the exception.
+                self.settopvalue(self.space.w_None)
         # this is always followed by END_FINALLY
         # in the stack now: [w_unroller-or-w_None..]
 
diff --git a/pypy/interpreter/test/test_coroutine.py b/pypy/interpreter/test/test_coroutine.py
--- a/pypy/interpreter/test/test_coroutine.py
+++ b/pypy/interpreter/test/test_coroutine.py
@@ -112,6 +112,27 @@
         assert seen == ['aenter', 'aexit']
         """
 
+    def test_async_with_exit_True(self): """
+        seen = []
+        class X:
+            async def __aenter__(self):
+                seen.append('aenter')
+            async def __aexit__(self, *args):
+                seen.append('aexit')
+                return True
+        async def f(x):
+            async with x:
+                return 42
+        c = f(X())
+        try:
+            c.send(None)
+        except StopIteration as e:
+            assert e.value == 42
+        else:
+            assert False, "should have raised"
+        assert seen == ['aenter', 'aexit']
+        """
+
     def test_await(self): """
         class X:
             def __await__(self):


More information about the pypy-commit mailing list