Commit d040c8d5 authored by Vincent Michel's avatar Vincent Michel

Add gevent compatibility

parent 3c491e17
Pipeline #1252 passed with stages
in 2 minutes and 34 seconds
...@@ -22,6 +22,7 @@ Run requirements: ...@@ -22,6 +22,7 @@ Run requirements:
- cffi - cffi
- numpy - numpy
- gevent (optional)
Test requirements: Test requirements:
...@@ -64,6 +65,16 @@ Example usage: ...@@ -64,6 +65,16 @@ Example usage:
array([13260, 52275, 256, ..., 0, 0, 0], dtype=uint32) array([13260, 52275, 256, ..., 0, 0, 0], dtype=uint32)
``` ```
Gevent mode
-----------
Make the interface gevent-compatible using:
``` python
>>> from handel.gevent import patch
>>> patch()
```
Tests Tests
----- -----
......
"""Provide gevent compatibility.
Usage:
>>> from handel.gevent import patch
>>> patch()
"""
from __future__ import absolute_import
from functools import wraps
from gevent import threadpool
from .interface import handel
# Green pool
# The 'maxsize=1' argument provides implicit locking
POOL = threadpool.ThreadPool(maxsize=1)
# Green decorator
def green(func, pool=POOL):
"""Make a given function gevent-compatible by running
it in a gevent threadpool."""
@wraps(func)
def wrapper(*args, **kwargs):
return pool.apply(func, args, kwargs)
return wrapper
# Patch function
def patch():
"""Provide gevent compatibility.
Usage:
>>> from handel.gevent import patch
>>> patch()
"""
for name in dir(handel):
if name.startswith('xia'):
func = getattr(handel, name)
setattr(handel, name, green(func))
...@@ -21,11 +21,12 @@ import sys ...@@ -21,11 +21,12 @@ import sys
import zerorpc import zerorpc
import msgpack_numpy import msgpack_numpy
import handel.gevent
import handel.interface as hi import handel.interface as hi
# Patching # Patching
handel.gevent.patch()
msgpack_numpy.patch() msgpack_numpy.patch()
......
...@@ -13,7 +13,7 @@ setup( ...@@ -13,7 +13,7 @@ setup(
packages=['handel'], packages=['handel'],
install_requires=['cffi', 'numpy'], install_requires=['cffi', 'numpy'],
setup_requires=['pytest-runner', 'pytest'] if TESTING else [], setup_requires=['pytest-runner', 'pytest'] if TESTING else [],
tests_require=['pytest-cov', 'mock'], tests_require=['pytest-cov', 'mock', 'gevent'],
description="Python binding for the Handel library", description="Python binding for the Handel library",
long_description=long_description, long_description=long_description,
......
import mock
def test_gevent_compatibility():
with mock.patch('cffi.FFI.dlopen') as dlopen:
# Declare xiaSomeFunction
handel = dlopen.return_value
original = handel.xiaSomeFunction
original.__name__ = 'xiaSomeFunction'
original.return_value = 'Some result'
# Patching
from handel.gevent import patch
from handel import interface
assert patch() is None
# Checking
assert interface.handel.xiaSomeFunction.__name__ == 'xiaSomeFunction'
assert interface.handel.xiaSomeFunction(1, a=2) is 'Some result'
original.assert_called_once_with(1, a=2)
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