Commits

Denis Bilenko committed a07213c

reorganize the package; rename timeout to Timeout; Hub's recovering from errors

- all the functions from __init__.py were moved to gevent/greenlet.py; __init__ imports only some of them back
- gevent.timeout is now known as gevent.Timeout
- Hub now tries to recover after dispatch() failures (seen only(?) on epoll even though event_reinit() was called as necessary)
This helps to pass test_socketserver.py all the time, not occasionally like before
- wsgi_test.py: move ssl tests to a separate class
- libevent version checking is gone as its done by gevent.core now

  • Participants
  • Parent commits 623025a

Comments (0)

Files changed (21)

gevent/__init__.py

-import sys
-import os
-import traceback
-
-from gevent import core
-
-try:
-    from py.magic import greenlet
-    Greenlet = greenlet
-except ImportError:
-    import greenlet
-    Greenlet = greenlet.greenlet
-
-getcurrent = greenlet.getcurrent
-GreenletExit = greenlet.GreenletExit
-
 version_info = (0, 9, 1)
 __version__ = '0.9.1'
 
-__all__ = ['Greenlet',
-           'getcurrent',
-           'GreenletExit',
-           'MAIN',
+__all__ = ['getcurrent',
            'TimeoutError',
+           'Timeout',
            'spawn',
            'spawn_later',
            'kill',
-           'get_hub',
            'sleep',
-           'wait_reader',
-           'wait_writer',
-           'timeout',
-           'with_timeout']
+           'signal',
+           'with_timeout',
+           'fork']
 
+# add here Queue, Event, Pipe?, Socket?
 
