diff --git a/.travis.yml b/.travis.yml index 2bad890a7df5393622b9cea4a8cc16d1643afdd5..62f8738d7a4b27778e0dc5de9902fd37dc68cbb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,10 @@ matrix: python: 3.6 env: - TOXENV=pylint + - os: linux + python: 3.6 + env: + - TOXENV=flake8 - os: linux python: 2.7 env: diff --git a/appveyor.yml b/appveyor.yml index 9b1e6841b12f1cd2842c10d0f271e23537d81d89..0f0dc53ea8c007919089b02fcdeac15c27e08c75 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -60,7 +60,7 @@ install: - conda info -a - conda install --yes nose conda-build setuptools pip numpy pytest-pylint - conda install --yes pycryptodomex scrypt pyyaml pytest pytest-mock coverage mock appdirs - - conda install --yes ecdsa requests future websocket-client pytz six Click prettytable + - conda install --yes ecdsa requests future websocket-client pytz six Click events prettytable # Upgrade to the latest version of pip to avoid it displaying warnings diff --git a/beem/account.py b/beem/account.py index 0b91f3e288136f63e806026ceaf281fab6524f2d..a3efbe81631539c682d49a3951203e8746884052 100644 --- a/beem/account.py +++ b/beem/account.py @@ -7,7 +7,7 @@ from builtins import bytes, int, str from beem.instance import shared_steem_instance from .exceptions import AccountDoesNotExistsException from .blockchainobject import BlockchainObject -from .utils import formatTimeString +from .utils import formatTimeString, formatTimedelta from beem.amount import Amount from datetime import datetime, timedelta import pytz @@ -195,11 +195,7 @@ class Account(BlockchainObject): """ Returns the account recharge time """ remainingTime = self.get_recharge_timedelta(voting_power_goal=voting_power_goal) - days, seconds = remainingTime.days, remainingTime.seconds - hours = days * 24 + seconds // 3600 - minutes = (seconds % 3600) // 60 - seconds = (seconds % 60) - return "%d:%s.%s" % (hours, str(minutes).zfill(2), str(seconds).zfill(2)) + return formatTimedelta(remainingTime) def get_recharge_timedelta(self, voting_power_goal=100): """ Returns the account voting power recharge time as timedelta object diff --git a/beem/discussions.py b/beem/discussions.py index a5af234ae8f03ad66872993d0facc28b7b726218..f7a4b9463760e4d0fd8a35ff9b881eb09141e973 100644 --- a/beem/discussions.py +++ b/beem/discussions.py @@ -24,8 +24,8 @@ class Query(dict): :param str parent_author :param str parent_permlink """ - def __init__(self, limit=0, tag="", truncate_body=0, - filter_tags=[""], select_authors=[""], select_tags=[""], + def __init__(self, limit=0, tag="", truncate_body=0, + filter_tags=[""], select_authors=[""], select_tags=[""], start_author=None, start_permlink=None, parent_author=None, parent_permlink=None): self["limit"] = limit self["truncate_body"] = truncate_body @@ -127,7 +127,7 @@ class Discussions_by_active(list): class Discussions_by_cashout(list): """ get_discussions_by_cashout. This query seems to be broken at the moment. The output is always empty. - + :param str discussion_query :param steem steem_instance: Steem() instance to use when accesing a RPC """ diff --git a/beem/price.py b/beem/price.py index f365e5ac3291a5a139e9a243993532882078cf5e..b55b90729c56256585ec9901f43221392c8848b2 100644 --- a/beem/price.py +++ b/beem/price.py @@ -227,7 +227,7 @@ class Price(dict): if not other["base"]["symbol"] == self["base"]["symbol"]: raise AssertionError() if not other["quote"]["symbol"] == self["quote"]["symbol"]: - raise AssertionError() + raise AssertionError() def __mul__(self, other): a = self.copy() diff --git a/beem/utils.py b/beem/utils.py index 7884bd4b205bdf3e179945b91d9e144a6eb5a159..cd922920e519e4fde528a9afa302a18146280cc3 100644 --- a/beem/utils.py +++ b/beem/utils.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals from builtins import next import re import time -from datetime import datetime, tzinfo +from datetime import datetime, tzinfo, timedelta import pytz import difflib from .exceptions import ObjectNotInProposalBuffer @@ -45,6 +45,18 @@ def formatTimeFromNow(secs=0): time.time() + int(secs)).strftime(timeFormat) +def formatTimedelta(td): + """Format timedelta to String + """ + if not isinstance(td, timedelta): + return "" + days, seconds = td.days, td.seconds + hours = days * 24 + seconds // 3600 + minutes = (seconds % 3600) // 60 + seconds = (seconds % 60) + return "%d:%s.%s" % (hours, str(minutes).zfill(2), str(seconds).zfill(2)) + + def parse_time(block_time): """Take a string representation of time from the blockchain, and parse it into datetime object. diff --git a/beemapi/websocket.py b/beemapi/websocket.py index c38e73a1e3f4a3f8389b8c1e8218d19200cc499f..9c89237544c32bd71ea5d9f433104297346ac569 100644 --- a/beemapi/websocket.py +++ b/beemapi/websocket.py @@ -147,7 +147,13 @@ class SteemWebsocket(Events): we call the ``on_block`` slot. """ # id = data["id"] + if "result" not in data: + return block = data["result"] + if block is None: + return + if isinstance(block, (bool, int)): + return if "previous" in block: block_id = block["previous"] block_number = int(block_id[:8], base=16) @@ -165,13 +171,12 @@ class SteemWebsocket(Events): """ log.debug("Received message: %s" % str(reply)) data = {} - # print(reply) try: data = json.loads(reply, strict=False) except ValueError: raise ValueError("API node returned invalid format. Expected JSON!") - if data.get("method") == "notice": + if "method" in data and data.get("method") == "notice": id = data["params"][0] # print(data) @@ -245,9 +250,9 @@ class SteemWebsocket(Events): except websocket.WebSocketException as exc: if (self.num_retries >= 0 and cnt > self.num_retries): raise NumRetriesReached() - + if cnt < 0: - seeptime = 0 + sleeptime = 0 elif cnt < 10: sleeptime = (cnt - 1) * 2 else: diff --git a/beemgraphenebase/types.py b/beemgraphenebase/types.py index 3fdd439ed61f699bbe90670ecb9f61d9003a33be..a6208a84e4a93e8f23d75f74efbfcf9f261fba58 100644 --- a/beemgraphenebase/types.py +++ b/beemgraphenebase/types.py @@ -418,9 +418,8 @@ class ObjectId(object): self.Id = object_str if type_verify: if not object_type[type_verify] == int(type): - raise AssertionError("Object id does not match object type! " +\ - "Excpected %d, got %d" %\ - (object_type[type_verify], int(type))) + raise AssertionError("Object id does not match object type! " + + "Excpected %d, got %d" % (object_type[type_verify], int(type))) else: raise Exception("Object id is invalid") @@ -463,7 +462,7 @@ class FullObjectId(object): class Enum8(Uint8): def __init__(self, selection): if selection not in self.options and \ - not (isinstance(selection, int) and len(self.options) < selection): + not (isinstance(selection, int) and len(self.options) < selection): raise AssertionError("Options are %s. Given '%s'" % ( self.options, selection)) if selection in self.options: diff --git a/examples/benchmark_beem.py b/examples/benchmark_beem.py new file mode 100644 index 0000000000000000000000000000000000000000..c5eb72779ad8aa975ada566269a9a88b26e56d74 --- /dev/null +++ b/examples/benchmark_beem.py @@ -0,0 +1,62 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals +import sys +from datetime import datetime, timedelta +import time +import io +import logging + +from beem.blockchain import Blockchain +from beem.block import Block +from beem.steem import Steem +from beem.utils import parse_time, formatTimedelta + + +if __name__ == "__main__": + stm = Steem() + blockchain = Blockchain(steem_instance=stm) + last_block_id = 19273700 + last_block = Block(last_block_id, steem_instance=stm) + startTime = datetime.now() + how_many_hours = 1 + stopTime = last_block.time() + timedelta(seconds=how_many_hours * 60 * 60) + ltime = time.time() + cnt = 0 + total_transaction = 0 + + start_time = time.time() + last_node = blockchain.steem.rpc.url + print("Current node:", last_node) + for entry in blockchain.blocks(start=last_block_id): + block_no = entry["block_num"] + + for tx in entry["transactions"]: + for op in tx["operations"]: + total_transaction += 1 + block_time = parse_time(entry["timestamp"]) + if block_time > stopTime: + total_duration = formatTimedelta(datetime.now() - startTime) + last_block_id = block_no + avtran = total_transaction / (last_block_id - 19273700) + print("* HOUR mark: Processed %d blockchain hours in %s" % (how_many_hours, total_duration)) + print("* Blocks %d, Transactions %d (Avg. per Block %f)" % ((last_block_id - 19273700), total_transaction, avtran)) + break + + if block_no != last_block_id: + cnt += 1 + last_block_id = block_no + if last_block_id % 100 == 0: + now = time.time() + duration = now - ltime + total_duration = now - start_time + speed = int(100000.0 / duration) * 1.0 / 1000 + avspeed = int((last_block_id - 19273700) * 1000 / total_duration) * 1.0 / 1000 + avtran = total_transaction / (last_block_id - 19273700) + ltime = now + if last_node != blockchain.steem.rpc.url: + last_node = blockchain.steem.rpc.url + print("Current node:", last_node) + print("* 100 blocks processed in %.2f seconds. Speed %.2f. Avg: %.2f. Avg.Trans:" + "%.2f Count: %d Block minutes: %d" % (duration, speed, avspeed, avtran, cnt, cnt * 3 / 60)) diff --git a/examples/print_votes.py b/examples/print_votes.py new file mode 100644 index 0000000000000000000000000000000000000000..17eebecfa2b29077e77d415fe753909fd19219de --- /dev/null +++ b/examples/print_votes.py @@ -0,0 +1,47 @@ +from __future__ import print_function +import sys +sys.path.append('../') +from datetime import timedelta +import time +import io +from beem.notify import Notify +from beem.utils import parse_time +import logging +log = logging.getLogger(__name__) +logging.basicConfig(level=logging.INFO) + + +class TestBot: + def __init__(self): + self.notify = None + self.blocks = 0 + self.hourcount = 0 + self.start = time.time() + self.last = time.time() + def new_block(self,block): + print(block["timestamp"]) + timestamp = parse_time(block["timestamp"]) + chunk = 10 + self.blocks = self.blocks + 1 + if self.blocks % chunk == 0: + self.notify.close() + now = time.time() + duration = now - self.last + total_duration = now - self.start + speed = int(chunk*1000.0/duration)*1.0/1000 + avspeed = int(self.blocks*1000/total_duration)*1.0/1000 + self.last = now + def hour(self): + self.hourcount = self.hourcount + 1 + now = time.time() + total_duration = str(timedelta(seconds=now-self.start)) + print("* HOUR mark: Processed "+str(self.hourcount)+ " blockchain hours in "+ total_duration) + if self.hourcount == 1*24: + print("Ending eventloop") + self.notify.close() + +if __name__ == "__main__": + tb = TestBot() + notify = Notify(on_block=tb.new_block) + tb.notify = notify + notify.listen() \ No newline at end of file diff --git a/tests/test_utils.py b/tests/test_utils.py index a8ca979c4303608926a2b6b5af9b3311d5fb704e..52abfb6f426168059b718da068b9b6e806d9e6ac 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -3,7 +3,9 @@ from __future__ import division from __future__ import print_function from __future__ import unicode_literals import unittest +from datetime import datetime from beem.utils import ( + formatTimedelta, assets_from_string, resolve_authorperm, resolve_authorpermvoter, @@ -58,3 +60,7 @@ class Testcases(unittest.TestCase): self.assertEqual(make_patch("aa", "ab"), '@@ -1 +1 @@\n-aa\n+ab\n') self.assertEqual(make_patch("Hello!\n Das ist ein Test!\nEnd.\n", "Hello!\n This is a Test\nEnd.\n"), '@@ -1,3 +1,3 @@\n Hello!\n- Das ist ein Test!\n+ This is a Test\n End.\n') + + def test_formatTimedelta(self): + now = datetime.now() + self.assertEqual(formatTimedelta(now-now), '0:00.00') diff --git a/tox.ini b/tox.ini index 3bd1aafcb5665765fe07e046bb95db6e9da00347..b3a07a59db697a95eb056bc57600b76f876e9ed6 100644 --- a/tox.ini +++ b/tox.ini @@ -17,12 +17,12 @@ commands = [testenv:flake8] deps= flake8 - flake8-docstrings>=0.2.7 - flake8-import-order>=0.9 - pep8-naming - flake8-colors + # flake8-docstrings>=0.2.7 + # flake8-import-order>=0.9 + # pep8-naming + # flake8-colors commands= - flake8 beem beemapi beembase beemgraphenebase beemgrapheneapi setup.py + flake8 beem beemapi beembase beemgraphenebase beemgrapheneapi setup.py examples [testenv:pylint] deps=