Ejemplo n.º 1
0
 def _write_response_doc(self, request_uuid, doc):
     """ Write response document
     """
     try:
         logstore.write_response(request_uuid, doc)
     except IOError as e:
         raise NoApplicableCode(
             'Writing Response Document failed with : %s' % e, code=500)
Ejemplo n.º 2
0
 def get_processes_for_request(self, idents: Iterable[str], 
                               map_uri: Optional[str]=None) -> Iterable[WPSProcess]:
     try:
         return self.get_processes(idents, map_uri)
     except UnknownProcessError as exc:
         raise InvalidParameterValue("Unknown process %s" % exc, "identifier") from None
     except Exception as e:
         LOGGER.critical("Exception:\n%s",traceback.format_exc())
         raise NoApplicableCode(str(e), code=500) from None
Ejemplo n.º 3
0
def parse_layer_spec(layerspec: str,
                     context: ProcessingContext,
                     allow_selection: bool = False) -> Tuple[str, bool]:
    """ Parse a layer specification

        if allow_selection is set to True: 'select' parameter
        is interpreted has holding a qgis feature request expression

        :return: A tuple (path, bool)
    """
    u = urlparse(layerspec)
    p = u.path
    if u.scheme == 'file':
        p = context.resolve_path(p)
    elif u.scheme and u.scheme != 'layer':
        raise InvalidParameterValue("Bad scheme: %s" % layerspec)

    if not allow_selection:
        return p, False

    has_selection = False
    qs = parse_qs(u.query)
    feat_requests = qs.get('select', [])
    feat_rects = qs.get('rect', [])
    if feat_rects or feat_requests:
        has_selection = True
        layer = context.getMapLayer(p)
        if not layer:
            LOGGER.error("No layer path for url %s", u)
            raise InvalidParameterValue("No layer '%s' found" % u.path, )

        if layer.type() != QgsMapLayer.VectorLayer:
            LOGGER.warning("Can apply selection only to vector layer")
        else:
            behavior = QgsVectorLayer.SetSelection
            try:
                LOGGER.debug("Applying features selection: %s", qs)
                # Apply filter rect first
                if feat_rects:
                    rect = QgsRectangle(feat_rects[-1].split(',')[:4])
                    layer.selectByRect(rect, behavior=behavior)
                    behavior = QgsVectorLayer.IntersectSelection
                # Selection by expressions
                if feat_requests:
                    ftreq = feat_requests[-1]
                    layer.selectByExpression(ftreq, behavior=behavior)
            except:
                LOGGER.error(traceback.format_exc())
                raise NoApplicableCode("Feature selection failed")
    return p, has_selection
Ejemplo n.º 4
0
def input_to_geometry(inp: WPSInput) -> Geometry:
    """ Handle point from complex input
    """
    data_format = inp.data_format

    if data_format.mime_type == FORMATS.WKT.mime_type:
        return wkt_to_geometry(inp.data)

    elif data_format.mime_type == FORMATS.GEOJSON.mime_type:
        return json_to_geometry(inp.data)

    elif data_format.mime_type == FORMATS.GML.mime_type:
        return gml_to_geometry(inp.data)

    raise NoApplicableCode("Unsupported data format: %s" % data_format)
Ejemplo n.º 5
0
def input_to_point( inp: WPSInput ):
    """ Handle point from complex input
    """
    data_format = inp.data_format
    geom = None
    if data_format.mime_type == FORMATS.GEOJSON.mime_type:
        geom = ogr.CreateGeometryFromJson(inp.data)
    elif data_format.mime_type == FORMATS.GML.mime_type:
        geom = ogr.CreateGeometryFromGML(inp.data)
 
    if geom:
        srs  = geom.GetSpatialReference()
        geom = QgsGeometry.fromWkt(geom.ExportToWkt())
        if srs:
            srs = QgsCoordinateReferenceSystem.fromWkt(srs.ExportToWkt())
        if srs and srs.isValid():
            geom = QgsReferencedPointXY( geom.centroid().asPoint(), srs )
            
        return geom

    raise NoApplicableCode("Unsupported data format: %s" % data_format)
Ejemplo n.º 6
0
def openurl(url: str,
            filename: os.PathLike,
            max_bytes: int = 0,
            **kwargs) -> None:
    """ Open url
    """
    LOGGER.info("Fetching URL %s", url)

    num_bytes = 0
    fail = False
    try:
        with open(filename, 'wb') as fh:

            def _callback(chunk: bytes) -> None:
                nonlocal num_bytes
                num_bytes += len(chunk)
                if num_bytes > max_bytes:
                    raise FileSizeExceeded(
                        'File size for input exceeded for ref %s', url)
                fh.write(chunk)

            client = httpclient.HTTPClient()
            try:
                client.fetch(url,
                             user_agent=USER_AGENT,
                             streaming_callback=_callback,
                             **kwargs)
            except Exception as e:
                fail = True
                raise NoApplicableCode("File Reference error %s: %s", url,
                                       str(e)) from None
            finally:
                client.close()
    finally:
        if fail and os.path.exists(filename):
            os.unlink(filename)
