8c177258833c36a8a232c78d73b522322383f4da
[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 import cfgparse
10
11 from manifold.util.singleton    import Singleton
12
13 # http://docs.python.org/dev/library/argparse.html#upgrading-optparse-code
14
15 class Options(object):
16
17     __metaclass__ = Singleton
18
19     # We should be able to use another default conf file
20     CONF_FILE = '/etc/manifold.conf'
21     
22     def __init__(self, name = None):
23         self._opt = optparse.OptionParser()
24         self._defaults = {}
25         self._name = name
26         self.clear()
27
28     def clear(self):
29         self.options  = {}
30         self.add_option(
31             "-c", "--config", dest = "cfg_file",
32             help = "Config file to use.",
33             default = self.CONF_FILE
34         )
35         self.uptodate = True
36
37     def parse(self):
38         """
39         \brief Parse options passed from command-line
40         """
41         # add options here
42
43         # if we have a logger singleton, add its options here too
44         # get defaults too
45         
46         # Initialize options to default values
47         cfg = cfgparse.ConfigParser()
48         cfg.add_optparse_help_option(self._opt)
49
50         # Load configuration file
51         try:
52             cfg_filename = sys.argv[sys.argv.index("-c") + 1]
53             try:
54                 with open(cfg_filename): cfg.add_file(cfg_filename)
55             except IOError: 
56                 raise Exception, "Cannot open specified configuration file: %s" % cfg_filename
57         except ValueError:
58             try:
59                 with open(self.CONF_FILE): cfg.add_file(self.CONF_FILE)
60             except IOError: pass
61
62         for option_name in self._defaults:
63             cfg.add_option(option_name, default = self._defaults[option_name])
64             
65         # Load/override options from configuration file and command-line 
66         (options, args) = cfg.parse(self._opt)
67         self.options.update(vars(options))
68         self.uptodate = True
69
70
71     def add_option(self, *args, **kwargs):
72         default = kwargs.get('default', None)
73         self._defaults[kwargs['dest']] = default
74         if 'default' in kwargs:
75             # This is very important otherwise file content is not taken into account
76             del kwargs['default']
77         kwargs['help'] += " Defaults to %r." % default
78         self._opt.add_option(*args, **kwargs)
79         self.uptodate = False
80         
81     def get_name(self):
82         return self._name if self._name else os.path.basename(sys.argv[0])
83
84     def __repr__(self):
85         return "<Options: %r>" % self.options
86
87     def __getattr__(self, key):
88         if not self.uptodate:
89             self.parse()
90         return self.options.get(key, None)
91
92     def __setattr(self, key, value):
93         self.options[key] = value