diff --git a/docs/api.rst b/docs/api.rst index 75ada84c..d1d8a705 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -117,6 +117,34 @@ contexts. for msg in mitogen.master.Select(selects): print msg.unpickle() + .. py:classmethod:: all (it) + + Take an iterable of receivers and retrieve a :py:class:`Message` from + each, returning the result of calling `msg.unpickle()` on each in turn. + Results are returned in the order they arrived. + + This is sugar for handling batch :py:class:`Context.call_async` + invocations: + + .. code-block:: python + + print('Total disk usage: %.02fMiB' % (sum( + mitogen.master.Select.all( + context.call_async(get_disk_usage) + for context in contexts + ) / 1048576.0 + ),)) + + However, unlike in a naive comprehension such as: + + .. code-block:: python + + sum(context.call_async(get_disk_usage).get().unpickle() + for context in contexts) + + Result processing happens concurrently to new results arriving, so + :py:meth:`all` should always be faster. + .. py:method:: get (timeout=None) Fetch the next available value from any receiver, or raise diff --git a/mitogen/master.py b/mitogen/master.py index da0983c8..6fbfaf8a 100644 --- a/mitogen/master.py +++ b/mitogen/master.py @@ -123,6 +123,10 @@ class SelectError(mitogen.core.Error): class Select(object): notify = None + @classmethod + def all(cls, receivers): + return list(msg.unpickle() for msg in cls(receivers)) + def __init__(self, receivers=(), oneshot=True): self._receivers = [] self._oneshot = oneshot