summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-11-24 17:31:32 +0100
committerVictor Stinner <victor.stinner@gmail.com>2014-11-24 17:31:32 +0100
commitfc6513fad282b1dbabec9e5fc4235f8e94af9fe9 (patch)
tree42a56ef60d081ae8f82a609121563e980f8549dc
parentf792f2d3b3b75382bdf2f6b2b5a2fbfa3e0728a7 (diff)
downloadaioeventlet-fc6513fad282b1dbabec9e5fc4235f8e94af9fe9.tar.gz
convert link_future to a method of EventletEventLoop
-rw-r--r--aiogreen.py52
-rw-r--r--doc/index.rst5
-rw-r--r--doc/using.rst113
-rw-r--r--tests/test_eventlet.py16
4 files changed, 105 insertions, 81 deletions
diff --git a/aiogreen.py b/aiogreen.py
index 08c8d46..8912d43 100644
--- a/aiogreen.py
+++ b/aiogreen.py
@@ -256,6 +256,32 @@ class EventletEventLoop(asyncio.SelectorEventLoop):
def time(self):
return self._hub.clock()
+ def link_future(self, future):
+ """Wait for a future, a task, or a coroutine object from a greenthread.
+
+ Return the result or raise the exception of the future.
+
+ The function must not be called from the greenthread
+ of the aiogreen event loop.
+ """
+ if self._greenthread == eventlet.getcurrent():
+ raise RuntimeError("link_future() must not be called from "
+ "the greenthread of the aiogreen event loop")
+
+ future = asyncio.async(future, loop=self)
+ event = eventlet.event.Event()
+
+ def done(fut):
+ try:
+ result = fut.result()
+ except Exception as exc:
+ event.send_exception(exc)
+ else:
+ event.send(result)
+
+ future.add_done_callback(done)
+ return event.wait()
+
class EventletEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
_loop_factory = EventletEventLoop
@@ -311,29 +337,3 @@ def wrap_greenthread(gt, loop=None):
fut.set_result(result)
gt.run = wrap_func
return fut
-
-
-def link_future(future, loop=None):
- """Wait for a future, a task, or a coroutine object from a greenthread.
-
- Return the result or raise the exception of the future.
-
- The function must not be called from the greenthread
- of the aiogreen event loop.
- """
- future = asyncio.async(future, loop=loop)
- if future._loop._greenthread == eventlet.getcurrent():
- raise RuntimeError("link_future() must not be called from "
- "the greenthread of the aiogreen event loop")
-
- event = eventlet.event.Event()
- def done(fut):
- try:
- result = fut.result()
- except Exception as exc:
- event.send_exception(exc)
- else:
- event.send(result)
-
- future.add_done_callback(done)
- return event.wait()
diff --git a/doc/index.rst b/doc/index.rst
index 280f895..d61e650 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -11,8 +11,9 @@ aiogreen implements the asyncio API (`PEP 3156
possible to write asyncio code in a project currently written for eventlet.
aiogreen allows to use greenthreads in asyncio coroutines, and to use asyncio
-coroutines, tasks and futures in greenthreads: see :func:`link_future` and
-:func:`wrap_greenthread` functions.
+coroutines, tasks and futures in greenthreads: see
+:meth:`EventletEventLoop.link_future` method and :func:`wrap_greenthread`
+function.
The main visible difference between aiogreen and trollius is the behaviour of
``run_forever()``: ``run_forever()`` blocks with trollius, whereas it runs in a
diff --git a/doc/using.rst b/doc/using.rst
index 810af1b..827d2ad 100644
--- a/doc/using.rst
+++ b/doc/using.rst
@@ -14,7 +14,7 @@ loop, example::
import aiogreen
import trollius
- trollius.set_event_loop_policy(aiogreen.EventLoopPolicy())
+ trollius.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
# ....
Hello World::
@@ -26,7 +26,7 @@ Hello World::
print("Hello World")
loop.stop()
- asyncio.set_event_loop_policy(aiogreen.EventLoopPolicy())
+ asyncio.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
loop = asyncio.get_event_loop()
loop.call_soon(hello_world)
loop.run_forever()
@@ -46,7 +46,7 @@ loop. Example::
import aiogreen
import asyncio
- asyncio.set_event_loop_policy(aiogreen.EventLoopPolicy())
+ asyncio.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
# ....
Setting the event loop policy should be enough to examples of the asyncio
@@ -68,7 +68,7 @@ Hello World::
print("Hello World")
loop.stop()
- asyncio.set_event_loop_policy(aiogreen.EventLoopPolicy())
+ asyncio.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
loop = asyncio.get_event_loop()
loop.call_soon(hello_world)
loop.run_forever()
@@ -126,63 +126,78 @@ aiogreen specific functions:
.. warning::
aiogreen API is not considered as stable yet.
-link_future
------------
+EventletEventLoop
+-----------------
-.. function:: link_future(future, loop=None)
+.. class:: EventletEventLoop
- Wait for a future, a task, or a coroutine object from a greenthread.
+ asyncio or trollius event loop running on top of eventlet.
- Return the result or raise the exception of the future.
+ The API is the API of asyncio event loop, with one extra method: :meth:`link_future`.
- The function must not be called from the greenthread of the aiogreen event
- loop.
+ .. versionchanged:: 0.4
- .. versionchanged:: 0.3
+ The class was renamed from ``EventLoop`` to ``EventletEventLoop``.
- Coroutine objects are also accepted. Added the *loop* parameter.
- An exception is raised if it is called from the greenthread of the
- aiogreen event loop.
+ .. method:: link_future(future)
- Example of greenthread waiting for a trollius task. The ``progress()``
- callback is called regulary to see that the event loop in not blocked::
+ Wait for a future, a task, or a coroutine object from a greenthread.
- import aiogreen
- import eventlet
- import trollius as asyncio
- from trollius import From, Return
+ Return the result or raise the exception of the future.
- def progress():
- print("computation in progress...")
- loop.call_later(0.5, progress)
+ The function must not be called from the greenthread of the aiogreen event
+ loop.
- @asyncio.coroutine
- def coro_slow_sum(x, y):
- yield From(asyncio.sleep(1.0))
- raise Return(x + y)
+ .. versionchanged:: 0.4
- def green_sum():
- loop.call_soon(progress)
+ The function was converted to a method of the
+ :class:`EventletEventLoop` class.
- task = asyncio.async(coro_slow_sum(1, 2))
+ .. versionchanged:: 0.3
- value = aiogreen.link_future(task)
- print("1 + 2 = %s" % value)
+ Coroutine objects are also accepted. Added the *loop* parameter.
+ An exception is raised if it is called from the greenthread of the
+ aiogreen event loop.
- loop.stop()
+ Example of greenthread waiting for a trollius task. The ``progress()``
+ callback is called regulary to see that the event loop in not blocked::
- asyncio.set_event_loop_policy(aiogreen.EventLoopPolicy())
- eventlet.spawn(green_sum)
- loop = asyncio.get_event_loop()
- loop.run_forever()
- loop.close()
+ import aiogreen
+ import eventlet
+ import trollius as asyncio
+ from trollius import From, Return
- Output::
+ def progress():
+ print("computation in progress...")
+ loop.call_later(0.5, progress)
- computation in progress...
- computation in progress...
- computation in progress...
- 1 + 2 = 3
+ @asyncio.coroutine
+ def coro_slow_sum(x, y):
+ yield From(asyncio.sleep(1.0))
+ raise Return(x + y)
+
+ def green_sum():
+ loop.call_soon(progress)
+
+ task = asyncio.async(coro_slow_sum(1, 2))
+
+ value = loop.link_future(task)
+ print("1 + 2 = %s" % value)
+
+ loop.stop()
+
+ asyncio.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
+ eventlet.spawn(green_sum)
+ loop = asyncio.get_event_loop()
+ loop.run_forever()
+ loop.close()
+
+ Output::
+
+ computation in progress...
+ computation in progress...
+ computation in progress...
+ 1 + 2 = 3
wrap_greenthread
----------------
@@ -231,7 +246,7 @@ wrap_greenthread
result = yield From(fut)
print("1 + 2 = %s" % result)
- asyncio.set_event_loop_policy(aiogreen.EventLoopPolicy())
+ asyncio.set_event_loop_policy(aiogreen.EventletEventLoopPolicy())
loop = asyncio.get_event_loop()
loop.run_until_complete(coro_sum())
loop.close()
@@ -244,6 +259,14 @@ wrap_greenthread
1 + 2 = 3
+EventletEventLoopPolicy
+-----------------------
+
+.. class:: EventletEventLoopPolicy
+
+ Event loop policy creating :class:`EventletEventLoop` event loops.
+
+
Installation
============
diff --git a/tests/test_eventlet.py b/tests/test_eventlet.py
index 9a83008..c7ee878 100644
--- a/tests/test_eventlet.py
+++ b/tests/test_eventlet.py
@@ -90,14 +90,14 @@ except ImportError:
def greenthread_link_future(result, loop):
try:
- value = aiogreen.link_future(coro_slow_append(result, 1, 0.020))
+ value = loop.link_future(coro_slow_append(result, 1, 0.020))
result.append(value)
- value = aiogreen.link_future(coro_slow_append(result, 2, 0.010))
+ value = loop.link_future(coro_slow_append(result, 2, 0.010))
result.append(value)
try:
- value = aiogreen.link_future(coro_slow_error())
+ value = loop.link_future(coro_slow_error())
except ValueError as exc:
result.append(str(exc))
@@ -174,7 +174,7 @@ class LinkFutureTests(tests.TestCase):
result = []
def func(fut):
- value = aiogreen.link_future(coro_slow_append(result, 3))
+ value = self.loop.link_future(coro_slow_append(result, 3))
result.append(value)
self.loop.stop()
@@ -188,7 +188,7 @@ class LinkFutureTests(tests.TestCase):
def func(event, fut):
event.send('link')
- value = aiogreen.link_future(fut)
+ value = self.loop.link_future(fut)
result.append(value)
self.loop.stop()
@@ -206,7 +206,7 @@ class LinkFutureTests(tests.TestCase):
def func(fut):
try:
- value = aiogreen.link_future(fut)
+ value = self.loop.link_future(fut)
except Exception as exc:
result.append('error')
else:
@@ -221,7 +221,7 @@ class LinkFutureTests(tests.TestCase):
def test_link_future_invalid_type(self):
def func(obj):
- return aiogreen.link_future(obj)
+ return self.loop.link_future(obj)
@asyncio.coroutine
def coro_func():
@@ -243,7 +243,7 @@ class LinkFutureTests(tests.TestCase):
def func(fut):
try:
- value = aiogreen.link_future(fut, loop=loop2)
+ value = loop2.link_future(fut)
except Exception as exc:
result.append(str(exc))
else: