Mercurial > hg > configuration
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(): |