-libevent_version = core.get_version()
-libevent_headers_version = core.get_header_version()
-if libevent_headers_version is not None and libevent_version != libevent_headers_version:
-    import warnings
-    msg = "version mismatch: system libevent version is %r but this gevent is compiled against %r" % (libevent_version, libevent_headers_version)
-    warnings.warn(msg, UserWarning, stacklevel=2)
+from gevent.greenlet import *
 
 
-_threadlocal = None
-MAIN = greenlet.getcurrent()
-
-def timer(*args, **kwargs):
-    return core.timer(*args, **kwargs)
-
-class TimeoutError(Exception):
-    """Exception raised if an asynchronous operation times out"""
-
-
-def spawn(function, *args, **kwargs):
-    """Create a new greenlet that will run `function(*args)'.
-    The current greenlet won't be unscheduled. Keyword arguments aren't
-    supported (limitation of greenlet), use spawn() to work around that.
-    """
-    g = Greenlet(lambda : function(*args, **kwargs))
-    g.parent = get_hub().greenlet
-    timer(0, g.switch)
-    return g
-
-
-def spawn_later(seconds, function, *args, **kwargs):
-    """Create a new greenlet that will run `function(*args)'.
-    The current greenlet won't be unscheduled. Keyword arguments aren't
-    supported (limitation of greenlet), use spawn() to work around that.
-    """
-    g = Greenlet(lambda : function(*args, **kwargs))
-    g.parent = get_hub().greenlet
-    timer(seconds, g.switch)
-    return g
-
-
-def kill(g, *throw_args):
-    timer(0, g.throw, *throw_args)
-    if getcurrent() is not get_hub().greenlet:
-        sleep(0)
-
-
-def get_hub():
-    global _threadlocal
-    try:
-        hub = _threadlocal.hub
-    except AttributeError:
-        # do not import anything that can be monkey-patched at top level
-        import threading
-        _threadlocal = threading.local()
-        hub = _threadlocal.hub = Hub()
-    return hub
-
-
-def sleep(seconds=0):
-    """Yield control to another eligible coroutine until at least *seconds* have
-    elapsed.
-
-    *seconds* may be specified as an integer, or a float if fractional seconds
-    are desired. Calling sleep with *seconds* of 0 is the canonical way of
-    expressing a cooperative yield. For example, if one is looping over a
-    large list performing an expensive calculation without calling any socket
-    methods, it's a good idea to call ``sleep(0)`` occasionally; otherwise
-    nothing else will run.
-    """
-    hub = get_hub()
-    assert hub.greenlet is not greenlet.getcurrent(), 'do not call blocking functions from the mainloop'
-    t = timer(seconds, greenlet.getcurrent().switch)
-    try:
-        hub.switch()
-    finally:
-        t.cancel()
-
-
-class Hub(object):
-
-    def __init__(self):
-        self.greenlet = Greenlet(self.run)
-        self.keyboard_interrupt_signal = None
-
-    def switch(self):
-        cur = getcurrent()
-        assert cur is not self.greenlet, 'Cannot switch to MAINLOOP from MAINLOOP'
-        switch_out = getattr(cur, 'switch_out', None)
-        if switch_out is not None:
-            try:
-                switch_out()
-            except:
-                traceback.print_exception(*sys.exc_info())
-        if self.greenlet.dead:
-            self.greenlet = Greenlet(self.run)
-        return self.greenlet.switch()
-
-    def run(self, *args, **kwargs):
-        if self.keyboard_interrupt_signal is None:
-            self.keyboard_interrupt_signal = signal(2, MAIN.throw, KeyboardInterrupt)
-        while True:
-            result = core.dispatch()
-            if result>0:
-                return 'Hub.run() has finished because there are no events registered'
-            elif result<0:
-                return 'Hub.run() has finished because there was an error'
-            return result
-
-
-def signal(signalnum, handler, *args, **kwargs):
-    def deliver_exception_to_MAIN():
-        try:
-            handler(*args, **kwargs)
-        except:
-            MAIN.throw(*sys.exc_info())
-    return core.signal(signalnum, deliver_exception_to_MAIN)
-
-def _wait_helper(ev, fd, evtype):
-    current, timeout_exc = ev.arg
-    if evtype & core.EV_TIMEOUT:
-        current.throw(timeout_exc)
-    else:
-        current.switch(ev)
-
-def wait_reader(fileno, timeout=-1, timeout_exc=TimeoutError):
-    evt = core.read(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
-    try:
-        returned_ev = get_hub().switch()
-        assert evt is returned_ev, (evt, returned_ev)
-    finally:
-        evt.cancel()
-
-def wait_writer(fileno, timeout=-1, timeout_exc=TimeoutError):
-    evt = core.write(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
-    try:
-        returned_ev = get_hub().switch()
-        assert evt is returned_ev, (evt, returned_ev)
-    finally:
-        evt.cancel()
-
-
-class _SilentException:
-    pass
-
-
-class timeout(object):
-    """Schedule an exception to raise in the current greenlet (TimeoutError by default).
-
-    Raise an exception in the block after timeout.
-
-    with timeout(seconds[, exc]):
-        ... code block ...
-
-    Assuming code block is yielding (i.e. gives up control to the hub),
-    an exception provided in `exc' argument will be raised
-    (TimeoutError if `exc' is omitted).
-
-    When exc is None, code block is interrupted silently.
-    """
-
-    def __init__(self, seconds, exception=TimeoutError):
-        if exception is None:
-            exception = _SilentException()
-        self.exception = exception
-        if seconds is None:
-            self.timeout = None
-        else:
-            self.timeout = timer(seconds, getcurrent().throw, exception)
-
-    def cancel(self):
-        if self.timeout is not None:
-            self.timeout.cancel()
-
-    def __repr__(self):
-        if self.timeout is not None:
-            return repr(self.timeout)
-        else:
-            return '<fake timeout>'
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, typ, value, tb):
-        self.cancel()
-        if typ is _SilentException and value is self.exception:
-            return True
-
-
-def with_timeout(seconds, func, *args, **kwds):
-    """Wrap a call to some (yielding) function with a timeout; if the called
-    function fails to return before the timeout, cancel it and return a flag
-    value.
-
-    seconds
-      (int or float) seconds before timeout occurs
-    func
-      the callable to execute with a timeout; must be one of the functions
-      that implicitly or explicitly yields
-    \*args, \*\*kwds
-      (positional, keyword) arguments to pass to *func*
-    timeout_value=
-      value to return if timeout occurs (default raise ``TimeoutError``)
-
-    **Returns**:
-
-    Value returned by *func* if *func* returns before *seconds*, else
-    *timeout_value* if provided, else raise ``TimeoutError``
-
-    **Raises**:
-
-    Any exception raised by *func*, and ``TimeoutError`` if *func* times out
-    and no ``timeout_value`` has been provided.
-
-    **Example**::
-
-      data = with_timeout(30, httpc.get, 'http://www.google.com/', timeout_value="")
-
-    Here *data* is either the result of the ``get()`` call, or the empty string if
-    it took too long to return. Any exception raised by the ``get()`` call is
-    passed through to the caller.
-    """
-    # Recognize a specific keyword argument, while also allowing pass-through
-    # of any other keyword arguments accepted by func. Use pop() so we don't
-    # pass timeout_value through to func().
-    has_timeout_value = "timeout_value" in kwds
-    timeout_value = kwds.pop("timeout_value", None)
-    error = TimeoutError()
-    timer = timeout(seconds, error)
-    try:
-        try:
-            return func(*args, **kwds)
-        except TimeoutError, ex:
-            if ex is error and has_timeout_value:
-                return timeout_value
-            raise
-    finally:
-        timer.cancel()
-
-_original_fork = os.fork
-
-def fork():
-    result = _original_fork()
-    core.reinit()
-    return result
-

gevent/backdoor.py

 import sys
 from code import InteractiveConsole
 
-import gevent
+from gevent.greenlet import Greenlet
+from gevent import core
 
 try:
     sys.ps1
     sys.ps2 = '... '
 
 
-class SocketConsole(gevent.Greenlet):
+class SocketConsole(Greenlet):
     def __init__(self, desc, hostport, locals):
         self.hostport = hostport
         self.locals = locals
                 self.old[key] = getattr(desc, key)
             setattr(desc, key, value)
 
-        gevent.Greenlet.__init__(self)
+        Greenlet.__init__(self)
 
     def run(self):
         try:
     def switch(self, *args, **kw):
         self.saved = sys.stdin, sys.stderr, sys.stdout
         sys.stdin = sys.stdout = sys.stderr = self.desc
-        gevent.Greenlet.switch(self, *args, **kw)
+        Greenlet.switch(self, *args, **kw)
 
     def switch_out(self):
         sys.stdin, sys.stderr, sys.stdout = self.saved
                 fl = conn.makeGreenFile("rw")
                 fl.newlines = '\n'
                 greenlet = SocketConsole(fl, (host, port), locals)
-                gevent.timer(0, greenlet.switch)
+                core.timer(0, greenlet.switch)
         except socket.error, e:
             # Broken pipe means it was shutdown
             if e[0] != 32:
     fl = conn.makeGreenFile("rw")
     fl.newlines = '\n'
     greenlet = SocketConsole(fl, (host, port), locals)
-    gevent.timer(0, greenlet.switch)
+    core.timer(0, greenlet.switch)
 
 
 if __name__ == '__main__':
 import time
 import traceback
 
-import gevent
-from gevent import get_hub, spawn, getcurrent, sleep
+from gevent.core import timer
+from gevent.greenlet import get_hub, spawn, getcurrent, sleep
 
 
 class Cancelled(RuntimeError):
             exc = (exc, )
         self._exc = exc
         if self._waiters:
-            gevent.timer(0, self._do_send, self._result, self._exc, self._waiters.copy())
+            timer(0, self._do_send, self._result, self._exc, self._waiters.copy())
 
     def _do_send(self, result, exc, waiters):
         while waiters:
         # `blocking' parameter is for consistency with BoundedSemaphore and is ignored
         self.counter += 1
         if self._waiters:
-            gevent.timer(0, self._do_acquire)
+            timer(0, self._do_acquire)
         return True
 
     def _do_acquire(self):
             exc = (exc, )
         self.items.append((result, exc))
         if self._waiters and self._timer is None:
-            self._timer = gevent.timer(0, self._do_send)
+            self._timer = timer(0, self._do_send)
 
     def send_exception(self, *args):
         # the arguments are the same as for greenlet.throw
         if getcurrent() is get_hub().greenlet:
             self.items.append((result, exc))
             if self._waiters and self._timer is None:
-                self._timer = gevent.timer(0, self._do_switch)
+                self._timer = timer(0, self._do_switch)
         else:
             if self._waiters and self._senders:
                 sleep(0)
             # note that send() does not work well with timeouts. if your timeout fires
             # after this point, the item will remain in the queue
             if self._waiters and self._timer is None:
-                self._timer = gevent.timer(0, self._do_switch)
+                self._timer = timer(0, self._do_switch)
             if len(self.items) > self.max_size:
                 self._senders.add(getcurrent())
                 try:
         if self.items:
             result, exc = self.items.popleft()
             if len(self.items) <= self.max_size and self._timer is None:
-                self._timer = gevent.timer(0, self._do_switch)
+                self._timer = timer(0, self._do_switch)
             if exc is None:
                 return result
             else:
                 getcurrent().throw(*exc)
         else:
             if self._senders and self._timer is None:
-                self._timer = gevent.timer(0, self._do_switch)
+                self._timer = timer(0, self._do_switch)
             self._waiters.add(getcurrent())
             try:
                 result, exc = get_hub().switch()

gevent/greenlet.py

+import sys
+import os
+import traceback
+from gevent import core
+
+__all__ = ['getcurrent',
+           'TimeoutError',
+           'Timeout',
+           'spawn',
+           'spawn_later',
+           'kill',
+           'killall',
+           'sleep',
+           'signal',
+           'with_timeout',
+           'fork']
+
+try:
+    from py.magic import greenlet
+    Greenlet = greenlet
+except ImportError:
+    greenlet = __import__('greenlet')
+    Greenlet = greenlet.greenlet
+
+getcurrent = greenlet.getcurrent
+GreenletExit = greenlet.GreenletExit
+MAIN = greenlet.getcurrent()
+_threadlocal = None
+
+class TimeoutError(Exception):
+    """Exception raised if an asynchronous operation times out"""
+
+
+def spawn(function, *args, **kwargs):
+    g = Greenlet(lambda : function(*args, **kwargs))
+    g.parent = get_hub().greenlet
+    core.timer(0, g.switch)
+    return g
+
+
+def spawn_later(seconds, function, *args, **kwargs):
+    g = Greenlet(lambda : function(*args, **kwargs))
+    g.parent = get_hub().greenlet
+    core.timer(seconds, g.switch)
+    return g
+
+
+def kill(g, *throw_args):
+    core.timer(0, g.throw, *throw_args)
+    if get_hub().greenlet is not getcurrent():
+        sleep()
+
+
+def killall(greenlets, *throw_args):
+    for g in greenlets:
+        if not g.dead:
+            core.timer(0, g.throw, *throw_args)
+    if get_hub().greenlet is not getcurrent():
+        sleep()
+
+
+def sleep(seconds=0):
+    """Yield control to another eligible coroutine until at least *seconds* have
+    elapsed.
+
+    *seconds* may be specified as an integer, or a float if fractional seconds
+    are desired. Calling sleep with *seconds* of 0 is the canonical way of
+    expressing a cooperative yield. For example, if one is looping over a
+    large list performing an expensive calculation without calling any socket
+    methods, it's a good idea to call ``sleep(0)`` occasionally; otherwise
+    nothing else will run.
+    """
+    hub = get_hub()
+    assert hub.greenlet is not greenlet.getcurrent(), 'do not call blocking functions from the mainloop'
+    t = core.timer(seconds, greenlet.getcurrent().switch)
+    try:
+        hub.switch()
+    finally:
+        t.cancel()
+
+
+def signal(signalnum, handler, *args, **kwargs):
+    def deliver_exception_to_MAIN():
+        try:
+            handler(*args, **kwargs)
+        except:
+            MAIN.throw(*sys.exc_info())
+    return core.signal(signalnum, deliver_exception_to_MAIN)
+
+
+
+def get_hub():
+    global _threadlocal
+    try:
+        hub = _threadlocal.hub
+    except AttributeError:
+        # do not import anything that can be monkey-patched at top level
+        import threading
+        # XXX use _local directly from _thread or from _threadlocal
+        _threadlocal = threading.local()
+        hub = _threadlocal.hub = Hub()
+    return hub
+
+
+class Hub(object):
+
+    def __init__(self):
+        self.greenlet = Greenlet(self.run)
+        self.keyboard_interrupt_signal = None
+
+    def switch(self):
+        cur = getcurrent()
+        assert cur is not self.greenlet, 'Cannot switch to MAINLOOP from MAINLOOP'
+        switch_out = getattr(cur, 'switch_out', None)
+        if switch_out is not None:
+            try:
+                switch_out()
+            except:
+                traceback.print_exception(*sys.exc_info())
+        if self.greenlet.dead:
+            self.greenlet = Greenlet(self.run)
+        return self.greenlet.switch()
+
+    def run(self):
+        if self.keyboard_interrupt_signal is None:
+            self.keyboard_interrupt_signal = signal(2, MAIN.throw, KeyboardInterrupt)
+        loop_count = 0
+        while True:
+            try:
+                result = core.dispatch()
+            except IOError, ex:
+                loop_count += 1
+                if loop_count > 100:
+                    raise
+                sys.stderr.write('Restarting gevent.core.dispatch() after an error [%s]: %s\n' % (loop_count, ex))
+                continue
+            if result>0:
+                return 'Hub.run() has finished because there are no events registered'
+            elif result<0:
+                return 'Hub.run() has finished because there was an error'
+            return result
+
+
+def _wait_helper(ev, fd, evtype):
+    current, timeout_exc = ev.arg
+    if evtype & core.EV_TIMEOUT:
+        current.throw(timeout_exc)
+    else:
+        current.switch(ev)
+
+
+def wait_reader(fileno, timeout=-1, timeout_exc=TimeoutError):
+    evt = core.read(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
+    try:
+        returned_ev = get_hub().switch()
+        assert evt is returned_ev, (evt, returned_ev)
+    finally:
+        evt.cancel()
+
+
+def wait_writer(fileno, timeout=-1, timeout_exc=TimeoutError):
+    evt = core.write(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc))
+    try:
+        returned_ev = get_hub().switch()
+        assert evt is returned_ev, (evt, returned_ev)
+    finally:
+        evt.cancel()
+
+
+class _SilentException:
+    pass
+
+
+class Timeout(object):
+    """Schedule an exception to raise in the current greenlet (TimeoutError by default).
+
+    Raise an exception in the block after timeout.
+
+    with Timeout(seconds[, exc]):
+        ... code block ...
+
+    Assuming code block is yielding (i.e. gives up control to the hub),
+    an exception provided in `exc' argument will be raised
+    (TimeoutError if `exc' is omitted).
+
+    When exc is None, code block is interrupted silently.
+    """
+
+    def __init__(self, seconds, exception=TimeoutError):
+        if exception is None:
+            exception = _SilentException()
+        self.exception = exception
+        if seconds is None:
+            self.timeout = None
+        else:
+            self.timeout = core.timer(seconds, getcurrent().throw, exception)
+
+    def cancel(self):
+        if self.timeout is not None:
+            self.timeout.cancel()
+
+    def __repr__(self):
+        if self.timeout is not None:
+            return repr(self.timeout)
+        else:
+            return '<fake timeout>'
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, typ, value, tb):
+        self.cancel()
+        if typ is _SilentException and value is self.exception:
+            return True
+
+# use this? less prone to errors (what if func has timeout_value argument or func is with_timeout itself?)
+# def with_timeout(seconds, func[, args[, kwds[, timeout_value]]]):
+# see what other similar standard library functions accept as params (start_new_thread, start new process)
+
+def with_timeout(seconds, func, *args, **kwds):
+    """Wrap a call to some (yielding) function with a timeout; if the called
+    function fails to return before the timeout, cancel it and return a flag
+    value.
+
+    seconds
+      (int or float) seconds before timeout occurs
+    func
+      the callable to execute with a timeout; must be one of the functions
+      that implicitly or explicitly yields
+    \*args, \*\*kwds
+      (positional, keyword) arguments to pass to *func*
+    timeout_value=
+      value to return if timeout occurs (default raise ``TimeoutError``)
+
+    **Returns**:
+
+    Value returned by *func* if *func* returns before *seconds*, else
+    *timeout_value* if provided, else raise ``TimeoutError``
+
+    **Raises**:
+
+    Any exception raised by *func*, and ``TimeoutError`` if *func* times out
+    and no ``timeout_value`` has been provided.
+
+    **Example**::
+
+      data = with_timeout(30, httpc.get, 'http://www.google.com/', timeout_value="")
+
+    Here *data* is either the result of the ``get()`` call, or the empty string if
+    it took too long to return. Any exception raised by the ``get()`` call is
+    passed through to the caller.
+    """
+    # Recognize a specific keyword argument, while also allowing pass-through
+    # of any other keyword arguments accepted by func. Use pop() so we don't
+    # pass timeout_value through to func().
+    has_timeout_value = "timeout_value" in kwds
+    timeout_value = kwds.pop("timeout_value", None)
+    error = TimeoutError()
+    timeout = Timeout(seconds, error)
+    try:
+        try:
+            return func(*args, **kwds)
+        except TimeoutError, ex:
+            if ex is error and has_timeout_value:
+                return timeout_value
+            raise
+    finally:
+        timeout.cancel()
+
+
+_original_fork = os.fork
+
+def fork():
+    result = _original_fork()
+    core.reinit()
+    return result
+
 import sys
 
 def patch_os():
