annotate configuration/config.py @ 20:dbfabe96187e

start to add types...still have some things to work out here
author Jeff Hammel <jhammel@mozilla.com>
date Mon, 26 Mar 2012 14:03:48 -0700
parents cadc9514f60a
children 0fe74db6a56c
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
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
7 import sys
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
8 import optparse
Jeff Hammel <jhammel@mozilla.com>
parents:
diff changeset
9
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
10 # imports for contigent configuration providers
4
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
11 try:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
12 import json
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
13 except ImportError:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
14 try:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
15 import simplejson as json
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
16 except ImportError:
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
17 json = None
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
18 try:
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
19 import yaml
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
20 except ImportError:
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
21 yaml = None
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
22
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
23 __all__ = ['Configuration', 'configuration_providers']
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
24
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
25 configuration_providers = []
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
26 if json:
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
27 class JSON(object):
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
28 extensions = ['json']
7
6e3cf8f05464 note TODO: reading JSON
Jeff Hammel <jhammel@mozilla.com>
parents: 6
diff changeset
29 def read(self, filename):
9
b28ec204df23 flush out JSON provider
Jeff Hammel <jhammel@mozilla.com>
parents: 8
diff changeset
30 return json.loads(file(filename).read())
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
31 configuration_providers.append(JSON)
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
32
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
33 if yaml:
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
34 class YAML(object):
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
35 extensions = ['yml']
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
36 def read(self, filename):
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
37 f = file(filename)
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
38 config = yaml.load(f)
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
39 f.close()
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
40 return config
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
41
5
7910b0ef0bab stub configuration providers
Jeff Hammel <jhammel@mozilla.com>
parents: 4
diff changeset
42 configuration_providers.append(YAML)
4
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
43
92e1b2dd60c8 more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 2
diff changeset
44
1
1dbdb4a57e0c stub configuration class
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
45 class Configuration(object):
1dbdb4a57e0c stub configuration class
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
46 options = {}
1dbdb4a57e0c stub configuration class
Jeff Hammel <jhammel@mozilla.com>
parents: 0
diff changeset
47
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
48 def __init__(self, configuration_providers=configuration_providers):
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
49 self.config = {}
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
50 self.configuration_providers = configuration_providers
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
51
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
52 def items(self):
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
53 # TODO: allow options to be a list of 2-tuples
13
0f8115a41ad6 bug fixes
Jeff Hammel <jhammel@mozilla.com>
parents: 12
diff changeset
54 return self.options.items()
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
55
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
56 def check(self, config):
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
57 """check validity of configuration"""
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
58
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
59 # TODO: ensure options in configuration are in self.options
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
60 unknown_options = []
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
61
10
c782d750fd6d comment
Jeff Hammel <jhammel@mozilla.com>
parents: 9
diff changeset
62 # TODO: ensure options are of the right type (if specified)
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
63
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
64 def __call__(self, *args):
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
65 """add items to configuration and check it"""
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
66
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
67 def add(self, config):
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
68 """update configuration: not undoable"""
6
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
69
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
70 self.check(config)
dce954a3831f more stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 5
diff changeset
71
2
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
72 self.config.update(config)
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
73 # TODO: option to extend; augment lists/dicts
35f57b21885f no stubbing
Jeff Hammel <jhammel@mozilla.com>
parents: 1
diff changeset
74
18
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
75 ### methods for optparse
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
76 ### XXX could go in a subclass
d8871956536e remove cruft and start to organize
Jeff Hammel <jhammel@mozilla.com>
parents: 17
diff changeset
77
20
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
78 @classmethod
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
79 def bool_cli(cls, value):
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
80 if value.get('default'):
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
81 pass
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
82 @classmethod
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
83 def list_cli(cls, value):
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
84 # TODO: could use 'extend'
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
85 # - http://hg.mozilla.org/build/mozharness/file/5f44ba08f4be/mozharness/base/config.py#l41
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
86 return dict(action='append')
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
87
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
88 types = {bool: bool_cli,
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
89 list: list_cli}
dbfabe96187e start to add types...still have some things to work out here
Jeff Hammel <jhammel@mozilla.com>
parents: 19
diff changeset
90
17
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
91 def optparse_options(self, parser):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
92 """add optparse options to a OptionParser instance"""
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
93 for key, value in self.items():
15
0df4bfdc2c96 make --help work
Jeff Hammel <jhammel@mozilla.com>
parents: 13
diff changeset
94 # TODO: move adding options to a separate function
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
95
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
96 # CLI arguments
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
97 args = value.get('flags', ['--%s' % key])
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
98 if not args:
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
99 continue
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
100
12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
101 kw = {'dest': key}
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
102 help = value.get('help', key)
12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
103 if 'default' in value:
11
e00afe2c83bf stubbing configuration parser
Jeff Hammel <jhammel@mozilla.com>
parents: 10
diff changeset
104
12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
105 kw['default'] = value['default']
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
106 # TODO: use default pattern a la
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
107 # - http://hg.mozilla.org/build/talos/file/c6013a2f09ce/talos/PerfConfigurator.py#l358
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
108 # - http://k0s.org/mozilla/hg/bzconsole/file/d5e88dadde69/bzconsole/command.py#l12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
109
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
110 help += ' [DEFAULT: %s]' % value['default']
15
0df4bfdc2c96 make --help work
Jeff Hammel <jhammel@mozilla.com>
parents: 13
diff changeset
111 kw['help'] = help
12
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
112 kw['action'] = 'store' # TODO: types
db43d30afcf5 note pattern to use
Jeff Hammel <jhammel@mozilla.com>
parents: 11
diff changeset
113 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
114
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
115 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
116 """
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
117 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
118 - 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
119 (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
120 for the configuration_providers)
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
121 - 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
122 """
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
123 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
124 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
125 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
126 class PlainDescriptionFormatter(optparse.IndentedHelpFormatter):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
127 """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
128 def format_description(self, description):
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
129 if description:
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
130 return description.strip() + '\n'
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
131 else:
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
132 return ''
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
133 parser_args['formatter'] = PlainDescriptionFormatter()
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
134 parser = optparse.OptionParser(**parser_args)
a78ab14ae376 separate thing to add options to its own function
Jeff Hammel <jhammel@mozilla.com>
parents: 15
diff changeset
135 self.optparse_options(parser)
15
0df4bfdc2c96 make --help work
Jeff Hammel <jhammel@mozilla.com>
parents: 13
diff changeset
136 return parser
19
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
137
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
138 def parse(self, args=sys.argv[1:], parser=None):
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
139 """parse configuration including command line options"""
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
140
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
141 # parse arguments
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
142 if parser is None:
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
143 parser = self.parser()
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
144 options, args = parser.parse_args(args)
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
145
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
146 # return parsed arguments
cadc9514f60a we have a legitimately failing test!
Jeff Hammel <jhammel@mozilla.com>
parents: 18
diff changeset
147 return options, args