From 5bafda23931d955910c76d660c6a9e35f3c207e7 Mon Sep 17 00:00:00 2001 From: Piper Merriam Date: Tue, 10 Jan 2017 08:59:58 -0700 Subject: [PATCH] more gevent abstractions --- README.md | 2 +- docs/quickstart.rst | 2 +- requirements-dev.txt | 3 +-- .../test_admin_start_stop_methods.py | 4 ++-- tests/providers/test_testrpc_provider.py | 2 +- tests/shh-module/test_shh_filter.py | 13 +++++++------ tests/txpool-module/test_txpool_content.py | 8 +++++--- tests/txpool-module/test_txpool_inspect.py | 8 +++++--- web3/utils/async/__init__.py | 2 ++ web3/utils/async/gevent_async.py | 1 + web3/utils/async/stdlib_async.py | 11 +++++++++++ web3/utils/filters.py | 19 +++++++++++-------- web3/utils/transactions.py | 8 ++++---- 13 files changed, 52 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 43aa948..5b0b66f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ For testing you can use the `TestRPCProvider`. This depends on following installation command. ```sh -pip install web3[Tester] +pip install web3[tester] ``` Then in your code: diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 4a68e92..b789159 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -18,7 +18,7 @@ Or to install with support for the ``TestRPCProvider`` and .. code-block:: shell - $ pip install web3[Tester] + $ pip install web3[tester] Installation from source can be done from the root of the project with the following command. diff --git a/requirements-dev.txt b/requirements-dev.txt index 3666418..5b81212 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,10 +2,9 @@ pytest>=2.8.2 pytest-pythonpath>=0.3 tox>=1.8.0 eth-testrpc>=0.9.3 -py-geth>=1.4.0 ethereum>=1.5.2 secp256k1>=0.13.1 -rlp>=0.4.6 +rlp>=0.4.6,<0.4.7 hypothesis>=3.4.2 flaky>=3.3.0 flake8==3.0.4 diff --git a/tests/admin-module/test_admin_start_stop_methods.py b/tests/admin-module/test_admin_start_stop_methods.py index 1dc0629..6c8b26b 100644 --- a/tests/admin-module/test_admin_start_stop_methods.py +++ b/tests/admin-module/test_admin_start_stop_methods.py @@ -1,9 +1,9 @@ import pytest -from gevent import socket - from flaky import flaky +from web3.utils.async import socket + def get_open_port(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) diff --git a/tests/providers/test_testrpc_provider.py b/tests/providers/test_testrpc_provider.py index 5e117f1..8efec76 100644 --- a/tests/providers/test_testrpc_provider.py +++ b/tests/providers/test_testrpc_provider.py @@ -1,11 +1,11 @@ import pytest -from gevent import socket from web3.providers.manager import RequestManager from web3.providers.tester import ( TestRPCProvider, is_testrpc_available, ) +from web3.utils.async import socket def get_open_port(): diff --git a/tests/shh-module/test_shh_filter.py b/tests/shh-module/test_shh_filter.py index 0f23f4b..75dd8ab 100644 --- a/tests/shh-module/test_shh_filter.py +++ b/tests/shh-module/test_shh_filter.py @@ -1,20 +1,21 @@ -import gevent +from web3.utils.async import sleep + def test_shh_filter(web3, skip_if_testrpc): skip_if_testrpc(web3) recieved_messages = [] shh_filter = web3.shh.filter({"topics":[web3.fromAscii("test")]}) shh_filter.watch(recieved_messages.append) - + payloads = [] payloads.append(str.encode("payload1")) web3.shh.post({"topics":[web3.fromAscii("test")], "payload":web3.fromAscii(payloads[len(payloads)-1])}) - gevent.sleep(1) - + sleep(1) + payloads.append(str.encode("payload2")) web3.shh.post({"topics":[web3.fromAscii("test")], "payload":web3.fromAscii(payloads[len(payloads)-1])}) - gevent.sleep(1) + sleep(1) assert len(recieved_messages) > 1 - + for message in recieved_messages: assert web3.toAscii(message["payload"]) in payloads diff --git a/tests/txpool-module/test_txpool_content.py b/tests/txpool-module/test_txpool_content.py index 41e2e8a..7daa887 100644 --- a/tests/txpool-module/test_txpool_content.py +++ b/tests/txpool-module/test_txpool_content.py @@ -1,5 +1,6 @@ import random -import gevent + +from web3.utils import async def test_txpool_content(web3_empty): @@ -7,9 +8,10 @@ def test_txpool_content(web3_empty): web3.miner.stop() - with gevent.Timeout(60): + with async.Timeout(60) as timeout: while web3.miner.hashrate or web3.eth.mining: - gevent.sleep(random.random()) + async.sleep(random.random()) + timeout.check() txn_1_hash = web3.eth.sendTransaction({ 'from': web3.eth.coinbase, diff --git a/tests/txpool-module/test_txpool_inspect.py b/tests/txpool-module/test_txpool_inspect.py index 43b1303..1475b95 100644 --- a/tests/txpool-module/test_txpool_inspect.py +++ b/tests/txpool-module/test_txpool_inspect.py @@ -1,5 +1,6 @@ import random -import gevent + +from web3.utils import async def test_txpool_inspect(web3_empty): @@ -7,9 +8,10 @@ def test_txpool_inspect(web3_empty): web3.miner.stop() - with gevent.Timeout(60): + with async.Timeout(60) as timeout: while web3.miner.hashrate or web3.eth.mining: - gevent.sleep(random.random()) + async.sleep(random.random()) + timeout.check() txn_1_hash = web3.eth.sendTransaction({ 'from': web3.eth.coinbase, diff --git a/web3/utils/async/__init__.py b/web3/utils/async/__init__.py index e2178ad..217fd09 100644 --- a/web3/utils/async/__init__.py +++ b/web3/utils/async/__init__.py @@ -8,6 +8,7 @@ if 'WEB3_ASYNC_GEVENT' in os.environ: socket, threading, make_server, + GreenletThread, ) else: from .stdlib_async import ( # noqa @@ -16,4 +17,5 @@ else: socket, threading, make_server, + GreenletThread, ) diff --git a/web3/utils/async/gevent_async.py b/web3/utils/async/gevent_async.py index c3d5f72..3a5023d 100644 --- a/web3/utils/async/gevent_async.py +++ b/web3/utils/async/gevent_async.py @@ -11,6 +11,7 @@ from gevent import ( # noqa: F401 sleep = gevent.sleep spawn = gevent.spawn +GreenletThread = gevent.Greenlet class Timeout(gevent.Timeout): diff --git a/web3/utils/async/stdlib_async.py b/web3/utils/async/stdlib_async.py index 36b700a..e256e84 100644 --- a/web3/utils/async/stdlib_async.py +++ b/web3/utils/async/stdlib_async.py @@ -101,3 +101,14 @@ def spawn(target, *args, **kwargs): thread.daemon = True thread.start() return thread + + +class GreenletThread(threading.Thread): + def __init__(self, target=None, args=None, kwargs=None): + if target is None: + target = self._run + super(GreenletThread, self).__init__(target=target, args=args, kwargs=kwargs) + self.daemon = True + + def _run(self): + pass diff --git a/web3/utils/filters.py b/web3/utils/filters.py index 7cf64ff..f4efdf0 100644 --- a/web3/utils/filters.py +++ b/web3/utils/filters.py @@ -1,6 +1,5 @@ import re import random -import gevent from .types import ( is_string, @@ -10,6 +9,10 @@ from .events import ( construct_event_topic_set, construct_event_data_set, ) +from .async import ( + sleep, + GreenletThread, +) def construct_event_filter_params(event_abi, @@ -56,7 +59,7 @@ def construct_event_filter_params(event_abi, return data_filters_set, filter_params -class Filter(gevent.Greenlet): +class Filter(GreenletThread): callbacks = None running = None stopped = False @@ -66,7 +69,7 @@ class Filter(gevent.Greenlet): self.web3 = web3 self.filter_id = filter_id self.callbacks = [] - gevent.Greenlet.__init__(self) + super(Filter, self).__init__() def __str__(self): return "Filter for {0}".format(self.filter_id) @@ -84,9 +87,9 @@ class Filter(gevent.Greenlet): if self.is_valid_entry(entry): callback_fn(self.format_entry(entry)) if self.poll_interval is None: - gevent.sleep(random.random()) + sleep(random.random()) else: - gevent.sleep(self.poll_interval) + sleep(self.poll_interval) def format_entry(self, entry): """ @@ -108,7 +111,7 @@ class Filter(gevent.Greenlet): if not self.running: self.start() - gevent.sleep(0) + sleep(0) def stop_watching(self, timeout=0): self.running = False @@ -224,9 +227,9 @@ class ShhFilter(Filter): if self.is_valid_entry(entry): callback_fn(self.format_entry(entry)) if self.poll_interval is None: - gevent.sleep(random.random()) + sleep(random.random()) else: - gevent.sleep(self.poll_interval) + sleep(self.poll_interval) def stop_watching(self, timeout=0): self.running = False diff --git a/web3/utils/transactions.py b/web3/utils/transactions.py index 2a2992a..5319bad 100644 --- a/web3/utils/transactions.py +++ b/web3/utils/transactions.py @@ -1,7 +1,5 @@ import random -import gevent - import rlp from rlp.sedes import big_endian_int, binary, Binary from rlp.utils import int_to_big_endian @@ -27,15 +25,17 @@ from .address import ( from .formatting import ( pad_left, ) +from . import async def wait_for_transaction_receipt(web3, txn_hash, timeout=120): - with gevent.Timeout(timeout): + with async.Timeout(timeout) as _timeout: while True: txn_receipt = web3.eth.getTransactionReceipt(txn_hash) if txn_receipt is not None: break - gevent.sleep(random.random()) + async.sleep(random.random()) + _timeout.check() return txn_receipt