From db95313f7355c17a278853f4ff6ee1b0008716e7 Mon Sep 17 00:00:00 2001 From: Holger Nahrstaedt <holgernahrstaedt@gmx.de> Date: Fri, 21 Aug 2020 23:43:33 +0200 Subject: [PATCH] Prepare next release 0.24.6 * Improved community selection in beempy createpost * Improved Transactionbuilder object representation * _fetchkeys function moved outside appendSigner * Fix get urls in parse body * Two more nodes have been added to nodelist --- CHANGELOG.rst | 8 +++ beem/blockchaininstance.py | 5 +- beem/cli.py | 7 +++ beem/nodelist.py | 16 +++++ beem/transactionbuilder.py | 117 +++++++++++++++++++++++------------- beem/version.py | 2 +- beemapi/version.py | 2 +- beembase/operationids.py | 2 - beembase/version.py | 2 +- beemgraphenebase/version.py | 2 +- setup.py | 2 +- 11 files changed, 115 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 50c7a3ae..ae85edab 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,13 @@ Changelog ========= +0.24.6 +------ +* Improved community selection in beempy createpost +* Improved Transactionbuilder object representation +* _fetchkeys function moved outside appendSigner +* Fix get urls in parse body +* Two more nodes have been added to nodelist + 0.24.5 ------ * replace percent_hive_dollars by percent_hbd (to make beem HF24 ready) diff --git a/beem/blockchaininstance.py b/beem/blockchaininstance.py index 00a0c589..ab58f3be 100644 --- a/beem/blockchaininstance.py +++ b/beem/blockchaininstance.py @@ -1930,7 +1930,8 @@ class BlockChainInstance(object): if parse_body: def get_urls(mdstring): - return list(set(re.findall(r'http[s]*://[^\s"><\)\(]+', mdstring))) + urls = (re.findall(r'http[s]*://[^\s"><\)\(]+', mdstring)) + return list(dict.fromkeys(urls)) def get_users(mdstring): users = [] @@ -1951,6 +1952,8 @@ class BlockChainInstance(object): img_exts = ['.jpg', '.png', '.gif', '.svg', '.jpeg'] if os.path.splitext(url)[1].lower() in img_exts: image.append(url) + elif url[:25] == "https://images.hive.blog/": + image.append(url) else: links.append(url) users = get_users(body) diff --git a/beem/cli.py b/beem/cli.py index 84c9b2c0..496099ec 100644 --- a/beem/cli.py +++ b/beem/cli.py @@ -2540,6 +2540,9 @@ def createpost(markdown_file, account, title, tags, community, beneficiaries, pe except: c = Communities(limit=1000) comm_cand = c.search_title(community) + if len(comm_cand) == 0: + print("No community could be found!") + continue print(comm_cand.printAsTable()) index = input("Enter community Nr:") if int(index) - 1 >= len(comm_cand): @@ -4739,6 +4742,7 @@ def info(objects): account = Account(obj, blockchain_instance=stm) t = PrettyTable(["Key", "Value"]) t.align = "l" + t._max_width = {"Value" : 80} account_json = account.json() for key in sorted(account_json): value = account_json[key] @@ -4777,6 +4781,7 @@ def info(objects): key_type = stm.wallet.getKeyType(account, obj) t = PrettyTable(["Account", "Key_type"]) t.align = "l" + t._max_width = {"Value" : 80} t.add_row([account["name"], key_type]) print(t) else: @@ -4788,6 +4793,7 @@ def info(objects): if post_json: t = PrettyTable(["Key", "Value"]) t.align = "l" + t._max_width = {"Value" : 80} for key in sorted(post_json): if key in ["body", "active_votes"]: value = "not shown" @@ -4807,6 +4813,7 @@ def info(objects): trx = b.get_transaction(obj) t = PrettyTable(["Key", "Value"]) t.align = "l" + t._max_width = {"Value" : 80} for key in trx: value = trx[key] if key in ["operations", "signatures"]: diff --git a/beem/nodelist.py b/beem/nodelist.py index 45965b77..e6426bbe 100644 --- a/beem/nodelist.py +++ b/beem/nodelist.py @@ -178,6 +178,22 @@ class NodeList(list): "owner": "roelandp", "hive": True, "score": 50 + }, + { + "url": "https://api.c0ff33a.uk", + "version": "0.23.0", + "type": "appbase", + "owner": "c0ff33a", + "hive": True, + "score": 40 + }, + { + "url": "https://api.deathwing.me", + "version": "0.23.0", + "type": "appbase", + "owner": "deathwing", + "hive": True, + "score": 40 } ] super(NodeList, self).__init__(nodes) diff --git a/beem/transactionbuilder.py b/beem/transactionbuilder.py index 9bb676fe..35d34e33 100644 --- a/beem/transactionbuilder.py +++ b/beem/transactionbuilder.py @@ -36,17 +36,17 @@ class TransactionBuilder(dict): :param dict tx: transaction (Optional). If not set, the new transaction is created. :param int expiration: Delay in seconds until transactions are supposed to expire *(optional)* (default is 30) - :param Steem steem_instance: If not set, shared_blockchain_instance() is used + :param Hive/Steem blockchain_instance: If not set, shared_blockchain_instance() is used .. testcode:: from beem.transactionbuilder import TransactionBuilder from beembase.operations import Transfer - from beem import Steem + from beem import Hive wif = "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3" - stm = Steem(nobroadcast=True, keys={'active': wif}) - tx = TransactionBuilder(steem_instance=stm) - transfer = {"from": "test", "to": "test1", "amount": "1 STEEM", "memo": ""} + hive = Hive(nobroadcast=True, keys={'active': wif}) + tx = TransactionBuilder(blockchain_instance=hive) + transfer = {"from": "test", "to": "test1", "amount": "1 HIVE", "memo": ""} tx.appendOps(Transfer(transfer)) tx.appendSigner("test", "active") # or tx.appendWif(wif) signed_tx = tx.sign() @@ -113,8 +113,13 @@ class TransactionBuilder(dict): def _unset_require_reconstruction(self): self._require_reconstruction = False + def _get_auth_field(self, permission): + return permission + def __repr__(self): - return str(self) + return "<Transaction num_ops={}, ops={}>".format( + len(self.ops), [op.__class__.__name__ for op in self.ops] + ) def __str__(self): return str(self.json()) @@ -150,26 +155,77 @@ class TransactionBuilder(dict): self.ops.append(ops) self._set_require_reconstruction() + def _fetchkeys(self, account, perm, level=0, required_treshold=1): + + # Do not travel recursion more than 2 levels + if level > 2: + return [] + + r = [] + # Let's go through all *keys* of the account + for authority in account[perm]["key_auths"]: + try: + # Try obtain the private key from wallet + wif = self.blockchain.wallet.getPrivateKeyForPublicKey(authority[0]) + except ValueError: + pass + except MissingKeyError: + pass + + if wif: + r.append([wif, authority[1]]) + # If we found a key for account, we add it + # to signing_accounts to be sure we do not resign + # another operation with the same account/wif + self.signing_accounts.append(account) + + # Test if we reached threshold already + if sum([x[1] for x in r]) >= required_treshold: + break + + # Let's see if we still need to go through accounts + if sum([x[1] for x in r]) < required_treshold: + # go one level deeper + for authority in account[perm]["account_auths"]: + # Let's see if we can find keys for an account in + # account_auths + # This is recursive with a limit at level 2 (see above) + auth_account = Account(authority[0], blockchain_instance=self.blockchain) + required_treshold = auth_account[perm]["weight_threshold"] + keys = self._fetchkeys(auth_account, perm, level + 1, required_treshold) + + for key in keys: + r.append(key) + + # Test if we reached threshold already and break + if sum([x[1] for x in r]) >= required_treshold: + break + + return r + def appendSigner(self, account, permission): """ Try to obtain the wif key from the wallet by telling which account and permission is supposed to sign the transaction It is possible to add more than one signer. + + :param str account: account to sign transaction with + :param str permission: type of permission, e.g. "active", "owner" etc """ if not self.blockchain.is_connected(): return if permission not in ["active", "owner", "posting"]: raise AssertionError("Invalid permission") account = Account(account, blockchain_instance=self.blockchain) - if permission not in account: + auth_field = self._get_auth_field(permission) + if auth_field not in account: account = Account(account, blockchain_instance=self.blockchain, lazy=False, full=True) account.clear_cache() account.refresh() - if permission not in account: + if auth_field not in account: account = Account(account, blockchain_instance=self.blockchain) - if permission not in account: + if auth_field not in account: raise AssertionError("Could not access permission") - - required_treshold = account[permission]["weight_threshold"] + if self._use_ledger: if not self._is_constructed() or self._is_require_reconstruction(): self.constructTx() @@ -177,7 +233,7 @@ class TransactionBuilder(dict): key_found = False if self.path is not None: current_pubkey = self.ledgertx.get_pubkey(self.path) - for authority in account[permission]["key_auths"]: + for authority in account[auth_field]["key_auths"]: if str(current_pubkey) == authority[0]: key_found = True if permission == "posting" and not key_found: @@ -197,30 +253,7 @@ class TransactionBuilder(dict): if self.blockchain.use_sc2 and self.blockchain.steemconnect is not None: self.blockchain.steemconnect.set_username(account["name"], permission) return - - def fetchkeys(account, perm, level=0): - if level > 2: - return [] - r = [] - for authority in account[perm]["key_auths"]: - try: - wif = self.blockchain.wallet.getPrivateKeyForPublicKey( - authority[0]) - if wif: - r.append([wif, authority[1]]) - except ValueError: - pass - except MissingKeyError: - pass - - if sum([x[1] for x in r]) < required_treshold: - # go one level deeper - for authority in account[perm]["account_auths"]: - auth_account = Account( - authority[0], blockchain_instance=self.blockchain) - r.extend(fetchkeys(auth_account, perm, level + 1)) - - return r + if account["name"] not in self.signing_accounts: # is the account an instance of public key? @@ -231,20 +264,20 @@ class TransactionBuilder(dict): ) ) else: - if permission not in account: + if auth_field not in account: raise AssertionError("Could not access permission") - required_treshold = account[permission]["weight_threshold"] - keys = fetchkeys(account, permission) + required_treshold = account[auth_field]["weight_threshold"] + keys = self._fetchkeys(account, permission, required_treshold=required_treshold) # If keys are empty, try again with active key if not keys and permission == "posting": - _keys = fetchkeys(account, "active") + _keys = self._fetchkeys(account, "active", required_treshold=required_treshold) keys.extend(_keys) # If keys are empty, try again with owner key if not keys and permission != "owner": - _keys = fetchkeys(account, "owner") + _keys = self._fetchkeys(account, "owner", required_treshold=required_treshold) keys.extend(_keys) for x in keys: - self.wifs.add(x[0]) + self.appendWif(x[0]) self.signing_accounts.append(account["name"]) diff --git a/beem/version.py b/beem/version.py index f8f66182..162cfc92 100644 --- a/beem/version.py +++ b/beem/version.py @@ -1,2 +1,2 @@ """THIS FILE IS GENERATED FROM beem SETUP.PY.""" -version = '0.24.5' +version = '0.24.6' diff --git a/beemapi/version.py b/beemapi/version.py index f8f66182..162cfc92 100644 --- a/beemapi/version.py +++ b/beemapi/version.py @@ -1,2 +1,2 @@ """THIS FILE IS GENERATED FROM beem SETUP.PY.""" -version = '0.24.5' +version = '0.24.6' diff --git a/beembase/operationids.py b/beembase/operationids.py index 70be3c32..6a1fbf7d 100644 --- a/beembase/operationids.py +++ b/beembase/operationids.py @@ -66,8 +66,6 @@ ops = [ 'comment_payout_update', 'return_vesting_delegation', 'comment_benefactor_reward', - 'return_vesting_delegation', - 'comment_benefactor_reward', 'producer_reward', 'clear_null_account_balance', 'proposal_pay', diff --git a/beembase/version.py b/beembase/version.py index f8f66182..162cfc92 100644 --- a/beembase/version.py +++ b/beembase/version.py @@ -1,2 +1,2 @@ """THIS FILE IS GENERATED FROM beem SETUP.PY.""" -version = '0.24.5' +version = '0.24.6' diff --git a/beemgraphenebase/version.py b/beemgraphenebase/version.py index f8f66182..162cfc92 100644 --- a/beemgraphenebase/version.py +++ b/beemgraphenebase/version.py @@ -1,2 +1,2 @@ """THIS FILE IS GENERATED FROM beem SETUP.PY.""" -version = '0.24.5' +version = '0.24.6' diff --git a/setup.py b/setup.py index 4c22d642..1d9a6015 100755 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ except LookupError: ascii = codecs.lookup('ascii') codecs.register(lambda name, enc=ascii: {True: enc}.get(name == 'mbcs')) -VERSION = '0.24.5' +VERSION = '0.24.6' tests_require = ['mock >= 2.0.0', 'pytest', 'pytest-mock', 'parameterized'] -- GitLab