1 # -*- coding: utf-8 -*-
2 # Copyright (c) 2009, 2010, 2011, 2013, 2014 Jack Kaliko <kaliko@azylum.org>
4 # This file is part of sima
6 # sima is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # sima is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with sima. If not, see <http://www.gnu.org/licenses/>.
22 Deal with configuration and data files.
23 Parse configuration file and set defaults for missing options.
30 from configparser import Error
31 from os import (makedirs, environ, stat, chmod)
32 from os.path import (join, isdir, isfile)
33 from stat import (S_IMODE, ST_MODE, S_IRWXO, S_IRWXG)
39 CONF_FILE = 'sima.cfg'
48 'internal': "Crop, Lastfm, RandomFallBack",
51 'history_duration': 8,
67 'queue_mode': "track", #TODO control values
69 'single_album': "false",
75 'queue_mode': "track", #TODO control values
77 'single_album': "false",
84 'flavour': "sensible", # in pure, sensible
91 class ConfMan(object): # CONFIG MANAGER CLASS
93 Configuration manager.
94 Default configuration is stored in DEFAULT_CONF dictionnary.
95 First init_config() run to get config from file.
96 Then control_conf() is run and retrieve configuration from defaults if not
98 These settings are then updated with command line options with
99 supersedes_config_with_cmd_line_options().
101 Order of priority for the origin of an option is then (lowest to highest):
103 * Env. Var for MPD host, port and password
104 * configuration file (overrides previous)
105 * command line options (overrides previous)
108 def __init__(self, logger, options=None):
110 # options settings priority:
111 # defauts < env. var. < conf. file < command line
112 self.conf_file = options.get('conf_file')
113 self.config = configparser.ConfigParser(inline_comment_prefixes='#')
114 self.config.read_dict(DEFAULT_CONF)
115 # update DEFAULT_CONF with env. var.
117 self.startopt = options
121 self.supersedes_config_with_cmd_line_options()
125 self.config.getboolean('MPD', 'password')
126 self.log.debug('No password set, proceeding without ' +
130 # ValueError if password not a boolean, hence an actual password.
131 pwd = self.config.get('MPD', 'password')
133 self.log.debug('Password set as an empty string.')
137 def control_mod(self):
139 Controls conf file permissions.
141 mode = S_IMODE(stat(self.conf_file)[ST_MODE])
142 self.log.debug('file permission is: %o' % mode)
143 if mode & S_IRWXO or mode & S_IRWXG:
144 self.log.warning('File is readable by "other" and/or' +
145 ' "group" (actual permission %o octal).' %
147 self.log.warning('Consider setting permissions' +
150 def supersedes_config_with_cmd_line_options(self):
151 """Updates defaults settings with command line options"""
152 for sec in self.config.sections():
153 for opt in self.config.options(sec):
154 if opt in list(self.startopt.keys()):
155 self.config.set(sec, opt, str(self.startopt.get(opt)))
158 """Use MPD en.var. to set defaults"""
159 mpd_host, mpd_port, passwd = utils.get_mpd_environ()
161 self.log.info('Env. variable MPD_HOST set to "%s"' % mpd_host)
162 self.config['MPD'].update(host=mpd_host)
164 self.log.info('Env. variable MPD_HOST contains password.')
165 self.config['MPD'].update(password=passwd)
167 self.log.info('Env. variable MPD_PORT set to "%s".' % mpd_port)
168 self.config['MPD'].update(port=mpd_port)
170 def init_config(self):
172 Use XDG directory standard if exists
173 else use "HOME/(.config|.local/share)/sima/"
174 http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
177 homedir = environ.get('HOME')
179 if environ.get('XDG_DATA_HOME'):
180 data_dir = join(environ.get('XDG_DATA_HOME'), DIRNAME)
181 elif homedir and isdir(homedir) and homedir not in ['/']:
182 data_dir = join(homedir, '.local', 'share', DIRNAME)
184 self.log.error('Can\'t find a suitable location for data folder (XDG_DATA_HOME)')
185 self.log.error('Please use "--var_dir" to set a proper location')
188 if not isdir(data_dir):
190 chmod(data_dir, 0o700)
192 if self.startopt.get('conf_file'):
193 # No need to handle conf file location
195 elif environ.get('XDG_CONFIG_HOME'):
196 conf_dir = join(environ.get('XDG_CONFIG_HOME'), DIRNAME)
197 elif homedir and isdir(homedir) and homedir not in ['/']:
198 conf_dir = join(homedir, '.config', DIRNAME)
199 # Create conf_dir if necessary
200 if not isdir(conf_dir):
202 chmod(conf_dir, 0o700)
203 self.conf_file = join(conf_dir, CONF_FILE)
205 self.log.error('Can\'t find a suitable location for config folder (XDG_CONFIG_HOME)')
206 self.log.error('Please use "--config" to locate the conf file')
210 self.config['sima']['var_dir'] = join(data_dir)
211 self.config['sima']['db_file'] = join(data_dir, 'sima.db')
213 # If no conf file present, uses defaults
214 if not isfile(self.conf_file):
217 self.log.info('Loading configuration from: %s' % self.conf_file)
221 self.config.read(self.conf_file)
227 # vim: ai ts=4 sw=4 sts=4 expandtab