Mercurial > hg > configuration
annotate configuration/configuration.py @ 66:f3b3f4046a8a
better docstring
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Wed, 28 Mar 2012 08:38:16 -0700 |
parents | 2a2e9aee5bc6 |
children | c831eb58fb52 |
rev | line source |
---|---|
0 | 1 #!/usr/bin/env python |
2 | |
3 """ | |
66 | 4 unified configuration with serialization/deserialization |
0 | 5 """ |
6 | |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
7 import copy |
37
a1f8dec4d4f9
we has another broken test
Jeff Hammel <jhammel@mozilla.com>
parents:
36
diff
changeset
|
8 import os |
0 | 9 import sys |
10 import optparse | |
11 | |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
12 # imports for contigent configuration providers |
4 | 13 try: |
14 import json | |
15 except ImportError: | |
16 try: | |
17 import simplejson as json | |
18 except ImportError: | |
19 json = None | |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
20 try: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
21 import yaml |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
22 except ImportError: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
23 yaml = None |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
24 |
48
84fb8ad5ba81
ensure that missing values raise the correct exception
Jeff Hammel <jhammel@mozilla.com>
parents:
47
diff
changeset
|
25 __all__ = ['Configuration', 'configuration_providers', 'types', 'MissingValueException', 'ConfigurationProviderException', 'TypeCastException', 'ConfigurationOption'] |
36
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
26 |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
27 ### exceptions |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
28 |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
29 class MissingValueException(Exception): |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
30 """exception raised when a required value is missing""" |
6 | 31 |
41
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
32 class ConfigurationProviderException(Exception): |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
33 """exception raised when a configuration provider is missing, etc""" |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
34 |
46 | 35 class TypeCastException(Exception): |
36 """exception raised when a configuration item cannot be coerced to a type""" | |
37 | |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
38 ### configuration providers for serialization/deserialization |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
39 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
40 configuration_providers = [] |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
41 |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
42 class ConfigurationProvider(object): |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
43 """ |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
44 abstract base class for configuration providers for |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
45 serialization/deserialization |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
46 """ |
27 | 47 def read(self, filename): |
48 raise NotImplementedError("Abstract base class") | |
49 | |
50 def write(self, config, filename): | |
51 if isinstance(filename, basestring): | |
52 f = file(filename, 'w') | |
53 newfile = True | |
54 else: | |
55 f = filename | |
56 newfile = False | |
57 try: | |
58 self._write(f, config) | |
59 finally: | |
60 # XXX try: finally: works in python >= 2.5 | |
61 if newfile: | |
62 f.close() | |
63 def _write(self, fp, config): | |
64 raise NotImplementedError("Abstract base class") | |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
65 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
66 if json: |
38
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
67 class JSON(ConfigurationProvider): |
27 | 68 indent = 2 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
69 extensions = ['json'] |
7 | 70 def read(self, filename): |
9 | 71 return json.loads(file(filename).read()) |
27 | 72 def _write(self, fp, config): |
38
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
73 fp.write(json.dumps(config, indent=self.indent, sort_keys=True)) |
27 | 74 # TODO: could use templates to get order down, etc |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
75 configuration_providers.append(JSON()) |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
76 |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
77 if yaml: |
38
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
78 class YAML(ConfigurationProvider): |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
79 extensions = ['yml', 'yaml'] |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
80 def read(self, filename): |
6 | 81 f = file(filename) |
82 config = yaml.load(f) | |
83 f.close() | |
84 return config | |
27 | 85 def _write(self, fp, config): |
86 fp.write(yaml.dump(config)) | |
87 # TODO: could use templates to get order down, etc | |
6 | 88 |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
89 configuration_providers.append(YAML()) |
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
90 |
50
113e8c2f7cab
start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents:
49
diff
changeset
|
91 # TODO: add a configuration provider for taking command-line arguments |
113e8c2f7cab
start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents:
49
diff
changeset
|
92 # from a file |
113e8c2f7cab
start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents:
49
diff
changeset
|
93 |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
94 __all__.extend([i.__class__.__name__ for i in configuration_providers]) |
4 | 95 |
44
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
96 ### optparse interface |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
97 |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
98 class ConfigurationOption(optparse.Option): |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
99 """option that keeps track if it is seen""" |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
100 # TODO: this should be configurable or something |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
101 def take_action(self, action, dest, opt, value, values, parser): |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
102 """add the parsed option to the set of things parsed""" |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
103 optparse.Option.take_action(self, action, dest, opt, value, values, parser) |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
104 if not hasattr(parser, 'parsed'): |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
105 parser.parsed = set() |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
106 parser.parsed.add(dest) |
b3db38b14567
stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents:
43
diff
changeset
|
107 |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
108 ### plugins for option types |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
109 ### TODO: this could use a bit of thought |
31 | 110 ### They should probably be classes |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
111 def base_cli(name, value): |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
112 # CLI arguments |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
113 args = value.get('flags', ['--%s' % name]) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
114 if not args: |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
115 # No CLI interface |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
116 return (), {} |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
117 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
118 kw = {'dest': name} |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
119 help = value.get('help', name) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
120 if 'default' in value: |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
121 kw['default'] = value['default'] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
122 # TODO: use default pattern a la |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
123 # - http://hg.mozilla.org/build/talos/file/c6013a2f09ce/talos/PerfConfigurator.py#l358 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
124 # - http://k0s.org/mozilla/hg/bzconsole/file/d5e88dadde69/bzconsole/command.py#l12 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
125 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
126 help += ' [DEFAULT: %s]' % value['default'] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
127 kw['help'] = help |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
128 kw['action'] = 'store' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
129 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
130 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
131 def bool_cli(name, value): |
23 | 132 |
133 # preserve the default values | |
134 help = value.get('help') | |
135 flags = value.get('flags') | |
136 | |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
137 args, kw = base_cli(name, value) |
23 | 138 kw['help'] = help # reset |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
139 if value.get('default'): |
23 | 140 kw['action'] = 'store_false' |
141 if not flags: | |
142 args = ['--no-%s' % name] | |
143 if not help: | |
144 kw['help'] = 'disable %s' % name | |
145 else: | |
146 kw['action'] = 'store_true' | |
147 if not help: | |
148 kw['help'] = 'enable %s' % name | |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
149 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
150 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
151 def list_cli(name, value): |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
152 args, kw = base_cli(name, value) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
153 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
154 # TODO: could use 'extend' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
155 # - http://hg.mozilla.org/build/mozharness/file/5f44ba08f4be/mozharness/base/config.py#l41 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
156 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
157 # TODO: what about nested types? |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
158 kw['action'] = 'append' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
159 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
160 |
23 | 161 def int_cli(name, value): |
162 args, kw = base_cli(name, value) | |
163 kw['type'] = 'int' | |
164 return args, kw | |
165 | |
166 def float_cli(name, value): | |
167 args, kw = base_cli(name, value) | |
168 kw['type'] = 'float' | |
169 return args, kw | |
170 | |
60 | 171 # TODO: 'dict'-type cli interface |
172 | |
23 | 173 types = {bool: bool_cli, |
174 int: int_cli, | |
175 float: float_cli, | |
176 list: list_cli, | |
177 None: base_cli} # default | |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
178 __all__ += [i.__name__ for i in types.values()] |
4 | 179 |
59
b8f066b8ab62
begin migration path towards inheriting from ConfigParser; ideally, Configuration should live in its own class and the CLI class should inherit from that
Jeff Hammel <jhammel@mozilla.com>
parents:
54
diff
changeset
|
180 class Configuration(optparse.OptionParser): |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
181 """declarative configuration object""" |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
182 |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
183 options = {} # configuration basis |
1 | 184 |
63 | 185 def __init__(self, configuration_providers=configuration_providers, configuration_provider_option=None, types=types, dump='--dump', **parser_args): |
61
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
186 |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
187 # setup configuration |
2 | 188 self.config = {} |
6 | 189 self.configuration_providers = configuration_providers |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
190 self.types = types |
61
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
191 |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
192 # setup optionparser |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
193 if 'description' not in parser_args: |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
194 parser_args['description'] = getattr(self, '__doc__', '') |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
195 if 'formatter' not in parser_args: |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
196 class PlainDescriptionFormatter(optparse.IndentedHelpFormatter): |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
197 """description formatter for console script entry point""" |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
198 def format_description(self, description): |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
199 if description: |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
200 return description.strip() + '\n' |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
201 else: |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
202 return '' |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
203 parser_args['formatter'] = PlainDescriptionFormatter() |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
204 parser_args.setdefault('option_class', ConfigurationOption) |
59
b8f066b8ab62
begin migration path towards inheriting from ConfigParser; ideally, Configuration should live in its own class and the CLI class should inherit from that
Jeff Hammel <jhammel@mozilla.com>
parents:
54
diff
changeset
|
205 optparse.OptionParser.__init__(self, **parser_args) |
61
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
206 self.parsed = set() |
ef2d1c6211b9
more stubbing to make Configuration an OptionParser
Jeff Hammel <jhammel@mozilla.com>
parents:
60
diff
changeset
|
207 self.optparse_options(self) |
63 | 208 # add option(s) for configuration_providers |
209 if configuration_provider_option: | |
210 self.add_option(configuration_provider_option, | |
211 dest='load', action='append', | |
212 help="load configuration from a file") | |
213 | |
214 # add an option for dumping | |
215 formats = self.formats() | |
216 if formats and dump: | |
217 self.add_option(dump, dest='dump', | |
218 help="dump configuration to a file; Formats: %s" % formats) | |
219 | |
2 | 220 |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
221 ### methods for iteration |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
222 ### TODO: make this a real iterator |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
223 |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
224 def items(self): |
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
225 # TODO: allow options to be a list of 2-tuples |
13 | 226 return self.options.items() |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
227 |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
228 ### methods for validating configuration |
2 | 229 |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
230 def check(self, config): |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
231 """ |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
232 check validity of configuration to be added |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
233 """ |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
234 # TODO: should probably deepcopy config |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
235 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
236 # ensure options in configuration are in self.options |
25
b39e550402ea
we now update configuration correctly
Jeff Hammel <jhammel@mozilla.com>
parents:
24
diff
changeset
|
237 unknown_options = [i for i in config if i not in self.options] |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
238 if unknown_options: |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
239 # TODO: more specific error type |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
240 raise Exception("Unknown options: %s" % ', '.join(unknown_options)) |
6 | 241 |
10 | 242 # TODO: ensure options are of the right type (if specified) |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
243 for key, value in config.items(): |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
244 _type = self.options[key].get('type') |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
245 if _type is not None: |
46 | 246 try: |
247 config[key] = _type(value) | |
248 except BaseException, e: | |
249 raise TypeCastException("Could not coerce %s, %s, to type %s: %s" % (key, value, _type.__name__, e)) | |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
250 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
251 return config |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
252 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
253 def validate(self): |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
254 """validate resultant configuration""" |
35
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
255 for key, value in self.options.items(): |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
256 if key not in self.config: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
257 required = value.get('required') |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
258 if required: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
259 if isinstance(required, basestring): |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
260 required_message = required |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
261 else: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
262 required_message = "Parameter %s is required but not present" % key |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
263 # TODO: more specific exception |
37
a1f8dec4d4f9
we has another broken test
Jeff Hammel <jhammel@mozilla.com>
parents:
36
diff
changeset
|
264 # Also, this should probably raise all missing values vs |
a1f8dec4d4f9
we has another broken test
Jeff Hammel <jhammel@mozilla.com>
parents:
36
diff
changeset
|
265 # one by one |
36
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
266 raise MissingValueException(required_message) |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
267 # TODO: configuration should be locked after this is called |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
268 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
269 ### methods for adding configuration |
6 | 270 |
2 | 271 def __call__(self, *args): |
272 """add items to configuration and check it""" | |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
273 for config in args: |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
274 self.add(config) |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
275 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
276 # add defaults if not present |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
277 for key, value in self.options.items(): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
278 if 'default' in value and key not in self.config: |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
279 self.config[key] = value['default'] |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
280 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
281 # validate total configuration |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
282 self.validate() |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
283 # TODO: configuration should be locked after this is called |
2 | 284 |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
285 def add(self, config, check=True): |
2 | 286 """update configuration: not undoable""" |
6 | 287 |
24
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
288 self.check(config) # check config to be added |
2 | 289 self.config.update(config) |
290 # TODO: option to extend; augment lists/dicts | |
291 | |
18
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
292 ### methods for optparse |
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
293 ### XXX could go in a subclass |
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
294 |
17
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
295 def optparse_options(self, parser): |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
296 """add optparse options to a OptionParser instance""" |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
297 for key, value in self.items(): |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
298 handler = self.types[value.get('type')] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
299 args, kw = handler(key, value) |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
300 if not args: |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
301 # No CLI interface |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
302 continue |
12 | 303 parser.add_option(*args, **kw) |
17
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
304 |
63 | 305 def parse_args(self, *args, **kw): |
306 options, args = optparse.OptionParser.parse_args(self, *args, **kw) | |
307 | |
308 # get CLI configuration options | |
309 cli_config = dict([(key, value) for key, value in options.__dict__.items() | |
64 | 310 if key in self.options and key in self.parsed]) |
63 | 311 |
312 # deserialize configuration | |
313 configuration_files = getattr(options, 'load', args) | |
314 missing = [i for i in configuration_files | |
315 if not os.path.exists(i)] | |
316 if missing: | |
64 | 317 self.error("Missing files: %s" % ', '.join(missing)) |
63 | 318 config = [] |
319 for f in configuration_files: | |
320 try: | |
321 config.append(self.deserialize(f)) | |
322 except BaseException, e: | |
323 parser.error(str(e)) | |
324 config.append(cli_config) | |
325 | |
326 missingvalues = None | |
327 try: | |
328 # generate configuration | |
329 self(*config) | |
330 except MissingValueException, missingvalues: | |
331 pass | |
332 | |
333 # dump configuration, if specified | |
334 dump = getattr(options, 'dump') | |
335 if dump: | |
336 # TODO: have a way of specifying format other than filename | |
337 self.serialize(dump) | |
338 | |
339 if missingvalues and not dump: | |
340 # XXX assuming if you don't have values you were just dumping | |
341 raise missingvalues | |
342 | |
64 | 343 # update options from config |
344 options.__dict__.update(self.config) | |
345 | |
63 | 346 # return parsed arguments |
347 return options, args | |
348 | |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
349 ### serialization/deserialization |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
350 |
43 | 351 def formats(self): |
352 """formats for deserialization""" | |
353 retval = [] | |
354 for provider in self.configuration_providers: | |
355 if provider.extensions and hasattr(provider, 'write'): | |
356 retval.append(provider.extensions[0]) | |
357 return retval | |
358 | |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
359 def configuration_provider(self, format): |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
360 """configuration provider guess for a given filename""" |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
361 for provider in self.configuration_providers: |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
362 if format in provider.extensions: |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
363 return provider |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
364 |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
365 def filename2format(self, filename): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
366 extension = os.path.splitext(filename)[-1] |
38
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
367 return extension.lstrip('.') or None |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
368 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
369 def serialize(self, filename, format=None, full=False): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
370 """ |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
371 serialize configuration to a file |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
372 - filename: path of file to serialize to |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
373 - format: format of configuration provider |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
374 - full: whether to serialize non-set optional strings [TODO] |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
375 """ |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
376 # TODO: allow file object vs file name |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
377 |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
378 if not format: |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
379 format = self.filename2format(filename) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
380 if not format: |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
381 raise Exception('Please specify a format') |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
382 # TODO: more specific exception type |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
383 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
384 provider = self.configuration_provider(format) |
38
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
385 if not provider: |
8909ae1cc4ea
fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents:
37
diff
changeset
|
386 raise Exception("Provider not found for format: %s" % format) |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
387 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
388 config = copy.deepcopy(self.config) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
389 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
390 provider.write(config, filename) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
391 |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
392 def deserialize(self, filename, format=None): |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
393 """load configuration from a file""" |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
394 # TODO: allow file object vs file name |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
395 |
50
113e8c2f7cab
start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents:
49
diff
changeset
|
396 assert os.path.exists(filename) |
113e8c2f7cab
start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents:
49
diff
changeset
|
397 |
41
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
398 # get the format |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
399 if not format: |
41
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
400 format = self.filename2format(filename) |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
401 |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
402 # get the providers in some sensible order |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
403 providers = self.configuration_providers[:] |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
404 if format: |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
405 providers.sort(key=lambda x: int(format in x.extensions), reverse=True) |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
406 |
41
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
407 # deserialize the data |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
408 for provider in providers: |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
409 try: |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
410 return provider.read(filename) |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
411 except: |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
412 continue |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
413 else: |
1bd4ddf2e81d
deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents:
38
diff
changeset
|
414 raise ConfigurationProviderException("Could not load %s" % filename) |