Merge pull request #1244 from kyuupichan/simple_config

Fix SimpleConfig
This commit is contained in:
ThomasV 2015-05-25 08:36:46 +02:00
commit d287152942
2 changed files with 35 additions and 52 deletions

View File

@ -3,6 +3,7 @@ import json
import threading import threading
import os import os
from copy import deepcopy
from util import user_dir, print_error, print_msg from util import user_dir, print_error, print_msg
SYSTEM_CONFIG_PATH = "/etc/electrum.conf" SYSTEM_CONFIG_PATH = "/etc/electrum.conf"
@ -32,19 +33,12 @@ class SimpleConfig(object):
They are taken in order (1. overrides config options set in 2., that They are taken in order (1. overrides config options set in 2., that
override config set in 3.) override config set in 3.)
""" """
def __init__(self, options=None, read_system_config_function=None, def __init__(self, options={}, read_system_config_function=None,
read_user_config_function=None, read_user_dir_function=None): read_user_config_function=None, read_user_dir_function=None):
# This is the holder of actual options for the current user.
self.read_only_options = {}
# This lock needs to be acquired for updating and reading the config in # This lock needs to be acquired for updating and reading the config in
# a thread-safe way. # a thread-safe way.
self.lock = threading.RLock() self.lock = threading.RLock()
# The path for the config directory. This is set later by init_path()
self.path = None
if options is None:
options = {} # Having a mutable as a default value is a bad idea.
# The following two functions are there for dependency injection when # The following two functions are there for dependency injection when
# testing. # testing.
@ -57,45 +51,39 @@ class SimpleConfig(object):
else: else:
self.user_dir = read_user_dir_function self.user_dir = read_user_dir_function
# Save the command-line keys to make sure we don't override them. # The command line options
self.command_line_keys = options.keys() self.cmdline_options = deepcopy(options)
# Save the system config keys to make sure we don't override them.
self.system_config_keys = []
if options.get('portable') is not True: # Portable wallets don't use a system config
# system conf if self.cmdline_options.get('portable', False):
system_config = read_system_config_function() self.system_config = read_system_config_function()
self.system_config_keys = system_config.keys() else:
self.read_only_options.update(system_config) self.system_config = {}
# update the current options with the command line options last (to # Set self.path and read the user config
# override both others). self.user_config = {} # for self.get in electrum_path()
self.read_only_options.update(options) self.path = self.electrum_path()
# init path
self.init_path()
# user config.
self.user_config = read_user_config_function(self.path) self.user_config = read_user_config_function(self.path)
# Make a singleton instance of 'self' # Make a singleton instance of 'self'
set_config(self) set_config(self)
def init_path(self): def electrum_path(self):
# Read electrum path in the command line configuration # Read electrum_path from command line / system configuration
self.path = self.read_only_options.get('electrum_path') # Otherwise use the user's default data directory.
path = self.get('electrum_path')
# If not set, use the user's default data directory. if path is None:
if self.path is None: path = self.user_dir()
self.path = self.user_dir()
# Make directory if it does not yet exist. # Make directory if it does not yet exist.
if not os.path.exists(self.path): if not os.path.exists(path):
os.mkdir(self.path) os.mkdir(path)
print_error( "electrum directory", self.path) print_error("electrum directory", path)
return path
def set_key(self, key, value, save = True): def set_key(self, key, value, save = True):
if not self.is_modifiable(key): if not self.is_modifiable(key):
print "Warning: not changing key '%s' because it is not modifiable" \ print_error("Warning: not changing config key '%s' set on the command line" % key)
" (passed as command line option or defined in /etc/electrum.conf)"%key
return return
with self.lock: with self.lock:
@ -105,19 +93,16 @@ class SimpleConfig(object):
return return
def get(self, key, default=None): def get(self, key, default=None):
out = None
with self.lock: with self.lock:
out = self.read_only_options.get(key) out = self.cmdline_options.get(key)
if out is None: if out is None:
out = self.user_config.get(key, default) out = self.user_config.get(key)
if out is None:
out = self.system_config.get(key, default)
return out return out
def is_modifiable(self, key): def is_modifiable(self, key):
if key in self.command_line_keys: return not key in self.cmdline_options
return False
if key in self.system_config_keys:
return False
return True
def save_user_config(self): def save_user_config(self):
if not self.path: if not self.path:

