def create_literal_inputs(self, source, inputs): """ Takes the http_request and parses the input to objects :return collections.deque: """ outinputs = deque(maxlen=source.max_occurs) for inpt in inputs: newinpt = source.clone() # set the input to the type defined in the process newinpt.uom = inpt.get('uom') data_type = inpt.get('datatype') if data_type: newinpt.data_type = data_type # get the value of the field newinpt.data = inpt.get('data') outinputs.append(newinpt) if len(outinputs) < source.min_occurs: description = "At least {} inputs are required. You provided {}.".format( source.min_occurs, len(outinputs), ) raise MissingParameterValue(description, locator=source.identifier) return outinputs
def describe(self, identifiers): if not identifiers: raise MissingParameterValue('', 'identifier') identifier_elements = [] # 'all' keyword means all processes if 'all' in (ident.lower() for ident in identifiers): for process in self.processes: try: identifier_elements.append(self.processes[process].describe_xml()) except Exception as e: raise NoApplicableCode(e) else: for identifier in identifiers: try: process = self.processes[identifier] except KeyError: raise InvalidParameterValue("Unknown process %r" % identifier, "identifier") else: try: identifier_elements.append(process.describe_xml()) except Exception as e: raise NoApplicableCode(e) doc = WPS.ProcessDescriptions( *identifier_elements ) doc.attrib['{http://www.w3.org/2001/XMLSchema-instance}schemaLocation'] = 'http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd' doc.attrib['service'] = 'WPS' doc.attrib['version'] = '1.0.0' doc.attrib['{http://www.w3.org/XML/1998/namespace}lang'] = 'en-CA' return xml_response(doc)
def create_bbox_inputs(self, source, inputs): """ Takes the http_request and parses the input to objects :return collections.deque: """ outinputs = deque(maxlen=source.max_occurs) for datainput in inputs: newinpt = source.clone() try: newinpt.data = [ datainput.minx, datainput.miny, datainput.maxx, datainput.maxy ] except AttributeError: newinpt.data = [ float(coord) for coord in datainput['data'].split(',')[:4] ] outinputs.append(newinpt) if len(outinputs) < source.min_occurs: description = "At least {} inputs are required. You provided {}.".format( source.min_occurs, len(outinputs), ) raise MissingParameterValue(description=description, locator=source.identifier) return outinputs
def _construct_doc(self): if not self.identifiers: raise MissingParameterValue('Missing parameter value "identifier"', 'identifier') template = self.template_env.get_template(self.version + '/describe/main.xml') max_size = int(config.get_size_mb(config.get_config_value('server', 'maxsingleinputsize'))) doc = template.render(max_size=max_size, **self.json) return doc
def check_and_set_version(self, version): """set this.version """ if not version: raise MissingParameterValue('Missing version', 'version') elif not _check_version(version): raise VersionNegotiationFailed( 'The requested version "{}" is not supported by this server'.format(version), 'version') else: self.set_version(version)
def create_bbox_inputs(self, source, inputs): """ Takes the http_request and parses the input to objects :return collections.deque: """ outinputs = deque(maxlen=source.max_occurs) for datainput in inputs: newinpt = source.clone() newinpt.data = [datainput.minx, datainput.miny, datainput.maxx, datainput.maxy] outinputs.append(newinpt) if len(outinputs) < source.min_occurs: raise MissingParameterValue(locator = source.identifier) return outinputs
def _get_request(self): """HTTP GET request parser """ # service shall be WPS service = _get_get_param(self.http_request, 'service') if service: if str(service).lower() != 'wps': raise InvalidParameterValue( 'parameter SERVICE [{}] not supported'.format(service), 'service') else: raise MissingParameterValue('service', 'service') operation = _get_get_param(self.http_request, 'request') request_parser = self._get_request_parser(operation) request_parser(self.http_request)
def parse_post_execute(doc): """Parse POST Execute request """ version = doc.attrib.get('version') wpsrequest.check_and_set_version(version) language = doc.attrib.get('language') wpsrequest.check_and_set_language(language) wpsrequest.operation = 'execute' identifier = xpath_ns(doc, './ows:Identifier') if not identifier: raise MissingParameterValue('Process identifier not set', 'Identifier') wpsrequest.identifier = identifier[0].text wpsrequest.lineage = 'false' wpsrequest.store_execute = 'false' wpsrequest.status = 'false' wpsrequest.inputs = get_inputs_from_xml(doc) wpsrequest.outputs = get_output_from_xml(doc) wpsrequest.raw = False if xpath_ns(doc, '/wps:Execute/wps:ResponseForm/wps:RawDataOutput'): wpsrequest.raw = True # executeResponse XML will not be stored wpsrequest.store_execute = 'false' # check if response document tag has been set then retrieve response_document = xpath_ns( doc, './wps:ResponseForm/wps:ResponseDocument') if len(response_document) > 0: wpsrequest.lineage = response_document[0].attrib.get( 'lineage', 'false') wpsrequest.store_execute = response_document[0].attrib.get( 'storeExecuteResponse', 'false') wpsrequest.status = response_document[0].attrib.get( 'status', 'false')
def create_complex_inputs(self, source, inputs): """Create new ComplexInput as clone of original ComplexInput because of inputs can be more than one, take it just as Prototype. :param source: The process's input definition. :param inputs: The request input data. :return collections.deque: """ outinputs = deque(maxlen=source.max_occurs) for inpt in inputs: data_input = source.clone() frmt = data_input.supported_formats[0] if 'mimeType' in inpt: if inpt['mimeType']: frmt = data_input.get_format(inpt['mimeType']) else: frmt = data_input.data_format if frmt: data_input.data_format = frmt else: raise InvalidParameterValue( 'Invalid mimeType value {} for input {}'.format( inpt.get('mimeType'), source.identifier), 'mimeType') data_input.method = inpt.get('method', 'GET') data_input.process(inpt) outinputs.append(data_input) if len(outinputs) < source.min_occurs: description = "At least {} inputs are required. You provided {}.".format( source.min_occurs, len(outinputs), ) raise MissingParameterValue(description=description, locator=source.identifier) return outinputs
def create_complex_inputs(self, source, inputs): """Create new ComplexInput as clone of original ComplexInput because of inputs can be more then one, take it just as Prototype :return collections.deque: """ outinputs = deque(maxlen=source.max_occurs) for inpt in inputs: data_input = source.clone() frmt = data_input.supported_formats[0] if 'mimeType' in inpt: if inpt['mimeType']: frmt = data_input.get_format(inpt['mimeType']) else: frmt = data_input.data_format if frmt: data_input.data_format = frmt else: raise InvalidParameterValue( 'Invalid mimeType value %s for input %s' %\ (inpt.get('mimeType'), source.identifier), 'mimeType') data_input.method = inpt.get('method', 'GET') # get the referenced input otherwise get the value of the field href = inpt.get('href', None) complex_data_handler = self._get_complex_input_handler(href) complex_data_handler(data_input, inpt) outinputs.append(data_input) if len(outinputs) < source.min_occurs: raise MissingParameterValue(locator = source.identifier) return outinputs
def _get_request(self): """HTTP GET request parser """ # WSDL request wsdl = _get_get_param(self.http_request, 'WSDL') if wsdl is not None: # TODO: fix #57 then remove the exception raise NoApplicableCode('WSDL not implemented') # service shall be WPS service = _get_get_param(self.http_request, 'service', aslist=False) if service: if str(service).lower() != 'wps': raise InvalidParameterValue( 'parameter SERVICE [%s] not supported' % service) else: raise MissingParameterValue('service', 'service') operation = _get_get_param(self.http_request, 'request', aslist=False) request_parser = self._get_request_parser(operation) request_parser(self.http_request)
def _parse_and_execute(self, process, wps_request): """Parse and execute request """ # check if datainputs is required and has been passed if process.inputs: if wps_request.inputs is None: raise MissingParameterValue('', 'datainputs') # check if all mandatory inputs have been passed data_inputs = {} for inpt in process.inputs: if inpt.identifier not in wps_request.inputs: if inpt.min_occurs > 0: raise MissingParameterValue(inpt.identifier, inpt.identifier) else: data_inputs[inpt.identifier] = inpt.clone() # Replace the dicts with the dict of Literal/Complex inputs # set the input to the type defined in the process if isinstance(inpt, ComplexInput): data_inputs[inpt.identifier] = self.create_complex_inputs(inpt, wps_request.inputs[inpt.identifier]) elif isinstance(inpt, LiteralInput): data_inputs[inpt.identifier] = self.create_literal_inputs(inpt, wps_request.inputs[inpt.identifier]) elif isinstance(inpt, BoundingBoxInput): data_inputs[inpt.identifier] = self.create_bbox_inputs(inpt, wps_request.inputs[inpt.identifier]) wps_request.inputs = data_inputs # set as_reference to True for all the outputs specified as reference # if the output is not required to be raw if not wps_request.raw: for wps_outpt in wps_request.outputs: is_reference = wps_request.outputs[wps_outpt].get('asReference', 'false') if is_reference.lower() == 'true': # check if store is supported if process.store_supported == 'false': raise StorageNotSupported('The storage of data is not supported for this process.') is_reference = True else: is_reference = False for outpt in process.outputs: if outpt.identifier == wps_outpt: outpt.as_reference = is_reference # catch error generated by process code try: wps_response = process.execute(wps_request) except Exception as e: raise NoApplicableCode('Service error: %s' % e) # get the specified output as raw if wps_request.raw: for outpt in wps_request.outputs: for proc_outpt in process.outputs: if outpt == proc_outpt.identifier: return Response(proc_outpt.data) # if the specified identifier was not found raise error raise InvalidParameterValue('') return wps_response
def _get_request_parser(self, operation): """Factory function returing propper parsing function """ wpsrequest = self def parse_get_getcapabilities(http_request): """Parse GET GetCapabilities request """ acceptedversions = _get_get_param(http_request, 'acceptversions') wpsrequest.check_accepted_versions(acceptedversions) def parse_get_describeprocess(http_request): """Parse GET DescribeProcess request """ version = _get_get_param(http_request, 'version') wpsrequest.check_and_set_version(version) language = _get_get_param(http_request, 'language') wpsrequest.check_and_set_language(language) wpsrequest.identifiers = _get_get_param( http_request, 'identifier', aslist=True) def parse_get_execute(http_request): """Parse GET Execute request """ version = _get_get_param(http_request, 'version') wpsrequest.check_and_set_version(version) language = _get_get_param(http_request, 'language') wpsrequest.check_and_set_language(language) wpsrequest.identifier = _get_get_param(http_request, 'identifier') wpsrequest.store_execute = _get_get_param( http_request, 'storeExecuteResponse', 'false') wpsrequest.status = _get_get_param(http_request, 'status', 'false') wpsrequest.lineage = _get_get_param( http_request, 'lineage', 'false') wpsrequest.inputs = get_data_from_kvp( _get_get_param(http_request, 'DataInputs'), 'DataInputs') if self.inputs is None: self.inputs = {} wpsrequest.outputs = {} # take responseDocument preferably resp_outputs = get_data_from_kvp( _get_get_param(http_request, 'ResponseDocument')) raw_outputs = get_data_from_kvp( _get_get_param(http_request, 'RawDataOutput')) wpsrequest.raw = False if resp_outputs: wpsrequest.outputs = resp_outputs elif raw_outputs: wpsrequest.outputs = raw_outputs wpsrequest.raw = True # executeResponse XML will not be stored and no updating of # status wpsrequest.store_execute = 'false' wpsrequest.status = 'false' if not operation: raise MissingParameterValue('Missing request value', 'request') else: self.operation = operation.lower() if self.operation == 'getcapabilities': return parse_get_getcapabilities elif self.operation == 'describeprocess': return parse_get_describeprocess elif self.operation == 'execute': return parse_get_execute else: raise OperationNotSupported( 'Unknown request {}'.format(self.operation), operation)
def _parse_and_execute(self, process, wps_request, uuid): """Parse and execute request """ LOGGER.debug('Checking if all mandatory inputs have been passed') data_inputs = {} for inpt in process.inputs: # Replace the dicts with the dict of Literal/Complex inputs # set the input to the type defined in the process. request_inputs = None if inpt.identifier in wps_request.inputs: request_inputs = wps_request.inputs[inpt.identifier] if not request_inputs: if inpt.data_set: data_inputs[inpt.identifier] = [inpt.clone()] else: if isinstance(inpt, ComplexInput): data_inputs[inpt.identifier] = self.create_complex_inputs( inpt, request_inputs) elif isinstance(inpt, LiteralInput): data_inputs[inpt.identifier] = self.create_literal_inputs( inpt, request_inputs) elif isinstance(inpt, BoundingBoxInput): data_inputs[inpt.identifier] = self.create_bbox_inputs( inpt, request_inputs) for inpt in process.inputs: if inpt.identifier not in data_inputs: if inpt.min_occurs > 0: LOGGER.error('Missing parameter value: %s', inpt.identifier) raise MissingParameterValue(inpt.identifier, inpt.identifier) wps_request.inputs = data_inputs # set as_reference to True for all the outputs specified as reference # if the output is not required to be raw if not wps_request.raw: for wps_outpt in wps_request.outputs: is_reference = wps_request.outputs[wps_outpt].get( 'asReference', 'false') if is_reference.lower() == 'true': # check if store is supported if process.store_supported == 'false': raise StorageNotSupported( 'The storage of data is not supported for this process.' ) is_reference = True else: is_reference = False for outpt in process.outputs: if outpt.identifier == wps_outpt: outpt.as_reference = is_reference # catch error generated by process code try: wps_response = process.execute(wps_request, uuid) except Exception as e: e_follow = e if not isinstance(e, NoApplicableCode): e_follow = NoApplicableCode('Service error: %s' % e) if wps_request.raw: resp = Response(e_follow.get_body(), mimetype='application/xml') resp.call_on_close(process.clean) return resp else: raise e_follow # get the specified output as raw if wps_request.raw: for outpt in wps_request.outputs: for proc_outpt in process.outputs: if outpt == proc_outpt.identifier: return Response(proc_outpt.data) # if the specified identifier was not found raise error raise InvalidParameterValue('') return wps_response
def _parse_and_execute(self, process, wps_request, uuid): """Parse and execute request """ LOGGER.debug('Checking if all mandatory inputs have been passed') data_inputs = {} for inpt in process.inputs: # Replace the dicts with the dict of Literal/Complex inputs # set the input to the type defined in the process. request_inputs = None if inpt.identifier in wps_request.inputs: request_inputs = wps_request.inputs[inpt.identifier] if not request_inputs: if inpt._default is not None: if not inpt.data_set and isinstance(inpt, ComplexInput): inpt._set_default_value() data_inputs[inpt.identifier] = [inpt.clone()] else: if isinstance(inpt, ComplexInput): data_inputs[inpt.identifier] = self.create_complex_inputs( inpt, request_inputs) elif isinstance(inpt, LiteralInput): data_inputs[inpt.identifier] = self.create_literal_inputs( inpt, request_inputs) elif isinstance(inpt, BoundingBoxInput): data_inputs[inpt.identifier] = self.create_bbox_inputs( inpt, request_inputs) for inpt in process.inputs: if inpt.identifier not in data_inputs: if inpt.min_occurs > 0: LOGGER.error('Missing parameter value: %s', inpt.identifier) raise MissingParameterValue(inpt.identifier, inpt.identifier) wps_request.inputs = data_inputs # set as_reference to True for all the outputs specified as reference # if the output is not required to be raw if not wps_request.raw: for wps_outpt in wps_request.outputs: is_reference = wps_request.outputs[wps_outpt].get( 'asReference', 'false') mimetype = wps_request.outputs[wps_outpt].get('mimetype', '') if is_reference.lower() == 'true': # check if store is supported if process.store_supported == 'false': raise StorageNotSupported( 'The storage of data is not supported for this process.' ) is_reference = True else: is_reference = False for outpt in process.outputs: if outpt.identifier == wps_outpt: outpt.as_reference = is_reference if isinstance(outpt, ComplexOutput) and mimetype != '': data_format = [ f for f in outpt.supported_formats if f.mime_type == mimetype ] if len(data_format) == 0: raise InvalidParameterValue('MimeType ' + mimetype + ' not valid') outpt.data_format = data_format[0] wps_response = process.execute(wps_request, uuid) return wps_response
def __init__(self, http_request): self.http_request = http_request if http_request.method == 'GET': # service shall be WPS service = self._get_get_param('service', aslist=False) if service: if str(service).lower() != 'wps': raise OperationNotSupported( 'parameter SERVICE [%s] not supported' % service) else: raise MissingParameterValue('service', 'service') # operation shall be one of GetCapabilities, DescribeProcess, # Execute self.operation = self._get_get_param('request', aslist=False) if not self.operation: raise MissingParameterValue('request') else: self.operation = self.operation.lower() if self.operation == 'getcapabilities': pass elif self.operation == 'describeprocess': self.identifiers = self._get_get_param('identifier', aslist=True) if not self.identifiers: raise MissingParameterValue('identifier') elif self.operation == 'execute': self.identifier = self._get_get_param('identifier') self.inputs = get_input_from_kvp( self._get_get_param('datainputs')) else: raise InvalidParameterValue(self.operation) elif http_request.method == 'POST': doc = lxml.etree.fromstring(http_request.get_data()) if doc.tag == WPS.GetCapabilities().tag: self.operation = 'getcapabilities' elif doc.tag == WPS.DescribeProcess().tag: self.operation = 'describeprocess' self.identifiers = [ identifier_el.text for identifier_el in xpath_ns(doc, './ows:Identifier') ] elif doc.tag == WPS.Execute().tag: self.operation = 'execute' self.identifier = xpath_ns(doc, './ows:Identifier')[0].text self.inputs = get_input_from_xml(doc) else: raise InvalidParameterValue(doc.tag) else: raise MethodNotAllowed()