Skip to content

Commit

Permalink
Fix history item with index 0 for https://api.hive.blog
Browse files Browse the repository at this point in the history
  • Loading branch information
holgern committed Nov 7, 2020
1 parent 5075fd9 commit d9b9f96
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 29 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Changelog
=========
0.24.19
-------
* Fix history item with index 0 for https://api.hive.blog

0.24.18
-------
* Adapt account history on api changes and fixes issue #267
Expand Down
68 changes: 46 additions & 22 deletions beem/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,8 @@ def virtual_op_count(self, until=None):
if op_count is None or len(op_count) == 0:
op_count = self._get_account_history(start=-1, limit=1)
if isinstance(op_count, list) and len(op_count) > 0 and len(op_count[0]) > 0:
if self.blockchain.rpc.url == "https://api.hive.blog":
return op_count[-1][0] + 1
return op_count[-1][0]
else:
return 0
Expand All @@ -1847,6 +1849,8 @@ def _get_account_history(self, account=None, start=-1, limit=1, operation_filter
account = extract_account_name(account)
if limit < 1:
limit = 1
elif limit > 1000:
limit = 1000
if not self.blockchain.is_connected():
raise OfflineHasNoRPCException("No RPC available in offline mode!")
self.blockchain.rpc.set_next_node_on_empty_reply(False)
Expand Down Expand Up @@ -1879,7 +1883,24 @@ def _get_account_history(self, account=None, start=-1, limit=1, operation_filter
api="database")
return ret

def estimate_virtual_op_num(self, blocktime, stop_diff=0, max_count=100):
def _get_blocknum_from_hist(self, index, min_index=1):
if index >= 0 and index < min_index:
index = min_index
op = self._get_account_history(start=(index))
if len(op) == 0:
return None
return op[0][1]['block']

def _get_first_blocknum(self):
min_index = 0
try:
created = self._get_blocknum_from_hist(0, min_index=min_index)
except:
min_index = 1
created = self._get_blocknum_from_hist(0, min_index=min_index)
return created, min_index

def estimate_virtual_op_num(self, blocktime, stop_diff=0, max_count=100, min_index=None):
""" Returns an estimation of an virtual operation index for a given time or blockindex
:param blocktime: start time or start block index from which account
Expand Down Expand Up @@ -1921,20 +1942,15 @@ def estimate_virtual_op_num(self, blocktime, stop_diff=0, max_count=100):
print(block_est - block_num)
"""
def get_blocknum(index):
if index == 0:
index = 1
op = self._get_account_history(start=(index))
if len(op) == 0:
return None
return op[0][1]['block']

max_index = self.virtual_op_count()
if max_index < stop_diff:
return 0

# calculate everything with block numbers
created = get_blocknum(1)
if min_index is None:
created, min_index = self._get_first_blocknum()
else:
created = self._get_blocknum_from_hist(0, min_index=min_index)

# convert blocktime to block number if given as a datetime/date/time
if isinstance(blocktime, (datetime, date, time)):
Expand All @@ -1948,7 +1964,7 @@ def get_blocknum(index):
return 0

# get the block number from the account's latest operation
latest_blocknum = get_blocknum(-1)
latest_blocknum = self._get_blocknum_from_hist(-1, min_index=min_index)

# requested blocknum/timestamp is after the latest account operation
if target_blocknum >= latest_blocknum:
Expand Down Expand Up @@ -1985,10 +2001,10 @@ def get_blocknum(index):

# get block number for current op number estimation
if op_num != last_op_num:
block_num = get_blocknum(op_num)
block_num = self._get_blocknum_from_hist(op_num, min_index=min_index)
while block_num is None and op_num < max_index:
op_num += 1
block_num = get_blocknum(op_num)
block_num = self._get_blocknum_from_hist(op_num, min_index=min_index)
last_op_num = op_num

# check if the required accuracy was reached
Expand Down Expand Up @@ -2267,9 +2283,10 @@ def history(
if start is not None and not use_block_num and not isinstance(start, (datetime, date, time)):
start_index = start
elif start is not None and max_index > batch_size:
op_est = self.estimate_virtual_op_num(start, stop_diff=1)
if op_est == 0:
op_est = 1
created, min_index = self._get_first_blocknum()
op_est = self.estimate_virtual_op_num(start, stop_diff=1, min_index=min_index)
if op_est < min_index:
op_est = min_index
est_diff = 0
if isinstance(start, (datetime, date, time)):
for h in self.get_account_history(op_est, 0):
Expand Down Expand Up @@ -2301,7 +2318,9 @@ def history(
if first > max_index:
_limit = max_index - start_index
first = start_index + _limit - 1
elif first < _limit:
elif first < _limit and self.blockchain.rpc.url == "https://api.hive.blog":
first = _limit - 1
elif first < _limit and self.blockchain.rpc.url != "https://api.hive.blog":
first = _limit
last_round = False

Expand All @@ -2316,7 +2335,9 @@ def history(

while True:
# RPC call
if first < _limit:
if first < _limit - 1 and self.blockchain.rpc.url == "https://api.hive.blog":
first = _limit - 1
elif first < _limit and self.blockchain.rpc.url != "https://api.hive.blog":
first = _limit
batch_count = 0
for item in self.get_account_history(first, _limit, start=None, stop=None, order=1, only_ops=only_ops, exclude_ops=exclude_ops, raw_output=raw_output):
Expand Down Expand Up @@ -2462,10 +2483,11 @@ def history_reverse(
elif start is not None and isinstance(start, int) and not use_block_num:
first = start
elif start is not None and first > batch_size:
op_est = self.estimate_virtual_op_num(start, stop_diff=1)
created, min_index = self._get_first_blocknum()
op_est = self.estimate_virtual_op_num(start, stop_diff=1, min_index=min_index)
est_diff = 0
if op_est == 0:
op_est = 1
if op_est < min_index:
op_est = min_index
if isinstance(start, (datetime, date, time)):
for h in self.get_account_history(op_est, 0):
block_date = formatTimeString(h["timestamp"])
Expand Down Expand Up @@ -2496,7 +2518,9 @@ def history_reverse(
last_item_index = first + 1
while True:
# RPC call
if first - _limit < 0:
if first - _limit < 0 and self.blockchain.rpc.url == 'https://api.hive.blog':
_limit = first + 1
elif first - _limit < 0 and self.blockchain.rpc.url != 'https://api.hive.blog':
_limit = first
batch_count = 0
for item in self.get_account_history(first, _limit, start=None, stop=None, order=-1, only_ops=only_ops, exclude_ops=exclude_ops, raw_output=raw_output):
Expand Down
2 changes: 1 addition & 1 deletion beem/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""THIS FILE IS GENERATED FROM beem SETUP.PY."""
version = '0.24.17'
version = '0.24.19'
2 changes: 1 addition & 1 deletion beemapi/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""THIS FILE IS GENERATED FROM beem SETUP.PY."""
version = '0.24.17'
version = '0.24.19'
2 changes: 1 addition & 1 deletion beembase/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""THIS FILE IS GENERATED FROM beem SETUP.PY."""
version = '0.24.17'
version = '0.24.19'
2 changes: 1 addition & 1 deletion beemgraphenebase/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""THIS FILE IS GENERATED FROM beem SETUP.PY."""
version = '0.24.17'
version = '0.24.19'
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
ascii = codecs.lookup('ascii')
codecs.register(lambda name, enc=ascii: {True: enc}.get(name == 'mbcs'))

VERSION = '0.24.18'
VERSION = '0.24.19'

tests_require = ['mock >= 2.0.0', 'pytest', 'pytest-mock', 'parameterized']

Expand Down
63 changes: 61 additions & 2 deletions tests/beem/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,12 +493,14 @@ def test_estimate_virtual_op_num(self):
self.assertTrue(abs(op_num1 - op_num3) < 200)
block_diff1 = 0
block_diff2 = 0
for h in account.get_account_history(op_num4 - 1, 0):
for h in account.get_account_history(op_num4 - 1, 1):
block_diff1 = (block_num - h["block"])
for h in account.get_account_history(op_num4 + 1, 0):
for h in account.get_account_history(op_num4 + 1, 1):
block_diff2 = (block_num - h["block"])
self.assertTrue(block_diff1 > 0)
self.assertTrue(block_diff1 < 1000)
self.assertTrue(block_diff2 <= 0)
self.assertTrue(block_diff2 > -1000)

def test_estimate_virtual_op_num2(self):
account = self.account
Expand Down Expand Up @@ -542,6 +544,47 @@ def test_history_votes(self):
self.assertEqual(votes_list[0]["voter"], votes_list2[-1]["voter"])
self.assertEqual(votes_list[-1]["voter"], votes_list2[0]["voter"])

def test_history_op_filter(self):
stm = Hive("https://api.hive.blog")
account = Account("beembot", blockchain_instance=stm)
votes_list = list(account.history(only_ops=["vote"]))
other_list = list(account.history(exclude_ops=["vote"]))
all_list = list(account.history())
self.assertEqual(len(all_list), len(votes_list) + len(other_list))
index = 0
for h in sorted((votes_list + other_list), key=lambda h: h["index"]):
self.assertEqual(index, h["index"])
index += 1
votes_list = list(account.history_reverse(only_ops=["vote"]))
other_list = list(account.history_reverse(exclude_ops=["vote"]))
all_list = list(account.history_reverse())
self.assertEqual(len(all_list), len(votes_list) + len(other_list))
index = 0
for h in sorted((votes_list + other_list), key=lambda h: h["index"]):
self.assertEqual(index, h["index"])
index += 1

def test_history_op_filter2(self):
stm = Hive("https://api.hive.blog")
batch_size = 100
account = Account("beembot", blockchain_instance=stm)
votes_list = list(account.history(only_ops=["vote"], batch_size=batch_size))
other_list = list(account.history(exclude_ops=["vote"], batch_size=batch_size))
all_list = list(account.history(batch_size=batch_size))
self.assertEqual(len(all_list), len(votes_list) + len(other_list))
index = 0
for h in sorted((votes_list + other_list), key=lambda h: h["index"]):
self.assertEqual(index, h["index"])
index += 1
votes_list = list(account.history_reverse(only_ops=["vote"], batch_size=batch_size))
other_list = list(account.history_reverse(exclude_ops=["vote"], batch_size=batch_size))
all_list = list(account.history_reverse(batch_size=batch_size))
self.assertEqual(len(all_list), len(votes_list) + len(other_list))
index = 0
for h in sorted((votes_list + other_list), key=lambda h: h["index"]):
self.assertEqual(index, h["index"])
index += 1

def test_comment_history(self):
account = self.account
comments = []
Expand Down Expand Up @@ -601,3 +644,19 @@ def test_extract_account_name(self):
self.assertEqual(extract_account_name("holger80"), "holger80")
self.assertEqual(extract_account_name({"name": "holger80"}), "holger80")
self.assertEqual(extract_account_name(""), "")

def test_get_blocknum_from_hist(self):
stm = Hive("https://api.hive.blog")
account = Account("beembot", blockchain_instance=stm)
created, min_index = account._get_first_blocknum()
if min_index == 0:
self.assertEqual(created, 23687631)
block = account._get_blocknum_from_hist(0, min_index=min_index)
self.assertEqual(block, 23687631)
hist_num = account.estimate_virtual_op_num(block, min_index=min_index)
self.assertEqual(hist_num, 0)
else:
self.assertEqual(created, 23721519)
min_index = 1
block = account._get_blocknum_from_hist(0, min_index=min_index)
self.assertEqual(block, 23721519)

0 comments on commit d9b9f96

Please sign in to comment.