comparison configuration/configuration.py @ 67:c831eb58fb52

minor fixes
author Jeff Hammel <jhammel@mozilla.com>
date Wed, 28 Mar 2012 09:03:02 -0700
parents f3b3f4046a8a
children c119eb07a378
comparison
equal deleted inserted replaced
66:f3b3f4046a8a 67:c831eb58fb52
7 import copy 7 import copy
8 import os 8 import os
9 import sys 9 import sys
10 import optparse 10 import optparse
11 11
12 # imports for contigent configuration providers 12 # imports for configuration providers
13 try: 13 try:
14 import json 14 import json
15 except ImportError: 15 except ImportError:
16 try: 16 try:
17 import simplejson as json 17 import simplejson as json
20 try: 20 try:
21 import yaml 21 import yaml
22 except ImportError: 22 except ImportError:
23 yaml = None 23 yaml = None
24 24
25 __all__ = ['Configuration', 'configuration_providers', 'types', 'MissingValueException', 'ConfigurationProviderException', 'TypeCastException', 'ConfigurationOption'] 25 __all__ = ['Configuration',
26 'configuration_providers',
27 'types',
28 'UnknownOptionException',
29 'MissingValueException',
30 'ConfigurationProviderException',
31 'TypeCastException',
32 'ConfigurationOption']
26 33
27 ### exceptions 34 ### exceptions
35
36 class UnknownOptionException(Exception):
37 """exception raised when a non-configuration value is present in the configuration"""
28 38
29 class MissingValueException(Exception): 39 class MissingValueException(Exception):
30 """exception raised when a required value is missing""" 40 """exception raised when a required value is missing"""
31 41
32 class ConfigurationProviderException(Exception): 42 class ConfigurationProviderException(Exception):
33 """exception raised when a configuration provider is missing, etc""" 43 """exception raised when a configuration provider is missing, etc"""
34 44
35 class TypeCastException(Exception): 45 class TypeCastException(Exception):
36 """exception raised when a configuration item cannot be coerced to a type""" 46 """exception raised when a configuration item cannot be coerced to a type"""
47
37 48
38 ### configuration providers for serialization/deserialization 49 ### configuration providers for serialization/deserialization
39 50
40 configuration_providers = [] 51 configuration_providers = []
41 52
217 self.add_option(dump, dest='dump', 228 self.add_option(dump, dest='dump',
218 help="dump configuration to a file; Formats: %s" % formats) 229 help="dump configuration to a file; Formats: %s" % formats)
219 230
220 231
221 ### methods for iteration 232 ### methods for iteration
222 ### TODO: make this a real iterator 233 ### TODO: make the class a real iterator
223 234
224 def items(self): 235 def items(self):
225 # TODO: allow options to be a list of 2-tuples 236 # TODO: allow options to be a list of 2-tuples
226 return self.options.items() 237 return self.options.items()
227 238
229 240
230 def check(self, config): 241 def check(self, config):
231 """ 242 """
232 check validity of configuration to be added 243 check validity of configuration to be added
233 """ 244 """
234 # TODO: should probably deepcopy config
235 245
236 # ensure options in configuration are in self.options 246 # ensure options in configuration are in self.options
237 unknown_options = [i for i in config if i not in self.options] 247 unknown_options = [i for i in config if i not in self.options]
238 if unknown_options: 248 if unknown_options:
239 # TODO: more specific error type 249 raise UnknownOptionException("Unknown options: %s" % ', '.join(unknown_options))
240 raise Exception("Unknown options: %s" % ', '.join(unknown_options)) 250
241 251 # ensure options are of the right type (if specified)
242 # TODO: ensure options are of the right type (if specified)
243 for key, value in config.items(): 252 for key, value in config.items():
244 _type = self.options[key].get('type') 253 _type = self.options[key].get('type')
245 if _type is not None: 254 if _type is None and 'default' in self.options[key]:
255 _type = type(self.options[key]['default'])
256 if _type is not None and not isinstance(value, _type):
246 try: 257 try:
247 config[key] = _type(value) 258 config[key] = _type(value)
248 except BaseException, e: 259 except BaseException, e:
249 raise TypeCastException("Could not coerce %s, %s, to type %s: %s" % (key, value, _type.__name__, e)) 260 raise TypeCastException("Could not coerce %s, %s, to type %s: %s" % (key, value, _type.__name__, e))
250 261
251 return config 262 return config
252 263
253 def validate(self): 264 def validate(self):
254 """validate resultant configuration""" 265 """validate resultant configuration"""
266
255 for key, value in self.options.items(): 267 for key, value in self.options.items():
256 if key not in self.config: 268 if key not in self.config:
257 required = value.get('required') 269 required = value.get('required')
258 if required: 270 if required:
259 if isinstance(required, basestring): 271 if isinstance(required, basestring):
260 required_message = required 272 required_message = required
261 else: 273 else:
262 required_message = "Parameter %s is required but not present" % key 274 required_message = "Parameter %s is required but not present" % key
263 # TODO: more specific exception 275 # TODO: this should probably raise all missing values vs
264 # Also, this should probably raise all missing values vs
265 # one by one 276 # one by one
266 raise MissingValueException(required_message) 277 raise MissingValueException(required_message)
267 # TODO: configuration should be locked after this is called 278 # TODO: configuration should be locked after this is called
268 279
269 ### methods for adding configuration 280 ### methods for adding configuration
270 281
271 def __call__(self, *args): 282 def __call__(self, *args):
272 """add items to configuration and check it""" 283 """add items to configuration and check it"""
284
273 for config in args: 285 for config in args:
274 self.add(config) 286 self.add(config)
275 287
276 # add defaults if not present 288 # add defaults if not present
277 for key, value in self.options.items(): 289 for key, value in self.options.items():