electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 9037f25da13873c751a1a333b43bae29296b0c13
parent 34569d172ff797047d11ae6f6bb6f95a9189879b
Author: SomberNight <somber.night@protonmail.com>
Date:   Sun, 28 Oct 2018 00:28:29 +0200

kill old-style namedtuples

Diffstat:
Melectrum/coinchooser.py | 18++++++++++--------
Melectrum/gui/qt/util.py | 11++++++++---
Melectrum/network.py | 11++++++-----
Melectrum/plugin.py | 23++++++++++++++++-------
Melectrum/plugins/coldcard/coldcard.py | 4++--
Melectrum/plugins/hw_wallet/plugin.py | 13++++++-------
Melectrum/transaction.py | 22++++++++++++++--------
Melectrum/util.py | 20++++++++++++--------
8 files changed, 74 insertions(+), 48 deletions(-)

diff --git a/electrum/coinchooser.py b/electrum/coinchooser.py @@ -22,8 +22,9 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from collections import defaultdict, namedtuple +from collections import defaultdict from math import floor, log10 +from typing import NamedTuple, List from .bitcoin import sha256, COIN, TYPE_ADDRESS, is_address from .transaction import Transaction, TxOutput @@ -68,13 +69,14 @@ class PRNG: x[i], x[j] = x[j], x[i] -Bucket = namedtuple('Bucket', - ['desc', - 'weight', # as in BIP-141 - 'value', # in satoshis - 'coins', # UTXOs - 'min_height', # min block height where a coin was confirmed - 'witness']) # whether any coin uses segwit +class Bucket(NamedTuple): + desc: str + weight: int # as in BIP-141 + value: int # in satoshis + coins: List[dict] # UTXOs + min_height: int # min block height where a coin was confirmed + witness: bool # whether any coin uses segwit + def strip_unneeded(bkts, sufficient_funds): '''Remove buckets that are unnecessary in achieving the spend amount''' diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py @@ -3,8 +3,8 @@ import time import sys import platform import queue -from collections import namedtuple from functools import partial +from typing import NamedTuple, Callable, Optional from PyQt5.QtGui import * from PyQt5.QtCore import * @@ -638,7 +638,12 @@ class TaskThread(QThread): '''Thread that runs background tasks. Callbacks are guaranteed to happen in the context of its parent.''' - Task = namedtuple("Task", "task cb_success cb_done cb_error") + class Task(NamedTuple): + task: Callable + cb_success: Optional[Callable] + cb_done: Optional[Callable] + cb_error: Optional[Callable] + doneSig = pyqtSignal(object, object, object) def __init__(self, parent, on_error=None): @@ -654,7 +659,7 @@ class TaskThread(QThread): def run(self): while True: - task = self.tasks.get() + task = self.tasks.get() # type: TaskThread.Task if not task: break try: diff --git a/electrum/network.py b/electrum/network.py @@ -110,11 +110,12 @@ def pick_random_server(hostmap = None, protocol = 's', exclude_set = set()): return random.choice(eligible) if eligible else None -NetworkParameters = NamedTuple("NetworkParameters", [("host", str), - ("port", str), - ("protocol", str), - ("proxy", Optional[dict]), - ("auto_connect", bool)]) +class NetworkParameters(NamedTuple): + host: str + port: str + protocol: str + proxy: Optional[dict] + auto_connect: bool proxy_modes = ['socks4', 'socks5'] diff --git a/electrum/plugin.py b/electrum/plugin.py @@ -22,13 +22,13 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from collections import namedtuple import traceback import sys import os import pkgutil import time import threading +from typing import NamedTuple, Any, Union from .i18n import _ from .util import (profiler, PrintError, DaemonThread, UserCancelled, @@ -259,14 +259,23 @@ class BasePlugin(PrintError): pass -class DeviceNotFoundError(Exception): - pass +class DeviceNotFoundError(Exception): pass +class DeviceUnpairableError(Exception): pass -class DeviceUnpairableError(Exception): - pass -Device = namedtuple("Device", "path interface_number id_ product_key usage_page") -DeviceInfo = namedtuple("DeviceInfo", "device label initialized") +class Device(NamedTuple): + path: Union[str, bytes] + interface_number: int + id_: str + product_key: Any # when using hid, often Tuple[int, int] + usage_page: int + + +class DeviceInfo(NamedTuple): + device: Device + label: str + initialized: bool + class DeviceMgr(ThreadJob, PrintError): '''Manages hardware clients. A client communicates over a hardware diff --git a/electrum/plugins/coldcard/coldcard.py b/electrum/plugins/coldcard/coldcard.py @@ -374,7 +374,7 @@ class Coldcard_KeyStore(Hardware_KeyStore): # give empty bytes for error cases; it seems to clear the old signature box return b'' - def build_psbt(self, tx, wallet=None, xfp=None): + def build_psbt(self, tx: Transaction, wallet=None, xfp=None): # Render a PSBT file, for upload to Coldcard. # if xfp is None: @@ -390,7 +390,7 @@ class Coldcard_KeyStore(Hardware_KeyStore): wallet.add_hw_info(tx) # wallet.add_hw_info installs this attr - assert hasattr(tx, 'output_info'), 'need data about outputs' + assert tx.output_info, 'need data about outputs' # Build map of pubkey needed as derivation from master, in PSBT binary format # 1) binary version of the common subpath for all keys diff --git a/electrum/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py @@ -28,7 +28,7 @@ from electrum.plugin import BasePlugin, hook from electrum.i18n import _ from electrum.bitcoin import is_address, TYPE_SCRIPT from electrum.util import bfh, versiontuple -from electrum.transaction import opcodes, TxOutput +from electrum.transaction import opcodes, TxOutput, Transaction class HW_PluginBase(BasePlugin): @@ -113,14 +113,13 @@ class HW_PluginBase(BasePlugin): return message -def is_any_tx_output_on_change_branch(tx): - if not hasattr(tx, 'output_info'): +def is_any_tx_output_on_change_branch(tx: Transaction): + if not tx.output_info: return False - for _type, address, amount in tx.outputs(): - info = tx.output_info.get(address) + for o in tx.outputs(): + info = tx.output_info.get(o.address) if info is not None: - index, xpubs, m = info.address_index, info.sorted_xpubs, info.num_sig - if index[0] == 1: + if info.address_index[0] == 1: return True return False diff --git a/electrum/transaction.py b/electrum/transaction.py @@ -31,7 +31,7 @@ import struct import traceback import sys from typing import (Sequence, Union, NamedTuple, Tuple, Optional, Iterable, - Callable, List) + Callable, List, Dict) from . import ecc, bitcoin, constants, segwit_addr from .util import print_error, profiler, to_bytes, bh2u, bfh @@ -63,17 +63,22 @@ class MalformedBitcoinScript(Exception): pass -TxOutput = NamedTuple("TxOutput", [('type', int), ('address', str), ('value', Union[int, str])]) -# ^ value is str when the output is set to max: '!' +class TxOutput(NamedTuple): + type: int + address: str + value: Union[int, str] # str when the output is set to max: '!' -TxOutputForUI = NamedTuple("TxOutputForUI", [('address', str), ('value', int)]) +class TxOutputForUI(NamedTuple): + address: str + value: int -TxOutputHwInfo = NamedTuple("TxOutputHwInfo", [('address_index', Tuple), - ('sorted_xpubs', Iterable[str]), - ('num_sig', Optional[int]), - ('script_type', str)]) +class TxOutputHwInfo(NamedTuple): + address_index: Tuple + sorted_xpubs: Iterable[str] + num_sig: Optional[int] + script_type: str class BCDataStream(object): @@ -682,6 +687,7 @@ class Transaction: # this value will get properly set when deserializing self.is_partial_originally = True self._segwit_ser = None # None means "don't know" + self.output_info = None # type: Optional[Dict[str, TxOutputHwInfo]] def update(self, raw): self.raw = raw diff --git a/electrum/util.py b/electrum/util.py @@ -902,14 +902,18 @@ def ignore_exceptions(func): return wrapper -TxMinedStatus = NamedTuple("TxMinedStatus", [("height", int), - ("conf", int), - ("timestamp", int), - ("header_hash", str)]) -VerifiedTxInfo = NamedTuple("VerifiedTxInfo", [("height", int), - ("timestamp", int), - ("txpos", int), - ("header_hash", str)]) +class TxMinedStatus(NamedTuple): + height: int + conf: int + timestamp: int + header_hash: str + + +class VerifiedTxInfo(NamedTuple): + height: int + timestamp: int + txpos: int + header_hash: str def make_aiohttp_session(proxy: dict, headers=None, timeout=None):