Mercurial > hg > configuration
annotate configuration/config.py @ 36:d218df4d0b4c
add test for missing values
author | Jeff Hammel <jhammel@mozilla.com> |
---|---|
date | Tue, 27 Mar 2012 09:40:15 -0700 |
parents | 321fe58a9eae |
children | a1f8dec4d4f9 |
rev | line source |
---|---|
0 | 1 #!/usr/bin/env python |
2 | |
3 """ | |
4 multi-level unified configuration | |
5 """ | |
6 | |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
7 import copy |
0 | 8 import sys |
9 import optparse | |
10 | |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
11 # imports for contigent configuration providers |
4 | 12 try: |
13 import json | |
14 except ImportError: | |
15 try: | |
16 import simplejson as json | |
17 except ImportError: | |
18 json = None | |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
19 try: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
20 import yaml |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
21 except ImportError: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
22 yaml = None |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
23 |
36
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
24 __all__ = ['Configuration', 'configuration_providers', 'types', 'MissingValueException'] |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
25 |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
26 ### exceptions |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
27 |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
28 class MissingValueException(Exception): |
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
29 """exception raised when a required value is missing""" |
6 | 30 |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
31 ### configuration providers for serialization/deserialization |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
32 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
33 configuration_providers = [] |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
34 |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
35 class ConfigurationProvider(object): |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
36 """ |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
37 abstract base class for configuration providers for |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
38 serialization/deserialization |
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
39 """ |
27 | 40 def read(self, filename): |
41 raise NotImplementedError("Abstract base class") | |
42 | |
43 def write(self, config, filename): | |
44 if isinstance(filename, basestring): | |
45 f = file(filename, 'w') | |
46 newfile = True | |
47 else: | |
48 f = filename | |
49 newfile = False | |
50 try: | |
51 self._write(f, config) | |
52 finally: | |
53 # XXX try: finally: works in python >= 2.5 | |
54 if newfile: | |
55 f.close() | |
56 def _write(self, fp, config): | |
57 raise NotImplementedError("Abstract base class") | |
26
4fd88b1b08d5
ABC-ing configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
25
diff
changeset
|
58 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
59 if json: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
60 class JSON(object): |
27 | 61 indent = 2 |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
62 extensions = ['json'] |
7 | 63 def read(self, filename): |
9 | 64 return json.loads(file(filename).read()) |
27 | 65 def _write(self, fp, config): |
66 fp.write(json.dumps(config), indent=self.indent, sort_keys=True) | |
67 # 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
|
68 configuration_providers.append(JSON()) |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
69 |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
70 if yaml: |
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
71 class YAML(object): |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
72 extensions = ['yml', 'yaml'] |
5
7910b0ef0bab
stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
4
diff
changeset
|
73 def read(self, filename): |
6 | 74 f = file(filename) |
75 config = yaml.load(f) | |
76 f.close() | |
77 return config | |
27 | 78 def _write(self, fp, config): |
79 fp.write(yaml.dump(config)) | |
80 # TODO: could use templates to get order down, etc | |
6 | 81 |
30
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
82 configuration_providers.append(YAML()) |
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
83 |
b27a7cb2dd5b
stub test for configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents:
29
diff
changeset
|
84 __all__.extend([i.__class__.__name__ for i in configuration_providers]) |
4 | 85 |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
86 ### plugins for option types |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
87 ### TODO: this could use a bit of thought |
31 | 88 ### They should probably be classes |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
89 def base_cli(name, value): |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
90 # CLI arguments |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
91 args = value.get('flags', ['--%s' % name]) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
92 if not args: |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
93 # No CLI interface |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
94 return (), {} |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
95 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
96 kw = {'dest': name} |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
97 help = value.get('help', name) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
98 if 'default' in value: |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
99 kw['default'] = value['default'] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
100 # TODO: use default pattern a la |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
101 # - 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
|
102 # - 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
|
103 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
104 help += ' [DEFAULT: %s]' % value['default'] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
105 kw['help'] = help |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
106 kw['action'] = 'store' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
107 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
108 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
109 def bool_cli(name, value): |
23 | 110 |
111 # preserve the default values | |
112 help = value.get('help') | |
113 flags = value.get('flags') | |
114 | |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
115 args, kw = base_cli(name, value) |
23 | 116 kw['help'] = help # reset |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
117 if value.get('default'): |
23 | 118 kw['action'] = 'store_false' |
119 if not flags: | |
120 args = ['--no-%s' % name] | |
121 if not help: | |
122 kw['help'] = 'disable %s' % name | |
123 else: | |
124 kw['action'] = 'store_true' | |
125 if not help: | |
126 kw['help'] = 'enable %s' % name | |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
127 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
128 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
129 def list_cli(name, value): |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
130 args, kw = base_cli(name, value) |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
131 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
132 # TODO: could use 'extend' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
133 # - 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
|
134 |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
135 # TODO: what about nested types? |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
136 kw['action'] = 'append' |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
137 return args, kw |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
138 |
23 | 139 def int_cli(name, value): |
140 args, kw = base_cli(name, value) | |
141 kw['type'] = 'int' | |
142 return args, kw | |
143 | |
144 def float_cli(name, value): | |
145 args, kw = base_cli(name, value) | |
146 kw['type'] = 'float' | |
147 return args, kw | |
148 | |
149 types = {bool: bool_cli, | |
150 int: int_cli, | |
151 float: float_cli, | |
152 list: list_cli, | |
153 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
|
154 __all__ += [i.__name__ for i in types.values()] |
4 | 155 |
1 | 156 class Configuration(object): |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
157 """declarative configuration object""" |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
158 |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
159 options = {} # configuration basis |
1 | 160 |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
161 def __init__(self, configuration_providers=configuration_providers, types=types): |
2 | 162 self.config = {} |
6 | 163 self.configuration_providers = configuration_providers |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
164 self.types = types |
2 | 165 |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
166 ### methods for iteration |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
167 ### TODO: make this a real iterator |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
168 |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
169 def items(self): |
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
170 # TODO: allow options to be a list of 2-tuples |
13 | 171 return self.options.items() |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
172 |
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
|
173 ### methods for validating configuration |
2 | 174 |
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
|
175 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
|
176 """ |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
177 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
|
178 """ |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
179 # 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
|
180 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
181 # ensure options in configuration are in self.options |
25
b39e550402ea
we now update configuration correctly
Jeff Hammel <jhammel@mozilla.com>
parents:
24
diff
changeset
|
182 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
|
183 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
|
184 # 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
|
185 raise Exception("Unknown options: %s" % ', '.join(unknown_options)) |
6 | 186 |
10 | 187 # 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
|
188 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
|
189 _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
|
190 if _type is not None: |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
191 config[key] = _type(value) |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
192 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
193 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
|
194 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
195 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
|
196 """validate resultant configuration""" |
35
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
197 for key, value in self.options.items(): |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
198 if key not in self.config: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
199 required = value.get('required') |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
200 if required: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
201 if isinstance(required, basestring): |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
202 required_message = required |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
203 else: |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
204 required_message = "Parameter %s is required but not present" % key |
321fe58a9eae
flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents:
34
diff
changeset
|
205 # TODO: more specific exception |
36
d218df4d0b4c
add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents:
35
diff
changeset
|
206 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
|
207 # 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
|
208 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
209 ### methods for adding configuration |
6 | 210 |
2 | 211 def __call__(self, *args): |
212 """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
|
213 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
|
214 self.add(config) |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
215 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
216 # add defaults if not present |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
217 for key, value in self.options.items(): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
218 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
|
219 self.config[key] = value['default'] |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
220 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
221 # validate total configuration |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
222 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
|
223 # TODO: configuration should be locked after this is called |
2 | 224 |
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
|
225 def add(self, config, check=True): |
2 | 226 """update configuration: not undoable""" |
6 | 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 self.check(config) # check config to be added |
2 | 229 self.config.update(config) |
230 # TODO: option to extend; augment lists/dicts | |
231 | |
18
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
232 ### methods for optparse |
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
233 ### XXX could go in a subclass |
d8871956536e
remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents:
17
diff
changeset
|
234 |
17
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
235 def optparse_options(self, parser): |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
236 """add optparse options to a OptionParser instance""" |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
237 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
|
238 handler = self.types[value.get('type')] |
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
239 args, kw = handler(key, value) |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
240 if not args: |
21
0fe74db6a56c
a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents:
20
diff
changeset
|
241 # No CLI interface |
11
e00afe2c83bf
stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents:
10
diff
changeset
|
242 continue |
12 | 243 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
|
244 |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
245 def parser(self, configuration_provider_option=None, **parser_args): |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
246 """ |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
247 return OptionParser for this Configuration instance |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
248 - configuration_provider_options : option for configuration files [TODO] |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
249 (also TODO: a special value that equates to the first file extension value |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
250 for the configuration_providers) |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
251 - parser_args : arguments to the OptionParser constructor |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
252 """ |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
253 if 'description' not in parser_args: |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
254 parser_args['description'] = getattr(self, '__doc__', '') |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
255 if 'formatter' not in parser_args: |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
256 class PlainDescriptionFormatter(optparse.IndentedHelpFormatter): |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
257 """description formatter for console script entry point""" |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
258 def format_description(self, description): |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
259 if description: |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
260 return description.strip() + '\n' |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
261 else: |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
262 return '' |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
263 parser_args['formatter'] = PlainDescriptionFormatter() |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
264 parser = optparse.OptionParser(**parser_args) |
a78ab14ae376
separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents:
15
diff
changeset
|
265 self.optparse_options(parser) |
15 | 266 return parser |
19
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
267 |
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
|
268 def parse(self, args=sys.argv[1:], parser=None, configuration_provider_option=None): |
19
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
269 """parse configuration including command line options""" |
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
270 |
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
271 # parse arguments |
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
272 if parser is None: |
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 parser = self.parser(configuration_provider_option=configuration_provider_option) |
19
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
274 options, args = parser.parse_args(args) |
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
275 |
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
|
276 # get CLI configuration 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
|
277 cli_config = dict([(key, value) for key, value in options.__dict__.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
|
278 if key in self.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
|
279 |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
280 # generate configuration |
39f2611db9be
rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents:
23
diff
changeset
|
281 self(cli_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
|
282 |
19
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
283 # return parsed arguments |
cadc9514f60a
we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents:
18
diff
changeset
|
284 return options, args |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
285 |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
286 ### serialization/deserialization |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
287 |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
288 def configuration_provider(self, format): |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
289 """configuration provider guess for a given filename""" |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
290 for provider in self.configuration_providers: |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
291 if format in provider.extensions: |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
292 return provider |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
293 |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
294 def filename2format(self, filename): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
295 extension = os.path.splitext(filename)[-1] |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
296 return extension.rstrip('.') or None |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
297 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
298 def serialize(self, filename, format=None, full=False): |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
299 """ |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
300 serialize configuration to a file |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
301 - filename: path of file to serialize to |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
302 - format: format of configuration provider |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
303 - 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
|
304 """ |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
305 # TODO: allow file object vs file name |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
306 |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
307 if not format: |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
308 format = self.filename2format(filename) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
309 if not format: |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
310 raise Exception('Please specify a format') |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
311 # TODO: more specific exception type |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
312 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
313 provider = self.configuration_provider(format) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
314 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
315 config = copy.deepcopy(self.config) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
316 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
317 provider.write(config, filename) |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
318 |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
319 def deserialize(self, filename, format=None): |
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
320 """load configuration from a file""" |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
321 # TODO: allow file object vs file name |
28
c516ab813079
begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents:
27
diff
changeset
|
322 |
29
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
323 if not format: |
fadcc6ab51d4
more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents:
28
diff
changeset
|
324 extension = os.path.splitext(filename)[-1] |
34
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
325 |
79aca36abd9a
fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents:
31
diff
changeset
|
326 raise NotImplementedError("TODO") |