Package brisa :: Package core :: Module config
[hide private]
[frames] | no frames]

Source Code for Module brisa.core.config

  1  # Licensed under the MIT license 
  2  # http://opensource.org/licenses/mit-license.php or see LICENSE file. 
  3  # Copyright 2007-2008 Brisa Team <brisa-develop@garage.maemo.org> 
  4   
  5  """ 
  6  BRisa configuration API consists of access methods (sets and gets) to the 
  7  configuration. 
  8   
  9  When initialized (imported), the configuration reads data from the 
 10  configuration persistence and stores it on a so called "state". By default, 
 11  gets/sets do not apply directly on the persistence, but on the state. For 
 12  example, setting a parameter value with a set_parameter() applies by default 
 13  on the state. 
 14   
 15  The state can be save()'d - stored on the persistence - or update()'d - updated 
 16  with latest persistence values. 
 17   
 18  There's an override that can be made in order to make sets/gets apply directly 
 19  on the persistence. This can be achieved by setting direct_access to True. One 
 20  can use directly config.manager.set_direct_access(True) or just set it 
 21  directly with config.manager.direct_access = True. 
 22   
 23  Basically, holding a state is useful for avoiding overhead during runtime (some 
 24  configurations never change during runtime and those that change are very out 
 25  numbered). Also, for those configurations that needs monitoring, setting 
 26  them and getting them is obviously faster when accessing the state. 
 27   
 28  Note that some methods of config.* are just links to methods of 
 29  config.manager (like config.get_parameter and config.manager.get_parameter). 
 30   
 31  Special variables 
 32  ================= 
 33  - brisa_home: BRisa's home folder for the user running brisa 
 34  - version: BRisa version 
 35  - __interface__: network interface. Can be modified directly during 
 36                   runtime for modifying other modules behavior 
 37  - shared_url: may be used as a global variable for sharing url between 
 38                web servers 
 39  """ 
 40   
 41  import sys 
 42  import os 
 43  import shutil 
 44  import cPickle 
 45  import platform 
 46   
 47  from brisa import version as brisa_version 
 48   
 49   
 50  brisa_home = os.path.join(os.path.expanduser('~'), ".brisa") 
 51   
 52   