-    from gevent import fork
+    from gevent.greenlet import fork
     import os
     os.fork = fork
 
 def patch_time():
-    from gevent import sleep
+    from gevent.greenlet import sleep
     _time = __import__('time')
     _time.sleep = sleep
 
 >>> p = spawn(demofunc, 1, 0)
 >>> _ = p.link_exception()
 >>> try:
-...     gevent.sleep(1)
+...     greenlet.sleep(1)
 ... except LinkedFailed:
 ...     print 'LinkedFailed'
 LinkedFailed
 and wait for all them to complete. Such function is provided by this module.
 """
 import sys
-import gevent
-from gevent import coros
+from gevent import coros, greenlet, core
 
 __all__ = ['LinkedExited',
            'LinkedFailed',
     msg = """%r was killed with %s"""
 
 def getLinkedFailed(name, typ, value=None, tb=None):
-    if issubclass(typ, gevent.GreenletExit):
+    if issubclass(typ, greenlet.GreenletExit):
         return LinkedKilled(name, typ, value, tb)
     return LinkedFailed(name, typ, value, tb)
 
 
-class ProcExit(gevent.GreenletExit):
+class ProcExit(greenlet.GreenletExit):
     """Raised when this proc is killed."""
 
 
         self._event.send((self._tag, value))
 
 
-def killall(procs, *throw_args, **kwargs):
+def killall(procs, *throw_args):
     if not throw_args:
         throw_args = (ProcExit, )
-    wait = kwargs.pop('wait', False)
-    if kwargs:
-        raise TypeError('Invalid keyword argument for proc.killall(): %s' % ', '.join(kwargs.keys()))
     for g in procs:
         if not g.dead:
-            gevent.timer(0, g.throw, *throw_args)
-    if wait and gevent.getcurrent() is not gevent.get_hub().greenlet:
-        gevent.sleep(0)
+            core.timer(0, g.throw, *throw_args)
 
 
 class NotUsed(object):
     The current greenlet won't be unscheduled. Keyword arguments aren't
     supported (limitation of greenlet), use spawn() to work around that.
     """
