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()
123 self.config['sima']['db_file'] = join(self.config['sima']['var_dir'], 'sima.db')
127 self.config.getboolean('MPD', 'password')
128 self.log.debug('No password set, proceeding without ' +
132 # ValueError if password not a boolean, hence an actual password.
133 pwd = self.config.get('MPD', 'password')
135 self.log.debug('Password set as an empty string.')
139 def control_mod(self):
141 Controls conf file permissions.
143 mode = S_IMODE(stat(self.conf_file)[ST_MODE])
144 self.log.debug('file permission is: %o' % mode)
145 if mode & S_IRWXO or mode & S_IRWXG:
146 self.log.warning('File is readable by "other" and/or' +
147 ' "group" (actual permission %o octal).' %
149 self.log.warning('Consider setting permissions' +
152 def supersedes_config_with_cmd_line_options(self):
153 """Updates defaults settings with command line options"""
154 for sec in self.config.sections():
155 for opt in self.config.options(sec):
156 if opt in list(self.startopt.keys()):
157 self.config.set(sec, opt, str(self.startopt.get(opt)))
160 """Use MPD en.var. to set defaults"""
161 mpd_host, mpd_port, passwd = utils.get_mpd_environ()
163 self.log.info('Env. variable MPD_HOST set to "%s"' % mpd_host)
164 self.config['MPD'].update(host=mpd_host)
166 self.log.info('Env. variable MPD_HOST contains password.')
167 self.config['MPD'].update(password=passwd)
169 self.log.info('Env. variable MPD_PORT set to "%s".' % mpd_port)
170 self.config['MPD'].update(port=mpd_port)
172 def init_config(self):
174 Use XDG directory standard if exists
175 else use "HOME/(.config|.local/share)/sima/"
176 http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
179 homedir = environ.get('HOME')
181 if environ.get('XDG_DATA_HOME'):
182 data_dir = join(environ.get('XDG_DATA_HOME'), DIRNAME)
183 elif homedir and isdir(homedir) and homedir not in ['/']:
184 data_dir = join(homedir, '.local', 'share', DIRNAME)
186 self.log.error('Can\'t find a suitable location for data folder (XDG_DATA_HOME)')
187 self.log.error('Please use "--var_dir" to set a proper location')
190 if not isdir(data_dir):
192 chmod(data_dir, 0o700)
194 if self.startopt.get('conf_file'):
195 # No need to handle conf file location
197 elif environ.get('XDG_CONFIG_HOME'):
198 conf_dir = join(environ.get('XDG_CONFIG_HOME'), DIRNAME)
199 elif homedir and isdir(homedir) and homedir not in ['/']:
200 conf_dir = join(homedir, '.config', DIRNAME)
201 # Create conf_dir if necessary
202 if not isdir(conf_dir):
204 chmod(conf_dir, 0o700)
205 self.conf_file = join(conf_dir, CONF_FILE)
207 self.log.error('Can\'t find a suitable location for config folder (XDG_CONFIG_HOME)')
208 self.log.error('Please use "--config" to locate the conf file')
212 self.config['sima']['var_dir'] = join(data_dir)
214 # If no conf file present, uses defaults
215 if not isfile(self.conf_file):
218 self.log.info('Loading configuration from: %s' % self.conf_file)
222 self.config.read(self.conf_file)
228 # vim: ai ts=4 sw=4 sts=4 expandtab