URI: 
       tadd some type hints - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 88307357ec3798e6d78720c74bae46d68c622bb8
   DIR parent 770ae6d8785c5deaa1ba3b827ed27d10522e141a
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Fri, 22 Nov 2019 22:59:33 +0100
       
       add some type hints
       
       mostly related to hw wallets
       
       Diffstat:
         M electrum/base_wizard.py             |      10 +++++-----
         M electrum/keystore.py                |      17 ++++++++++-------
         M electrum/plugin.py                  |       2 +-
         M electrum/plugins/hw_wallet/plugin.… |       3 ++-
         M electrum/plugins/hw_wallet/qt.py    |      33 ++++++++++++++++++++-----------
       
       5 files changed, 39 insertions(+), 26 deletions(-)
       ---
   DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
       t@@ -34,7 +34,7 @@ from . import bitcoin
        from . import keystore
        from . import mnemonic
        from .bip32 import is_bip32_derivation, xpub_type, normalize_bip32_derivation, BIP32Node
       -from .keystore import bip44_derivation, purpose48_derivation
       +from .keystore import bip44_derivation, purpose48_derivation, Hardware_KeyStore
        from .wallet import (Imported_Wallet, Standard_Wallet, Multisig_Wallet,
                             wallet_types, Wallet, Abstract_Wallet)
        from .storage import (WalletStorage, StorageEncryptionVersion,
       t@@ -47,7 +47,7 @@ from .logging import Logger
        from .plugins.hw_wallet.plugin import OutdatedHwFirmwareException, HW_PluginBase
        
        if TYPE_CHECKING:
       -    from .plugin import DeviceInfo
       +    from .plugin import DeviceInfo, BasePlugin
        
        
        # hardware device setup purpose
       t@@ -84,7 +84,7 @@ class BaseWizard(Logger):
                self.data = {}
                self.pw_args = None  # type: Optional[WizardWalletPasswordSetting]
                self._stack = []  # type: List[WizardStackItem]
       -        self.plugin = None
       +        self.plugin = None  # type: Optional[BasePlugin]
                self.keystores = []
                self.is_kivy = config.get('gui') == 'kivy'
                self.seed_type = None
       t@@ -532,9 +532,9 @@ class BaseWizard(Logger):
                encrypt_keystore = any(k.may_have_password() for k in self.keystores)
                # note: the following condition ("if") is duplicated logic from
                # wallet.get_available_storage_encryption_version()
       -        if self.wallet_type == 'standard' and isinstance(self.keystores[0], keystore.Hardware_KeyStore):
       +        if self.wallet_type == 'standard' and isinstance(self.keystores[0], Hardware_KeyStore):
                    # offer encrypting with a pw derived from the hw device
       -            k = self.keystores[0]
       +            k = self.keystores[0]  # type: Hardware_KeyStore
                    try:
                        k.handler = self.plugin.create_handler(self)
                        password = k.get_password_for_storage_encryption()
   DIR diff --git a/electrum/keystore.py b/electrum/keystore.py
       t@@ -44,23 +44,25 @@ from .plugin import run_hook
        from .logging import Logger
        
        if TYPE_CHECKING:
       +    from .gui.qt.util import TaskThread
            from .transaction import Transaction, PartialTransaction, PartialTxInput, PartialTxOutput
            from .plugins.hw_wallet import HW_PluginBase, HardwareClientBase
        
        
        class KeyStore(Logger):
       +    type: str
        
            def __init__(self):
                Logger.__init__(self)
                self.is_requesting_to_be_rewritten_to_wallet_file = False  # type: bool
        
       -    def has_seed(self):
       +    def has_seed(self) -> bool:
                return False
        
       -    def is_watching_only(self):
       +    def is_watching_only(self) -> bool:
                return False
        
       -    def can_import(self):
       +    def can_import(self) -> bool:
                return False
        
            def get_type_text(self) -> str:
       t@@ -85,12 +87,12 @@ class KeyStore(Logger):
                        keypairs[pubkey.hex()] = derivation
                return keypairs
        
       -    def can_sign(self, tx):
       +    def can_sign(self, tx) -> bool:
                if self.is_watching_only():
                    return False
                return bool(self.get_tx_derivations(tx))
        
       -    def ready_to_sign(self):
       +    def ready_to_sign(self) -> bool:
                return not self.is_watching_only()
        
            def dump(self) -> dict:
       t@@ -629,6 +631,7 @@ class Hardware_KeyStore(KeyStore, Xpub):
            hw_type: str
            device: str
            plugin: 'HW_PluginBase'
       +    thread: Optional['TaskThread'] = None
        
            type = 'hardware'
        
       t@@ -684,7 +687,7 @@ class Hardware_KeyStore(KeyStore, Xpub):
                assert not self.has_seed()
                return False
        
       -    def get_password_for_storage_encryption(self):
       +    def get_password_for_storage_encryption(self) -> str:
                from .storage import get_derivation_used_for_hw_device_encryption
                client = self.plugin.get_client(self)
                derivation = get_derivation_used_for_hw_device_encryption()
       t@@ -692,7 +695,7 @@ class Hardware_KeyStore(KeyStore, Xpub):
                password = self.get_pubkey_from_xpub(xpub, ())
                return password
        
       -    def has_usable_connection_with_device(self):
       +    def has_usable_connection_with_device(self) -> bool:
                if not hasattr(self, 'plugin'):
                    return False
                client = self.plugin.get_client(self, force_pair=False)
   DIR diff --git a/electrum/plugin.py b/electrum/plugin.py
       t@@ -352,7 +352,7 @@ class DeviceMgr(ThreadJob):
                ThreadJob.__init__(self)
                # Keyed by xpub.  The value is the device id
                # has been paired, and None otherwise.
       -        self.xpub_ids = {}
       +        self.xpub_ids = {}  # type: Dict[str, str]
                # A list of clients.  The key is the client, the value is
                # a (path, id_) pair.
                self.clients = {}  # type: Dict[HardwareClientBase, Tuple[Union[str, bytes], str]]
   DIR diff --git a/electrum/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py
       t@@ -40,6 +40,7 @@ if TYPE_CHECKING:
        
        class HW_PluginBase(BasePlugin):
            keystore_class: Type['Hardware_KeyStore']
       +    libraries_available: bool
        
            minimum_library = (0, )
        
       t@@ -211,7 +212,7 @@ def get_xpubs_and_der_suffixes_from_txinout(tx: PartialTransaction,
        def only_hook_if_libraries_available(func):
            # note: this decorator must wrap @hook, not the other way around,
            # as 'hook' uses the name of the function it wraps
       -    def wrapper(self, *args, **kwargs):
       +    def wrapper(self: 'HW_PluginBase', *args, **kwargs):
                if not self.libraries_available: return None
                return func(self, *args, **kwargs)
            return wrapper
   DIR diff --git a/electrum/plugins/hw_wallet/qt.py b/electrum/plugins/hw_wallet/qt.py
       t@@ -26,6 +26,7 @@
        
        import threading
        from functools import partial
       +from typing import TYPE_CHECKING, Union, Optional, Callable, Any
        
        from PyQt5.QtCore import QObject, pyqtSignal
        from PyQt5.QtWidgets import QVBoxLayout, QLineEdit, QHBoxLayout, QLabel
       t@@ -33,12 +34,18 @@ from PyQt5.QtWidgets import QVBoxLayout, QLineEdit, QHBoxLayout, QLabel
        from electrum.gui.qt.password_dialog import PasswordLayout, PW_PASSPHRASE
        from electrum.gui.qt.util import (read_QIcon, WWLabel, OkButton, WindowModalDialog,
                                          Buttons, CancelButton, TaskThread, char_width_in_lineedit)
       +from electrum.gui.qt.main_window import StatusBarButton, ElectrumWindow
        
        from electrum.i18n import _
        from electrum.logging import Logger
       -from electrum.util import parse_URI, InvalidBitcoinURI
       +from electrum.util import parse_URI, InvalidBitcoinURI, UserCancelled
       +from electrum.plugin import hook, DeviceUnpairableError
        
       -from .plugin import OutdatedHwFirmwareException
       +from .plugin import OutdatedHwFirmwareException, HW_PluginBase
       +
       +if TYPE_CHECKING:
       +    from electrum.wallet import Abstract_Wallet
       +    from electrum.keystore import Hardware_KeyStore
        
        
        # The trickiest thing about this handler was getting windows properly
       t@@ -190,15 +197,10 @@ class QtHandlerBase(QObject, Logger):
                self.done.set()
        
        
       -
       -from electrum.plugin import hook
       -from electrum.util import UserCancelled
       -from electrum.gui.qt.main_window import StatusBarButton
       -
        class QtPluginBase(object):
        
            @hook
       -    def load_wallet(self, wallet, window):
       +    def load_wallet(self: Union['QtPluginBase', HW_PluginBase], wallet: 'Abstract_Wallet', window: ElectrumWindow):
                for keystore in wallet.get_keystores():
                    if not isinstance(keystore, self.keystore_class):
                        continue
       t@@ -220,7 +222,8 @@ class QtPluginBase(object):
                    # Trigger a pairing
                    keystore.thread.add(partial(self.get_client, keystore))
        
       -    def on_task_thread_error(self, window, keystore, exc_info):
       +    def on_task_thread_error(self: Union['QtPluginBase', HW_PluginBase], window: ElectrumWindow,
       +                             keystore: 'Hardware_KeyStore', exc_info):
                e = exc_info[1]
                if isinstance(e, OutdatedHwFirmwareException):
                    if window.question(e.text_ignore_old_fw_and_continue(), title=_("Outdated device firmware")):
       t@@ -236,7 +239,8 @@ class QtPluginBase(object):
                else:
                    window.on_error(exc_info)
        
       -    def choose_device(self, window, keystore):
       +    def choose_device(self: Union['QtPluginBase', HW_PluginBase], window: ElectrumWindow,
       +                      keystore: 'Hardware_KeyStore') -> Optional[str]:
                '''This dialog box should be usable even if the user has
                forgotten their PIN or it is in bootloader mode.'''
                device_id = self.device_manager().xpub_id(keystore.xpub)
       t@@ -248,10 +252,12 @@ class QtPluginBase(object):
                    device_id = info.device.id_
                return device_id
        
       -    def show_settings_dialog(self, window, keystore):
       +    def show_settings_dialog(self, window: ElectrumWindow, keystore: 'Hardware_KeyStore') -> None:
                device_id = self.choose_device(window, keystore)
        
       -    def add_show_address_on_hw_device_button_for_receive_addr(self, wallet, keystore, main_window):
       +    def add_show_address_on_hw_device_button_for_receive_addr(self, wallet: 'Abstract_Wallet',
       +                                                              keystore: 'Hardware_KeyStore',
       +                                                              main_window: ElectrumWindow):
                plugin = keystore.plugin
                receive_address_e = main_window.receive_address_e
        
       t@@ -267,3 +273,6 @@ class QtPluginBase(object):
                    keystore.thread.add(partial(plugin.show_address, wallet, addr, keystore))
                dev_name = f"{plugin.device} ({keystore.label})"
                receive_address_e.addButton("eye1.png", show_address, _("Show on {}").format(dev_name))
       +
       +    def create_handler(self, window: ElectrumWindow) -> 'QtHandlerBase':
       +        raise NotImplementedError()