commands: getconfig to use default values, add existence checks
- getconfig and setconfig now both check configvars for existence - getconfig returns default values when applicable - setconfig does not side-step type-checks for values fixes https://github.com/spesmilo/electrum/issues/8607 closes https://github.com/spesmilo/electrum/pull/8608
This commit is contained in:
@@ -59,7 +59,7 @@ from .lnutil import SENT, RECEIVED
|
||||
from .lnutil import LnFeatures
|
||||
from .lnutil import extract_nodeid
|
||||
from .lnpeer import channel_id_from_funding_tx
|
||||
from .plugin import run_hook, DeviceMgr
|
||||
from .plugin import run_hook, DeviceMgr, Plugins
|
||||
from .version import ELECTRUM_VERSION
|
||||
from .simple_config import SimpleConfig
|
||||
from .invoices import Invoice
|
||||
@@ -305,7 +305,11 @@ class Commands:
|
||||
@command('')
|
||||
async def getconfig(self, key):
|
||||
"""Return a configuration variable. """
|
||||
return self.config.get(key)
|
||||
if Plugins.is_plugin_enabler_config_key(key):
|
||||
return self.config.get(key)
|
||||
else:
|
||||
cv = self.config.cv.from_key(key)
|
||||
return cv.get()
|
||||
|
||||
@classmethod
|
||||
def _setconfig_normalize_value(cls, key, value):
|
||||
@@ -326,7 +330,11 @@ class Commands:
|
||||
self.daemon.commands_server.rpc_user = value
|
||||
if self.daemon and key == SimpleConfig.RPC_PASSWORD.key():
|
||||
self.daemon.commands_server.rpc_password = value
|
||||
self.config.set_key(key, value)
|
||||
if Plugins.is_plugin_enabler_config_key(key):
|
||||
self.config.set_key(key, value)
|
||||
else:
|
||||
cv = self.config.cv.from_key(key)
|
||||
cv.set(value)
|
||||
return True
|
||||
|
||||
@command('')
|
||||
|
||||
@@ -160,6 +160,15 @@ class Plugins(DaemonThread):
|
||||
p.close()
|
||||
self.logger.info(f"closed {name}")
|
||||
|
||||
@classmethod
|
||||
def is_plugin_enabler_config_key(cls, key: str) -> bool:
|
||||
if not key.startswith('use_'):
|
||||
return False
|
||||
# note: the 'use_' prefix is not sufficient to check, there are
|
||||
# non-plugin-related config keys that also have it... hence:
|
||||
name = key[4:]
|
||||
return name in cls.find_all_plugins()
|
||||
|
||||
def toggle(self, name: str) -> Optional['BasePlugin']:
|
||||
p = self.get(name)
|
||||
return self.disable(name) if p else self.enable(name)
|
||||
|
||||
@@ -52,6 +52,9 @@ _logger = get_logger(__name__)
|
||||
FINAL_CONFIG_VERSION = 3
|
||||
|
||||
|
||||
_config_var_from_key = {} # type: Dict[str, 'ConfigVar']
|
||||
|
||||
|
||||
class ConfigVar(property):
|
||||
|
||||
def __init__(
|
||||
@@ -65,6 +68,7 @@ class ConfigVar(property):
|
||||
self._default = default
|
||||
self._type = type_
|
||||
property.__init__(self, self._get_config_value, self._set_config_value)
|
||||
_config_var_from_key[key] = self
|
||||
|
||||
def _get_config_value(self, config: 'SimpleConfig'):
|
||||
with config.lock:
|
||||
@@ -132,6 +136,11 @@ class ConfigVarWithConfig:
|
||||
def __repr__(self):
|
||||
return f"<ConfigVarWithConfig key={self.key()!r}>"
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
if not isinstance(other, ConfigVarWithConfig):
|
||||
return False
|
||||
return self._config is other._config and self._config_var is other._config_var
|
||||
|
||||
|
||||
class SimpleConfig(Logger):
|
||||
"""
|
||||
@@ -818,10 +827,18 @@ class SimpleConfig(Logger):
|
||||
"""
|
||||
class CVLookupHelper:
|
||||
def __getattribute__(self, name: str) -> ConfigVarWithConfig:
|
||||
if name in ("from_key", ): # don't apply magic, just use standard lookup
|
||||
return super().__getattribute__(name)
|
||||
config_var = config.__class__.__getattribute__(type(config), name)
|
||||
if not isinstance(config_var, ConfigVar):
|
||||
raise AttributeError()
|
||||
return ConfigVarWithConfig(config=config, config_var=config_var)
|
||||
def from_key(self, key: str) -> ConfigVarWithConfig:
|
||||
try:
|
||||
config_var = _config_var_from_key[key]
|
||||
except KeyError:
|
||||
raise KeyError(f"No ConfigVar with key={key!r}") from None
|
||||
return ConfigVarWithConfig(config=config, config_var=config_var)
|
||||
def __setattr__(self, name, value):
|
||||
raise Exception(
|
||||
f"Cannot assign value to config.cv.{name} directly. "
|
||||
|
||||
@@ -199,6 +199,12 @@ class Test_SimpleConfig(ElectrumTestCase):
|
||||
config.NETWORK_MAX_INCOMING_MSG_SIZE = 2_222_222
|
||||
self.assertEqual(5_555_555, config.NETWORK_MAX_INCOMING_MSG_SIZE)
|
||||
|
||||
def test_configvars_from_key(self):
|
||||
config = SimpleConfig(self.options)
|
||||
self.assertEqual(config.cv.NETWORK_SERVER, config.cv.from_key("server"))
|
||||
with self.assertRaises(KeyError):
|
||||
config.cv.from_key("server333")
|
||||
|
||||
def test_depth_target_to_fee(self):
|
||||
config = SimpleConfig(self.options)
|
||||
config.mempool_fees = [[49, 100110], [10, 121301], [6, 153731], [5, 125872], [1, 36488810]]
|
||||
|
||||
Reference in New Issue
Block a user