53 -def get_platform_name():
54 """ Returns the platform name for this machine. May return 'win32', 55 'unix', 'java', 'mac' or '' (in case it wasn't possible to resolve 56 the name). 57 58 """ 59 if platform.mac_ver()[0]: 60 return 'mac' 61 if platform.win32_ver()[0]: 62 return 'windows' 63 if any(platform.dist()): 64 return 'unix' 65 if platform.java_ver()[0] or platform.java_ver()[1]: 66 return 'java' 67 68 return ''
69 70
71 -class ConfigurationManager(object):
72 """ Class that provides an easy way of managing configurations. 73 74 Configuration is organized in sections, which may contain parameters. 75 Each section has a name and a parameter has a name and a value. 76 77 Concerning storage, the configuration can be saved on a sqlite database. 78 Also, there's a feature called "direct access" that enables direct 79 operations on the database. For example, a get_parameter() call would 80 retrieve the value of a parameter directly from the database, if the 81 feature is enabled. 82 83 When disabled, all methods apply to (what we call) the "state". The state 84 initially contains the same information that is on the database, but if 85 the "direct access" feature is disabled, all get()'s and set()'s apply 86 to the state. This means you can have a "runtime configuration" and a 87 "static configuration". 88 89 By default, the "direct access" feature is disabled. To enable it, just 90 call set_direct_access(True). 91 92 The state can be saved on the persistence by explicitly calling manager.\ 93 save(). It can also update its values by explicitly calling update(). 94 """ 95
96 - def __init__(self, config_path='', default_config={}):
97 """ Constructor for the ConfigurationManager class. 98 99 @param config_path: path of the database to work on. If not supplied 100 will work on a memory database. 101 @param default_config: default sections and parameters. Keys are 102 section names and values are dicts where 103 keys,value pairs represent a parameter 104 name and value, respectivelly. 105 106 @type config_path: string 107 @type default_config: dict 108 """ 109 self._state = {} 110 self._state_diffs = {} 111 self._default_config = default_config 112 self._config_path = config_path 113 self.direct_access = False
114
115 - def set_direct_access(self, access=False):
116 """ Sets the direct access option of the ConfigurationManager. When 117 True, direct access makes all get and set methods work directly on the 118 database, not on the current state. 119 120 Another short description is: direct access disables the 121 ConfigurationManager state feature. 122 123 @param access: The direct access option of the ConfigurationManager 124 125 @type access: boolean 126 """ 127 self.direct_access = access
128
129 - def get_direct_access(self):
130 """ Returns False if the ConfigurationManager is currently working on 131 the runtime state. Otherwise, it will return True, which means it's 132 working directly on the persistence. 133 134 @return: The current status of the ConfigurationManager 135 @rtype: boolean 136 """ 137 return self.direct_access
138
139 - def update(self):
140 """ Updates the current state of the manager according to persistence 141 data. 142 """ 143 self._state = cPickle.load(open(self._config_path, 'rb'))
144
145 - def save(self):
146 """ Stores the state of the manager on the persistence. 147 """ 148 cPickle.dump(self._state, open(self._config_path, 'wb'), 149 cPickle.HIGHEST_PROTOCOL)
150
151 - def get_parameter(self, section='', parameter=''):
152 """ Retrieves the value associated with the parameter in the section 153 given. 154 155 @param section: section to find the parameter 156 @param parameter: parameter to return the value 157 158 @type section: string 159 @type parameter: string 160 161 @return: the value for the given parameter 162 @rtype: string 163 """ 164 if self.get_direct_access(): 165 self.update() 166 167 if section in self._state: 168 return self._state[section].get(parameter, '') 169 170 return ''
171
172 - def get_parameter_bool(self, section='', parameter=''):
173 """ Retrieves the bool associated with the parameter in the section 174 given. Returns True in case of 'on', 'yes', '1' or 'True' (False if 175 not on this list). 176 177 @param section: section to find the parameter 178 @param parameter: parameter to return the value 179 180 @type section: string 181 @type parameter: string 182 183 @return: the existence or not of the parameter 184 @rtype: boolean 185 """ 186 value = self.get_parameter(section, parameter) 187 188 if value in ['on', 'yes', '1', 'True', True]: 189 return True 190 191 return False
192
193 - def get_parameter_as_list(self, section='', parameter='', token=':'):
194 """ Retrieves the list associated with the parameter in the section 195 given. 196 197 @param section: section to find the parameter 198 @param parameter: parameter where is located the list 199 @param token: split token for the list 200 201 @type section: string 202 @type parameter: string 203 @type token: string 204 205 @return: list associated with the parameter 206 @rtype: [] 207 """ 208 value = self.get_parameter(section, parameter) 209 210 if value: 211 return value.split(token) 212 213 return []
214
215 - def set_parameter(self, section, parameter, par_value=None):
216 """ Sets a parameter's value in the given section. If the parameter 217 does not exist, it gets created. 218 219 @param section: section to set the parameter 220 @param parameter: parameter to set the value 221 @param par_value: value to be set 222 223 @type section: string 224 @type parameter: string 225 @type par_value: string 226 """ 227 if section not in self._state: 228 self._state[section] = {} 229 230 if par_value == None and parameter in self._state[section]: 231 self._state[section].pop(parameter) 232 else: 233 self._state[section][parameter] = par_value 234 235 if self.get_direct_access(): 236 self.save()
237
238 - def rem_section(self, section):
239 """ Removes a section given the name. 240 241 @param section: section name to be removed 242 @type section: string 243 """ 244 if section in self._state: 245 self._state.pop(section) 246 else: 247 raise ValueError('section %s does not exist' % section) 248 249 if self.get_direct_access(): 250 self.save()
251
252 - def contains(self, section, parameter):
253 """ Returns wether the given section exists and contains the given 254 parameter. 255 256 @param section: section name 257 @param parameter: parameter to check if present 258 259 @type section: string 260 @type parameter: string 261 262 @return: Exitance of the parameter on the given section. 263 @rtype: boolean 264 """ 265 if self.get_parameter(section, parameter): 266 return True 267 return False
268
269 - def items(self, section):
270 """ Returns all the items of the given section. 271 272 @param section: string 273 274 @type section: string 275 276 @return: all the items of the given section 277 @rtype: dictionary 278 """ 279 if self.get_direct_access(): 280 self.update() 281 282 return self._state.get(section, {})
283
284 - def get_section_names(self):
285 """ Returns the names of all sections. 286 287 @return: name of all sections 288 @rtype: list 289 """ 290 if self.get_direct_access(): 291 self.update() 292 293 return self._state.keys()
294 295 296 # BRisa Default configuration 297 # keys, values = sections, dict of parameters 298 _default_config = {'brisa': 299 {'owner': 'brisa', 300 'version': '0.10.0', 301 'encoding': 'utf-8', 302 'logging': 'INFO', 303 'logging.field_type': 'entry', 304 'logging_output': 'file', 305 'logging_output.field_type': 'entry', 306 'listen_interface': 'eth0'}} 307 308
309 -class _BRisaConfigurationManager(ConfigurationManager):
310 """ Custom ConfigurationManager adapted to provide auto-upgrade with 311 configurations merging for BRisa. 312 """ 313 _merge_configurations = False 314 brisa_version = brisa_version 315 brisa_home = brisa_home 316
317 - def __init__(self):
318 """ Constructor for the _BRisaConfigurationManager class. """ 319 ConfigurationManager.__init__(self, os.path.join(brisa_home, 320 'configurations.pickle'), 321 _default_config) 322 self._check_config_file() 323 324 if self._merge_configurations: 325 self._merge_configs() 326 327 self.update()
328
329 - def _merge_configs(self):
330 """ Merges an old configuration with the default one. 331 """ 332 # Check version 333 section = self.items('brisa') 334 335 if not section: 336 self.set_direct_access(False) 337 return 338 339 if 'version' not in section: 340 return 341 342 version = section['version'] 343 344 if not version: 345 return 346 347 if version.value == self.brisa_version: 348 return 349 350 self.set_direct_access(True) 351 352 for section in self.get_section_names(): 353 s = self.items(section) 354 355 # If section retrieved successfully 356 if s: 357 for k, v in s: 358 if k in self._default_config[section]: 359 self._default_config[section][k] = v 360 361 self.set_direct_access(False) 362 363 # Rename configuration.db to configuration.db.old 364 old_config_path = '%s%s' % (self._config_path, '.old') 365 os.rename(self._config_path, old_config_path) 366 367 # Initialize the database based on self._default_config 368 self._initialize_database()
369
370 - def _check_config_file(self):
371 """ If brisa home does not exist for the user or it exists and does not 372 contain a configuration file, a default configuration is used. 373 374 If there's already one configuration, then it gets merged with the 375 default. 376 """ 377 if os.path.exists(brisa_home): 378 # Home exists 379 if os.path.isfile(self._config_path): 380 # There's an old config file 381 self._merge_configurations = True 382 else: 383 # There's no old config file, just create the default 384 self._merge_configurations = False 385 self._initialize_database() 386 else: 387 # Home does not exist 388 os.mkdir(brisa_home) 389 os.chmod(brisa_home, 0777) 390 self._merge_configurations = False 391 self._initialize_database() 392 os.chmod(self._config_path, 0666)
393
394 - def _initialize_database(self):
395 """ Creates an initial database for BRisa. This database contains base 396 sections and parameters with default values. Creating this through code 397 is better than manually because it is better maintainable and the 398 creation is automatic. 399 """ 400 self._state = self._default_config 401 self.save()
402 403 404 # Manager for BRisa 405 manager = _BRisaConfigurationManager() 406 407 shared_url = "" 408 get_parameter_bool = manager.get_parameter_bool 409 get_parameter = manager.get_parameter 410 get_parameter_as_list = manager.get_parameter_as_list 411 set_parameter = manager.set_parameter 412 contains = manager.contains 413 __interface__ = get_parameter('connection', 'listenif') 414 platform_name = get_platform_name() 415