[pypy-commit] pypy stacklet: throw().

arigo noreply at buildbot.pypy.org
Fri Aug 19 15:21:40 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: stacklet
Changeset: r46641:3682adb1904e
Date: 2011-08-19 15:25 +0200
http://bitbucket.org/pypy/pypy/changeset/3682adb1904e/

Log:	throw().

diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -41,12 +41,19 @@
     def switch(self, *args):
         "Switch execution to this greenlet, optionally passing the values "
         "given as argument(s).  Returns the value passed when switching back."
+        return self.__switch(_continulet.switch, args)
+
+    def throw(self, typ=GreenletExit, val=None, tb=None):
+        "raise exception in greenlet, return value passed when switching back"
+        return self.__switch(_continulet.throw, typ, val, tb)
+
+    def __switch(self, unbound_method, *args):
         current = getcurrent()
         target = self
         if not target.is_pending() and not target.__main:
             if not target.__started:
-                _continulet.__init__(target, _greenlet_start, args)
-                args = None
+                _continulet.__init__(target, _greenlet_start, *args)
+                args = (None,)
                 target.__started = True
             else:
                 # already done, go to main instead... xxx later
@@ -56,17 +63,18 @@
             if current.__main:
                 if target.__main:
                     # switch from main to main
-                    pass
+                    if unbound_method == _continulet.throw:
+                        raise args[0], args[1], args[2]
                 else:
                     # enter from main to target
-                    args = _continulet.switch(target, args)
+                    args = unbound_method(target, *args)
             else:
                 if target.__main:
                     # leave to go to target=main
-                    args = _continulet.switch(current, args)
+                    args = unbound_method(current, *args)
                 else:
                     # switch from non-main to non-main
-                    args = _continulet.switch(current, args, to=target)
+                    args = unbound_method(current, *args, to=target)
         except GreenletExit, e:
             args = (e,)
         finally:
@@ -77,10 +85,6 @@
         else:
             return args
 
-    def throw(self, typ=GreenletExit, val=None, tb=None):
-        "raise exception in greenlet, return value passed when switching back"
-        XXX
-
     __nonzero__ = _continulet.is_pending
 
     @property
diff --git a/pypy/module/test_lib_pypy/test_greenlet.py b/pypy/module/test_lib_pypy/test_greenlet.py
--- a/pypy/module/test_lib_pypy/test_greenlet.py
+++ b/pypy/module/test_lib_pypy/test_greenlet.py
@@ -81,3 +81,52 @@
         g1 = greenlet(fmain)
         res = g1.switch('foo', 'bar')
         assert isinstance(res, GreenletExit) and res.args == ('foo', 'bar')
+
+    def test_throw_1(self):
+        from greenlet import greenlet
+        gmain = greenlet.getcurrent()
+        #
+        def f():
+            try:
+                gmain.switch()
+            except ValueError:
+                return "ok"
+        #
+        g = greenlet(f)
+        g.switch()
+        res = g.throw(ValueError)
+        assert res == "ok"
+
+    def test_throw_2(self):
+        from greenlet import greenlet
+        gmain = greenlet.getcurrent()
+        #
+        def f():
+            gmain.throw(ValueError)
+        #
+        g = greenlet(f)
+        raises(ValueError, g.switch)
+
+    def test_throw_3(self):
+        from greenlet import greenlet
+        gmain = greenlet.getcurrent()
+        raises(ValueError, gmain.throw, ValueError)
+
+    def test_throw_4(self):
+        from greenlet import greenlet
+        gmain = greenlet.getcurrent()
+        #
+        def f1():
+            g2.throw(ValueError)
+        #
+        def f2():
+            try:
+                gmain.switch()
+            except ValueError:
+                return "ok"
+        #
+        g1 = greenlet(f1)
+        g2 = greenlet(f2)
+        g2.switch()
+        res = g1.switch()
+        assert res == "ok"


More information about the pypy-commit mailing list