diff --git a/lbrynet/conf.py b/lbrynet/conf.py index 1f840e1b4..c3c1910bb 100644 --- a/lbrynet/conf.py +++ b/lbrynet/conf.py @@ -45,11 +45,11 @@ else: class Settings(object): """A collection of configuration settings""" __fixed = [] - __excluded = ['get_dict', 'update'] + _excluded = ['get_dict', 'update'] def __iter__(self): for k in self.__dict__.iterkeys(): - if k.startswith('_') or k in self.__excluded: + if k.startswith('_') or k in self._excluded: continue yield k @@ -67,8 +67,8 @@ class Settings(object): def get_dict(self): return {k: self[k] for k in self} - def update(self, other): - for k, v in other.iteritems(): + def update(self, updated_settings): + for k, v in updated_settings.iteritems(): try: self.__setitem__(k, v) except (KeyError, AssertionError): @@ -180,9 +180,15 @@ ENVIRONMENT = Env( class AdjustableSettings(Settings): + _excluded = ['get_dict', 'update', 'environ'] + """Settings that are allowed to be overriden by the user""" def __init__(self, environ=None): self.environ = environ or ENVIRONMENT + + for opt in self.environ.original_schema: + self.__dict__[opt] = self.environ(opt) + Settings.__init__(self) def __getattr__(self, attr): @@ -190,13 +196,6 @@ class AdjustableSettings(Settings): return self.environ(attr) raise AttributeError - def get_dict(self): - return { - name: self.environ(name) - for name in self.environ.original_schema - } - - class ApplicationSettings(Settings): """Settings that are constants and shouldn't be overriden""" def __init__(self): @@ -268,6 +267,12 @@ class Config(DefaultSettings): def UI_ADDRESS(self): return "http://%s:%i" % (DEFAULT_SETTINGS.API_INTERFACE, self.api_port) + def get_dict(self): + return {k: self[k] for k in self} + + def get_adjustable_settings_dict(self): + return {opt: val for opt, val in self.get_dict().iteritems() if opt in self.environ.original_schema} + def ensure_data_dir(self): # although there is a risk of a race condition here we don't # expect there to be multiple processes accessing this @@ -335,7 +340,8 @@ def load_settings(path): # or command line flag we don't want to persist it for future settings. def save_settings(path=None): path = path or settings.get_conf_filename() - to_save = {k: v for k, v in settings.__dict__.iteritems() if k in ADJUSTABLE_SETTINGS} + to_save = settings.get_adjustable_settings_dict() + ext = os.path.splitext(path)[1] encoder = settings_encoders.get(ext, False) assert encoder is not False, "Unknown settings format .%s" % ext diff --git a/lbrynet/lbrynet_daemon/Daemon.py b/lbrynet/lbrynet_daemon/Daemon.py index b3109c771..4bd20222f 100644 --- a/lbrynet/lbrynet_daemon/Daemon.py +++ b/lbrynet/lbrynet_daemon/Daemon.py @@ -665,6 +665,7 @@ class Daemon(AuthJSONRPCServer): except Exception as err: log.warning(err.message) log.warning("error converting setting '%s' to type %s", key, setting_type) + conf.save_settings() self.run_on_startup = conf.settings.run_on_startup self.data_rate = conf.settings.data_rate @@ -1234,7 +1235,7 @@ class Daemon(AuthJSONRPCServer): """ log.info("Get daemon settings") - return self._render_response(conf.settings.__dict__, OK_CODE) + return self._render_response(conf.settings.get_dict(), OK_CODE) @AuthJSONRPCServer.auth_required def jsonrpc_set_settings(self, p): @@ -1255,12 +1256,12 @@ class Daemon(AuthJSONRPCServer): """ def _log_settings_change(): - log.info("Set daemon settings to " + json.dumps(conf.settings.configurable_settings)) + log.info("Set daemon settings to " + json.dumps(conf.settings.get_adjustable_settings_dict())) d = self._update_settings(p) d.addErrback(lambda err: log.info(err.getTraceback())) d.addCallback(lambda _: _log_settings_change()) - d.addCallback(lambda _: self._render_response(conf.settings.configurable_settings, OK_CODE)) + d.addCallback(lambda _: self._render_response(conf.settings.get_adjustable_settings_dict(), OK_CODE)) return d diff --git a/tests/unit/test_conf.py b/tests/unit/test_conf.py new file mode 100644 index 000000000..1cd9a2e7f --- /dev/null +++ b/tests/unit/test_conf.py @@ -0,0 +1,36 @@ +import os + +from twisted.trial import unittest + +from lbrynet import conf + + +class SettingsTest(unittest.TestCase): + def setUp(self): + os.environ['LBRY_TEST'] = 'test_string' + + def tearDown(self): + del os.environ['LBRY_TEST'] + + def test_envvar_is_read(self): + env = conf.Env(test=(str, '')) + settings = conf.AdjustableSettings(env) + self.assertEqual('test_string', settings.test) + + def test_setting_can_be_overriden(self): + env = conf.Env(test=(str, '')) + settings = conf.AdjustableSettings(env) + settings.test = 'my_override' + self.assertEqual('my_override', settings.test) + + def test_setting_can_be_updated(self): + env = conf.Env(test=(str, '')) + settings = conf.AdjustableSettings(env) + settings.update({'test': 'my_update'}) + self.assertEqual('my_update', settings.test) + + def test_setting_is_in_dict(self): + env = conf.Env(test=(str, '')) + settings = conf.AdjustableSettings(env) + setting_dict = settings.get_dict() + self.assertEqual({'test': 'test_string'}, setting_dict)