Beispiel #1
0
 def decorator_selector(data_type, data):
     convert = None
     if data_type in LITERAL_DATA_TYPES:
         if data_type == 'string':
             convert = convert_string
         elif data_type == 'integer':
             convert = convert_integer
         elif data_type == 'float':
             convert = convert_float
         elif data_type == 'boolean':
             convert = convert_boolean
         elif data_type == 'positiveInteger':
             convert = convert_positiveInteger
         elif data_type == 'anyURI':
             convert = convert_anyURI
         elif data_type == 'time':
             convert = convert_time
         elif data_type == 'scale':
             convert = convert_scale
         elif data_type == 'angle':
             convert = convert_angle
         elif data_type == 'nonNegativeInteger':
             convert = convert_positiveInteger
         else:
             raise InvalidParameterValue(
                 "Invalid data_type value of LiteralInput " +
                 "set to '{}'".format(data_type))
     try:
         return convert(data)
     except ValueError:
         raise InvalidParameterValue(
             "Could not convert value '{}' to format '{}'".format(
                 data, data_type))
Beispiel #2
0
    def _handler(self, request, response):

        # Need to process the elevationOut inputs from a list of strings, into an array of tuples.
        ranges = []
        for elevationrange in request.inputs['elevationOut']:
            if '-' in elevationrange.data:
                minrange, maxrange = elevationrange.data.split('-')
                ranges.append((int(minrange), int(maxrange))) # need to error catch int() and min < max
            else:
                raise InvalidParameterValue(
                    'The value "{}" does not contain a "-" character to define a range, '
                    'e.g. 0-100'.format(elevationrange.data))

        LOGGER.debug("domains: %s" % (request.inputs['domain'][0].data))
        domains = []
        for val in request.inputs['domain'][0].data:
            ## Values appear to be coming in as minY, minX, maxY, maxX
            domains.append(float(val))
        # If minX and maxX are 180, need to reset to 179.9
        if domains[1] == -180 and domains[3] == 180:
            domains[1] = -179.875
            domains[3] = 179.9

        params = dict()
        for p in request.inputs:
            if p == 'elevationOut':
                params[p] = ranges
            elif p == 'domain':
                params[p] = domains
            else:
                params[p] = request.inputs[p][0].data

        # Need to test start and end dates make sense relative to each other
        if params['startdate'] >= params['enddate'] + timedelta(days=1):
            raise InvalidParameterValue("The end date is earlier than the start date!")

        if (params['enddate'] + timedelta(days=1)) - params['startdate'] >= timedelta(days=93):
            raise InvalidParameterValue("Can only run across a maximum of three months in one go")

        # Need to test we don't run too far backwards/forwards
        if params['timeFmt'] == "days":
            if params['time'] > 20:
                raise InvalidParameterValue("Can only run NAME over a maximum of 20 days forwards/backwards")
        else:
            if params['time'] > 20 * 24:
                raise InvalidParameterValue("Can only run NAME over a maximum of 20 days forwards/backwards")

        response.update_status("Processed parameters", 5)

        outdir, zippedfile, mapfile = run_name(params, response)

        response.outputs['FileContents'].file = zippedfile + '.zip'
        response.outputs['runid'].data = outdir
        response.outputs['ExamplePlot'].file = mapfile

        response.update_status("done", 100)
        return response
Beispiel #3
0
 def translate_elevation(self, elevation_range):
     if '-' not in elevation_range:
         raise InvalidParameterValue(
             f'The value "{elevation_range}" does not contain a "-" character to define a range, e.g. 0-100')
     mini, maxi = elevation_range.split('-')
     try:
         mini = int(mini)
         maxi = int(maxi)
     except ValueError:
         raise InvalidParameterValue(f'The value {elevation_range} is incorrect: cannot find two numbers')
     if mini >= maxi:
         raise InvalidParameterValue(f'The value {elevation_range} is incorrect: minimum is not less than maximum')
     if mini < 0 or maxi < 0:
         raise InvalidParameterValue(f'The value {elevation_range} is incorrect: Entire range must be above 0')
     return mini, maxi
Beispiel #4
0
    def execute(self, identifier, wps_request, uuid):
        """Parse and perform Execute WPS request call

        :param identifier: process identifier string
        :param wps_request: pywps.WPSRequest structure with parsed inputs, still in memory
        :param uuid: string identifier of the request
        """
        self._set_grass()
        response = None
        try:
            process = self.processes[identifier]

            # make deep copy of the process instace
            # so that processes are not overriding each other
            # just for execute
            process = copy.deepcopy(process)

            workdir = os.path.abspath(
                config.get_config_value('server', 'workdir'))
            tempdir = tempfile.mkdtemp(prefix='pywps_process_', dir=workdir)
            process.set_workdir(tempdir)
        except KeyError:
            raise InvalidParameterValue("Unknown process '%r'" % identifier,
                                        'Identifier')

        olddir = os.path.abspath(os.curdir)
        try:
            os.chdir(process.workdir)
            response = self._parse_and_execute(process, wps_request, uuid)
        finally:
            os.chdir(olddir)

        return response
Beispiel #5
0
    def __init__(self,
                 identifier,
                 title=None,
                 abstract=None,
                 keywords=[],
                 crss=None,
                 dimensions=None,
                 workdir=None,
                 mode=MODE.SIMPLE,
                 min_occurs=1,
                 max_occurs=1,
                 metadata=[],
                 default=None,
                 default_type=SOURCE_TYPE.DATA):
        BasicIO.__init__(self, identifier, title, abstract, keywords,
                         min_occurs, max_occurs, metadata)
        BasicBoundingBox.__init__(self, crss, dimensions)
        DataHandler.__init__(self, workdir=workdir, mode=mode)

        if default_type != SOURCE_TYPE.DATA:
            raise InvalidParameterValue(
                "Source types other than data are not supported.")

        self._default = default
        self._default_type = default_type

        self._set_default_value(default, default_type)
Beispiel #6
0
    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)
Beispiel #7
0
    def set_data(self, data):
        """Set data value. input data are converted into target format
        """
        if self.data_type:
            # TODO: check datatypeabstract class somethings missing here
            # check if it is a valid data_type
            if self.data_type.lower() in LITERAL_DATA_TYPES:
                if self.data_type.lower() == 'string':
                    data = text_type(data)
                elif self.data_type.lower() == 'integer':
                    data = int(data)
                elif self.data_type.lower() == 'float':
                    data = float(data)
                elif self.data_type.lower() == 'boolean':
                    if data.lower() == 'true':
                        data = True
                    else:
                        data = False
                #data = self.data_type.convert(data)

                _valid = self.validator(self, self.valid_mode)
                if not _valid:
                    raise InvalidParameterValue('Input data not valid using '
                                                'mode %s' % (self.valid_mode))

                IOHandler.set_data(self, data)
Beispiel #8
0
    def execute(self, identifier, wps_request):
        """Parse and perform Execute WPS request call

        :param identifier: process identifier string
        :param wps_request: pywps.WPSRequest structure with parsed inputs, still in memory
        """
        response = None
        try:
            process = self.processes[identifier]

            workdir = config.get_config_value('server', 'workdir')
            tempdir = tempfile.mkdtemp(prefix='pypws_process_', dir=workdir)
            process.set_workdir(tempdir)
        except KeyError:
            raise InvalidParameterValue("Unknown process '%r'" % identifier)

        olddir = os.path.abspath(os.curdir)
        try:
            os.chdir(process.workdir)
            response = self._parse_and_execute(process, wps_request)
            os.chdir(olddir)
            shutil.rmtree(process.workdir)
        except Exception as e:
            os.chdir(olddir)
            shutil.rmtree(process.workdir)
            raise e

        return response