-    g = gevent.Greenlet(function)
-    g.parent = gevent.get_hub().greenlet
-    gevent.timer(0, g.switch, *args)
+    g = greenlet.Greenlet(function)
+    g.parent = greenlet.get_hub().greenlet
+    core.timer(0, g.switch, *args)
     return g
 
 
         if self.ready() and self._exc is not None:
             return
         if listener is None:
-            listener = gevent.getcurrent()
+            listener = greenlet.getcurrent()
         if link is None:
             link = self.getLink(listener)
-        if self.ready() and listener is gevent.getcurrent():
+        if self.ready() and listener is greenlet.getcurrent():
             link(self)
         else:
             self._value_links[listener] = link
         if self.value is not _NOT_USED and self._exc is None:
             return
         if listener is None:
-            listener = gevent.getcurrent()
+            listener = greenlet.getcurrent()
         if link is None:
             link = self.getLink(listener)
-        if self.ready() and listener is gevent.getcurrent():
+        if self.ready() and listener is greenlet.getcurrent():
             link(self)
         else:
             self._exception_links[listener] = link
 
     def link(self, listener=None, link=None):
         if listener is None:
-            listener = gevent.getcurrent()
+            listener = greenlet.getcurrent()
         if link is None:
             link = self.getLink(listener)
