Commit ebfc9c3f authored by Denis Bilenko's avatar Denis Bilenko

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

--HG--
rename : gevent/__init__.py => gevent/greenlet.py
parent f93c5023
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']
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)
_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="")
'signal',
'with_timeout',
'fork']
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()
# add here Queue, Event, Pipe?, Socket?
_original_fork = os.fork
from gevent.greenlet import *
def fork():
result = _original_fork()
core.reinit()
return result
......@@ -26,7 +26,8 @@ import socket
import sys
from code import InteractiveConsole
import gevent
from gevent.greenlet import Greenlet
from gevent import core
try:
sys.ps1
......@@ -38,7 +39,7 @@ except AttributeError:
sys.ps2 = '... '
class SocketConsole(gevent.Greenlet):
class SocketConsole(Greenlet):
def __init__(self, desc, hostport, locals):
self.hostport = hostport
self.locals = locals
......@@ -57,7 +58,7 @@ class SocketConsole(gevent.Greenlet):
self.old[key] = getattr(desc, key)
setattr(desc, key, value)
gevent.Greenlet.__init__(self)
Greenlet.__init__(self)
def run(self):
try:
......@@ -70,7 +71,7 @@ class SocketConsole(gevent.Greenlet):
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
......@@ -100,7 +101,7 @@ def backdoor_server(server, locals=None):
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:
......@@ -118,7 +119,7 @@ def backdoor((conn, addr), locals=None):
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__':
......
......@@ -25,8 +25,8 @@ import collections
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):
......@@ -187,7 +187,7 @@ class event(object):
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:
......@@ -249,7 +249,7 @@ class Semaphore(object):
# `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):
......@@ -373,7 +373,7 @@ class Queue(object):
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
......@@ -442,7 +442,7 @@ class Channel(object):
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)
......@@ -450,7 +450,7 @@ class Channel(object):
# 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:
......@@ -487,14 +487,14 @@ class Channel(object):
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()
......
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
......
......@@ -67,7 +67,7 @@ fails then there's no way to complete the task so the parent must fail as well;
>>> p = spawn(demofunc, 1, 0)
>>> _ = p.link_exception()
>>> try:
... gevent.sleep(1)
... greenlet.sleep(1)
... except LinkedFailed:
... print 'LinkedFailed'
LinkedFailed
......@@ -76,8 +76,7 @@ One application of linking is `waitall' function: link to a bunch of coroutines
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',
......@@ -124,12 +123,12 @@ class LinkedKilled(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."""
......@@ -210,17 +209,12 @@ class decorate_send(object):
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):
......@@ -238,9 +232,9 @@ def spawn_greenlet(function, *args):
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
......@@ -339,10 +333,10 @@ class Source(object):
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
......@@ -354,10 +348,10 @@ class Source(object):
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
......@@ -367,10 +361,10 @@ class Source(object):
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:
......@@ -387,7 +381,7 @@ class Source(object):
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)
......@@ -409,7 +403,7 @@ class Source(object):
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
......@@ -418,7 +412,7 @@ class Source(object):
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:
......@@ -430,7 +424,7 @@ class Source(object):
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):
......@@ -446,16 +440,16 @@ class Source(object):
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
......@@ -487,15 +481,15 @@ class Waiter(object):
"""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)
......@@ -504,11 +498,11 @@ class Waiter(object):
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
......@@ -598,9 +592,9 @@ class Proc(Source):
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)
......@@ -693,7 +687,7 @@ class RunningProcSet(object):
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:
......@@ -748,7 +742,7 @@ class Pool(object):
"""
# 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
......@@ -45,7 +45,7 @@ class Queue(object):
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)
......@@ -80,7 +80,7 @@ class Queue(object):
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:
......@@ -13,9 +12,9 @@ def get_fileno(obj):
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 = []
......@@ -33,11 +32,11 @@ def select(read_list, write_list, error_list, t=None):
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
......
......@@ -18,15 +18,6 @@
# 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
......@@ -40,6 +31,15 @@ __socket__ = __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):
......
......@@ -25,6 +25,7 @@ import os
import errno
import unittest
import gevent
from gevent.greenlet import get_hub
disabled_marker = '-*-*-*-*-*- disabled -*-*-*-*-*-'
def exit_disabled():
......@@ -38,6 +39,7 @@ class TestCase(unittest.TestCase):
__timeout__ = 1
__switch_check__ = True
_switch_count = None
def disable_switch_check(self):
self._switch_count = None
......@@ -47,14 +49,16 @@ class TestCase(unittest.TestCase):
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())
......@@ -75,7 +79,7 @@ def find_command(command):
main = unittest.main
_original_Hub = gevent.Hub
_original_Hub = gevent.greenlet.Hub
class CountingHub(_original_Hub):
......@@ -85,4 +89,4 @@ class CountingHub(_original_Hub):
self.switch_count += 1
return _original_Hub.switch(self)
gevent.Hub = CountingHub
gevent.greenlet.Hub = CountingHub
......@@ -24,6 +24,7 @@ import os.path
from greentest import TestCase, main
import gevent
from gevent import greenlet
from gevent import socket
......@@ -119,7 +120,7 @@ class TestApi(TestCase):
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:
......@@ -138,7 +139,7 @@ class TestApi(TestCase):
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"
......@@ -175,7 +176,7 @@ class TestApi(TestCase):
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:
......
......@@ -87,7 +87,7 @@ class TestEvent(TestCase):
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)
......
......@@ -72,7 +72,7 @@ class TestGreenIo(TestCase):
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
......
......@@ -21,6 +21,7 @@
import greentest
import gevent
from gevent import core
DELAY = 0.1
......@@ -65,7 +66,7 @@ class TestTimers(greentest.TestCase):
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)
......
......@@ -24,7 +24,8 @@ import sys
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):
......@@ -34,13 +35,13 @@ class Test(greentest.TestCase):
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
......@@ -49,14 +50,14 @@ class Test(greentest.TestCase):
# 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
......@@ -65,7 +66,7 @@ class Test(greentest.TestCase):
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')
......@@ -75,7 +76,7 @@ class Test(greentest.TestCase):
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)
......@@ -84,39 +85,40 @@ class Test(greentest.TestCase):
# 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'
......
......@@ -21,7 +21,7 @@ class TestQueue(TestCase):
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()
......@@ -90,7 +90,7 @@ class TestQueue(TestCase):
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)
......@@ -110,7 +110,7 @@ class TestQueue(TestCase):
q = coros.Queue()
def do_receive(q, evt):
gevent.timeout(0, RuntimeError())
gevent.Timeout(0, RuntimeError())
try:
result = q.wait()
evt.send(result)
......@@ -138,7 +138,7 @@ class TestQueue(TestCase):
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)
......@@ -157,7 +157,7 @@ class TestQueue(TestCase):
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)
......
......@@ -21,7 +21,7 @@
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
......@@ -50,7 +50,7 @@ class TestEvent(TestCase):
event2 = event()
spawn(event1.send, 'hello event1')
timeout(0, ValueError('interrupted'))
Timeout(0, ValueError('interrupted'))
try:
result = event1.wait()
except ValueError:
......
......@@ -22,6 +22,7 @@
import greentest
import time
import gevent
from gevent import core
from gevent import socket
DELAY = 0.1
......@@ -37,7 +38,7 @@ class TestScheduleCall(greentest.TestCase):
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
......@@ -47,7 +48,7 @@ class TestCloseSocketWhilePolling(greentest.TestCase):
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)
......@@ -68,7 +69,7 @@ class TestExceptionInMainloop(greentest.TestCase):
def fail():
1/0
gevent.timer(0, fail)
core.timer(0, fail)
start = time.time()
gevent.sleep(DELAY)
......
......@@ -95,7 +95,7 @@ class TestCoroutinePool(TestCase):
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:
......
......@@ -164,7 +164,7 @@ class TestHttpd(TestCase):
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()
......@@ -278,42 +278,6 @@ class TestHttpd(TestCase):
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))
......@@ -359,6 +323,46 @@ class TestHttpd(TestCase):
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."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment