[pypy-commit] pypy default: Update this --- support for switch() with keyword arguments --- to the

arigo noreply at buildbot.pypy.org
Fri Jun 28 19:59:49 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r65072:307d5501ecf6
Date: 2013-06-28 19:45 +0200
http://bitbucket.org/pypy/pypy/changeset/307d5501ecf6/

Log:	Update this --- support for switch() with keyword arguments --- to
	the current version of greenlet-for-CPython.

diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -46,16 +46,16 @@
         if parent is not None:
             self.parent = parent
 
-    def switch(self, *args):
+    def switch(self, *args, **kwds):
         "Switch execution to this greenlet, optionally passing the values "
         "given as argument(s).  Returns the value passed when switching back."
-        return self.__switch('switch', args)
+        return self.__switch('switch', (args, kwds))
 
     def throw(self, typ=GreenletExit, val=None, tb=None):
         "raise exception in greenlet, return value passed when switching back"
         return self.__switch('throw', typ, val, tb)
 
-    def __switch(target, methodname, *args):
+    def __switch(target, methodname, *baseargs):
         current = getcurrent()
         #
         while not (target.__main or _continulet.is_pending(target)):
@@ -65,9 +65,9 @@
                     greenlet_func = _greenlet_start
                 else:
                     greenlet_func = _greenlet_throw
-                _continulet.__init__(target, greenlet_func, *args)
+                _continulet.__init__(target, greenlet_func, *baseargs)
                 methodname = 'switch'
-                args = ()
+                baseargs = ()
                 target.__started = True
                 break
             # already done, go to the parent instead
@@ -78,11 +78,15 @@
         #
         try:
             unbound_method = getattr(_continulet, methodname)
-            args = unbound_method(current, *args, to=target)
+            args, kwds = unbound_method(current, *baseargs, to=target)
         finally:
             _tls.current = current
         #
-        if len(args) == 1:
+        if kwds:
+            if args:
+                return args, kwds
+            return kwds
+        elif len(args) == 1:
             return args[0]
         else:
             return args
@@ -128,15 +132,15 @@
     _tls.main = gmain
     _tls.current = gmain
 
-def _greenlet_start(greenlet, args):
+def _greenlet_start(greenlet, (args, kwds)):
     _tls.current = greenlet
     try:
-        res = greenlet.run(*args)
+        res = greenlet.run(*args, **kwds)
     except GreenletExit, e:
         res = e
     finally:
         _continuation.permute(greenlet, greenlet.parent)
-    return (res,)
+    return ((res,), None)
 
 def _greenlet_throw(greenlet, exc, value, tb):
     _tls.current = greenlet
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
@@ -319,3 +319,25 @@
         g = G(lambda: 42)
         x = g.switch()
         assert x == 42
+
+    def test_kwargs_to_f(self):
+        import greenlet
+        seen = []
+        def f(*args, **kwds):
+            seen.append([args, kwds])
+        g = greenlet.greenlet(f)
+        g.switch(1, 2, x=3, y=4)
+        assert seen == [[(1, 2), {'x': 3, 'y': 4}]]
+
+    def test_kwargs_to_switch(self):
+        import greenlet
+        main = greenlet.getcurrent()
+        assert main.switch() == ()
+        assert main.switch(5) == 5
+        assert main.switch(5, 6) == (5, 6)
+        #
+        assert main.switch(x=5) == {'x': 5}
+        assert main.switch(x=5, y=6) == {'x': 5, 'y': 6}
+        assert main.switch(3, x=5) == ((3,), {'x': 5})
+        assert main.switch(3, x=5, y=6) == ((3,), {'x': 5, 'y': 6})
+        assert main.switch(2, 3, x=6) == ((2, 3), {'x': 6})


More information about the pypy-commit mailing list