-        if self.ready() and listener is gevent.getcurrent():
+        if self.ready() and listener is greenlet.getcurrent():
             if self._exc is None:
                 link(self)
             else:
 
     def unlink(self, listener=None):
         if listener is None:
-            listener = gevent.getcurrent()
+            listener = greenlet.getcurrent()
         self._value_links.pop(listener, None)
         self._exception_links.pop(listener, None)
 
         self._start_send()
 
     def _start_send(self):
-        gevent.timer(0, self._do_send, self._value_links.items(), self._value_links)
+        core.timer(0, self._do_send, self._value_links.items(), self._value_links)
 
     def send_exception(self, *throw_args):
         assert not self.ready(), "%s has been fired already" % self
         self._start_send_exception()
 
     def _start_send_exception(self):
-        gevent.timer(0, self._do_send, self._exception_links.items(), self._exception_links)
+        core.timer(0, self._do_send, self._exception_links.items(), self._exception_links)
 
     def _do_send(self, links, consult):
         while links:
                     finally:
                         consult.pop(listener, None)
             except:
-                gevent.timer(0, self._do_send, links, consult)
+                core.timer(0, self._do_send, links, consult)
                 raise
 
     def wait(self, timeout=None, *throw_args):
             if self._exc is None:
                 return self.value
             else:
-                gevent.getcurrent().throw(*self._exc)
+                greenlet.getcurrent().throw(*self._exc)
         if timeout is not None:
-            timer = gevent.timeout(timeout, *throw_args)
+            timer = greenlet.Timeout(timeout, *throw_args)
             timer.__enter__()
             if timeout==0:
                 if timer.__exit__(None, None, None):
                     return
                 else:
                     try:
-                        gevent.getcurrent().throw(timer.exception)
+                        greenlet.getcurrent().throw(timer.exception)
                     except:
                         if not timer.__exit__(*sys.exc_info()):
                             raise
         """Wake up the greenlet that is calling wait() currently (if there is one).
         Can only be called from get_hub().greenlet.
         """
-        assert gevent.getcurrent() is gevent.get_hub().greenlet
+        assert greenlet.getcurrent() is greenlet.get_hub().greenlet
         if self.greenlet is not None:
             self.greenlet.switch(value)
 
     def send_exception(self, *throw_args):
         """Make greenlet calling wait() wake up (if there is a wait()).
-        Can only be called from gevent.get_hub().greenlet.
+        Can only be called from greenlet.get_hub().greenlet.
         """