Beispiel #9
0
    def __init__(self,
                 identifier,
                 title=None,
                 abstract=None,
                 keywords=None,
                 data_type="integer",
                 workdir=None,
                 allowed_values=None,
                 uoms=None,
                 mode=MODE.NONE,
                 min_occurs=1,
                 max_occurs=1,
                 metadata=[],
                 default=None,
                 default_type=SOURCE_TYPE.DATA):
        BasicIO.__init__(self, identifier, title, abstract, keywords,
                         min_occurs, max_occurs, metadata)
        BasicLiteral.__init__(self, data_type, uoms)
        SimpleHandler.__init__(self, workdir, data_type, mode=mode)

        if default_type != SOURCE_TYPE.DATA:
            raise InvalidParameterValue(
                "Source types other than data are not supported.")

        self.any_value = is_anyvalue(allowed_values)
        self.allowed_values = []
        if not self.any_value:
            self.allowed_values = make_allowedvalues(allowed_values)

        self._default = default
        self._default_type = default_type

        if default is not None:
            self.data = default
Beispiel #10
0
    def _handler(request, response):
        model = request.inputs['model'][0].data
        variable = request.inputs['variable'][0].data

        # Throw manually with temporary bbox solution
        if request.inputs['min_lon'][0].data < 0:
            raise InvalidParameterValue(
                'Minimum longitude input cannot be below 0')
        if request.inputs['max_lon'][0].data > 360:
            raise InvalidParameterValue(
                'Maximum longitude input cannot be above 360')
        if request.inputs['min_lat'][0].data < -90:
            raise InvalidParameterValue(
                'Minimum latitude input cannot be below -90')
        if request.inputs['max_lat'][0].data > 90:
            raise InvalidParameterValue(
                'Minimum latitude input cannot be above 90')

        d1 = cftime.Datetime360Day(2010, 1, 1)
        d2 = cftime.Datetime360Day(2020, 1, 1)

        nc_files_path = f'xarray'
        files_path = os.path.join(str(Path.home()), nc_files_path)
        files = glob.glob(files_path + '/tas*.nc')

        #response.update_status("Reading through files", 10)
        files_to_open = get_years(files)
        new_dataset = open_mfdatasets(files_to_open)
        #response.update_status("Calculating temporal average", 50)

        sliced_dataset = new_dataset.sel(
            time=slice(d1, d2),
            lon=slice(request.inputs['min_lon'][0].data,
                      request.inputs['max_lon'][0].data),
            lat=slice(request.inputs['min_lat'][0].data,
                      request.inputs['max_lat'][0].data))
        # calculate temporal average across the time axis only
        mean_array = sliced_dataset.mean(dim='time')
        print(mean_array)
        response.update_status("Writing results to a new NetCDF4 file", 50)
        # result_nc_file = mean_array.to_netcdf('results.nc')

        response.outputs['output'].nc_file = mean_array.to_netcdf(
            'resultsssss.nc')
        response.update_status("Done.", 100)
        return response
Beispiel #11
0
    def _check_valid(self):
        """Validate this input usig given validator
        """

        validate = self.validator
        _valid = validate(self, self.valid_mode)
        if not _valid:
            raise InvalidParameterValue('Input data not valid using '
                                        'mode %s' % (self.valid_mode))
Beispiel #12
0
def convert_positiveInteger(inpt):
    """Return value of input"""

    inpt = convert_integer(inpt)
    if inpt < 0:
        raise InvalidParameterValue(
            'The value "{}" is not of type positiveInteger'.format(inpt))
    else:
        return inpt
Beispiel #13
0
    def _check_valid(self):
        """Validate this input using given validator
        """

        validate = self.validator
        _valid = validate(self, self.valid_mode)
        if not _valid:
            self.data_set = False
            raise InvalidParameterValue('Input data not valid using '
                                        'mode {}'.format(self.valid_mode))
        self.data_set = True
Beispiel #14
0
    def check_and_set_language(self, language):
        """set this.language
        """

        if not language:
            language = 'None'
        elif language != 'en-US':
            raise InvalidParameterValue(
                'The requested language "{}" is not supported by this server'.format(language), 'language')
        else:
            self.language = language
