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:
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')