Google analytics in README
[wrigit.git] / cfg.py
blob527874154cceeb315a7d79cbd750014e863d3f50
1 """A simple wrapper around optparse and configobj
3 >>> from cfg import o, setup_cfg
4 >>> cfg = setup_cfg([
5 o('-c', '--conf', dest='conf',
6 help='Configuration file'),
7 ...
8 ], {'foo': 34})
9 >>> print cfg['bar.yaht']
10 ...
11 """
13 from os.path import dirname, abspath
15 import configobj
16 from optparse import make_option as o, OptionParser
18 # Global 'cfg' object
19 cfg = None
21 # ConfigObj does not support passing custom template variables like in
22 # most HTML templating systems. This is bad.
23 # ConfigObj code is also not very extensible. This is very bad.
24 # So we hack around the `interpolation_engines` global variable to
25 # get our job done.
27 def configobj_namespace(namespace):
28 global configobj
29 import re
31 class GoodConfigParserInterpolation(configobj.ConfigParserInterpolation):
32 """Resolve custom template variables manually passed"""
34 def interpolate(self, key, value):
35 try:
36 return super(GoodConfigParserInterpolation,
37 self).interpolate(key, value)
38 except configobj.InterpolationError:
39 # eg: extract 'var' out of '%(var)s'
40 match = self._KEYCRE.search(value)
41 if match:
42 var = match.group(1)
43 if var in namespace:
44 return re.sub(self._KEYCRE, namespace[var], value)
45 raise
47 # There is another engine 'template' which, for me, never seems to
48 # work. voidspace?
49 configobj.interpolation_engines['configparser'] = \
50 GoodConfigParserInterpolation
53 def married(options, configobj):
54 """
55 Marry optparse and configobj
56 http://wiki.python.org/moin/ConfigParserShootout
57 """
59 class sex(object):
61 def __setitem__(self, item, value):
62 return setattr(options, item, value)
64 def __getitem__(self, item):
65 # If `item` is not found in `options` read from `configobj`
66 try:
67 value = getattr(options, item)
68 if value is None:
69 raise AttributeError
70 else:
71 return value
72 except AttributeError:
73 c = configobj
74 try:
75 for a in item.split('.'):
76 c = c[a]
77 except KeyError:
78 return None # optparse, too, returns None in this case.
79 return c
81 def __str__(self):
82 return "<cfg {\n%s,\n\n%s\n}>" % (options, configobj)
84 return sex()
86 def setup_cfg(option_list, defaults, namespace={}):
87 global cfg
89 oparser = OptionParser(option_list=option_list)
90 oparser.set_defaults(**defaults)
91 (options, args) = oparser.parse_args()
93 if options.conf is None:
94 raise SystemExit, "You must specify the --conf option."
96 # `pwd` contains the directory where the conf file lies.
97 namespace['pwd'] = abspath(dirname(abspath(options.conf)))
99 # patch it!
100 configobj_namespace(namespace)
102 cobj = configobj.ConfigObj(options.conf)
103 cfg = married(options, cobj)
104 return cfg
106 __all__ = ['setup_cfg', 'o', 'cfg']