electrum

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

commit 2105c6c4e6085f9c53eb58dfe8447f2b5b1abad7
parent 2b1a150c52cf2a3c9df9046bc5268d3eadf3b577
Author: SomberNight <somber.night@protonmail.com>
Date:   Fri,  1 May 2020 06:33:38 +0200

qt exception window: turn Exception_Hook into singleton

related #4905
related Electron-Cash/Electron-Cash@6a3d76b0ab7bf3fe58390100f5bf2ab8a3261d87

conceptually did not really make sense that the Exception_Hook kept a reference
to an ~arbitrary main window (preventing gc)

Diffstat:
Melectrum/base_crash_reporter.py | 2+-
Melectrum/gui/qt/exception_window.py | 43+++++++++++++++++++++++++++++++------------
Melectrum/gui/qt/main_window.py | 7++++---
3 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/electrum/base_crash_reporter.py b/electrum/base_crash_reporter.py @@ -132,7 +132,7 @@ class BaseCrashReporter(Logger): def get_user_description(self): raise NotImplementedError - def get_wallet_type(self): + def get_wallet_type(self) -> str: raise NotImplementedError diff --git a/electrum/gui/qt/exception_window.py b/electrum/gui/qt/exception_window.py @@ -23,6 +23,7 @@ # SOFTWARE. import sys import html +from typing import TYPE_CHECKING, Optional, Set from PyQt5.QtCore import QObject import PyQt5.QtCore as QtCore @@ -33,16 +34,22 @@ from electrum.i18n import _ from electrum.base_crash_reporter import BaseCrashReporter from electrum.logging import Logger from electrum import constants +from electrum.network import Network from .util import MessageBoxMixin, read_QIcon, WaitingDialog +if TYPE_CHECKING: + from electrum.simple_config import SimpleConfig + from electrum.wallet import Abstract_Wallet + class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger): _active_window = None - def __init__(self, main_window, exctype, value, tb): + def __init__(self, config: 'SimpleConfig', exctype, value, tb): BaseCrashReporter.__init__(self, exctype, value, tb) - self.main_window = main_window + self.network = Network.get_instance() + self.config = config QWidget.__init__(self) self.setWindowTitle('Electrum - ' + _('An Error Occurred')) @@ -115,8 +122,8 @@ class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger): f' <a href="{constants.GIT_REPO_ISSUES_URL}">on GitHub</a>.'), rich_text=True) - proxy = self.main_window.network.proxy - task = lambda: BaseCrashReporter.send_report(self, self.main_window.network.asyncio_loop, proxy) + proxy = self.network.proxy + task = lambda: BaseCrashReporter.send_report(self, self.network.asyncio_loop, proxy) msg = _('Sending crash report...') WaitingDialog(self, msg, task, on_success, on_failure) @@ -125,7 +132,7 @@ class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger): self.close() def show_never(self): - self.main_window.config.set_key(BaseCrashReporter.config_key, False) + self.config.set_key(BaseCrashReporter.config_key, False) self.close() def closeEvent(self, event): @@ -136,7 +143,8 @@ class Exception_Window(BaseCrashReporter, QWidget, MessageBoxMixin, Logger): return self.description_textfield.toPlainText() def get_wallet_type(self): - return self.main_window.wallet.wallet_type + wallet_types = Exception_Hook._INSTANCE.wallet_types_seen + return ",".join(wallet_types) def _get_traceback_str(self) -> str: # The msg_box that shows the report uses rich_text=True, so @@ -154,15 +162,26 @@ def _show_window(*args): class Exception_Hook(QObject, Logger): _report_exception = QtCore.pyqtSignal(object, object, object, object) - def __init__(self, main_window, *args, **kwargs): - QObject.__init__(self, *args, **kwargs) + _INSTANCE = None # type: Optional[Exception_Hook] # singleton + + def __init__(self, *, config: 'SimpleConfig'): + QObject.__init__(self) Logger.__init__(self) - if not main_window.config.get(BaseCrashReporter.config_key, default=True): - return - self.main_window = main_window + assert self._INSTANCE is None, "Exception_Hook is supposed to be a singleton" + self.config = config + self.wallet_types_seen = set() # type: Set[str] + sys.excepthook = self.handler self._report_exception.connect(_show_window) + @classmethod + def maybe_setup(cls, *, config: 'SimpleConfig', wallet: 'Abstract_Wallet') -> None: + if not config.get(BaseCrashReporter.config_key, default=True): + return + if not cls._INSTANCE: + cls._INSTANCE = Exception_Hook(config=config) + cls._INSTANCE.wallet_types_seen.add(wallet.wallet_type) + def handler(self, *exc_info): self.logger.error('exception caught by crash reporter', exc_info=exc_info) - self._report_exception.emit(self.main_window, *exc_info) + self._report_exception.emit(self.config, *exc_info) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py @@ -167,12 +167,12 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): self.gui_object = gui_object self.config = config = gui_object.config # type: SimpleConfig self.gui_thread = gui_object.gui_thread + assert wallet, "no wallet" + self.wallet = wallet self.setup_exception_hook() self.network = gui_object.daemon.network # type: Network - assert wallet, "no wallet" - self.wallet = wallet self.fx = gui_object.daemon.fx # type: FxThread self.contacts = wallet.contacts self.tray = gui_object.tray @@ -304,7 +304,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): self._update_check_thread.start() def setup_exception_hook(self): - Exception_Hook(self) + Exception_Hook.maybe_setup(config=self.config, + wallet=self.wallet) def on_fx_history(self): self.history_model.refresh('fx_history')