annotate configuration/config.py @ 54:135322cc5bc0

document this
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 27 Mar 2012 14:41:13 -0700
parents 18f8107aa4f9
children b8f066b8ab62
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
1 #!/usr/bin/env python
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
2
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
3 """
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
4 multi-level unified configuration
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
5 """
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
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
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
9 import sys
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
10 import optparse
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
11
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
12 # imports for contigent configuration providers
4
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
13 try:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
14 import json
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
15 except ImportError:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
16 try:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
17 import simplejson as json
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
18 except ImportError:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
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
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
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
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
35 class TypeCastException(Exception):
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
36 """exception raised when a configuration item cannot be coerced to a type"""
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
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
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
47 def read(self, filename):
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
48 raise NotImplementedError("Abstract base class")
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
49
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
50 def write(self, config, filename):
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
51 if isinstance(filename, basestring):
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
52 f = file(filename, 'w')
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
53 newfile = True
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
54 else:
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
55 f = filename
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
56 newfile = False
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
57 try:
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
58 self._write(f, config)
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
59 finally:
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
60 # XXX try: finally: works in python >= 2.5
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
61 if newfile:
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
62 f.close()
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
63 def _write(self, fp, config):
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
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
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
68 indent = 2
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
69 extensions = ['json']
7
6e3cf8f05464 note TODO: reading JSON
Jeff Hammel <jhammel@mozilla.com>
parents: 6
diff changeset
70 def read(self, filename):
9
b28ec204df23 flush out JSON provider
Jeff Hammel <jhammel@mozilla.com>
parents: 8
diff changeset
71 return json.loads(file(filename).read())
27
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
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
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
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
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
81 f = file(filename)
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
82 config = yaml.load(f)
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
83 f.close()
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
84 return config
27
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
85 def _write(self, fp, config):
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
86 fp.write(yaml.dump(config))
c6d966431498 add serialization details
Jeff Hammel <jhammel@mozilla.com>
parents: 26
diff changeset
87 # TODO: could use templates to get order down, etc
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
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
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
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
5571d1608cba add comments
Jeff Hammel <jhammel@mozilla.com>
parents: 30
diff changeset
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
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
132
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
133 # preserve the default values
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
134 help = value.get('help')
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
135 flags = value.get('flags')
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
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
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
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
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
140 kw['action'] = 'store_false'
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
141 if not flags:
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
142 args = ['--no-%s' % name]
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
143 if not help:
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
144 kw['help'] = 'disable %s' % name
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
145 else:
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
146 kw['action'] = 'store_true'
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
147 if not help:
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
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
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
161 def int_cli(name, value):
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
162 args, kw = base_cli(name, value)
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
163 kw['type'] = 'int'
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
164 return args, kw
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
165
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
166 def float_cli(name, value):
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
167 args, kw = base_cli(name, value)
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
168 kw['type'] = 'float'
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
169 return args, kw
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
170
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
171 types = {bool: bool_cli,
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
172 int: int_cli,
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
173 float: float_cli,
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
174 list: list_cli,
73e72a764c3a fix bool parser, i hope
Jeff Hammel <jhammel@mozilla.com>
parents: 21
diff changeset
175 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
176 __all__ += [i.__name__ for i in types.values()]
4
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
177
1
1dbdb4a57e0c stub configuration class
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
178 class Configuration(object):
29
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
179 """declarative configuration object"""
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
180
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
181 options = {} # configuration basis
1
1dbdb4a57e0c stub configuration class
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
182
21
0fe74db6a56c a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
183 def __init__(self, configuration_providers=configuration_providers, types=types):
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
184 self.config = {}
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
185 self.configuration_providers = configuration_providers
21
0fe74db6a56c a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
186 self.types = types
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
187
29
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
188 ### methods for iteration
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
189 ### TODO: make this a real iterator
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
190
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
191 def items(self):
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
192 # TODO: allow options to be a list of 2-tuples
13
0f8115a41ad6 bug fixes
Jeff Hammel <jhammel@mozilla.com>
parents: 12
diff changeset
193 return self.options.items()
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
194
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
195 ### methods for validating configuration
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
196
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
197 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
198 """
39f2611db9be rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
199 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
200 """
39f2611db9be rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
201 # 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
202
39f2611db9be rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
203 # ensure options in configuration are in self.options
25
b39e550402ea we now update configuration correctly
Jeff Hammel <jhammel@mozilla.com>
parents: 24
diff changeset
204 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
205 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
206 # 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
207 raise Exception("Unknown options: %s" % ', '.join(unknown_options))
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
208
10
c782d750fd6d comment
Jeff Hammel <jhammel@mozilla.com>
parents: 9
diff changeset
209 # 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
210 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
211 _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
212 if _type is not None:
46
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
213 try:
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
214 config[key] = _type(value)
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
215 except BaseException, e:
346c702f63db better error message
Jeff Hammel <jhammel@mozilla.com>
parents: 45
diff changeset
216 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
217
39f2611db9be rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
218 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
219
39f2611db9be rename a bunch of things and begin to work on the sanity of validation
Jeff Hammel <jhammel@mozilla.com>
parents: 23
diff changeset
220 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
221 """validate resultant configuration"""
35
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
222 for key, value in self.options.items():
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
223 if key not in self.config:
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
224 required = value.get('required')
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
225 if required:
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
226 if isinstance(required, basestring):
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
227 required_message = required
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
228 else:
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
229 required_message = "Parameter %s is required but not present" % key
321fe58a9eae flush out validate function
Jeff Hammel <jhammel@mozilla.com>
parents: 34
diff changeset
230 # TODO: more specific exception
37
a1f8dec4d4f9 we has another broken test
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
231 # Also, this should probably raise all missing values vs
a1f8dec4d4f9 we has another broken test
Jeff Hammel <jhammel@mozilla.com>
parents: 36
diff changeset
232 # one by one
36
d218df4d0b4c add test for missing values
Jeff Hammel <jhammel@mozilla.com>
parents: 35
diff changeset
233 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
234 # 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
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 ### methods for adding configuration
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
237
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
238 def __call__(self, *args):
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
239 """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
240 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
241 self.add(config)
34
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
242
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
243 # add defaults if not present
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
244 for key, value in self.options.items():
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
245 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
246 self.config[key] = value['default']
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
247
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
248 # validate total configuration
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
249 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
250 # TODO: configuration should be locked after this is called
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
251
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
252 def add(self, config, check=True):
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
253 """update configuration: not undoable"""
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
254
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
255 self.check(config) # check config to be added
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
256 self.config.update(config)
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
257 # TODO: option to extend; augment lists/dicts
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
258
18
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
259 ### methods for optparse
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
260 ### XXX could go in a subclass
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
261
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
262 def optparse_options(self, parser):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
263 """add optparse options to a OptionParser instance"""
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
264 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
265 handler = self.types[value.get('type')]
0fe74db6a56c a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
266 args, kw = handler(key, value)
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
267 if not args:
21
0fe74db6a56c a hacky way to do CLI types handlers
Jeff Hammel <jhammel@mozilla.com>
parents: 20
diff changeset
268 # No CLI interface
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
269 continue
12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
270 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
271
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
272 def parser(self, configuration_provider_option=None, dump='--dump', **parser_args):
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
273 """
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
274 return OptionParser for this Configuration instance
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
275 - configuration_provider_options : option for configuration files
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
276 (or '-' for taking from the extensions names)
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
277 - dump : option for dumping configuration
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
278 - 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
279 """
44
b3db38b14567 stub adding an option of keeping track of what is parsed
Jeff Hammel <jhammel@mozilla.com>
parents: 43
diff changeset
280
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
281 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
282 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
283 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
284 class PlainDescriptionFormatter(optparse.IndentedHelpFormatter):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
285 """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
286 def format_description(self, description):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
287 if description:
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
288 return description.strip() + '\n'
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
289 else:
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
290 return ''
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
291 parser_args['formatter'] = PlainDescriptionFormatter()
47
7abea9a6fa16 try using optionclass; still failing
Jeff Hammel <jhammel@mozilla.com>
parents: 46
diff changeset
292 parser_args.setdefault('option_class', ConfigurationOption)
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
293 parser = optparse.OptionParser(**parser_args)
49
09fbc09455d4 fix broken test
Jeff Hammel <jhammel@mozilla.com>
parents: 48
diff changeset
294 parser.parsed = set()
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
295 self.optparse_options(parser)
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
296
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
297 # add option(s) for configuration_providers
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
298 if configuration_provider_option:
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
299 if configuration_provider_option == '-':
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
300 raise NotImplementedError("""
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
301 The arguments will be interspersed. Will need to be more clever to get this
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
302 to work properly.
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
303 """)
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
304
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
305 # take option from configuration_provider extensions
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
306 for format in self.formats():
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
307 parser.add_option('--%s' % format,
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
308 dest='load_%s' % format,
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
309 action='append',
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
310 help="load configuration from a %s file" % format)
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
311 else:
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
312 parser.add_option(configuration_provider_option,
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
313 dest='load', action='append',
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
314 help="load configuration from a file")
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
315
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
316 # add an option for dumping
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
317 formats = self.formats()
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
318 if formats and dump:
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
319 parser.add_option(dump, dest='dump',
51
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
320 help="dump configuration to a file; Formats: %s" % formats)
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
321
15
0df4bfdc2c96 make --help work
Jeff Hammel <jhammel@mozilla.com>
parents: 13
diff changeset
322 return parser
19
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
323
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
324 def parse(self, args=sys.argv[1:], parser=None, configuration_provider_option=None):
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
325 """
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
326 parse configuration including command line options
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
327 - args: command line arguments to parse (default: system arguments)
54
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
328 - parser: a parser instance
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
329 - config_provider_option: option for configuration files; if None,
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
330 will be taken from remaining args
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
331 """
19
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
332
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
333 # parse arguments
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
334 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
335 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
336 options, args = parser.parse_args(args)
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
337
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
338 # 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
339 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
340 if key in self.options])
45
bb5f4eeb56c5 stub only using parsed attributes
Jeff Hammel <jhammel@mozilla.com>
parents: 44
diff changeset
341 if hasattr(parser, 'parsed'):
bb5f4eeb56c5 stub only using parsed attributes
Jeff Hammel <jhammel@mozilla.com>
parents: 44
diff changeset
342 # only use parsed arguments
bb5f4eeb56c5 stub only using parsed attributes
Jeff Hammel <jhammel@mozilla.com>
parents: 44
diff changeset
343 # (though i'm not sure what to do with parser doesn't have the parsed attribute)
47
7abea9a6fa16 try using optionclass; still failing
Jeff Hammel <jhammel@mozilla.com>
parents: 46
diff changeset
344 cli_config = dict([(key, value) for key, value in cli_config.items()
7abea9a6fa16 try using optionclass; still failing
Jeff Hammel <jhammel@mozilla.com>
parents: 46
diff changeset
345 if key in parser.parsed])
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
346
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
347 # deserialize configuration
54
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
348 configuration_files = getattr(options, 'load', args)
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
349 missing = [i for i in configuration_files
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
350 if not os.path.exists(i)]
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
351 if missing:
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
352 parser.error("Missing files: %s" % ', '.join(missing))
51
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
353 config = []
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
354 for f in configuration_files:
51
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
355 try:
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
356 config.append(self.deserialize(f))
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
357 except BaseException, e:
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
358 parser.error(str(e))
fb133bc3bed1 actually deserialize things
Jeff Hammel <jhammel@mozilla.com>
parents: 50
diff changeset
359 config.append(cli_config)
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
360
53
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
361 missingvalues = None
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
362 try:
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
363 # generate configuration
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
364 self(*config)
54
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
365 except MissingValueException, missingvalues:
53
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
366 pass
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
367
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
368 # dump configuration, if specified
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
369 dump = getattr(options, 'dump')
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
370 if dump:
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
371 # TODO: have a way of specifying format other than filename
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
372 self.serialize(dump)
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
373
53
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
374 if missingvalues and not dump:
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
375 # XXX assuming if you don't have values you were just dumping
54
135322cc5bc0 document this
Jeff Hammel <jhammel@mozilla.com>
parents: 53
diff changeset
376 raise missingvalues
53
18f8107aa4f9 tests fail again, what fun
Jeff Hammel <jhammel@mozilla.com>
parents: 51
diff changeset
377
19
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
378 # return parsed arguments
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
379 return options, args
28
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
380
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
381 ### serialization/deserialization
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
382
43
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
383 def formats(self):
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
384 """formats for deserialization"""
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
385 retval = []
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
386 for provider in self.configuration_providers:
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
387 if provider.extensions and hasattr(provider, 'write'):
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
388 retval.append(provider.extensions[0])
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
389 return retval
f09982d47b3c add --dump option
Jeff Hammel <jhammel@mozilla.com>
parents: 41
diff changeset
390
28
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
391 def configuration_provider(self, format):
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
392 """configuration provider guess for a given filename"""
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
393 for provider in self.configuration_providers:
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
394 if format in provider.extensions:
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
395 return provider
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
396
34
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
397 def filename2format(self, filename):
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
398 extension = os.path.splitext(filename)[-1]
38
8909ae1cc4ea fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents: 37
diff changeset
399 return extension.lstrip('.') or None
34
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
400
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
401 def serialize(self, filename, format=None, full=False):
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
402 """
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
403 serialize configuration to a file
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
404 - filename: path of file to serialize to
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
405 - format: format of configuration provider
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
406 - 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
407 """
29
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
408 # TODO: allow file object vs file name
28
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
409
34
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
410 if not format:
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
411 format = self.filename2format(filename)
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
412 if not format:
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
413 raise Exception('Please specify a format')
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
414 # TODO: more specific exception type
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
415
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
416 provider = self.configuration_provider(format)
38
8909ae1cc4ea fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents: 37
diff changeset
417 if not provider:
8909ae1cc4ea fix serialization (stub) tests
Jeff Hammel <jhammel@mozilla.com>
parents: 37
diff changeset
418 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
419
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
420 config = copy.deepcopy(self.config)
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
421
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
422 provider.write(config, filename)
79aca36abd9a fill in defaults if not present
Jeff Hammel <jhammel@mozilla.com>
parents: 31
diff changeset
423
28
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
424 def deserialize(self, filename, format=None):
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
425 """load configuration from a file"""
29
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
426 # TODO: allow file object vs file name
28
c516ab813079 begin stubbing serialization/deserialization
Jeff Hammel <jhammel@mozilla.com>
parents: 27
diff changeset
427
50
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
428 assert os.path.exists(filename)
113e8c2f7cab start to hook up deserializers
Jeff Hammel <jhammel@mozilla.com>
parents: 49
diff changeset
429
41
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
430 # get the format
29
fadcc6ab51d4 more (de/)serialization stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 28
diff changeset
431 if not format:
41
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
432 format = self.filename2format(filename)
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
433
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
434 # get the providers in some sensible order
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
435 providers = self.configuration_providers[:]
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
436 if format:
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
437 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
438
41
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
439 # deserialize the data
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
440 for provider in providers:
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
441 try:
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
442 return provider.read(filename)
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
443 except:
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
444 continue
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
445 else:
1bd4ddf2e81d deserialization should work now
Jeff Hammel <jhammel@mozilla.com>
parents: 38
diff changeset
446 raise ConfigurationProviderException("Could not load %s" % filename)