View File

@ -48,17 +48,16 @@ class Test_SimpleConfig(unittest.TestCase):
self.assertEqual(self.options.get("electrum_path"), self.assertEqual(self.options.get("electrum_path"),
config.get("electrum_path")) config.get("electrum_path"))
def test_simple_config_system_config_overrides_user_config(self): def test_simple_config_user_config_overrides_system_config(self):
"""Options passed in system config override user config.""" """Options passed in user config override system config."""
fake_read_system = lambda : {"electrum_path": self.electrum_dir} fake_read_system = lambda : {"electrum_path": self.electrum_dir}
fake_read_user = lambda _: {"electrum_path": "b"} fake_read_user = lambda _: {"electrum_path": "b"}
read_user_dir = lambda : self.user_dir read_user_dir = lambda : self.user_dir
config = SimpleConfig(options=None, config = SimpleConfig(options={},
read_system_config_function=fake_read_system, read_system_config_function=fake_read_system,
read_user_config_function=fake_read_user, read_user_config_function=fake_read_user,
read_user_dir_function=read_user_dir) read_user_dir_function=read_user_dir)
self.assertEqual(self.options.get("electrum_path"), self.assertEqual("b", config.get("electrum_path"))
config.get("electrum_path"))
def test_simple_config_system_config_ignored_if_portable(self): def test_simple_config_system_config_ignored_if_portable(self):
"""If electrum is started with the "portable" flag, system """If electrum is started with the "portable" flag, system
@ -79,7 +78,7 @@ class Test_SimpleConfig(unittest.TestCase):
fake_read_system = lambda : {} fake_read_system = lambda : {}
fake_read_user = lambda _: {"electrum_path": self.electrum_dir} fake_read_user = lambda _: {"electrum_path": self.electrum_dir}
read_user_dir = lambda : self.user_dir read_user_dir = lambda : self.user_dir
config = SimpleConfig(options=None, config = SimpleConfig(options={},
read_system_config_function=fake_read_system, read_system_config_function=fake_read_system,
read_user_config_function=fake_read_user, read_user_config_function=fake_read_user,
read_user_dir_function=read_user_dir) read_user_dir_function=read_user_dir)
@ -98,7 +97,7 @@ class Test_SimpleConfig(unittest.TestCase):
self.assertEqual(self.options.get("electrum_path"), self.assertEqual(self.options.get("electrum_path"),
config.get("electrum_path")) config.get("electrum_path"))
def test_cannot_set_options_from_system_config(self): def test_can_set_options_from_system_config(self):
fake_read_system = lambda : {"electrum_path": self.electrum_dir} fake_read_system = lambda : {"electrum_path": self.electrum_dir}
fake_read_user = lambda _: {} fake_read_user = lambda _: {}
read_user_dir = lambda : self.user_dir read_user_dir = lambda : self.user_dir
@ -107,8 +106,7 @@ class Test_SimpleConfig(unittest.TestCase):
read_user_config_function=fake_read_user, read_user_config_function=fake_read_user,
read_user_dir_function=read_user_dir) read_user_dir_function=read_user_dir)
config.set_key("electrum_path", "c") config.set_key("electrum_path", "c")
self.assertEqual(self.options.get("electrum_path"), self.assertEqual("c", config.get("electrum_path"))
config.get("electrum_path"))
def test_can_set_options_set_in_user_config(self): def test_can_set_options_set_in_user_config(self):
another_path = tempfile.mkdtemp() another_path = tempfile.mkdtemp()