commit b2920db8b8a10600e8851317118699b34ba926d8
parent a43be6657defe92631872d401fa0a940b680a540
Author: SomberNight <somber.night@protonmail.com>
Date: Tue, 10 Sep 2019 18:01:10 +0200
config: enforce that SimpleConfig is singleton
related: #5629
Diffstat:
9 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/electrum/__init__.py b/electrum/__init__.py
@@ -5,7 +5,7 @@ from .storage import WalletStorage
from .coinchooser import COIN_CHOOSERS
from .network import Network, pick_random_server
from .interface import Interface
-from .simple_config import SimpleConfig, get_config, set_config
+from .simple_config import SimpleConfig
from . import bitcoin
from . import transaction
from . import daemon
diff --git a/electrum/gui/qt/qrcodewidget.py b/electrum/gui/qt/qrcodewidget.py
@@ -9,6 +9,8 @@ from PyQt5.QtWidgets import (
import electrum
from electrum.i18n import _
+from electrum.simple_config import SimpleConfig
+
from .util import WindowModalDialog
@@ -105,7 +107,7 @@ class QRDialog(WindowModalDialog):
hbox = QHBoxLayout()
hbox.addStretch(1)
- config = electrum.get_config()
+ config = SimpleConfig.get_instance()
if config:
filename = os.path.join(config.path, "qrcode.png")
diff --git a/electrum/gui/qt/qrtextedit.py b/electrum/gui/qt/qrtextedit.py
@@ -2,6 +2,7 @@ from PyQt5.QtWidgets import QFileDialog
from electrum.i18n import _
from electrum.plugin import run_hook
+from electrum.simple_config import SimpleConfig
from .util import ButtonsTextEdit, MessageBoxMixin, ColorScheme
@@ -54,9 +55,9 @@ class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
self.setText(data)
def qr_input(self):
- from electrum import qrscanner, get_config
+ from electrum import qrscanner
try:
- data = qrscanner.scan_barcode(get_config().get_video_device())
+ data = qrscanner.scan_barcode(SimpleConfig.get_instance().get_video_device())
except BaseException as e:
self.show_error(repr(e))
data = ''
diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
@@ -35,7 +35,6 @@ from .util import bfh, bh2u, PR_PAID, PR_FAILED
from .bitcoin import TYPE_SCRIPT, TYPE_ADDRESS
from .bitcoin import redeem_script_to_address
from .crypto import sha256, sha256d
-from .simple_config import get_config
from .transaction import Transaction
from .logging import Logger
diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
@@ -18,7 +18,6 @@ from datetime import datetime
import aiorpcx
-from .simple_config import get_config
from .crypto import sha256, sha256d
from . import bitcoin
from . import ecc
diff --git a/electrum/network.py b/electrum/network.py
@@ -224,7 +224,7 @@ class UntrustedServerReturnedError(NetworkException):
return f"<UntrustedServerReturnedError original_exception: {repr(self.original_exception)}>"
-INSTANCE = None
+_INSTANCE = None
class Network(Logger):
@@ -235,8 +235,9 @@ class Network(Logger):
LOGGING_SHORTCUT = 'n'
def __init__(self, config: SimpleConfig):
- global INSTANCE
- INSTANCE = self
+ global _INSTANCE
+ assert _INSTANCE is None, "Network is a singleton!"
+ _INSTANCE = self
Logger.__init__(self)
@@ -322,7 +323,7 @@ class Network(Logger):
@staticmethod
def get_instance() -> Optional["Network"]:
- return INSTANCE
+ return _INSTANCE
def with_recent_servers_lock(func):
def func_wrapper(self, *args, **kwargs):
diff --git a/electrum/simple_config.py b/electrum/simple_config.py
@@ -31,19 +31,9 @@ FEERATE_STATIC_VALUES = [1000, 2000, 5000, 10000, 20000, 30000,
FEERATE_REGTEST_HARDCODED = 180000 # for eclair compat
-config = {}
_logger = get_logger(__name__)
-def get_config():
- global config
- return config
-
-
-def set_config(c):
- global config
- config = c
-
def estimate_fee(tx_size_bytes: int) -> int:
def use_fallback_feerate():
fee_per_kb = FEERATE_FALLBACK_STATIC_FEE
@@ -61,6 +51,10 @@ def estimate_fee(tx_size_bytes: int) -> int:
FINAL_CONFIG_VERSION = 3
+_INSTANCE = None
+_ENFORCE_SIMPLECONFIG_SINGLETON = True # disabled in tests
+
+
class SimpleConfig(Logger):
"""
The SimpleConfig class is responsible for handling operations involving
@@ -74,6 +68,12 @@ class SimpleConfig(Logger):
def __init__(self, options=None, read_user_config_function=None,
read_user_dir_function=None):
+ # note: To be honest, singletons are bad design... :/
+ # However currently we somewhat rely on config being one.
+ global _INSTANCE
+ if _ENFORCE_SIMPLECONFIG_SINGLETON:
+ assert _INSTANCE is None, "SimpleConfig is a singleton!"
+ _INSTANCE = self
if options is None:
options = {}
@@ -120,8 +120,9 @@ class SimpleConfig(Logger):
if self.requires_upgrade():
self.upgrade()
- # Make a singleton instance of 'self'
- set_config(self)
+ @staticmethod
+ def get_instance() -> Optional["SimpleConfig"]:
+ return _INSTANCE
def electrum_path(self):
# Read electrum_path from command line
diff --git a/electrum/tests/__init__.py b/electrum/tests/__init__.py
@@ -2,6 +2,7 @@ import unittest
import threading
from electrum import constants
+from electrum import simple_config
# Set this locally to make the test suite run faster.
@@ -11,6 +12,9 @@ from electrum import constants
FAST_TESTS = False
+simple_config._ENFORCE_SIMPLECONFIG_SINGLETON = False
+
+
# some unit tests are modifying globals; sorry.
class SequentialTestCase(unittest.TestCase):
diff --git a/electrum/wallet.py b/electrum/wallet.py
@@ -47,7 +47,7 @@ from .util import (NotEnoughFunds, UserCancelled, profiler,
InvalidPassword, format_time, timestamp_to_datetime, Satoshis,
Fiat, bfh, bh2u, TxMinedInfo, quantize_feerate, create_bip21_uri, OrderedDictWithIndex)
from .util import PR_TYPE_ADDRESS, PR_TYPE_BIP70, PR_TYPE_LN
-from .simple_config import get_config
+from .simple_config import SimpleConfig
from .bitcoin import (COIN, TYPE_ADDRESS, is_address, address_to_script,
is_minikey, relayfee, dust_threshold)
from .crypto import sha256d
@@ -71,7 +71,6 @@ from .paymentrequest import PaymentRequest
if TYPE_CHECKING:
from .network import Network
- from .simple_config import SimpleConfig
_logger = get_logger(__name__)
@@ -236,7 +235,9 @@ class Abstract_Wallet(AddressSynchronizer):
self.contacts = Contacts(self.storage)
self._coin_price_cache = {}
- self.config = get_config()
+ # TODO config should be passed as a param instead? SimpleConfig should not be a singleton.
+ self.config = SimpleConfig.get_instance()
+ assert self.config is not None, "config must not be None"
self.lnworker = LNWallet(self) if self.config.get('lightning') else None
def stop_threads(self):