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,
64 'queue_mode': "track", #TODO control values
66 'single_album': "false",
72 'queue_mode': "track", #TODO control values
74 'single_album': "false",
80 'flavour': "sensible", # in pure, sensible
87 class ConfMan(object): # CONFIG MANAGER CLASS
89 Configuration manager.
90 Default configuration is stored in DEFAULT_CONF dictionnary.
91 First init_config() run to get config from file.
92 Then control_conf() is run and retrieve configuration from defaults if not
94 These settings are then updated with command line options with
95 supersedes_config_with_cmd_line_options().
97 Order of priority for the origin of an option is then (lowest to highest):
99 * Env. Var for MPD host, port and password
100 * configuration file (overrides previous)
101 * command line options (overrides previous)
104 def __init__(self, logger, options=None):
106 # options settings priority:
107 # defauts < env. var. < conf. file < command line
108 self.conf_file = options.get('conf_file')
109 self.config = configparser.ConfigParser(inline_comment_prefixes='#')
110 self.config.read_dict(DEFAULT_CONF)
111 # update DEFAULT_CONF with env. var.
113 self.startopt = options
117 self.supersedes_config_with_cmd_line_options()
121 self.config.getboolean('MPD', 'password')
122 self.log.debug('No password set, proceeding without ' +
126 # ValueError if password not a boolean, hence an actual password.
127 pwd = self.config.get('MPD', 'password')
129 self.log.debug('Password set as an empty string.')
133 def control_mod(self):
135 Controls conf file permissions.
137 mode = S_IMODE(stat(self.conf_file)[ST_MODE])
138 self.log.debug('file permission is: %o' % mode)
139 if mode & S_IRWXO or mode & S_IRWXG:
140 self.log.warning('File is readable by "other" and/or' +
141 ' "group" (actual permission %o octal).' %
143 self.log.warning('Consider setting permissions' +
146 def supersedes_config_with_cmd_line_options(self):
147 """Updates defaults settings with command line options"""
148 for sec in self.config.sections():
149 for opt in self.config.options(sec):
150 if opt in list(self.startopt.keys()):
151 self.config.set(sec, opt, str(self.startopt.get(opt)))
154 """Use MPD en.var. to set defaults"""
155 mpd_host, mpd_port, passwd = utils.get_mpd_environ()
157 self.log.info('Env. variable MPD_HOST set to "%s"' % mpd_host)
158 self.config['MPD'].update(host=mpd_host)
160 self.log.info('Env. variable MPD_HOST contains password.')
161 self.config['MPD'].update(password=passwd)
163 self.log.info('Env. variable MPD_PORT set to "%s".' % mpd_port)
164 self.config['MPD'].update(port=mpd_port)
166 def init_config(self):
168 Use XDG directory standard if exists
169 else use "HOME/(.config|.local/share)/sima/"
170 http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
173 homedir = environ.get('HOME')
175 if environ.get('XDG_DATA_HOME'):
176 data_dir = join(environ.get('XDG_DATA_HOME'), DIRNAME)
177 elif homedir and isdir(homedir) and homedir not in ['/']:
178 data_dir = join(homedir, '.local', 'share', DIRNAME)
180 self.log.error('Can\'t find a suitable location for data folder (XDG_DATA_HOME)')
181 self.log.error('Please use "--var_dir" to set a proper location')
184 if not isdir(data_dir):
186 chmod(data_dir, 0o700)
188 if self.startopt.get('conf_file'):
189 # No need to handle conf file location
191 elif environ.get('XDG_CONFIG_HOME'):
192 conf_dir = join(environ.get('XDG_CONFIG_HOME'), DIRNAME)
193 elif homedir and isdir(homedir) and homedir not in ['/']:
194 conf_dir = join(homedir, '.config', DIRNAME)
195 # Create conf_dir if necessary
196 if not isdir(conf_dir):
198 chmod(conf_dir, 0o700)
199 self.conf_file = join(conf_dir, CONF_FILE)
201 self.log.error('Can\'t find a suitable location for config folder (XDG_CONFIG_HOME)')
202 self.log.error('Please use "--config" to locate the conf file')
206 self.config['sima']['var_dir'] = join(data_dir)
207 self.config['sima']['db_file'] = join(data_dir, 'sima.db')
209 # If no conf file present, uses defaults
210 if not isfile(self.conf_file):
213 self.log.info('Loading configuration from: %s' % self.conf_file)
217 self.config.read(self.conf_file)
223 # vim: ai ts=4 sw=4 sts=4 expandtab