twizard: some fixes - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 2da6692f73921f3b651569900a63e9f3ce7fbc57 DIR parent ef1330df5d3f7b5021bf7fc453657a7ea0d3af1c HTML Author: SomberNight <somber.night@protonmail.com> Date: Mon, 4 Mar 2019 02:08:23 +0100 wizard: some fixes related: #5174 Diffstat: M electrum/base_wizard.py | 9 +++++---- M electrum/gui/qt/__init__.py | 84 ++++++++++++++++--------------- M electrum/gui/qt/installwizard.py | 23 +++++++++++++---------- M electrum/storage.py | 5 ++++- 4 files changed, 66 insertions(+), 55 deletions(-) --- DIR diff --git a/electrum/base_wizard.py b/electrum/base_wizard.py t@@ -299,7 +299,8 @@ class BaseWizard(object): _('Debug message') + '\n', debug_msg ]) - self.confirm_dialog(title=title, message=msg, run_next= lambda x: self.choose_hw_device(purpose)) + self.confirm_dialog(title=title, message=msg, + run_next=lambda x: self.choose_hw_device(purpose, storage=storage)) return # select device self.devices = devices t@@ -326,15 +327,15 @@ class BaseWizard(object): + _('Please try again.')) devmgr = self.plugins.device_manager devmgr.unpair_id(device_info.device.id_) - self.choose_hw_device(purpose) + self.choose_hw_device(purpose, storage=storage) return except (UserCancelled, GoBack): - self.choose_hw_device(purpose) + self.choose_hw_device(purpose, storage=storage) return except BaseException as e: traceback.print_exc(file=sys.stderr) self.show_error(str(e)) - self.choose_hw_device(purpose) + self.choose_hw_device(purpose, storage=storage) return if purpose == HWD_SETUP_NEW_WALLET: def f(derivation, script_type): DIR diff --git a/electrum/gui/qt/__init__.py b/electrum/gui/qt/__init__.py t@@ -28,6 +28,7 @@ import signal import sys import traceback import threading +from typing import Optional try: t@@ -46,9 +47,9 @@ from electrum.plugin import run_hook from electrum.base_wizard import GoBack from electrum.util import (UserCancelled, PrintError, profiler, WalletFileException, BitcoinException, get_new_wallet_name) -from electrum.wallet import Wallet +from electrum.wallet import Wallet, Abstract_Wallet -from .installwizard import InstallWizard +from .installwizard import InstallWizard, WalletAlreadyOpenInMemory from .util import get_default_language, read_QIcon, ColorScheme t@@ -191,7 +192,7 @@ class ElectrumGui(PrintError): self.network_updated_signal_obj) self.nd.show() - def create_window_for_wallet(self, wallet): + def _create_window_for_wallet(self, wallet): w = ElectrumWindow(self, wallet) self.windows.append(w) self.build_tray_menu() t@@ -212,9 +213,10 @@ class ElectrumGui(PrintError): return wrapper @count_wizards_in_progress - def start_new_window(self, path, uri, app_is_starting=False): + def start_new_window(self, path, uri, *, app_is_starting=False): '''Raises the window for the wallet if it is open. Otherwise opens the wallet and creates a new window for it''' + wallet = None try: wallet = self.daemon.load_wallet(path, None) except BaseException as e: t@@ -222,49 +224,20 @@ class ElectrumGui(PrintError): d = QMessageBox(QMessageBox.Warning, _('Error'), _('Cannot load wallet') + ' (1):\n' + str(e)) d.exec_() - if app_is_starting: - # do not return so that the wizard can appear - wallet = None - else: + # if app is starting, still let wizard to appear + if not app_is_starting: return if not wallet: - wizard = InstallWizard(self.config, self.app, self.plugins) - storage = None - try: - path, storage = wizard.select_storage(path, self.daemon.get_wallet) - # storage is None if file does not exist - if storage is None: - wizard.path = path # needed by trustedcoin plugin - wizard.run('new') - storage = wizard.create_storage(path) - else: - wizard.run_upgrades(storage) - except UserCancelled: - return - except GoBack as e: - self.print_error('[start_new_window] Exception caught (GoBack)', e) - except (WalletFileException, BitcoinException) as e: - traceback.print_exc(file=sys.stderr) - d = QMessageBox(QMessageBox.Warning, _('Error'), - _('Cannot load wallet') + ' (2):\n' + str(e)) - d.exec_() - return - finally: - wizard.terminate() - # return if wallet creation is not complete - if storage is None or storage.get_action(): - return - wallet = Wallet(storage) - if not self.daemon.get_wallet(wallet.storage.path): - # wallet was not in memory - wallet.start_network(self.daemon.network) - self.daemon.add_wallet(wallet) + wallet = self._start_wizard_to_select_or_create_wallet(path) + if not wallet: + return + # create or raise window try: for w in self.windows: if w.wallet.storage.path == wallet.storage.path: break else: - w = self.create_window_for_wallet(wallet) + w = self._create_window_for_wallet(wallet) except BaseException as e: traceback.print_exc(file=sys.stdout) d = QMessageBox(QMessageBox.Warning, _('Error'), t@@ -284,6 +257,37 @@ class ElectrumGui(PrintError): w.activateWindow() return w + def _start_wizard_to_select_or_create_wallet(self, path) -> Optional[Abstract_Wallet]: + wizard = InstallWizard(self.config, self.app, self.plugins) + try: + path, storage = wizard.select_storage(path, self.daemon.get_wallet) + # storage is None if file does not exist + if storage is None: + wizard.path = path # needed by trustedcoin plugin + wizard.run('new') + storage = wizard.create_storage(path) + else: + wizard.run_upgrades(storage) + except (UserCancelled, GoBack): + return + except WalletAlreadyOpenInMemory as e: + return e.wallet + except (WalletFileException, BitcoinException) as e: + traceback.print_exc(file=sys.stderr) + d = QMessageBox(QMessageBox.Warning, _('Error'), + _('Cannot load wallet') + ' (2):\n' + str(e)) + d.exec_() + return + finally: + wizard.terminate() + # return if wallet creation is not complete + if storage is None or storage.get_action(): + return + wallet = Wallet(storage) + wallet.start_network(self.daemon.network) + self.daemon.add_wallet(wallet) + return wallet + def close_window(self, window): if window in self.windows: self.windows.remove(window) DIR diff --git a/electrum/gui/qt/installwizard.py b/electrum/gui/qt/installwizard.py t@@ -6,7 +6,7 @@ import os import sys import threading import traceback -from typing import Tuple, List, Callable +from typing import Tuple, List, Callable, NamedTuple, Optional from PyQt5.QtCore import QRect, QEventLoop, Qt, pyqtSignal from PyQt5.QtGui import QPalette, QPen, QPainter, QPixmap t@@ -14,7 +14,7 @@ from PyQt5.QtWidgets import (QWidget, QDialog, QLabel, QHBoxLayout, QMessageBox, QVBoxLayout, QLineEdit, QFileDialog, QPushButton, QGridLayout, QSlider, QScrollArea) -from electrum.wallet import Wallet +from electrum.wallet import Wallet, Abstract_Wallet from electrum.storage import WalletStorage from electrum.util import UserCancelled, InvalidPassword, WalletFileException from electrum.base_wizard import BaseWizard, HWD_SETUP_DECRYPT_WALLET, GoBack t@@ -104,6 +104,11 @@ def wizard_dialog(func): return func_wrapper +class WalletAlreadyOpenInMemory(Exception): + def __init__(self, wallet: Abstract_Wallet): + super().__init__() + self.wallet = wallet + # WindowModalDialog must come first as it overrides show_error class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): t@@ -162,7 +167,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): self.raise_() self.refresh_gui() # Need for QT on MacOSX. Lame. - def select_storage(self, path, get_wallet_from_daemon): + def select_storage(self, path, get_wallet_from_daemon) -> Tuple[str, Optional[WalletStorage]]: vbox = QVBoxLayout() hbox = QHBoxLayout() t@@ -254,7 +259,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): break wallet_from_memory = get_wallet_from_daemon(self.temp_storage.path) if wallet_from_memory: - return wallet_from_memory + raise WalletAlreadyOpenInMemory(wallet_from_memory) if self.temp_storage.file_exists() and self.temp_storage.is_encrypted(): if self.temp_storage.is_encrypted_with_user_pw(): password = self.pw_e.text() t@@ -267,7 +272,7 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): except BaseException as e: traceback.print_exc(file=sys.stdout) QMessageBox.information(None, _('Error'), str(e)) - return + raise UserCancelled() elif self.temp_storage.is_encrypted_with_hw_device(): try: self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, storage=self.temp_storage) t@@ -281,11 +286,9 @@ class InstallWizard(QDialog, MessageBoxMixin, BaseWizard): except BaseException as e: traceback.print_exc(file=sys.stdout) QMessageBox.information(None, _('Error'), str(e)) - return - if self.temp_storage.is_past_initial_decryption(): - break - else: - return + raise UserCancelled() + assert self.temp_storage.is_past_initial_decryption() + break else: raise Exception('Unexpected encryption version') DIR diff --git a/electrum/storage.py b/electrum/storage.py t@@ -119,7 +119,10 @@ class WalletStorage(PrintError): if encryption is disabled completely (self.is_encrypted() == False), or if encryption is enabled but the contents have already been decrypted. """ - return bool(self.db.data) + try: + return bool(self.db.data) + except AttributeError: + return False def is_encrypted(self): """Return if storage encryption is currently enabled."""