diff --git a/doc/modules.rst b/doc/modules.rst index 574c1bc..cda9405 100644 --- a/doc/modules.rst +++ b/doc/modules.rst @@ -16,7 +16,6 @@ Module Reference modules/processes modules/proc modules/saranwrap - modules/timer modules/tpool modules/util modules/wsgi diff --git a/doc/modules/pools.rst b/doc/modules/pools.rst index 2e06a3b..9980530 100644 --- a/doc/modules/pools.rst +++ b/doc/modules/pools.rst @@ -1,6 +1,5 @@ -:mod:`pools` -================== +:mod:`pools` - Generic pools of resources +========================================== .. automodule:: eventlet.pools :members: - :undoc-members: diff --git a/doc/modules/timer.rst b/doc/modules/timer.rst deleted file mode 100644 index d67da08..0000000 --- a/doc/modules/timer.rst +++ /dev/null @@ -1,6 +0,0 @@ -:mod:`timer` -================== - -.. automodule:: eventlet.timer - :members: - :undoc-members: diff --git a/doc/modules/tpool.rst b/doc/modules/tpool.rst index 7aa2863..e4e6303 100644 --- a/doc/modules/tpool.rst +++ b/doc/modules/tpool.rst @@ -3,4 +3,4 @@ .. automodule:: eventlet.tpool :members: - :undoc-members: + diff --git a/doc/modules/wsgi.rst b/doc/modules/wsgi.rst index 8993dd4..798bb95 100644 --- a/doc/modules/wsgi.rst +++ b/doc/modules/wsgi.rst @@ -3,4 +3,3 @@ .. automodule:: eventlet.wsgi :members: - :undoc-members: diff --git a/eventlet/corolocal.py b/eventlet/corolocal.py index b90f544..1ed1193 100644 --- a/eventlet/corolocal.py +++ b/eventlet/corolocal.py @@ -4,7 +4,9 @@ def get_ident(): """ Returns ``id()`` of current greenlet. Useful for debugging.""" return id(api.getcurrent()) +# TODO: The base threadlocal class wants to call __init__ on itself for every new thread that associates with it; our corolocal doesn't do this, but should for 100% compatibility. The implementation in _threading_local.py is so janky.... class local(object): + """Coroutine equivalent of threading.local class.""" def __getattribute__(self, attr, g=get_ident): try: d = object.__getattribute__(self, '__dict__') diff --git a/eventlet/pools.py b/eventlet/pools.py index f15b506..f24ca2b 100644 --- a/eventlet/pools.py +++ b/eventlet/pools.py @@ -3,16 +3,7 @@ import collections from eventlet import api from eventlet import coros -class FanFailed(RuntimeError): - pass - - -class SomeFailed(FanFailed): - pass - - -class AllFailed(FanFailed): - pass +__all__ = ['Pool', 'TokenPool'] # have to stick this in an exec so it works in 2.4 try: @@ -44,6 +35,9 @@ except ImportError: class Pool(object): """ + Pool is a base class that is meant to be subclassed. When subclassing, + define the :meth:`create` method to implement the desired resource. + When using the pool, if you do a get, you should **always** do a :meth:`put`. @@ -141,8 +135,8 @@ class Token(object): class TokenPool(Pool): - """A pool which gives out tokens, an object indicating that - the person who holds the token has a right to consume some + """A pool which gives out tokens (opaque unique objects), which indicate + that the coroutine which holds the token has a right to consume some limited resource. """ def create(self): diff --git a/eventlet/tpool.py b/eventlet/tpool.py index 02bc8b2..8f562cf 100644 --- a/eventlet/tpool.py +++ b/eventlet/tpool.py @@ -20,6 +20,8 @@ from Queue import Empty, Queue from eventlet import api, coros, greenio +__all__ = ['execute', 'Proxy', 'killall'] + QUIET=False _rfile = _wfile = None @@ -91,8 +93,14 @@ def erecv(e): def execute(meth,*args, **kwargs): """ - Execute *meth* in a thread, blocking the current coroutine until the method - completes. + Execute *meth* in a Python thread, blocking the current coroutine/ + greenthread until the method completes. + + The primary use case for this is to wrap an object or module that is not + amenable to monkeypatching or any of the other tricks that Eventlet uses + to achieve cooperative yielding. With tpool, you can force such objects to + cooperate with green threads by sticking them in native threads, at the cost + of some overhead. """ setup() e = esend(meth,*args,**kwargs) @@ -104,9 +112,13 @@ def proxy_call(autowrap, f, *args, **kwargs): """ Call a function *f* and returns the value. If the type of the return value is in the *autowrap* collection, then it is wrapped in a :class:`Proxy` - object before return. Normally *f* will be called nonblocking with the - execute method; if the keyword argument "nonblocking" is set to ``True``, - it will simply be executed directly. + object before return. + + Normally *f* will be called in the threadpool with :func:`execute`; if the + keyword argument "nonblocking" is set to ``True``, it will simply be + executed directly. This is useful if you have an object which has methods + that don't need to be called in a separate thread, but which return objects + that should be Proxy wrapped. """ if kwargs.pop('nonblocking',False): rv = f(*args, **kwargs) @@ -119,11 +131,17 @@ def proxy_call(autowrap, f, *args, **kwargs): class Proxy(object): """ - a simple proxy-wrapper of any object that comes with a methods-only - interface, in order to forward every method invocation onto a thread in the - native-thread pool. A key restriction is that the object's methods cannot - call into eventlets, since the eventlet dispatcher runs on a different - native thread. This is for running native-threaded code only. + A simple proxy-wrapper of any object, in order to forward every method + invocation onto a thread in the native-thread pool. A key restriction is + that the object's methods cannot use Eventlet primitives without great care, + since the Eventlet dispatcher runs on a different native thread. + + Construct the Proxy with the instance that you want proxied. The optional + parameter *autowrap* is used when methods are called on the proxied object. + If a method on the proxied object returns something whose type is in + *autowrap*, then that object gets a Proxy wrapped around it, too. An + example use case for this is ensuring that DB-API connection objects + return cursor objects that are also Proxy-wrapped. """ def __init__(self, obj,autowrap=()): self._obj = obj diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 440367b..1d5946c 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -16,6 +16,7 @@ DEFAULT_MAX_HTTP_VERSION = 'HTTP/1.1' MAX_REQUEST_LINE = 8192 MINIMUM_CHUNK_SIZE = 4096 +__all__ = ['server', 'format_date_time'] # Weekday and month names for HTTP date/time formatting; always English! _weekdayname = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] @@ -24,6 +25,7 @@ _monthname = [None, # Dummy so we can use 1-based month numbers "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] def format_date_time(timestamp): + """Formats a unix timestamp into an HTTP standard string.""" year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp) return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( _weekdayname[wd], day, _monthname[month], year, hh, mm, ss @@ -422,9 +424,18 @@ def server(sock, site, server_event=None, minimum_chunk_size=None, log_x_forwarded_for=True): - """ Start up a wsgi server handling requests from the supplied server socket. + """ Start up a `WSGI `_ server handling requests from the supplied server + socket. This function loops forever. - This function loops forever. + :param sock: Server socket, must be already bound to a port and listening. + :param site: WSGI application function. + :param log: File-like object that logs should be written to. If not specified, sys.stderr is used. + :param environ: Additional parameters that go into the environ dictionary of every request. + :param max_size: Maximum number of client connections opened at any time by this server. + :param protocol: Protocol class. Deprecated. + :param server_event: Used to collect the Server object. Deprecated. + :param minimum_chunk_size: Minimum size for http chunks, which can be used to improve performance of applications which yield many small strings, though it technically violates the WSGI spec. + :param log_x_forwarded_for: If True (the default), logs all ip addresses found in the x-forwarded-for header in addition to the actual client ip address. """ serv = Server(sock, sock.getsockname(),