-        assert gevent.getcurrent() is gevent.get_hub().greenlet
+        assert greenlet.getcurrent() is greenlet.get_hub().greenlet
         if self.greenlet is not None:
             self.greenlet.throw(*throw_args)
 
         into send() or raise exception passed into send_exception().
         """
         assert self.greenlet is None
-        current = gevent.getcurrent()
-        assert current is not gevent.get_hub().greenlet
+        current = greenlet.getcurrent()
+        assert current is not greenlet.get_hub().greenlet
         self.greenlet = current
         try:
-            return gevent.get_hub().switch()
+            return greenlet.get_hub().switch()
         finally:
             self.greenlet = None
 
         if not self.dead:
             if not throw_args:
                 throw_args = (ProcExit, )
-            gevent.timer(0, self.greenlet.throw, *throw_args)
-            if gevent.getcurrent() is not gevent.get_hub().greenlet:
-                gevent.sleep(0)
+            core.timer(0, self.greenlet.throw, *throw_args)
+            if greenlet.getcurrent() is not greenlet.get_hub().greenlet:
+                greenlet.sleep(0)
 
     # QQQ maybe Proc should not inherit from Source (because its send() and send_exception()
     # QQQ methods are for internal use only)
         return len(self.procs)
 
     def __contains__(self, item):
-        if isinstance(item, gevent.Greenlet):
+        if isinstance(item, greenlet.Greenlet):
             # special case for "getcurrent() in running_proc_set" to work
             for x in self.procs:
                 if x.greenlet == item:
         """
         # if reentering an empty pool, don't try to wait on a coroutine freeing
         # itself -- instead, just execute in the current coroutine
-        if self.sem.locked() and gevent.getcurrent() in self.procs:
+        if self.sem.locked() and greenlet.getcurrent() in self.procs:
             p = spawn(func, *args, **kwargs)
             try:
                 p.wait()
 from __future__ import with_statement
 from Queue import Full, Empty
-import gevent
+from gevent.greenlet import Timeout
 from gevent import coros
 
 
             else:
                 if timeout < 0:
                     raise ValueError("'timeout' must be a positive number")
-                with gevent.timeout(timeout, Full):
+                with Timeout(timeout, Full):
                     # XXX even if timeout fires, item ends up in a queue anyway, because
                     # Channel.send is not transactional
                     return self.q.send(item)
             elif timeout < 0:
                 raise ValueError("'timeout' must be a positive number")
             else:
-                with gevent.timeout(timeout, Empty):
+                with Timeout(timeout, Empty):
                     return self.q.wait()
         else:
             if not self.q:
-import gevent
-from gevent import core
+from gevent import core, greenlet
 
 def get_fileno(obj):
     try:
 
 
 def select(read_list, write_list, error_list, t=None):
-    hub = gevent.get_hub()
+    hub = greenlet.get_hub()
     t = None
-    current = gevent.getcurrent()
+    current = greenlet.getcurrent()
     assert hub.greenlet is not current, 'do not call blocking functions from the mainloop'
     allevents = []
 
         allevents.append(core.write(get_fileno(r), callback, arg=w))
 
     if t is not None:
-        t = gevent.timeout(t)
+        t = greenlet.Timeout(t)
     try:
         try:
-            return hub.switch()
-        except gevent.TimeoutError:
+            result = hub.switch()
+        except greenlet.TimeoutError:
             return [], [], []
         if hasattr(result, '__len__') and len(result)==3:
             return result
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
-from gevent import wait_reader, wait_writer, spawn
-
-BUFFER_SIZE = 4096
-
-import errno
-import os
-import time
-from errno import EAGAIN
-
 __all__ = ['GreenSocket', 'GreenFile', 'GreenPipe']
 
 import _socket
 _fileobject = __socket__._fileobject
 sslerror = __socket__.sslerror
 
+import errno
+import os
+import time
+from errno import EAGAIN
+
+from gevent.greenlet import wait_reader, wait_writer, spawn
+
+BUFFER_SIZE = 4096
+
 try:
     from OpenSSL import SSL
 except ImportError:
 """implements standard module 'thread' with greenlets"""
 __thread = __import__('thread')
-from gevent import spawn, getcurrent, GreenletExit
+from gevent.greenlet import spawn, getcurrent, GreenletExit
 from gevent.coros import Semaphore as LockType
 
 def get_ident(gr=None):

greentest/__init__.py

 import errno
 import unittest
 import gevent
+from gevent.greenlet import get_hub
 
 disabled_marker = '-*-*-*-*-*- disabled -*-*-*-*-*-'
 def exit_disabled():
 
     __timeout__ = 1
     __switch_check__ = True
+    _switch_count = None
 
     def disable_switch_check(self):
         self._switch_count = None
         gevent.sleep(0) # switch at least once to setup signal handlers
         if hasattr(core, '_event_count'):
             self._event_count = (core._event_count(), core._event_count_active())
-        self._switch_count = gevent.get_hub().switch_count
-        self._timer = gevent.timeout(self.__timeout__, RuntimeError('test is taking too long'))
+        if hasattr(get_hub(), 'switch_count'):
+            self._switch_count = get_hub().switch_count
+        self._timer = gevent.Timeout(self.__timeout__, RuntimeError('test is taking too long'))
 
     def tearDown(self):
         if hasattr(self, '_timer'):
             self._timer.cancel()
-            if self.__switch_check__ and self._switch_count is not None and gevent.get_hub().switch_count <= self._switch_count:
-                sys.stderr.write('WARNING: %s.%s did not switch\n' % (type(self).__name__, self._testMethodName))
+            if self.__switch_check__ and self._switch_count is not None and hasattr(get_hub(), 'switch_count') and get_hub().switch_count <= self._switch_count:
+                name = getattr(self, '_testMethodName', '') # 2.4 does not have it
+                sys.stderr.write('WARNING: %s.%s did not switch\n' % (type(self).__name__, name))
             from gevent import core
             if hasattr(core, '_event_count'):
                 event_count = (core._event_count(), core._event_count_active())
 
 main = unittest.main
 
-_original_Hub = gevent.Hub
+_original_Hub = gevent.greenlet.Hub
 
 class CountingHub(_original_Hub):
 
         self.switch_count += 1
         return _original_Hub.switch(self)
 
-gevent.Hub = CountingHub
+gevent.greenlet.Hub = CountingHub

greentest/api_test.py

 from greentest import TestCase, main
 
 import gevent
