pypy / lib_pypy /

Full commit
import _continuation, sys

# ____________________________________________________________
# Exceptions

class GreenletExit(Exception):
    """This special exception does not propagate to the parent greenlet; it
can be used to kill a single greenlet."""

error = _continuation.error

# ____________________________________________________________
# Helper function

def getcurrent():
    "Returns the current greenlet (i.e. the one which called this function)."
        return _tls.current
    except AttributeError:
        # first call in this thread: current == main
        return _tls.current

# ____________________________________________________________
# The 'greenlet' class

_continulet = _continuation.continulet

class greenlet(_continulet):
    getcurrent = staticmethod(getcurrent)
    error = error
    GreenletExit = GreenletExit
    __main = False
    __started = False

    def __new__(cls, *args, **kwds):
        self = _continulet.__new__(cls)
        self.parent = getcurrent()
        return self

    def __init__(self, run=None, parent=None):
        if run is not None:
   = run
        if parent is not None:
            self.parent = parent

    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(target, unbound_method, *args):
        current = getcurrent()
        while not target:
            if not target.__started:
                _continulet.__init__(target, _greenlet_start, *args)
                args = ()
                target.__started = True
            # already done, go to the parent instead
            # (NB. infinite loop possible, but unlikely, unless you mess
            # up the 'parent' explicitly.  Good enough, because a Ctrl-C
            # will show that the program is caught in this loop here.)
            target = target.parent
            if current.__main:
                if target.__main:
                    # switch from main to main
                    if unbound_method == _continulet.throw:
                        raise args[0], args[1], args[2]
                    (args,) = args
                    # enter from main to target
                    args = unbound_method(target, *args)
                if target.__main:
                    # leave to go to target=main
                    args = unbound_method(current, *args)
                    # switch from non-main to non-main
                    args = unbound_method(current, *args, to=target)
        except GreenletExit, e:
            args = (e,)
            _tls.current = current
        if len(args) == 1:
            return args[0]
            return args

    def __nonzero__(self):
        return self.__main or _continulet.is_pending(self)

    def dead(self):
        return self.__started and not self

    def gr_frame(self):
        raise NotImplementedError("attribute 'gr_frame' of greenlet objects")

# ____________________________________________________________
# Internal stuff

    from thread import _local
except ImportError:
    class _local(object):    # assume no threads

_tls = _local()

def _green_create_main():
    # create the main greenlet for this thread
    _tls.current = None
    gmain = greenlet.__new__(greenlet)
    gmain._greenlet__main = True
    gmain._greenlet__started = True
    assert gmain.parent is None
    _tls.main = gmain
    _tls.current = gmain

def _greenlet_start(greenlet, args):
    _tls.current = greenlet
        res =*args)
        if greenlet.parent is not _tls.main:
            _continuation.permute(greenlet, greenlet.parent)
    return (res,)