Commit 326e563f authored by Jason Madden's avatar Jason Madden

Simplify AsyncResult now that its keeping the exc_info around. Docs.

parent 105c1abe
...@@ -255,4 +255,4 @@ class MyClassDocumenter(ClassDocumenter): ...@@ -255,4 +255,4 @@ class MyClassDocumenter(ClassDocumenter):
members.sort(key=key) members.sort(key=key)
return members_check_module, members return members_check_module, members
#autodoc.ClassDocumenter = MyClassDocumenter autodoc.ClassDocumenter = MyClassDocumenter
...@@ -42,6 +42,12 @@ def generate_rst_for_module(module, do=True): ...@@ -42,6 +42,12 @@ def generate_rst_for_module(module, do=True):
m = getattr(m, module) m = getattr(m, module)
title = getattr(m, '__doc__', None) title = getattr(m, '__doc__', None)
if title: if title:
lines = title.strip().splitlines()
for line in lines:
# skip leading blanks. Support both styles of docstrings.
if line:
title = line
break
title = title.strip().split('\n')[0] title = title.strip().split('\n')[0]
title = title.strip(' .') title = title.strip(' .')
prefix = ':mod:`gevent.%s`' % module prefix = ':mod:`gevent.%s`' % module
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.. method:: is_set() .. method:: is_set()
isSet() isSet()
ready()
Return true if and only if the internal flag is true. Return true if and only if the internal flag is true.
...@@ -15,8 +16,3 @@ ...@@ -15,8 +16,3 @@
.. autoclass:: gevent.event.AsyncResult .. autoclass:: gevent.event.AsyncResult
:members: :members:
:undoc-members: :undoc-members:
.. attribute:: value
Holds the value passed to :meth:`set` if :meth:`set` was called. Otherwise ``None``.
...@@ -39,8 +39,12 @@ class Event(object): ...@@ -39,8 +39,12 @@ class Event(object):
ready = is_set # makes it compatible with AsyncResult and Greenlet (for example in wait()) ready = is_set # makes it compatible with AsyncResult and Greenlet (for example in wait())
def set(self): def set(self):
"""Set the internal flag to true. All greenlets waiting for it to become true are awakened. """
Greenlets that call :meth:`wait` once the flag is true will not block at all. Set the internal flag to true.
All greenlets waiting for it to become true are awakened.
Greenlets that call :meth:`wait` once the flag is true will
not block at all.
""" """
self._flag = True self._flag = True
self._todo.update(self._links) self._todo.update(self._links)
...@@ -48,14 +52,17 @@ class Event(object): ...@@ -48,14 +52,17 @@ class Event(object):
self._notifier = self.hub.loop.run_callback(self._notify_links) self._notifier = self.hub.loop.run_callback(self._notify_links)
def clear(self): def clear(self):
"""Reset the internal flag to false. """
Subsequently, threads calling :meth:`wait` Reset the internal flag to false.
will block until :meth:`set` is called to set the internal flag to true again.
Subsequently, threads calling :meth:`wait` will block until
:meth:`set` is called to set the internal flag to true again.
""" """
self._flag = False self._flag = False
def wait(self, timeout=None): def wait(self, timeout=None):
"""Block until the internal flag is true. """Block until the internal flag is true.
If the internal flag is true on entry, return immediately. Otherwise, If the internal flag is true on entry, return immediately. Otherwise,
block until another thread calls :meth:`set` to set the flag to true, block until another thread calls :meth:`set` to set the flag to true,
or until the optional timeout occurs. or until the optional timeout occurs.
...@@ -64,11 +71,12 @@ class Event(object): ...@@ -64,11 +71,12 @@ class Event(object):
floating point number specifying a timeout for the operation in seconds floating point number specifying a timeout for the operation in seconds
(or fractions thereof). (or fractions thereof).
Return the value of the internal flag (``True`` or ``False``). :return: The value of the internal flag (``True`` or ``False``).
(If no timeout was given, the only possible return value is ``True``.)
""" """
if self._flag: if self._flag:
return self._flag return self._flag
else:
switch = getcurrent().switch switch = getcurrent().switch
self.rawlink(switch) self.rawlink(switch)
try: try:
...@@ -125,11 +133,11 @@ class Event(object): ...@@ -125,11 +133,11 @@ class Event(object):
class AsyncResult(object): class AsyncResult(object):
"""A one-time event that stores a value or an exception. """A one-time event that stores a value or an exception.
Like :class:`Event` it wakes up all the waiters when :meth:`set` or :meth:`set_exception` method Like :class:`Event` it wakes up all the waiters when :meth:`set` or :meth:`set_exception`
is called. Waiters may receive the passed value or exception by calling :meth:`get` is called. Waiters may receive the passed value or exception by calling :meth:`get`
method instead of :meth:`wait`. An :class:`AsyncResult` instance cannot be reset. instead of :meth:`wait`. An :class:`AsyncResult` instance cannot be reset.
To pass a value call :meth:`set`. Calls to :meth:`get` (those that currently blocking as well as To pass a value call :meth:`set`. Calls to :meth:`get` (those that are currently blocking as well as
those made in the future) will return the value: those made in the future) will return the value:
>>> result = AsyncResult() >>> result = AsyncResult()
...@@ -157,13 +165,35 @@ class AsyncResult(object): ...@@ -157,13 +165,35 @@ class AsyncResult(object):
... print('ZeroDivisionError') ... print('ZeroDivisionError')
ZeroDivisionError ZeroDivisionError
""" """
_value = _NONE
_exc_info = ()
_notifier = None
def __init__(self): def __init__(self):
self._links = deque() self._links = deque()
self.value = None
self._exception = _NONE
self._exc_info = ()
self.hub = get_hub() self.hub = get_hub()
self._notifier = None
@property
def _exception(self):
return self._exc_info[1] if self._exc_info else _NONE
@property
def value(self):
"""
Holds the value passed to :meth:`set` if :meth:`set` was called. Otherwise,
``None``
"""
return self._value if self._value is not _NONE else None
@property
def exc_info(self):
"""
The three-tuple of exception information if :meth:`set_exception` was called.
"""
if self._exc_info:
return (self._exc_info[0], self._exc_info[1], load_traceback(self._exc_info[2]))
return ()
def __str__(self): def __str__(self):
result = '<%s ' % (self.__class__.__name__, ) result = '<%s ' % (self.__class__.__name__, )
...@@ -177,11 +207,11 @@ class AsyncResult(object): ...@@ -177,11 +207,11 @@ class AsyncResult(object):
def ready(self): def ready(self):
"""Return true if and only if it holds a value or an exception""" """Return true if and only if it holds a value or an exception"""
return self._exception is not _NONE return self._exc_info or self._value is not _NONE
def successful(self): def successful(self):
"""Return true if and only if it is ready and holds a value""" """Return true if and only if it is ready and holds a value"""
return self._exception is None return self._value is not _NONE
@property @property
def exception(self): def exception(self):
...@@ -191,50 +221,59 @@ class AsyncResult(object): ...@@ -191,50 +221,59 @@ class AsyncResult(object):
return self._exc_info[1] return self._exc_info[1]
def set(self, value=None): def set(self, value=None):
"""Store the value. Wake up the waiters. """Store the value and wake up any waiters.
All greenlets blocking on :meth:`get` or :meth:`wait` are woken up. All greenlets blocking on :meth:`get` or :meth:`wait` are awakened.
Sequential calls to :meth:`wait` and :meth:`get` will not block at all. Subsequent calls to :meth:`wait` and :meth:`get` will not block at all.
""" """
self.value = value self._value = value
self._exception = None
if self._links and not self._notifier: if self._links and not self._notifier:
self._notifier = self.hub.loop.run_callback(self._notify_links) self._notifier = self.hub.loop.run_callback(self._notify_links)
def set_exception(self, exception, exc_info=None): def set_exception(self, exception, exc_info=None):
"""Store the exception. Wake up the waiters. """Store the exception and wake up any waiters.
All greenlets blocking on :meth:`get` or :meth:`wait` are woken up. All greenlets blocking on :meth:`get` or :meth:`wait` are awakened.
Sequential calls to :meth:`wait` and :meth:`get` will not block at all. Subsequent calls to :meth:`wait` and :meth:`get` will not block at all.
:keyword tuple exc_info: If given, a standard three-tuple of type, value, :class:`traceback`
as returned by :func:`sys.exc_info`. This will be used when the exception
is re-raised to propagate the correct traceback.
""" """
self._exception = exception
if exc_info: if exc_info:
self._exc_info = (exc_info[0], exc_info[1], dump_traceback(exc_info[2])) self._exc_info = (exc_info[0], exc_info[1], dump_traceback(exc_info[2]))
else:
self._exc_info = (type(exception), exception, dump_traceback(None))
if self._links and not self._notifier: if self._links and not self._notifier:
self._notifier = self.hub.loop.run_callback(self._notify_links) self._notifier = self.hub.loop.run_callback(self._notify_links)
def _raise_exception(self): def _raise_exception(self):
if self._exc_info: reraise(*self.exc_info)
reraise(self._exc_info[0], self._exc_info[1], load_traceback(self._exc_info[2]))
raise self._exception
def get(self, block=True, timeout=None): def get(self, block=True, timeout=None):
"""Return the stored value or raise the exception. """Return the stored value or raise the exception.
If this instance already holds a value / an exception, return / raise it immediatelly. If this instance already holds a value or an exception, return or raise it immediatelly.
Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception` or Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception` or
until the optional timeout occurs. until the optional timeout occurs.
When the *timeout* argument is present and not ``None``, it should be a When the *timeout* argument is present and not ``None``, it should be a
floating point number specifying a timeout for the operation in seconds floating point number specifying a timeout for the operation in seconds
(or fractions thereof). (or fractions thereof).
:keyword bool block: If set to ``False`` and this instance is not ready,
immediately raise a :class:`Timeout` exception.
""" """
if self._exception is not _NONE: if self._value is not _NONE:
if self._exception is None: return self._value
return self.value if self._exc_info:
self._raise_exception() return self._raise_exception()
elif block:
if not block:
# Not ready and not blocking, so immediately timeout
raise Timeout()
switch = getcurrent().switch switch = getcurrent().switch
self.rawlink(switch) self.rawlink(switch)
try: try:
...@@ -247,16 +286,16 @@ class AsyncResult(object): ...@@ -247,16 +286,16 @@ class AsyncResult(object):
except: except:
self.unlink(switch) self.unlink(switch)
raise raise
if self._exception is None:
return self.value # by definition we are now ready
self._raise_exception() return self.get(block=False)
else:
raise Timeout
def get_nowait(self): def get_nowait(self):
"""Return the value or raise the exception without blocking. """
Return the value or raise the exception without blocking.
If nothing is available, raise :class:`gevent.Timeout` immediatelly. If this object is not yet :meth:`ready <ready>`, raise
:class:`gevent.Timeout` immediately.
""" """
return self.get(block=False) return self.get(block=False)
...@@ -266,7 +305,7 @@ class AsyncResult(object): ...@@ -266,7 +305,7 @@ class AsyncResult(object):
If this instance already holds a value, it is returned immediately. If this If this instance already holds a value, it is returned immediately. If this
instance already holds an exception, ``None`` is returned immediately. instance already holds an exception, ``None`` is returned immediately.
Otherwise, block until another thread calls :meth:`set` or :meth:`set_exception` Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception`
(at which point either the value or ``None`` will be returned, respectively), (at which point either the value or ``None`` will be returned, respectively),
or until the optional timeout expires (at which point ``None`` will also be or until the optional timeout expires (at which point ``None`` will also be
returned). returned).
...@@ -278,11 +317,10 @@ class AsyncResult(object): ...@@ -278,11 +317,10 @@ class AsyncResult(object):
.. note:: If a timeout is given and expires, ``None`` will be returned .. note:: If a timeout is given and expires, ``None`` will be returned
(no timeout exception will be raised). (no timeout exception will be raised).
Return :attr:`value`.
""" """
if self._exception is not _NONE: if self.ready():
return self.value return self.value
else:
switch = getcurrent().switch switch = getcurrent().switch
self.rawlink(switch) self.rawlink(switch)
try: try:
......
# Copyright (c) 2009-2011 Denis Bilenko. See LICENSE for details. # Copyright (c) 2009-2011 Denis Bilenko. See LICENSE for details.
"""
Waiting for I/O completion.
"""
from __future__ import absolute_import from __future__ import absolute_import
from gevent.event import Event from gevent.event import Event
from gevent.hub import get_hub from gevent.hub import get_hub
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
This module provides socket operations and some related functions. This module provides socket operations and some related functions.
The API of the functions and classes matches the API of the corresponding The API of the functions and classes matches the API of the corresponding
items in standard :mod:`socket` module exactly, but the synchronous functions items in the standard :mod:`socket` module exactly, but the synchronous functions
in this module only block the current greenlet and let the others run. in this module only block the current greenlet and let the others run.
For convenience, exceptions (like :class:`error <socket.error>` and :class:`timeout <socket.timeout>`) For convenience, exceptions (like :class:`error <socket.error>` and :class:`timeout <socket.timeout>`)
as well as the constants from :mod:`socket` module are imported into this module. as well as the constants from the :mod:`socket` module are imported into this module.
""" """
import sys import sys
...@@ -43,7 +43,7 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=N ...@@ -43,7 +43,7 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=N
global default timeout setting returned by :func:`getdefaulttimeout` global default timeout setting returned by :func:`getdefaulttimeout`
is used. If *source_address* is set it must be a tuple of (host, port) is used. If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection. for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default. A host of '' or port 0 tells the OS to use the default.
""" """
host, port = address host, port = address
......
"""
Secure Sockets Layer (SSL/TLS) module.
"""
from gevent.hub import PY3 from gevent.hub import PY3
from gevent.hub import PYGTE279 from gevent.hub import PYGTE279
......
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