+from gevent import greenlet
 from gevent import socket
 
 
         try:
             desc = socket.GreenSocket()
             desc.connect(('127.0.0.1', bound_port))
-            gevent.wait_reader(desc.fileno(), timeout=0.1)
+            greenlet.wait_reader(desc.fileno(), timeout=0.1)
         except gevent.TimeoutError:
             pass # test passed
         else:
             desc = socket.GreenSocket()
             desc.connect(('127.0.0.1', bound_port))
             try:
-                gevent.wait_reader(desc.fileno(), timeout=0.1)
+                greenlet.wait_reader(desc.fileno(), timeout=0.1)
             except gevent.TimeoutError:
                 assert False, "Timed out"
 
         try:
             # try and get some data off of this pipe
             # but bail before any is sent
-            gevent.timeout(0.01)
+            gevent.Timeout(0.01)
             _c = wrap_rfile.read(1)
             self.fail()
         except gevent.TimeoutError:

greentest/coros_test.py

         self.assertRaises(RuntimeError, evt.wait)
         evt.reset()
         # shouldn't see the RuntimeError again
-        gevent.timeout(0.001, gevent.TimeoutError('from test_double_exception'))
+        gevent.Timeout(0.001, gevent.TimeoutError('from test_double_exception'))
         self.assertRaises(gevent.TimeoutError, evt.wait)
 
 

greentest/greenio_test.py

 
 
     def test_del_closes_socket(self):
-        timer = gevent.timeout(0.5)
+        timer = gevent.Timeout(0.5)
         def accept_once(listener):
             # delete/overwrite the original conn
             # object, only keeping the file object around

greentest/test__api.py

 
 import greentest
 import gevent
+from gevent import core
 
 DELAY = 0.1
 
     def test_timer_fired(self):
 
         def func():
-            gevent.timer(0.1, self.lst.pop)
+            core.timer(0.1, self.lst.pop)
             gevent.sleep(0.2)
 
         gevent.spawn(func)

greentest/test__api_timeout.py

 import greentest
 import weakref
 import time
-from gevent import sleep, timeout, TimeoutError, _SilentException
+from gevent import sleep, Timeout, TimeoutError
+from gevent.greenlet import _SilentException
 DELAY = 0.04
 
 class Error(Exception):
 
     def test_api(self):
         # Nothing happens if with-block finishes before the timeout expires
-        with timeout(DELAY*2):
+        with Timeout(DELAY*2):
             sleep(DELAY)
         sleep(DELAY*2) # check if timer was actually cancelled
 
         # An exception will be raised if it's not
         try:
-            with timeout(DELAY):
+            with Timeout(DELAY):
                 sleep(DELAY*2)
         except TimeoutError:
             pass
 
         # You can customize the exception raised:
         try:
-            with timeout(DELAY, IOError("Operation takes way too long")):
+            with Timeout(DELAY, IOError("Operation takes way too long")):
                 sleep(DELAY*2)
         except IOError, ex:
             assert str(ex)=="Operation takes way too long", repr(ex)
 
         # Providing classes instead of values should be possible too:
         try:
-            with timeout(DELAY, ValueError):
+            with Timeout(DELAY, ValueError):
                 sleep(DELAY*2)
         except ValueError:
             pass
             1/0
         except:
             try:
-                with timeout(DELAY, sys.exc_info()[0]):
+                with Timeout(DELAY, sys.exc_info()[0]):
                     sleep(DELAY*2)
                     raise AssertionError('should not get there')
                 raise AssertionError('should not get there')
             raise AssertionError('should not get there')
 
         # It's possible to cancel the timer inside the block:
-        with timeout(DELAY) as timer:
+        with Timeout(DELAY) as timer:
             timer.cancel()
             sleep(DELAY*2)
 
         # outside.
         XDELAY=0.1
         start = time.time()
-        with timeout(XDELAY, None):
+        with Timeout(XDELAY, None):
             sleep(XDELAY*2)
         delta = (time.time()-start)
         assert delta<XDELAY*2, delta
 
         # passing None as seconds disables the timer
-        with timeout(None):
+        with Timeout(None):
             sleep(DELAY)
         sleep(DELAY)
 
     def test_ref(self):
         err = Error()
         err_ref = weakref.ref(err)
-        with timeout(DELAY*2, err):
+        with Timeout(DELAY*2, err):
             sleep(DELAY)
         del err
         assert not err_ref(), repr(err_ref())
 
     def test_nested_timeout(self):
-        with timeout(DELAY, None):
-            with timeout(DELAY*2, None):
+        with Timeout(DELAY, None):
+            with Timeout(DELAY*2, None):
                 sleep(DELAY*3)
             raise AssertionError('should not get there')
 
-        with timeout(DELAY, _SilentException()):
-            with timeout(DELAY*2, _SilentException()):
+        with Timeout(DELAY, _SilentException()):
+            with Timeout(DELAY*2, _SilentException()):
                 sleep(DELAY*3)
             raise AssertionError('should not get there')
 
+
         # this case fails and there's no intent to fix it.
         # just don't do it like that
-        #with timeout(DELAY, _SilentException):
-        #    with timeout(DELAY*2, _SilentException):
+        #with Timeout(DELAY, _SilentException):
+        #    with Timeout(DELAY*2, _SilentException):
         #        sleep(DELAY*3)
         #    assert False, 'should not get there'
 

greentest/test__coros_queue.py

     def test_send_last(self):
         q = coros.Queue()
         def waiter(q):
-            timer = gevent.timeout(0.1, gevent.TimeoutError)
+            timer = gevent.Timeout(0.1, gevent.TimeoutError)
             self.assertEquals(q.wait(), 'hi2')
             timer.cancel()
 
         results = set()
         def collect_pending_results():
             for i, e in enumerate(evts):
