~vpec/maus/tof_calib_read

« back to all changes in this revision

Viewing changes to src/common_py/Configuration.py

reverse merge from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
22
22
import os
23
23
import json
24
24
import ErrorHandler
 
25
import argparse
25
26
 
26
27
class Configuration:
27
28
    """
34
35
        """        
35
36
        self.readme = os.path.join(os.environ['MAUS_ROOT_DIR'], 'README')
36
37
 
37
 
    def getConfigJSON(self, config_file = None):
 
38
    def getConfigJSON(self, config_file = None, command_line_args = False):
38
39
        """
39
40
        Returns JSON config document
40
41
 
42
43
        then (if applicable) values are added/replaced
43
44
        by the passed file.  A JSON file is returned.
44
45
 
45
 
        \param config_file (optional) overriding configuration file handle.  If
 
46
        @param config_file (optional) overriding configuration file handle.  If
46
47
                          None then this argument is ignored. If it is a python
47
48
                          file handle (ie. open('my_config.dat','r') ) then that
48
49
                          file is read.
 
50
        @param command_line_args if set to True, take arguments from the command
 
51
               line. Can produce undesirable results if you are running the main
 
52
               process from e.g. nosetests so disabled by default.
49
53
        """
50
54
        maus_root_dir = os.environ.get('MAUS_ROOT_DIR')
51
55
        assert maus_root_dir != None
54
58
        defaults = open(maus_root_dir+"/src/common_py/ConfigurationDefaults.py")
55
59
        exec(defaults, globals(), config_dict) # pylint: disable=W0122
56
60
 
 
61
        if command_line_args:
 
62
            config_dict = self.command_line_arguments(config_dict)
 
63
 
 
64
        if config_dict["configuration_file"] != "":
 
65
            cmd_line_config_file = open(config_dict["configuration_file"])
 
66
            exec(cmd_line_config_file.read(), globals(), config_dict) # pylint: disable=W0122,C0301
 
67
 
57
68
        if config_file != None:
58
69
            assert not isinstance(config_file, str)
59
70
            exec(config_file.read(), globals(), config_dict) # pylint: disable=W0122,C0301
60
71
 
 
72
        if config_dict['maus_version'] != "":
 
73
            raise ValueError("MAUS version cannot be changed by the user")
61
74
        config_dict['maus_version'] = self.get_version_from_readme()
 
75
        config_dict = self.check_config_dict(config_dict)
62
76
        self.configuration_to_error_handler(config_dict)
63
77
        config_json_str = json.JSONEncoder().encode(config_dict)
64
 
 
65
78
        return config_json_str
 
79
 
 
80
    def command_line_arguments(self, config_dict):
 
81
        """
 
82
        Parse arguments from the command line
 
83
 
 
84
        Use argparse module to control command line arguments. First add the
 
85
        arguments to the file taken from ConfigurationDefaults; force the 
 
86
        arguments into the right type; and then push them to config_dict.
 
87
 
 
88
        @returns the modified config_dict
 
89
        """
 
90
        # Argparse allows for a command line parser with keywords given by 
 
91
        # ConfigurationDefaults.p Additionally a keyword command has been
 
92
        # created to store the path and filename to a datacard
 
93
        parser = argparse.ArgumentParser()
 
94
        for key, value in config_dict.iteritems():
 
95
            parser.add_argument('-'+key, action='store', dest=key, 
 
96
                                default=value)
 
97
        results = parser.parse_args()
 
98
 
 
99
        # All parsed values are input as string types, this checks the type in
 
100
        # ConfigurationDefaults.py and attempts to return the parsed values to
 
101
        # orginal or similar type. Currently does not work for dict type
 
102
        # arguments
 
103
        for key, def_value in config_dict.iteritems(): # value is from defaults
 
104
            ap_value = getattr(results, key)
 
105
            if def_value == ap_value:
 
106
                continue
 
107
            elif isinstance (def_value, str):
 
108
                config_dict[key] = ap_value # shouldn't throw
 
109
            elif isinstance (def_value, bool):
 
110
                try:
 
111
                    config_dict[key] = self.string_to_bool(ap_value)
 
112
                except ValueError:
 
113
                    raise ValueError('Could not convert command line argument '\
 
114
                          +str(key)+' with value '+ap_value+\
 
115
                          ' to a boolean')
 
116
 
 
117
            # Checks if the default is an integer, if it is, it will try to
 
118
            # force the parsed argument back into int type, failing that, it
 
119
            # will try to force it into float type.  If the argument is no
 
120
            # longer a number an exception is raised.
 
121
            elif isinstance (def_value, int):
 
122
                try:
 
123
                    config_dict[key] = int(ap_value)
 
124
                except ValueError:
 
125
                    raise ValueError('Could not convert command line '+\
 
126
                          'argument '+str(key)+' with value '+\
 
127
                          str(ap_value)+' to an int')
 
128
 
 
129
            # Checks if the default is a float, if it is, this will try and
 
130
            # force the parsed argument back into float type.  If the argument
 
131
            # is no longer a number an exception is raised.
 
132
            elif isinstance (def_value, float):
 
133
                try:
 
134
                    config_dict[key] = float(ap_value)
 
135
                except ValueError:
 
136
                    raise ValueError('Could not convert command line argument '\
 
137
                          +str(key)+' with value '+ap_value+\
 
138
                          ' to a float')
 
139
            # If attempt to modify something that was neither int, bool, string,
 
140
            # float; raise NotImplementedError (json allows dict and arrays)
 
141
            else:
 
142
                raise NotImplementedError("Could not convert command line "+\
 
143
                "argument "+str(key)+" of type "+str(type(def_value))+\
 
144
                ". Can only parse string, int, bool, float types.")
 
145
        return config_dict
66
146
        
67
147
    def get_version_from_readme(self):
68
148
        """
72
152
        version = readme.readline().rstrip('\n')
73
153
        return version
74
154
 
75
 
    def configuration_to_error_handler(self, config_dict):
 
155
    def configuration_to_error_handler(self, config_dict): #pylint:disable=R0201
76
156
        """
77
157
        Hand configuration parameters to the error handler, so it can set itself
78
158
        up
79
159
        """
80
160
        ErrorHandler.DefaultHandler().ConfigurationToErrorHandler(config_dict)
81
161
 
 
162
    def check_config_dict(self, config_dict): #pylint:disable=R0201
 
163
        """
 
164
        @brief Check to see if config_dict can be encoded into json
 
165
        @params config_dict dictionary to be checked
 
166
        @returns Copy of config_dict with non-encodable items stripped out
 
167
        """
 
168
        dict_copy = {}
 
169
        for key, value in config_dict.iteritems():
 
170
            try:
 
171
                json.JSONEncoder().encode({key:value})
 
172
                dict_copy[key] = value
 
173
            except TypeError:
 
174
                pass
 
175
        return dict_copy
 
176
    
 
177
    def string_to_bool(self, string_in): #pylint:disable=R0201
 
178
        """
 
179
        Convert from a string to a boolean value
 
180
 
 
181
        @params string_in if string_in is any one of true, 1, yes, y, t returns
 
182
                 true. Case insensitive.
 
183
 
 
184
        @returns boolean True or False
 
185
        """
 
186
        if str.lower(string_in) in ["true", "1", "yes", "y", "t"]:
 
187
            return True
 
188
        elif str.lower(string_in) in ["false", "0", "no", "n", "f"]:
 
189
            return False
 
190
        else:
 
191
            raise ValueError("Could not parse "+string_in+" as a boolean")
 
192