URI: 
       twizard,hw: tell user about errors during plugin init - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 386e0d560eee1ad82380c4000d2afa8e6a07963c
   DIR parent 4f7283a3b0b3301195f68cca915db2c49d410a15
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Wed, 31 Oct 2018 17:58:47 +0100
       
       wizard,hw: tell user about errors during plugin init
       
       see #4817 (issuecomment-434765570)
       
       Diffstat:
         M electrum/base_wizard.py             |      25 ++++++++++++++-----------
         M electrum/plugin.py                  |      23 ++++++++++++++++++++---
         M run_electrum                        |      14 ++++++++------
       
       3 files changed, 42 insertions(+), 20 deletions(-)
       ---
   DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py
       t@@ -228,14 +228,7 @@ class BaseWizard(object):
            def choose_hw_device(self, purpose=HWD_SETUP_NEW_WALLET):
                title = _('Hardware Keystore')
                # check available plugins
       -        support = self.plugins.get_hardware_support()
       -        if not support:
       -            msg = '\n'.join([
       -                _('No hardware wallet support found on your system.'),
       -                _('Please install the relevant libraries (eg python-trezor for Trezor).'),
       -            ])
       -            self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_hw_device(purpose))
       -            return
       +        supported_plugins = self.plugins.get_hardware_support()
                # scan devices
                devices = []
                devmgr = self.plugins.device_manager
       t@@ -246,14 +239,24 @@ class BaseWizard(object):
                    debug_msg = '  {}:\n    {}'.format(_('Error scanning devices'), e)
                else:
                    debug_msg = ''
       -            for name, description, plugin in support:
       +            for splugin in supported_plugins:
       +                name, plugin = splugin.name, splugin.plugin
       +                # plugin init errored?
       +                if not plugin:
       +                    e = splugin.exception
       +                    indented_error_msg = '    '.join([''] + str(e).splitlines(keepends=True))
       +                    debug_msg += f'  {name}: (error during plugin init)\n'
       +                    debug_msg += '    {}\n'.format(_('You might have an incompatible library.'))
       +                    debug_msg += f'{indented_error_msg}\n'
       +                    continue
       +                # see if plugin recognizes 'scanned_devices'
                        try:
                            # FIXME: side-effect: unpaired_device_info sets client.handler
                            u = devmgr.unpaired_device_infos(None, plugin, devices=scanned_devices)
                        except BaseException as e:
       -                    devmgr.print_error('error getting device infos for {}: {}'.format(name, e))
       +                    devmgr.print_error(f'error getting device infos for {name}: {e}')
                            indented_error_msg = '    '.join([''] + str(e).splitlines(keepends=True))
       -                    debug_msg += '  {}:\n{}\n'.format(plugin.name, indented_error_msg)
       +                    debug_msg += f'  {name}: (error getting device infos)\n{indented_error_msg}\n'
                            continue
                        devices += list(map(lambda x: (name, x), u))
                if not debug_msg:
   DIR diff --git a/electrum/plugin.py b/electrum/plugin.py
       t@@ -28,7 +28,7 @@ import os
        import pkgutil
        import time
        import threading
       -from typing import NamedTuple, Any, Union
       +from typing import NamedTuple, Any, Union, TYPE_CHECKING, Optional
        
        from .i18n import _
        from .util import (profiler, PrintError, DaemonThread, UserCancelled,
       t@@ -37,6 +37,9 @@ from . import bip32
        from . import plugins
        from .simple_config import SimpleConfig
        
       +if TYPE_CHECKING:
       +    from .plugins.hw_wallet import HW_PluginBase
       +
        
        plugin_loaders = {}
        hook_names = set()
       t@@ -148,10 +151,17 @@ class Plugins(DaemonThread):
                        try:
                            p = self.get_plugin(name)
                            if p.is_enabled():
       -                        out.append([name, details[2], p])
       -                except:
       +                        out.append(HardwarePluginToScan(name=name,
       +                                                        description=details[2],
       +                                                        plugin=p,
       +                                                        exception=None))
       +                except Exception as e:
                            traceback.print_exc()
                            self.print_error("cannot load plugin for:", name)
       +                    out.append(HardwarePluginToScan(name=name,
       +                                                    description=details[2],
       +                                                    plugin=None,
       +                                                    exception=e))
                return out
        
            def register_wallet_type(self, name, gui_good, wallet_type):
       t@@ -277,6 +287,13 @@ class DeviceInfo(NamedTuple):
            initialized: bool
        
        
       +class HardwarePluginToScan(NamedTuple):
       +    name: str
       +    description: str
       +    plugin: Optional['HW_PluginBase']
       +    exception: Optional[Exception]
       +
       +
        class DeviceMgr(ThreadJob, PrintError):
            '''Manages hardware clients.  A client communicates over a hardware
            channel with the device.
   DIR diff --git a/run_electrum b/run_electrum
       t@@ -165,18 +165,20 @@ def init_cmdline(config_options, server):
        
        
        def get_connected_hw_devices(plugins):
       -    support = plugins.get_hardware_support()
       -    if not support:
       -        print_msg('No hardware wallet support found on your system.')
       -        sys.exit(1)
       +    supported_plugins = plugins.get_hardware_support()
            # scan devices
            devices = []
            devmgr = plugins.device_manager
       -    for name, description, plugin in support:
       +    for splugin in supported_plugins:
       +        name, plugin = splugin.name, splugin.plugin
       +        if not plugin:
       +            e = splugin.exception
       +            print_stderr(f"{name}: error during plugin init: {repr(e)}")
       +            continue
                try:
                    u = devmgr.unpaired_device_infos(None, plugin)
                except:
       -            devmgr.print_error("error", name)
       +            devmgr.print_error(f'error getting device infos for {name}: {e}')
                    continue
                devices += list(map(lambda x: (name, x), u))
            return devices