diff --git a/.gitignore b/.gitignore index 72364f9..f9ecd6e 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,4 @@ ENV/ # Rope project settings .ropeproject +.pytest_cache/ diff --git a/a_sync/a_sync.py b/a_sync/a_sync.py index e30596e..4851ca4 100644 --- a/a_sync/a_sync.py +++ b/a_sync/a_sync.py @@ -102,7 +102,7 @@ def to_async(blocking_func: AnyCallable) -> AnyCallable: * keep an async partial the same * validate that it doesn't matter if the loop is running. """ - if asyncio.iscoroutinefunction(getattr(blocking_func, 'func', blocking_func)): + if asyncio.iscoroutinefunction(blocking_func) or asyncio.iscoroutinefunction(getattr(blocking_func, 'func', None)): # caller messed up - this is already async async_func = blocking_func else: @@ -146,7 +146,7 @@ def to_blocking(async_func: AnyCallable) -> AnyCallable: * keep blocking partial the same * convert async partial """ - if not asyncio.iscoroutinefunction(getattr(async_func, 'func', async_func)): + if not (asyncio.iscoroutinefunction(async_func) or asyncio.iscoroutinefunction(getattr(async_func, 'func', None))): # caller messed up - this is already blocking blocking = async_func else: diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..1dede35 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,3 @@ +pytest==3.5.1 +asynctest==0.12.0 +pytest-asyncio==0.8.0 \ No newline at end of file diff --git a/tests/test_a_sync.py b/tests/test_a_sync.py new file mode 100644 index 0000000..6bc06ae --- /dev/null +++ b/tests/test_a_sync.py @@ -0,0 +1,67 @@ +import functools + +import asynctest +import pytest + +import a_sync + + +def test_block(): + async def async_func(): + return 5 + + def sync_func(): + return 4 + + assert a_sync.block(async_func) == 5 + assert a_sync.block(sync_func) == 4 + + +def test_block_partials(): + def sync_func_to_partial(retval): + return retval + + async def async_func_to_partial(retval): + return retval + + sync_partial = functools.partial(sync_func_to_partial, 5) + async_partial = functools.partial(async_func_to_partial, 4) + + assert a_sync.block(sync_partial) == 5 + assert a_sync.block(async_partial) == 4 + + +def test_block_works_with_CoroutineMock(): + assert 3 == a_sync.block(asynctest.CoroutineMock(return_value=3)) + + +@pytest.mark.asyncio +async def test_run(): + async def async_func(): + return 5 + + def sync_func(): + return 4 + + assert await a_sync.run(async_func) == 5 + assert await a_sync.run(sync_func) == 4 + + +@pytest.mark.asyncio +async def test_run_works_with_CoroutineMock(): + assert 3 == await a_sync.run(asynctest.CoroutineMock(return_value=3)) + + +@pytest.mark.asyncio +async def test_run_partials(): + def sync_func_to_partial(retval): + return retval + + async def async_func_to_partial(retval): + return retval + + sync_partial = functools.partial(sync_func_to_partial, 5) + async_partial = functools.partial(async_func_to_partial, 4) + + assert await a_sync.run(sync_partial) == 5 + assert await a_sync.run(async_partial) == 4 diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..d28b9e1 --- /dev/null +++ b/tox.ini @@ -0,0 +1,9 @@ +[tox] +envlist = py36 + +[testenv] +basepython = python3.6 +deps = + --requirement={toxinidir}/requirements-dev.txt +commands = + py.test {posargs:tests} \ No newline at end of file