From 262c009c673db2b252cec610ee15214709f96557 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 17 Nov 2023 11:19:47 +0000 Subject: [PATCH] pyinstaller build: towards fixing missing "gui/common_qt" folder pyinstaller tries to import electrum and its different submodules at build-time during the "Analysis" phase. sys._GUI_QT_VERSION was not getting set there, and the resulting exception was blocking pyinstaller from discovering that gui/common_qt is being used. at runtime: ``` $ ./dist/Electrum.app/Contents/MacOS/run_electrum 1.53 | E | daemon.Daemon | GUI raised exception: Exception('Error loading trustedcoin plugin: ModuleNotFoundError("No module named \'electrum.gui.common_qt\'")'). shutting down. 1.53 | E | __main__ | daemon.run_gui errored Traceback (most recent call last): File "electrum/plugin.py", line 135, in load_plugin spec.loader.exec_module(module) File "", line 883, in exec_module File "", line 241, in _call_with_frames_removed File "/Users/vagrant/electrum/dist/Electrum.app/Contents/MacOS/electrum/plugins/trustedcoin/qt.py", line 51, in from .common_qt import TrustedcoinPluginQObject File "/Users/vagrant/electrum/dist/Electrum.app/Contents/MacOS/electrum/plugins/trustedcoin/common_qt.py", line 16, in from electrum.gui.common_qt.plugins import PluginQObject ModuleNotFoundError: No module named 'electrum.gui.common_qt' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "run_electrum", line 456, in handle_cmd d.run_gui() File "electrum/daemon.py", line 617, in run_gui self.gui_object = gui.ElectrumGui(config=self.config, daemon=self, plugins=self._plugins) File "electrum/util.py", line 473, in do_profile o = func(*args, **kw_args) File "electrum/gui/qt/__init__.py", line 153, in __init__ self.plugins.load_plugin('trustedcoin') File "electrum/plugin.py", line 138, in load_plugin raise Exception(f"Error loading {name} plugin: {repr(e)}") from e Exception: Error loading trustedcoin plugin: ModuleNotFoundError("No module named 'electrum.gui.common_qt'") ``` --- contrib/build-wine/deterministic.spec | 1 + contrib/osx/osx.spec | 1 + electrum/gui/common_qt/__init__.py | 16 ++++++++++++++++ electrum/gui/common_qt/plugins.py | 8 ++++++-- electrum/plugins/trustedcoin/common_qt.py | 8 ++++++-- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/contrib/build-wine/deterministic.spec b/contrib/build-wine/deterministic.spec index c133de4e6..62b471c23 100644 --- a/contrib/build-wine/deterministic.spec +++ b/contrib/build-wine/deterministic.spec @@ -62,6 +62,7 @@ a = Analysis([home+'run_electrum', home+'electrum/bitcoin.py', home+'electrum/dnssec.py', home+'electrum/commands.py', + home+'electrum/plugins/trustedcoin/qt.py', home+'electrum/plugins/cosigner_pool/qt.py', home+'electrum/plugins/trezor/qt.py', home+'electrum/plugins/safe_t/client.py', diff --git a/contrib/osx/osx.spec b/contrib/osx/osx.spec index b4fb53df9..4f3a53acb 100644 --- a/contrib/osx/osx.spec +++ b/contrib/osx/osx.spec @@ -67,6 +67,7 @@ a = Analysis([electrum+ MAIN_SCRIPT, electrum+'electrum/bitcoin.py', electrum+'electrum/dnssec.py', electrum+'electrum/commands.py', + electrum+'electrum/plugins/trustedcoin/qt.py', electrum+'electrum/plugins/cosigner_pool/qt.py', electrum+'electrum/plugins/trezor/qt.py', electrum+'electrum/plugins/safe_t/client.py', diff --git a/electrum/gui/common_qt/__init__.py b/electrum/gui/common_qt/__init__.py index e69de29bb..b2be0c9a4 100644 --- a/electrum/gui/common_qt/__init__.py +++ b/electrum/gui/common_qt/__init__.py @@ -0,0 +1,16 @@ +# Copyright (C) 2023 The Electrum developers +# Distributed under the MIT software license, see the accompanying +# file LICENCE or http://www.opensource.org/licenses/mit-license.php + +import sys + + +# FIXME: remove when both desktop and mobile are Qt6 +def get_qt_major_version() -> int: + _GUI_QT_VERSION = getattr(sys, '_GUI_QT_VERSION', None) + if _GUI_QT_VERSION is None: + # used by pyinstaller when building (analysis phase) + _GUI_QT_VERSION = 5 + if _GUI_QT_VERSION in (5, 6): + return _GUI_QT_VERSION + raise Exception(f"unexpected {_GUI_QT_VERSION=}") diff --git a/electrum/gui/common_qt/plugins.py b/electrum/gui/common_qt/plugins.py index 0934477b4..9edaa9b19 100644 --- a/electrum/gui/common_qt/plugins.py +++ b/electrum/gui/common_qt/plugins.py @@ -1,9 +1,13 @@ import sys -if getattr(sys, '_GUI_QT_VERSION') == 5: # FIXME: remove when both desktop and mobile are Qt6 +from . import get_qt_major_version + +if (qt_ver := get_qt_major_version()) == 5: from PyQt5.QtCore import pyqtSignal, pyqtProperty, QObject -else: +elif qt_ver == 6: from PyQt6.QtCore import pyqtSignal, pyqtProperty, QObject +else: + raise Exception(f"unexpected {qt_ver=}") from electrum.logging import get_logger diff --git a/electrum/plugins/trustedcoin/common_qt.py b/electrum/plugins/trustedcoin/common_qt.py index 31b9954e7..01836d972 100644 --- a/electrum/plugins/trustedcoin/common_qt.py +++ b/electrum/plugins/trustedcoin/common_qt.py @@ -4,10 +4,14 @@ import base64 import sys from typing import TYPE_CHECKING -if getattr(sys, '_GUI_QT_VERSION') == 5: # FIXME: remove when both desktop and mobile are Qt6 +from electrum.gui.common_qt import get_qt_major_version + +if (qt_ver := get_qt_major_version()) == 5: from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot -else: +elif qt_ver == 6: from PyQt6.QtCore import pyqtSignal, pyqtProperty, pyqtSlot +else: + raise Exception(f"unexpected {qt_ver=}") from electrum.i18n import _ from electrum.bip32 import BIP32Node