Ejemplo n.º 7
0
    def get_results(self, uuid: str) -> Any:
        doc = self.executor.get_results(uuid)
        if doc is None:
            raise NoApplicableCode('No results found for %s' % uuid, code=404)

        return doc
Ejemplo n.º 8
0
##################################################################
# Copyright 2016 OSGeo Foundation,                               #
# represented by PyWPS Project Steering Committee,               #
# licensed under MIT, Please consult LICENSE.txt for details     #
##################################################################

try:
    from osgeo import gdal, ogr
except ImportError as err:
    from pyqgiswps.exceptions import NoApplicableCode
    raise NoApplicableCode('Complex validation requires GDAL/OGR support')
Ejemplo n.º 9
0
    def parse_post_request(handler):
        """Factory function returing propper parsing function
        """
        try:
            doc = lxml.etree.fromstring(handler.request.body)
        except Exception as e:
            raise NoApplicableCode(e.msg)

        wpsrequest = WPSRequest()

        tagname = doc.tag

        def parse_post_getcapabilities():
            """Parse POST GetCapabilities request
            """
            acceptedversions = 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():
            """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 xpath_ns(doc, './ows:Identifier')
            ]

        def parse_post_execute():
            """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')
                # XXX If storeExecuteResponse is set then we enforce
                # the status supports
                wpsrequest.status = wpsrequest.store_execute
                # Set timeout
                timeout = response_document[0].attrib.get('timeout')
                wpsrequest.check_and_set_timeout(timeout)
                # Set expiration
                expire = response_document[0].attrib.get('expire')
                wpsrequest.check_and_set_expiration(expire)

        if tagname == WPS.GetCapabilities().tag:
            wpsrequest.operation = 'getcapabilities'
            parse_post_getcapabilities()
        elif tagname == WPS.DescribeProcess().tag:
            wpsrequest.operation = 'describeprocess'
            parse_post_describeprocess()
        elif tagname == WPS.Execute().tag:
            wpsrequest.operation = 'execute'
            parse_post_execute()
        else:
            raise InvalidParameterValue('Unknown request %r' % tagname,
                                        'request')

        # Return the created WPSRequest object
        return wpsrequest
Ejemplo n.º 10
0
    async def execute(self, wps_request, wps_response):
        """ Execute a process

            :return: wps_response or None
        """
        process = wps_response.process
        process.uuid = wps_response.uuid

        # Start request
        logstore.log_request(process.uuid, wps_request)

        # Check if we need no store the response
        wps_response.store = (wps_response.status >= STATUS.STORE_STATUS)

        # Get request defined timeout
        timeout = wps_request.timeout

        apply_future = self._pool.apply_async(self._run_process,
                                              args=(process.handler,
                                                    wps_request, wps_response),
                                              timeout=timeout)

        if wps_response.status == STATUS.STORE_AND_UPDATE_STATUS:
            # ---------------------------------
            # Run the processe asynchronously
            # ---------------------------------
            async def do_execute_async():
                # Handle errors while we are going async
                try:
                    await apply_future
                except asyncio.TimeoutError:
                    wps_response.update_status("Timeout Error", None,
                                               STATUS.ERROR_STATUS)
                except MaxRequestsExceeded:
                    wps_response.update_status(
                        "Server busy, please retry later", None,
                        STATUS.ERROR_STATUS)
                except Exception:
                    # There is no point to let the error go outside
                    LOGGER.error(traceback.format_exc())
                    wps_response.update_status("Internal Error", None,
                                               STATUS.ERROR_STATUS)
                    pass

            # Fire and forget
            asyncio.ensure_future(do_execute_async())

            wps_response.update_status('Task accepted')
            return wps_response.document
        else:
            # -------------------------------
            # Run process and wait for response
            # -------------------------------
            try:
                return await apply_future
            except asyncio.TimeoutError:
                wps_response.update_status("Timeout Error", None,
                                           STATUS.ERROR_STATUS)
                raise NoApplicableCode("Execute Timeout", code=424)
            except MaxRequestsExceeded:
                raise NoApplicableCode("Server busy, please retry later",
                                       code=509)
            except RequestBackendError as e:
                if isinstance(e.response, ProcessException):
                    raise NoApplicableCode("Process Error", code=424)
                else:
                    raise