source: cows_wps/trunk/cows_wps/utils/parse_capabilities_config.py @ 7576

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/cows_wps/trunk/cows_wps/utils/parse_capabilities_config.py@7576
Revision 7576, 9.6 KB checked in by astephen, 10 years ago (diff)

Now we can have multiple basedirs set in the config file.

Line 
1"""
2parseCapabilitiesConfig.py
3==========================
4
5Code to parse the capabilities.ini config file for WPS in Python Paste.
6
7"""
8
9# Import standard library modules
10import ConfigParser
11from cStringIO import StringIO
12import time
13import datetime
14import os
15import sys
16import re
17import glob 
18
19# Local modules
20import cows_wps.utils.case_sensitive_ordered_config_parser as cp
21
22import logging
23log = logging.getLogger(__name__)
24
25from cows_wps.utils.parse_wps_config import wps_config_dict
26
27def fixTrueFalse(value):
28    "Make true or false value a lower title cased version."
29    if value.lower() in ("true", "false"):
30        value = eval(value.title())
31    return value
32 
33def isValidLengthDescription(item):
34    "Returns False if length description doesn't match patterns allowed and True if it does."
35    # Check "<low>-<high>" pattern first
36    low_high_match = re.match("(\d+)*-(\d+)*$", item)
37    if low_high_match:
38        # Now check low is not bigger than high (only if both provided)
39       
40        (low, high) = [int(x) for x in low_high_match.groups()]
41        if low > high:
42            raise Exception("Minimum array length cannot be greater than maximum: " + item)
43        return True
44
45    # Now check other patterns
46    for pattern in ("\d+$", "(\d+)(,\d+)*$"):
47        if re.match(pattern, item): return True
48   
49    return False
50
51
52def commaSplitOrNone(s):
53    if s == None:
54        return None
55
56    return s.strip().split(",")
57
58
59def stripOrNone(s):
60    if s == None:
61        return None
62
63    return s.strip()
64
65def boolOrFalse(s):
66    if s:
67        return fixTrueFalse(s.strip())
68
69    return False
70
71
72
73def parseDataOutputInputs(outputInputDict):
74    outin_dict = {}
75
76    allowed_types = ("xml", 'complex','xml_complex_value',"string", "float", "int", "bool", "filepath", "bbox", "datetime")
77    additional_param_options = ("extent", "basedir", 
78                               "possible_values_url_template",
79                               "possible_values_xml_path")
80    additional_params_to_split = ("basedir",)
81
82    # Create short name for d
83    d = outputInputDict
84
85    for item in d:
86
87        item_with_params = item.split(".")
88        p = item_with_params[0]
89
90        if not outin_dict.has_key(p):
91
92            item_dict = {}
93            item_type = d[p].strip().split(".")
94
95            if item_type[0] not in allowed_types:
96                raise Exception("Type must be %s, cannot recognise: %s" % (allowed_types, item_type[0]))
97            else:
98                item_dict["type"] = item_type[0]
99
100                if item_type[0] == "xml_complex_value":
101                    try:
102                        item_dict["template"] = d[p + ".template"]
103                    except:
104                        raise Exception("xml_complex_value type must have a template")
105                   
106                if len(item_type) > 1:
107                    if item_type[1] == "list":
108                        item_dict["item_type"] = item_type[1]
109                    else:
110                        raise Exception("Type must be 'list', cannot recognise: " + item_type[1])
111                else:
112                    item_dict["item_type"] = "item"
113
114                item_dict["possible_values"] = commaSplitOrNone(d.get(p + ".possible_values", None)) 
115
116                item_dict["dynamic"] = boolOrFalse(d.get(p + ".dynamic", False))
117
118                if d.has_key(p + ".default"):
119                    value = fixTrueFalse(d[p + ".default"].strip()) 
120                    if value == "now":
121                        value = apply(datetime.datetime, time.localtime(time.time())[:6])
122
123                    item_dict["default"] = value
124
125                if d.has_key(p + ".optional"):
126                    item_dict["optional"] = fixTrueFalse(d[p + ".optional"].strip())
127
128                if d.has_key(p + ".length"):
129                    if isValidLengthDescription(d[p + ".length"].strip()):
130                        item_dict["allowed_length"] = d[p + ".length"].strip().replace(" ","-")
131                    else:
132                        raise Exception("Variable length %s not recognised" % d[p + ".length"].strip())
133                else:
134                    item_dict["allowed_length"] = None
135
136                # Loop through items that are strings or should be set to None
137                for i in ("schema", "encoding", "mime_type"):
138
139                    item_dict[i] = stripOrNone(d.get(p + "." + i, None))
140
141                for add_option in additional_param_options:
142                    key_name = p + "." + add_option
143
144                    if d.has_key(key_name):
145                        value = d[key_name].strip()
146
147                        if add_option in additional_params_to_split:
148                            value = value.split()
149
150                        item_dict[add_option] = value
151
152                outin_dict[p.strip()] = item_dict
153
154    return outin_dict
155
156def parseWpsInterface(wps_interface):
157    wps_dict = {}
158    for item in wps_interface:
159        value = wps_interface[item].strip()
160        if item == "response_types":
161                mappings = value.split(" ")
162                map_dict = {}
163                for i in mappings:
164                   map = i.split(":")
165                   if len (map) ==2 :
166                       map_dict[map[0]] = map[1]
167                   else:
168                       raise Exception ('Invalid response types values')
169                wps_dict[item] = map_dict
170        else:
171                wps_dict[item]= fixTrueFalse(value)
172
173
174    if wps_dict.has_key('response_types') == False:
175        wps_dict['response_types'] = {}
176
177#    log.debug('wps_dict["process_type"] = %s' % wps_dict.has_key('process_type'))
178
179    if not wps_dict.has_key('process_type'):
180        raise Exception ('A correct process type must be specified')
181    else:
182        if wps_dict.has_key('status'):
183                if wps_dict['status'] and wps_dict['process_type'] == 'sync':
184                        raise Exception ('Status cannot supported by a synchronous process')
185    return wps_dict
186   
187def parseGlobals(globals):
188    identifier= ""
189    global_dict={}
190    for item in globals:
191        if item == "Identifier":
192                identifier = globals[item].strip()
193        else:
194                global_dict[item] = fixTrueFalse(globals[item].strip())
195    return identifier, global_dict
196               
197def makeCapabilitiesConfigDict(config_file_list=None): #fname=capabilities_file):
198    '''Parses capabilities config file to return dictionary of:
199    {"identifiers" = [id1, id2...]
200    id1 = {"wps_interface":{"call_locally": "package.module#callable",....},
201           "globals" : {"Title" : "jsdkfjdslfj", "Abstract" : "lllll"...},
202           "DataInputs" : {"plotType" : {"item_type": "array",
203                                         "type": "string"
204                                         "allowed_length": "1-5",
205                                         "optional": True,
206                                         "default": True,
207                                         "enumeration" : ["yvsx", "....]},
208           "OrderedDataInputs": [key1, key2,....],
209           "ProcessOutputs" : {"title": {"item_type" : "item",
210                                         "type" : "string",
211                                         "allowed_length" : "-",
212                                         "enumeration": "-" } }
213    '''
214    global caps_config_dict
215   
216    if config_file_list == None:
217        try:
218            config_dir = wps_config_dict['proc_config_dir']
219        except KeyError:
220            log.warn('No process_config_dir option in application configuration')
221            base_dir = os.environ.get("WPS_BASE", ".")
222            config_dir = os.path.join(base_dir, "configs")
223           
224        config_file_list = glob.glob("%s/*.ini" % config_dir)
225   
226    caps_config_dict={}
227    ids = []
228    caps_config_dict["Identifiers"] = ids
229    for confFile in config_file_list:
230#        log.debug('Reading process config file %s' % confFile)
231       
232        try:
233            process_config = {}
234            config =  cp.CaseSensitiveOrderedConfigParser()
235            config.read([confFile])
236
237            identifier, process_config["globals"] = parseGlobals(dict(config.items("globals")))
238                                                         
239            process_config["wps_interface"] = parseWpsInterface(dict(config.items("wps_interface")))
240           
241            process_config["DataInputs"] = parseDataOutputInputs(dict(config.items("DataInputs")))
242            process_config["ProcessOutputs"] = parseDataOutputInputs(dict(config.items("ProcessOutputs")))
243           
244            # Correct code for parsing in options ordered within each section
245            all_data_input_options_ordered = config._option_orders["DataInputs"]
246            process_config["OrderedDataInputs"] = [di_opt for di_opt in all_data_input_options_ordered if di_opt.find(".") < 0]
247
248
249            ids.append(identifier)
250            caps_config_dict[identifier] = process_config
251        except:
252            print >> sys.stderr, "Exception occurred while reading config file %s" % (confFile)
253            raise
254
255
256caps_config_dict = None
257makeCapabilitiesConfigDict()
258
259if __name__=="__main__":
260    #setup the test wps dict and re-import
261    import cows_wps.tests.setup_test_wps_config
262    from cows_wps.utils.parse_wps_config import wps_config_dict
263   
264    makeCapabilitiesConfigDict()
265   
266   
267    def printDict(d, indent=None):
268        if indent == None: indent = ''
269       
270        for k in sorted(d):
271           
272            if d[k].__class__ == dict:
273                print indent + k, ':'
274                printDict(d[k], indent + ' ')
275            else:
276                print indent + k,'=',d[k], d[k].__class__
277   
278    printDict(caps_config_dict['GetData'])
279    print caps_config_dict['GetData'].keys()
280    print caps_config_dict['GetData']['DataInputs']
281
282
Note: See TracBrowser for help on using the repository browser.