-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathconfig.py
172 lines (137 loc) · 4.53 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/python
#
# -*- coding: utf-8 -*-
# vim: set ts=4 sw=4 et sts=4 ai:
import cStringIO as StringIO
import json
import os
import re
import string
import warnings
VALID_GROUP_CHARACTERS = string.letters + string.digits + '_'
def _config_merge_into(dicta, dictb):
for nameb, valueb in dictb.iteritems():
if nameb in dicta and isinstance(dicta[nameb], dict):
valuea = dicta[nameb]
assert isinstance(valuea, dict), "%r not dict" % valuea
assert isinstance(valueb, dict), "%r not dict" % valueb
_config_merge_into(valuea, valueb)
else:
dicta[nameb] = valueb
def _remove_comments(filename):
fi = open(filename)
fo = StringIO.StringIO()
for line in fi.readlines():
if re.match("^\s*//", line):
continue
if not line.strip():
continue
fo.write(line)
fo.seek(0)
return fo
def _clean_empty(dicta):
if "" in dicta:
del dicta[""]
for name, value in dicta.items():
if isinstance(value, dict):
_clean_empty(value)
def config_load():
"""Load configuration and return dictionary."""
myloc = os.path.dirname(__file__)
if not myloc:
myloc = "."
public_config = myloc+'/config.json'
private_config = myloc+'/config.private.json'
try:
config = json.load(_remove_comments(public_config))
except ValueError, e:
raise IOError('Unable to open config.json\n%s' % e)
if os.path.exists(private_config):
try:
config_private = json.load(_remove_comments(private_config))
except Exception, e:
raise IOError('Unable to open config.private.json\n%s' % e)
else:
warnings.warn('No config.private.json file!\n')
config_private = {}
_clean_empty(config)
_clean_empty(config_private)
_config_merge_into(config, config_private)
all_keys = set(config['default'].keys())
for group_name, group_config in config.iteritems():
if group_name == "config":
continue
group_keys = set(group_config.keys())
assert group_keys.issubset(all_keys), \
'Group %s has invalid keys: %s' % (
group_name, group_keys.difference(all_keys))
for c in group_name:
if c not in VALID_GROUP_CHARACTERS:
# non-JS-safe group name, fail
# This causes strange bugs otherwise.
raise IOError("Non-letter/digit/_ character in group name: %r" % (group_name,))
return ConfigWrapper(config)
class ConfigWrapper(dict):
def groups(self):
"""Get a list of groups defined in the config file."""
groups = self.keys()
groups.remove('config')
groups.remove('default')
#groups.remove('example')
return list(sorted(groups))
def config(self, group):
"""Get a dictionary containing configuration values for a group."""
assert group in self, "%s not %s" % (group, self.keys())
config_group = {'group': group}
for name, default_value in self['default'].iteritems():
config_group[name] = self[group].get(name, default_value)
for name, value in config_group.iteritems():
context = dict(config_group)
try:
config_group[name] = value % context
except:
pass
return config_group
def valid(self, group):
"""Check if a given group is valid."""
return group in self.groups()
def main(args):
if args[-1] == 'groups':
CONFIG = config_load()
for group in CONFIG.groups():
print group
return 0
# Check the json files
print "config.json"
print "="*80
if os.system("cat config.json | grep -v '^\s*//' | python -m json.tool") != 0:
return -1
print "="*80
print
print "config.private.json"
print "="*80
if os.system("cat config.private.json | grep -v '^\s*//' | python -m json.tool") != 0:
return -1
print "="*80
print
# Try loading the config
print "Loading config"
CONFIG = config_load()
print
# Pretty print the resulting merged config output
print "Merged config"
print "="*80
import pprint
pprint.pprint(CONFIG)
print "="*80
# Print out each individual group
for group in CONFIG.groups():
print
print group
print "-"*80
pprint.pprint(CONFIG.config(group))
print "-"*80
return 0
if __name__ == "__main__":
import sys
sys.exit(main(sys.argv))