import cfgparse in method that needs it for more robustness
[myslice.git] / manifold / util / options.py
1 import sys
2 import os.path
3 import optparse
4 # xxx warning : this is not taken care of by the debian packaging
5 # cfgparse seems to be available by pip only (on debian, that is)
6 # there seems to be another package that might be used to do similar stuff
7 # python-configglue - Glues together optparse.OptionParser and ConfigParser.ConfigParser
8 # additionally argumentparser would probably be the way to go, notwithstanding
9 # xxx Moving this into the parse method so this module can at least be imported
10 #import cfgparse
11
12 from manifold.util.singleton    import Singleton
13
14 # http://docs.python.org/dev/library/argparse.html#upgrading-optparse-code
15
16 class Options(object):
17
18     __metaclass__ = Singleton
19
20     # We should be able to use another default conf file
21     CONF_FILE = '/etc/manifold.conf'
22     
23     def __init__(self, name = None):
24         self._opt = optparse.OptionParser()
25         self._defaults = {}
26         self._name = name
27         self.clear()
28
29     def clear(self):
30         self.options  = {}
31         self.add_option(
32             "-c", "--config", dest = "cfg_file",
33             help = "Config file to use.",
34             default = self.CONF_FILE
35         )
36         self.uptodate = True
37
38     def parse(self):
39         """
40         \brief Parse options passed from command-line
41         """
42         # add options here
43
44         # if we have a logger singleton, add its options here too
45         # get defaults too
46         
47         # Initialize options to default values
48         import cfgparse
49         cfg = cfgparse.ConfigParser()
50         cfg.add_optparse_help_option(self._opt)
51
52         # Load configuration file
53         try:
54             cfg_filename = sys.argv[sys.argv.index("-c") + 1]
55             try:
56                 with open(cfg_filename): cfg.add_file(cfg_filename)
57             except IOError: 
58                 raise Exception, "Cannot open specified configuration file: %s" % cfg_filename
59         except ValueError:
60             try:
61                 with open(self.CONF_FILE): cfg.add_file(self.CONF_FILE)
62             except IOError: pass
63
64         for option_name in self._defaults:
65             cfg.add_option(option_name, default = self._defaults[option_name])
66             
67         # Load/override options from configuration file and command-line 
68         (options, args) = cfg.parse(self._opt)
69         self.options.update(vars(options))
70         self.uptodate = True
71
72
73     def add_option(self, *args, **kwargs):
74         default = kwargs.get('default', None)
75         self._defaults[kwargs['dest']] = default
76         if 'default' in kwargs:
77             # This is very important otherwise file content is not taken into account
78             del kwargs['default']
79         kwargs['help'] += " Defaults to %r." % default
80         self._opt.add_option(*args, **kwargs)
81         self.uptodate = False
82         
83     def get_name(self):
84         return self._name if self._name else os.path.basename(sys.argv[0])
85
86     def __repr__(self):
87         return "<Options: %r>" % self.options
88
89     def __getattr__(self, key):
90         if not self.uptodate:
91             self.parse()
92         return self.options.get(key, None)
93
94     def __setattr(self, key, value):
95         self.options[key] = value