URI: 
       tconfig: enforce that SimpleConfig is singleton - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit b2920db8b8a10600e8851317118699b34ba926d8
   DIR parent a43be6657defe92631872d401fa0a940b680a540
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Tue, 10 Sep 2019 18:01:10 +0200
       
       config: enforce that SimpleConfig is singleton
       
       related: #5629
       
       Diffstat:
         M electrum/__init__.py                |       2 +-
         M electrum/gui/qt/qrcodewidget.py     |       4 +++-
         M electrum/gui/qt/qrtextedit.py       |       5 +++--
         M electrum/lnchannel.py               |       1 -
         M electrum/lnpeer.py                  |       1 -
         M electrum/network.py                 |       9 +++++----
         M electrum/simple_config.py           |      25 +++++++++++++------------
         M electrum/tests/__init__.py          |       4 ++++
         M electrum/wallet.py                  |       7 ++++---
       
       9 files changed, 33 insertions(+), 25 deletions(-)
       ---
   DIR diff --git a/electrum/__init__.py b/electrum/__init__.py
       t@@ -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
   DIR diff --git a/electrum/gui/qt/qrcodewidget.py b/electrum/gui/qt/qrcodewidget.py
       t@@ -9,6 +9,8 @@ from PyQt5.QtWidgets import (
        
        import electrum
        from electrum.i18n import _
       +from electrum.simple_config import SimpleConfig
       +
        from .util import WindowModalDialog
        
        
       t@@ -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")
        
   DIR diff --git a/electrum/gui/qt/qrtextedit.py b/electrum/gui/qt/qrtextedit.py
       t@@ -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
        
       t@@ -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 = ''
   DIR diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py
       t@@ -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
        
   DIR diff --git a/electrum/lnpeer.py b/electrum/lnpeer.py
       t@@ -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
   DIR diff --git a/electrum/network.py b/electrum/network.py
       t@@ -224,7 +224,7 @@ class UntrustedServerReturnedError(NetworkException):
                return f"<UntrustedServerReturnedError original_exception: {repr(self.original_exception)}>"
        
        
       -INSTANCE = None
       +_INSTANCE = None
        
        
        class Network(Logger):
       t@@ -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)
        
       t@@ -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):
   DIR diff --git a/electrum/simple_config.py b/electrum/simple_config.py
       t@@ -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
       t@@ -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
       t@@ -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 = {}
       t@@ -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
   DIR diff --git a/electrum/tests/__init__.py b/electrum/tests/__init__.py
       t@@ -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.
       t@@ -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):
        
   DIR diff --git a/electrum/wallet.py b/electrum/wallet.py
       t@@ -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
       t@@ -71,7 +71,6 @@ from .paymentrequest import PaymentRequest
        
        if TYPE_CHECKING:
            from .network import Network
       -    from .simple_config import SimpleConfig
        
        
        _logger = get_logger(__name__)
       t@@ -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):