mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
We store it in the config object instead of in the blockchain object. The blockchain object now refers to its config, and calls refresh_height() to update it. The network objects also refer to the config rather than the blockchain. This is the first of many small steps to untangle the verifier from stored state and so permit the history tab to work in offline mode. The refactoring will simultaneously clean up a lot of accumulated cruft.
190 lines
5.8 KiB
Python
190 lines
5.8 KiB
Python
import ast
|
|
import json
|
|
import threading
|
|
import os
|
|
|
|
from util import user_dir, print_error, print_msg
|
|
|
|
SYSTEM_CONFIG_PATH = "/etc/electrum.conf"
|
|
|
|
config = None
|
|
|
|
|
|
def get_config():
|
|
global config
|
|
return config
|
|
|
|
|
|
def set_config(c):
|
|
global config
|
|
config = c
|
|
|
|
|
|
class SimpleConfig(object):
|
|
"""
|
|
The SimpleConfig class is responsible for handling operations involving
|
|
configuration files.
|
|
|
|
There are 3 different sources of possible configuration values:
|
|
1. Command line options.
|
|
2. User configuration (in the user's config directory)
|
|
3. System configuration (in /etc/)
|
|
They are taken in order (1. overrides config options set in 2., that
|
|
override config set in 3.)
|
|
"""
|
|
def __init__(self, options=None, read_system_config_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
|
|
# a thread-safe way.
|
|
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
|
|
# testing.
|
|
if read_system_config_function is None:
|
|
read_system_config_function = read_system_config
|
|
if read_user_config_function is None:
|
|
read_user_config_function = read_user_config
|
|
if read_user_dir_function is None:
|
|
self.user_dir = user_dir
|
|
else:
|
|
self.user_dir = read_user_dir_function
|
|
|
|
# Save the command-line keys to make sure we don't override them.
|
|
self.command_line_keys = options.keys()
|
|
# Save the system config keys to make sure we don't override them.
|
|
self.system_config_keys = []
|
|
|
|
if options.get('portable') is not True:
|
|
# system conf
|
|
system_config = read_system_config_function()
|
|
self.system_config_keys = system_config.keys()
|
|
self.read_only_options.update(system_config)
|
|
|
|
# update the current options with the command line options last (to
|
|
# override both others).
|
|
self.read_only_options.update(options)
|
|
|
|
# init path
|
|
self.init_path()
|
|
|
|
# user config.
|
|
self.user_config = read_user_config_function(self.path)
|
|
|
|
self.refresh_height()
|
|
|
|
set_config(self) # Make a singleton instance of 'self'
|
|
|
|
def init_path(self):
|
|
# Read electrum path in the command line configuration
|
|
self.path = self.read_only_options.get('electrum_path')
|
|
|
|
# If not set, use the user's default data directory.
|
|
if self.path is None:
|
|
self.path = self.user_dir()
|
|
|
|
# Make directory if it does not yet exist.
|
|
if not os.path.exists(self.path):
|
|
os.mkdir(self.path)
|
|
|
|
print_error( "electrum directory", self.path)
|
|
|
|
def set_key(self, key, value, save = True):
|
|
if not self.is_modifiable(key):
|
|
print "Warning: not changing key '%s' because it is not modifiable" \
|
|
" (passed as command line option or defined in /etc/electrum.conf)"%key
|
|
return
|
|
|
|
with self.lock:
|
|
self.user_config[key] = value
|
|
if save:
|
|
self.save_user_config()
|
|
|
|
return
|
|
|
|
def get(self, key, default=None):
|
|
out = None
|
|
with self.lock:
|
|
out = self.read_only_options.get(key)
|
|
if out is None:
|
|
out = self.user_config.get(key, default)
|
|
return out
|
|
|
|
def is_modifiable(self, key):
|
|
if key in self.command_line_keys:
|
|
return False
|
|
if key in self.system_config_keys:
|
|
return False
|
|
return True
|
|
|
|
def headers_filename(self):
|
|
return os.path.join(self.path, 'blockchain_headers')
|
|
|
|
def refresh_height(self):
|
|
name = self.headers_filename()
|
|
if os.path.exists(name):
|
|
self.height = os.path.getsize(name) / 80 - 1
|
|
else:
|
|
self.height = 0
|
|
|
|
def save_user_config(self):
|
|
if not self.path:
|
|
return
|
|
path = os.path.join(self.path, "config")
|
|
s = json.dumps(self.user_config, indent=4, sort_keys=True)
|
|
f = open(path, "w")
|
|
f.write(s)
|
|
f.close()
|
|
if self.get('gui') != 'android':
|
|
import stat
|
|
os.chmod(path, stat.S_IREAD | stat.S_IWRITE)
|
|
|
|
def read_system_config(path=SYSTEM_CONFIG_PATH):
|
|
"""Parse and return the system config settings in /etc/electrum.conf."""
|
|
result = {}
|
|
if os.path.exists(path):
|
|
try:
|
|
import ConfigParser
|
|
except ImportError:
|
|
print "cannot parse electrum.conf. please install ConfigParser"
|
|
return
|
|
|
|
p = ConfigParser.ConfigParser()
|
|
try:
|
|
p.read(path)
|
|
for k, v in p.items('client'):
|
|
result[k] = v
|
|
except (ConfigParser.NoSectionError, ConfigParser.MissingSectionHeaderError):
|
|
pass
|
|
|
|
return result
|
|
|
|
def read_user_config(path):
|
|
"""Parse and store the user config settings in electrum.conf into user_config[]."""
|
|
if not path:
|
|
return {}
|
|
config_path = os.path.join(path, "config")
|
|
try:
|
|
with open(config_path, "r") as f:
|
|
data = f.read()
|
|
except IOError:
|
|
print_msg("Error: Cannot read config file.")
|
|
return {}
|
|
try:
|
|
result = json.loads(data)
|
|
except:
|
|
try:
|
|
result = ast.literal_eval(data)
|
|
except:
|
|
print_msg("Error: Cannot read config file.")
|
|
return {}
|
|
if not type(result) is dict:
|
|
return {}
|
|
return result
|