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

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

added type ahead and filepath into UI options.

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