-                timer = gevent.timeout(0.001, gevent.TimeoutError)
+                timer = gevent.Timeout(0.001, gevent.TimeoutError)
                 try:
                     x = e.wait()
                     results.add(x)
         q = coros.Queue()
 
         def do_receive(q, evt):
-            gevent.timeout(0, RuntimeError())
+            gevent.Timeout(0, RuntimeError())
             try:
                 result = q.wait()
                 evt.send(result)
         def waiter(q, evt):
             evt.send(q.wait())
         def do_receive(q, evt):
-            gevent.timeout(0, RuntimeError())
+            gevent.Timeout(0, RuntimeError())
             try:
                 result = q.wait()
                 evt.send(result)
 
     def test_two_bogus_waiters(self):
         def do_receive(q, evt):
-            gevent.timeout(0, RuntimeError())
+            gevent.Timeout(0, RuntimeError())
             try:
                 result = q.wait()
                 evt.send(result)

greentest/test__event.py

 
 import greentest
 from gevent.coros import event
-from gevent import spawn, sleep, timeout, with_timeout
+from gevent import spawn, sleep, Timeout, with_timeout
 from greentest import TestCase
 
 DELAY= 0.01
         event2 = event()
 
         spawn(event1.send, 'hello event1')
-        timeout(0, ValueError('interrupted'))
+        Timeout(0, ValueError('interrupted'))
         try:
             result = event1.wait()
         except ValueError:

greentest/test__hub.py

 import greentest
 import time
 import gevent
+from gevent import core
 from gevent import socket
 
 DELAY = 0.1
 
     def test_global(self):
         lst = [1]
-        gevent.spawn(gevent.timer, DELAY, lst.pop)
+        gevent.spawn(core.timer, DELAY, lst.pop)
         gevent.sleep(DELAY*2)
         assert lst == [], lst
 
     def test(self):
         try:
             sock = socket.socket()
-            gevent.timer(0, sock.close)
+            core.timer(0, sock.close)
             sock.connect(('python.org', 81))
         except Exception:
             gevent.sleep(0)
         def fail():
             1/0
 
-        gevent.timer(0, fail)
+        core.timer(0, fail)
 
         start = time.time()
         gevent.sleep(DELAY)

greentest/test__proc_pool.py

             gevent.sleep(0)
             self.assertEqual(pool.free_count(), 1)
             # shouldn't block when trying to get
-            t = gevent.timeout(0.1)
+            t = gevent.Timeout(0.1)
             try:
                 pool.execute(gevent.sleep, 1)
             finally:

greentest/wsgi_test.py

 
         fd = sock.makeGreenFile()
         fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
-        cancel = gevent.timeout(1, RuntimeError)
+        cancel = gevent.Timeout(1, RuntimeError)
         self.assertRaises(TypeError, fd.read, "This shouldn't work")
         cancel.cancel()
         fd.close()
             chunklen = int(fd.readline(), 16)
         self.assert_(chunks > 1)
 
-    def test_012_ssl_server(self):
-        def wsgi_app(environ, start_response):
-            start_response('200 OK', {})
-            return [environ['wsgi.input'].read()]
-
-        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-
-        sock = socket.ssl_listener(('', 4201), certificate_file, private_key_file)
-
-        g = gevent.spawn(wsgi.server, sock, wsgi_app)
-        try:
-            req = HTTPRequest("https://localhost:4201/foo", method="POST", data='abc')
-            f = urllib2.urlopen(req)
-            result = f.read()
-            self.assertEquals(result, 'abc')
-        finally:
-            gevent.kill(g)
-
-    def test_013_empty_return(self):
-        def wsgi_app(environ, start_response):
-            start_response("200 OK", [])
-            return [""]
-
-        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
-        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
-        sock = socket.ssl_listener(('', 4202), certificate_file, private_key_file)
-        g = gevent.spawn(wsgi.server, sock, wsgi_app)
-        try:
-            req = HTTPRequest("https://localhost:4202/foo")
-            f = urllib2.urlopen(req)
-            result = f.read()
-            self.assertEquals(result, '')
-        finally:
-            gevent.kill(g)
-
     def test_014_chunked_post(self):
         self.site.application = chunked_post
         sock = socket.connect_tcp(('127.0.0.1', 12346))
         self.assert_(headers['transfer-encoding'] == 'chunked')
 
 
+class TestHttps(TestCase):
+    mode = 'static'
+
+    def test_012_ssl_server(self):
+        def wsgi_app(environ, start_response):
+            start_response('200 OK', {})
+            return [environ['wsgi.input'].read()]
+
+        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
+        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
+
+        sock = socket.ssl_listener(('', 4201), certificate_file, private_key_file)
+
+        g = gevent.spawn(wsgi.server, sock, wsgi_app)
+        try:
+            req = HTTPRequest("https://localhost:4201/foo", method="POST", data='abc')
+            f = urllib2.urlopen(req)
+            result = f.read()
+            self.assertEquals(result, 'abc')
+        finally:
+            gevent.kill(g)
+
+    def test_013_empty_return(self):
+        def wsgi_app(environ, start_response):
+            start_response("200 OK", [])
+            return [""]
+
+        certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt')
+        private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key')
+        sock = socket.ssl_listener(('', 4202), certificate_file, private_key_file)
+        g = gevent.spawn(wsgi.server, sock, wsgi_app)
+        try:
+            req = HTTPRequest("https://localhost:4202/foo")
+            f = urllib2.urlopen(req)
+            result = f.read()
+            self.assertEquals(result, '')
+        finally:
+            gevent.kill(g)
+
+
 class HTTPRequest(urllib2.Request):
     """Hack urllib2.Request to support PUT and DELETE methods."""