qt exception window: turn Exception_Hook into singleton
related #4905 related Electron-Cash/Electron-Cash@6a3d76b0ab conceptually did not really make sense that the Exception_Hook kept a reference to an ~arbitrary main window (preventing gc)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user