Skip to content

Commit

Permalink
Merge 425210e into 2da05e0
Browse files Browse the repository at this point in the history
  • Loading branch information
lime-green committed Feb 19, 2019
2 parents 2da05e0 + 425210e commit 4d43e8b
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 10 deletions.
9 changes: 9 additions & 0 deletions pykka/compat.py
Expand Up @@ -2,6 +2,7 @@

PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
GTE_PY37 = sys.version_info[0:3] >= (3, 7, 0)

if PY2:
import Queue as queue # noqa
Expand All @@ -25,3 +26,11 @@ def reraise(tp, value, tb=None):
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value


if GTE_PY37:
def generator_return(value):
exec('return value')
else:
def generator_return(value):
exec('raise StopIteration(value)')
8 changes: 8 additions & 0 deletions pykka/future.py
@@ -1,4 +1,5 @@
import functools
from pykka.compat import generator_return


__all__ = ['Future', 'get_all']
Expand All @@ -19,6 +20,13 @@ def __init__(self):
self._get_hook = None
self._get_hook_result = None

def __await__(self):
yield
value = self.get()
generator_return(value)

__iter__ = __await__

def get(self, timeout=None):
"""
Get the value encapsulated by the future.
Expand Down
14 changes: 14 additions & 0 deletions tests/__init__.py
Expand Up @@ -15,3 +15,17 @@
has_gevent = pytest.mark.skipif(True, reason='gevent required')
else:
has_gevent = pytest.mark.skipif(False, reason='gevent required')


try:
compile('async def f(): pass', '', 'exec')
except SyntaxError:
has_async_await = pytest.mark.skipif(
True,
reason='async await syntax required',
)
else:
has_async_await = pytest.mark.skipif(
False,
reason='async await syntax required',
)
26 changes: 26 additions & 0 deletions tests/conftest.py
@@ -1,4 +1,6 @@
import logging
import os
import sys
import threading
import time
from collections import namedtuple
Expand All @@ -15,6 +17,20 @@
['name', 'actor_class', 'event_class', 'future_class', 'sleep_func'],
)

running_py3 = sys.version_info >= (3, 4, 0)


class NullCollector(pytest.collect.File):
def collect(self):
return []


# skip test files that end with _py3 if not testing under Python 3
def pytest_pycollect_makemodule(path, parent):
file_name = os.path.splitext(path.basename)[0]
if not running_py3 and file_name.endswith('_py3'):
return NullCollector(path, parent=parent)


RUNTIMES = {
'threading': pytest.param(
Expand Down Expand Up @@ -176,3 +192,13 @@ def on_failure(self, *args):
self.events.on_failure_was_called.set()

return FailingOnFailureActor


@pytest.fixture
def future(runtime):
return runtime.future_class()


@pytest.fixture
def futures(runtime):
return [runtime.future_class() for _ in range(3)]
10 changes: 0 additions & 10 deletions tests/test_future.py
Expand Up @@ -8,16 +8,6 @@
from tests import has_gevent


@pytest.fixture
def future(runtime):
return runtime.future_class()


@pytest.fixture
def futures(runtime):
return [runtime.future_class() for _ in range(3)]


def test_base_future_get_is_not_implemented():
future = Future()

Expand Down
23 changes: 23 additions & 0 deletions tests/test_future_py3.py
@@ -0,0 +1,23 @@
from tests import has_async_await

def _run_async(coroutine):
import asyncio
loop = asyncio.get_event_loop()
f = asyncio.ensure_future(coroutine, loop=loop)
return loop.run_until_complete(f)


@has_async_await
def test_future_supports_await_syntax(future):
async def _get_value():
return await future
future.set(1)
assert _run_async(_get_value()) == 1


def test_future_supports_yield_from_syntax(future):
def _get_value():
val = yield from future
return val
future.set(1)
assert _run_async(_get_value()) == 1

0 comments on commit 4d43e8b

Please sign in to comment.