Beispiel #15
0
def input_from_json(json_data):
    if json_data['type'] == 'complex':
        inpt = ComplexInput.from_json(json_data)
    elif json_data['type'] == 'literal':
        inpt = LiteralInput.from_json(json_data)
    elif json_data['type'] == 'bbox':
        inpt = BoundingBoxInput.from_json(json_data)
    else:
        raise InvalidParameterValue("Input type not recognized: {}".format(json_data['type']))

    return inpt
Beispiel #16
0
 def data_format(self, data_format):
     """self data_format setter
     """
     if self._is_supported(data_format):
         self._data_format = data_format
         if not data_format.validate or data_format.validate == emptyvalidator:
             data_format.validate = get_validator(data_format.mime_type)
     else:
         raise InvalidParameterValue(
             "Requested format {}, {}, {} not supported".format(
                 data_format.mime_type, data_format.encoding,
                 data_format.schema), 'mimeType')
Beispiel #17
0
def convert_anyURI(inpt):
    """Return value of input

    :rtype: url components
    """
    inpt = convert_string(inpt)
    components = urlparse.urlparse(inpt)

    if components[0] and components[1]:
        return components
    else:
        raise InvalidParameterValue(
            'The value "{}" does not seem to be of type anyURI'.format(inpt))
    def _handler(request, response):
        model = request.inputs['model'][0].data
        variable = request.inputs['variable'][0].data

        # Throw manually with temporary bbox solution
        if request.inputs['min_lon'][0].data < 0:
            raise InvalidParameterValue('Minimum longitude input cannot be below 0')
        if request.inputs['max_lon'][0].data > 360:
            raise InvalidParameterValue('Maximum longitude input cannot be above 360')
        if request.inputs['min_lat'][0].data < -90:
            raise InvalidParameterValue('Minimum latitude input cannot be below -90')
        if request.inputs['max_lat'][0].data > 90:
            raise InvalidParameterValue('Minimum latitude input cannot be above 90')

        d1 = cftime.Datetime360Day(2010, 1, 1)
        d2 = cftime.Datetime360Day(2020, 1, 1)

        glob_pattern = f'/badc/cmip5/data/cmip5/output1/MOHC/{model}/rcp45/mon/atmos/Amon/r1i1p1/latest/{variable}/*.nc'
        files = glob.glob(glob_pattern)

        files_to_open = get_years(files)
        new_dataset = open_mfdatasets(files_to_open)

        sliced_dataset = new_dataset.sel(time=slice(d1, d2), lon=slice(request.inputs['min_lon'][0].data,
                                                                    request.inputs['max_lon'][0].data),
                                                            lat=slice(request.inputs['min_lat'][0].data,
                                                                    request.inputs['max_lat'][0].data))
        # calculate temporal average across the time axis only
        mean_array = sliced_dataset.mean(dim='time')
        print(mean_array)
        response.update_status("Writing results to a new NetCDF4 file", 50)
        
        output_path = '/tmp/output.nc'
        response.outputs['output'].nc_file = mean_array.to_netcdf(output_path)
        print(f'Wrote: {output_path}')
        response.update_status("Done.", 100)
        return response
Beispiel #19
0
 def prepare_process_for_execution(self, identifier):
     """Prepare the process identified by ``identifier`` for execution.
     """
     try:
         process = self.processes[identifier]
     except KeyError:
         raise InvalidParameterValue("Unknown process '{}'".format(identifier), 'Identifier')
     # make deep copy of the process instace
     # so that processes are not overriding each other
     # just for execute
     process = copy.deepcopy(process)
     process.service = self
     workdir = os.path.abspath(config.get_config_value('server', 'workdir'))
     tempdir = tempfile.mkdtemp(prefix='pywps_process_', dir=workdir)
     process.set_workdir(tempdir)
     return process
Beispiel #20
0
    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)
Beispiel #21
0
 def describe(self, identifiers):
     identifier_elements = []
     # 'all' keyword means all processes
     if 'all' in (ident.lower() for ident in identifiers):
         for process in self.processes:
             identifier_elements.append(
                 self.processes[process].describe_xml())
     else:
         for identifier in identifiers:
             try:
                 process = self.processes[identifier]
             except KeyError:
                 raise InvalidParameterValue(
                     "Unknown process %r" % identifier, "identifier")
             else:
                 identifier_elements.append(process.describe_xml())
     doc = WPS.ProcessDescriptions(*identifier_elements)
     return xml_response(doc)
