Browse Source

simple_config: implement complex default values

Besides a literal value, the default can now also be a callable,
which gets called with the config and evaluated as needed, lazily.

This potentially allows e.g. the default value of one configvar to
depend on the current value of another configvar.
master
SomberNight 2 years ago
parent
commit
6a2806c2c5
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 25
      electrum/simple_config.py
  2. 2
      electrum/submarine_swaps.py
  3. 21
      electrum/tests/test_simple_config.py

25
electrum/simple_config.py

@ -4,7 +4,7 @@ import time
import os import os
import stat import stat
from decimal import Decimal from decimal import Decimal
from typing import Union, Optional, Dict, Sequence, Tuple, Any, Set from typing import Union, Optional, Dict, Sequence, Tuple, Any, Set, Callable
from numbers import Real from numbers import Real
from functools import cached_property from functools import cached_property
@ -54,15 +54,23 @@ FINAL_CONFIG_VERSION = 3
class ConfigVar(property): class ConfigVar(property):
def __init__(self, key: str, *, default, type_=None): def __init__(
self,
key: str,
*,
default: Union[Any, Callable[['SimpleConfig'], Any]], # typically a literal, but can also be a callable
type_=None,
):
self._key = key self._key = key
self._default = default self._default = default
self._type = type_ self._type = type_
property.__init__(self, self._get_config_value, self._set_config_value) property.__init__(self, self._get_config_value, self._set_config_value)
def _get_config_value(self, config: 'SimpleConfig'): def _get_config_value(self, config: 'SimpleConfig'):
value = config.get(self._key, default=self._default) with config.lock:
if self._type is not None and value != self._default: if config.is_set(self._key):
value = config.get(self._key)
if self._type is not None:
assert value is not None, f"got None for key={self._key!r}" assert value is not None, f"got None for key={self._key!r}"
try: try:
value = self._type(value) value = self._type(value)
@ -70,6 +78,9 @@ class ConfigVar(property):
raise ValueError( raise ValueError(
f"ConfigVar.get type-check and auto-conversion failed. " f"ConfigVar.get type-check and auto-conversion failed. "
f"key={self._key!r}. type={self._type}. value={value!r}") from e f"key={self._key!r}. type={self._type}. value={value!r}") from e
else:
d = self._default
value = d(config) if callable(d) else d
return value return value
def _set_config_value(self, config: 'SimpleConfig', value, *, save=True): def _set_config_value(self, config: 'SimpleConfig', value, *, save=True):
@ -817,14 +828,14 @@ class SimpleConfig(Logger):
f"Either use config.cv.{name}.set() or assign to config.{name} instead.") f"Either use config.cv.{name}.set() or assign to config.{name} instead.")
return CVLookupHelper() return CVLookupHelper()
def get_swapserver_url(self): def _default_swapserver_url(self) -> str:
if constants.net == constants.BitcoinMainnet: if constants.net == constants.BitcoinMainnet:
default = 'https://swaps.electrum.org/api' default = 'https://swaps.electrum.org/api'
elif constants.net == constants.BitcoinTestnet: elif constants.net == constants.BitcoinTestnet:
default = 'https://swaps.electrum.org/testnet' default = 'https://swaps.electrum.org/testnet'
else: else:
default = 'http://localhost:5455' default = 'http://localhost:5455'
return self.SWAPSERVER_URL or default return default
# config variables -----> # config variables ----->
NETWORK_AUTO_CONNECT = ConfigVar('auto_connect', default=True, type_=bool) NETWORK_AUTO_CONNECT = ConfigVar('auto_connect', default=True, type_=bool)
@ -940,7 +951,7 @@ class SimpleConfig(Logger):
CONFIG_FORGET_CHANGES = ConfigVar('forget_config', default=False, type_=bool) CONFIG_FORGET_CHANGES = ConfigVar('forget_config', default=False, type_=bool)
# submarine swap server # submarine swap server
SWAPSERVER_URL = ConfigVar('swapserver_url', default='', type_=str) SWAPSERVER_URL = ConfigVar('swapserver_url', default=_default_swapserver_url, type_=str)
SWAPSERVER_PORT = ConfigVar('swapserver_port', default=5455, type_=int) SWAPSERVER_PORT = ConfigVar('swapserver_port', default=5455, type_=int)
TEST_SWAPSERVER_REFUND = ConfigVar('test_swapserver_refund', default=False, type_=bool) TEST_SWAPSERVER_REFUND = ConfigVar('test_swapserver_refund', default=False, type_=bool)

2
electrum/submarine_swaps.py

@ -206,7 +206,7 @@ class SwapManager(Logger):
if swap.prepay_hash is not None: if swap.prepay_hash is not None:
self.prepayments[swap.prepay_hash] = bytes.fromhex(k) self.prepayments[swap.prepay_hash] = bytes.fromhex(k)
# api url # api url
self.api_url = wallet.config.get_swapserver_url() self.api_url = wallet.config.SWAPSERVER_URL
# init default min & max # init default min & max
self.init_min_max_values() self.init_min_max_values()

21
electrum/tests/test_simple_config.py

@ -3,9 +3,10 @@ import sys
import os import os
import tempfile import tempfile
import shutil import shutil
from io import StringIO from io import StringIO
from electrum.simple_config import (SimpleConfig, read_user_config)
from electrum.simple_config import SimpleConfig, read_user_config
from electrum import constants
from . import ElectrumTestCase from . import ElectrumTestCase
@ -147,6 +148,22 @@ class Test_SimpleConfig(ElectrumTestCase):
config.NETWORK_MAX_INCOMING_MSG_SIZE = None config.NETWORK_MAX_INCOMING_MSG_SIZE = None
self.assertEqual(MAX_MSG_SIZE_DEFAULT, config.NETWORK_MAX_INCOMING_MSG_SIZE) self.assertEqual(MAX_MSG_SIZE_DEFAULT, config.NETWORK_MAX_INCOMING_MSG_SIZE)
def test_configvars_get_default_value_complex_fn(self):
config = SimpleConfig(self.options)
self.assertEqual("https://swaps.electrum.org/api", config.SWAPSERVER_URL)
config.SWAPSERVER_URL = "http://localhost:9999"
self.assertEqual("http://localhost:9999", config.SWAPSERVER_URL)
config.SWAPSERVER_URL = None
self.assertEqual("https://swaps.electrum.org/api", config.SWAPSERVER_URL)
constants.set_testnet()
try:
self.assertEqual("https://swaps.electrum.org/testnet", config.SWAPSERVER_URL)
finally:
constants.set_mainnet()
def test_configvars_is_set(self): def test_configvars_is_set(self):
config = SimpleConfig(self.options) config = SimpleConfig(self.options)
self.assertEqual(MAX_MSG_SIZE_DEFAULT, config.NETWORK_MAX_INCOMING_MSG_SIZE) self.assertEqual(MAX_MSG_SIZE_DEFAULT, config.NETWORK_MAX_INCOMING_MSG_SIZE)

Loading…
Cancel
Save