Beispiel #22
0
    def json(self):

        processes = []

        if 'all' in (ident.lower() for ident in self.identifiers):
            processes = (self.processes[p].json for p in self.processes)
        else:
            for identifier in self.identifiers:
                if identifier not in self.processes:
                    msg = "Unknown process {}".format(identifier)
                    raise InvalidParameterValue(msg, "identifier")
                else:
                    processes.append(self.processes[identifier].json)

        return {
            'pywps_version': __version__,
            'processes': processes,
            'lang': 'en-US'
        }
Beispiel #23
0
    def check_and_set_language(self, language):
        """set this.language
        """
        supported_languages = configuration.get_config_value(
            'server', 'language').split(',')
        supported_languages = [lang.strip() for lang in supported_languages]

        if not language:
            # default to the first supported language
            language = supported_languages[0]

        if language not in supported_languages:
            raise InvalidParameterValue(
                'The requested language "{}" is not supported by this server'.
                format(language),
                'language',
            )

        self.language = language
Beispiel #24
0
    def __init__(self,
                 identifier,
                 title=None,
                 abstract=None,
                 keywords=None,
                 data_type="integer",
                 workdir=None,
                 allowed_values=None,
                 uoms=None,
                 mode=MODE.NONE,
                 min_occurs=1,
                 max_occurs=1,
                 metadata=[],
                 default=None,
                 default_type=SOURCE_TYPE.DATA):
        BasicIO.__init__(self, identifier, title, abstract, keywords,
                         min_occurs, max_occurs, metadata)
        BasicLiteral.__init__(self, data_type, uoms)
        SimpleHandler.__init__(self, workdir, data_type, mode=mode)

        if default_type != SOURCE_TYPE.DATA:
            raise InvalidParameterValue(
                "Source types other than data are not supported.")

        self.any_value = False
        self.values_reference = None
        self.allowed_values = []

        if allowed_values:
            if not isinstance(allowed_values, (tuple, list)):
                allowed_values = [allowed_values]
            self.any_value = any(is_anyvalue(a) for a in allowed_values)
            for value in allowed_values:
                if is_values_reference(value):
                    self.values_reference = value
                    break
            self.allowed_values = make_allowedvalues(allowed_values)

        self._default = default
        self._default_type = default_type

        if default is not None:
            self.data = default
Beispiel #25
0
    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
Beispiel #26
0
    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
Beispiel #27
0
    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)
Beispiel #28
0
    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
Beispiel #29
0
    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
Beispiel #30
0
    def _post_request_parser(self, tagname):
        """Factory function returing propper parsing function
        """

        wpsrequest = self

        def parse_post_getcapabilities(doc):
            """Parse POST GetCapabilities request
            """
            acceptedversions = self.xpath_ns(
                doc, '/wps:GetCapabilities/ows:AcceptVersions/ows:Version')
            acceptedversions = ','.join(
                map(lambda v: v.text, acceptedversions))
            wpsrequest.check_accepted_versions(acceptedversions)

        def parse_post_describeprocess(doc):
            """Parse POST DescribeProcess 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 = 'describeprocess'
            wpsrequest.identifiers = [identifier_el.text for identifier_el in
                                      self.xpath_ns(doc, './ows:Identifier')]

        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 = self.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 self.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 = self.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')

        if tagname == self.WPS.GetCapabilities().tag:
            self.operation = 'getcapabilities'
            return parse_post_getcapabilities
        elif tagname == self.WPS.DescribeProcess().tag:
            self.operation = 'describeprocess'
            return parse_post_describeprocess
        elif tagname == self.WPS.Execute().tag:
            self.operation = 'execute'
            return parse_post_execute
        else:
            raise InvalidParameterValue(
                'Unknown request {}'.format(tagname), 'request')