def parse_point_input( param: QgsProcessingParameterDefinition, kwargs) -> ComplexInput: """ Convert processing point input to complex input """ if isinstance(param, QgsProcessingParameterPoint): kwargs['supported_formats'] = [Format.from_definition(FORMATS.GEOJSON), Format.from_definition(FORMATS.GML)] return ComplexInput(**kwargs)
def test_format_class(): """Test pyqgiswps.formats.Format class """ frmt = Format('mimetype', schema='halloworld', encoding='asdf', validate=validate) assert frmt.mime_type == 'mimetype' assert frmt.schema == 'halloworld' assert frmt.encoding == 'asdf' assert frmt.validate('the input', 1) describeel = frmt.describe_xml() assert 'Format' == describeel.tag mimetype = xpath_ns(describeel, '/Format/MimeType') encoding = xpath_ns(describeel, '/Format/Encoding') schema = xpath_ns(describeel, '/Format/Schema') assert mimetype assert encoding assert schema assert mimetype[0].text == 'mimetype' assert encoding[0].text == 'asdf' assert schema[0].text == 'halloworld' frmt2 = get_format('GML') assert not frmt.same_as(frmt2)
def parse_layer_output(outdef: QgsProcessingOutputDefinition, kwargs) -> ComplexOutput: """ Parse layer output A layer output is merged to a qgis project, we return the wms uri associated to the project """ if isinstance(outdef, OUTPUT_LAYER_TYPES): if isinstance(outdef, QgsProcessingOutputVectorLayer): return ComplexOutput(supported_formats=[ Format("application/x-ogc-wms"), Format("application/x-ogc-wfs") ], as_reference=True, **kwargs) elif isinstance(outdef, QgsProcessingOutputRasterLayer): return ComplexOutput(supported_formats=[ Format("application/x-ogc-wms"), Format("application/x-ogc-wcs") ], as_reference=True, **kwargs) else: return ComplexOutput( supported_formats=[Format("application/x-ogc-wms")], as_reference=True, **kwargs)
def parse_file_output( outdef: QgsProcessingOutputDefinition, kwargs, alg: QgsProcessingAlgorithm=None ) -> ComplexOutput: """ Parse file output definition QgsProcessingOutputDefinition metadata will be checked to get wps parameter settings: - 'wps:as_reference': boolean, True if the file will be sent as reference. If false, the file will included in the body of the response. Default is True. """ as_reference = confservice.getboolean('server','outputfile_as_reference') if isinstance(outdef, QgsProcessingOutputHtml): mime = mimetypes.types_map.get('.html') return ComplexOutput(supported_formats=[Format(mime)],**kwargs) elif isinstance(outdef, QgsProcessingOutputFile): # Try to get a corresponding inputFileDefinition # See https://qgis.org/pyqgis/master/core/QgsProcessingParameterFileDestination.html mime = None if alg: inputdef = alg.parameterDefinition(outdef.name()) if isinstance(inputdef, QgsProcessingParameterFileDestination): mime = mimetypes.types_map.get("."+inputdef.defaultFileExtension()) as_reference = inputdef.metadata().get('wps:as_reference',as_reference) if mime is None: LOGGER.warning("Cannot set file type for output %s", outdef.name()) mime = "application/octet-stream" return ComplexOutput(supported_formats=[Format(mime)], as_reference=as_reference, **kwargs)
def parse_input_definition(param: QgsProcessingParameterDefinition, kwargs, context: MapContext = None) -> WPSInput: """ Convert processing input to File Input """ typ = param.type() if typ == 'crs': kwargs['data_type'] = 'string' return LiteralInput(**kwargs) elif typ == "extent": return parse_extent_input(param, kwargs, context) elif isinstance(param, GeometryParameterTypes): kwargs['supported_formats'] = [ Format.from_definition(FORMATS.GEOJSON), Format.from_definition(FORMATS.GML), Format.from_definition(FORMATS.WKT) ] if isinstance(param, QgsProcessingParameterGeometry): # Add metadata from requiered geometryTypes kwargs['metadata'].extend( Metadata('processing:geometryType', QgsWkbTypes.geometryDisplayString(geomtype)) \ for geomtype in param.geometryTypes() ) if param.allowMultipart(): kwargs['metadata'].append( Metadata('processing:allowMultipart')) return ComplexInput(**kwargs) return None
def test_complex_output_href(): """ Test external reference in complex output """ kwargs = { 'identifier': 'hreftest', 'title': '', 'abstract': '', } output = ComplexOutput(supported_formats=[ Format("application/x-ogc-wms"), Format("application/x-ogc-wfs") ], as_reference=True, **kwargs) output.output_format = "application/x-ogc-wms" output.url = "http://my.org/external/ref" output_elements = output.execute_xml() # Check that <wps:Reference href=...> is not namspaced element = output_elements.xpath( '//wps:Reference', namespaces={'wps': "http://www.opengis.net/wps/1.0.0"}) assert len(element) == 1 assert 'href' in element[0].attrib
def test_complex_input_default_and_supported(): complex_in = ComplexInput('foo', 'Complex foo', supported_formats=[Format('a/b'), Format('c/d')]) doc = complex_in.describe_xml() [default_format] = xpath_ns(doc, './ComplexData/Default/Format') [default_mime_el] = xpath_ns(default_format, './MimeType') assert default_mime_el.text == 'a/b' supported_mime_types = [] for supported_el in xpath_ns(doc, './ComplexData/Supported/Format'): [mime_el] = xpath_ns(supported_el, './MimeType') supported_mime_types.append(mime_el.text) assert supported_mime_types == ['a/b', 'c/d']
def test_geometry_script(outputdir, data): """ Test geometry script """ alg = _find_algorithm('script:testinputgeometry') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inp = inputs['INPUT'][0] inp.data_format = Format.from_definition(FORMATS.WKT) inp.data = 'CRS=EPSG:4326;MULTIPOINT((3.5 5.6), (4.8 10.5))' # Load source project source = QgsProject() rv = source.read(str(data/'france_parts.qgs')) assert rv == True context = Context(source, outputdir) feedback = QgsProcessingFeedback() parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() ) # Check marshalled value value = parameters['INPUT'] assert isinstance( value, QgsReferencedGeometry ) assert value.wkbType() == QgsWkbTypes.MultiPoint context.wms_url = "http://localhost/wms/?MAP=test/{name}.qgs".format(name=alg.name()) # Run algorithm with chdir(outputdir): results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context, outputs=outputs) out = json.loads(outputs.get('OUTPUT').data) assert out['type'] == 'MultiPoint'
def parse_file_input(param: QgsProcessingParameterDefinition, kwargs) -> Union[LiteralInput, ComplexInput]: """ Input is file """ typ = param.type() if typ == 'file': if param.behavior() == QgsProcessingParameterFile.Folder: kwargs['data_type'] = 'string' return LiteralInput(**kwargs) ext = param.extension() if ext: mime = mimetypes.types_map.get(param.extension()) if mime is not None: kwargs['supported_formats'] = [Format(mime)] kwargs['metadata'].append( Metadata('processing:extension', param.extension())) return ComplexInput(**kwargs) elif typ == 'fileDestination': extension = '.' + param.defaultFileExtension() kwargs['data_type'] = 'string' kwargs['metadata'].append( Metadata('processing:format', mimetypes.types_map.get(extension, ''))) return LiteralInput(**kwargs) elif typ == 'folderDestination': kwargs['data_type'] = 'string' return LiteralInput(**kwargs)
def test_complex_input_identifier(): complex_in = ComplexInput('foo', 'Complex foo', supported_formats=[Format('bar/baz')]) doc = complex_in.describe_xml() assert doc.tag == E.Input().tag [identifier_el] = xpath_ns(doc, './ows:Identifier') assert identifier_el.text == 'foo'
def test_json_in(): """Test json import """ injson = {} injson['schema'] = 'elcepelce' injson['extension'] = '.gml' injson['mime_type'] = 'application/gml+xml' injson['encoding'] = 'utf-8' frmt = Format(injson['mime_type']) frmt.json = injson assert injson['schema'] == frmt.schema assert injson['extension'] == frmt.extension assert injson['mime_type'] == frmt.mime_type assert injson['encoding'] == frmt.encoding
def test_complex_output(): complexo = ComplexOutput('complex', 'Complex foo', [Format('GML')]) doc = complexo.describe_xml() [outpt] = xpath_ns(doc, '/Output') [default] = xpath_ns(doc, '/Output/ComplexOutput/Default/Format/MimeType') supported = xpath_ns(doc, '/Output/ComplexOutput/Supported/Format/MimeType') assert default.text == 'application/gml+xml' assert len(supported) == 1
def parse_file_output(outdef: QgsProcessingOutputDefinition, kwargs, alg: QgsProcessingAlgorithm = None) -> ComplexOutput: """ Parse file output definition """ if isinstance(outdef, QgsProcessingOutputHtml): mime = mimetypes.types_map.get('.html') return ComplexOutput(supported_formats=[Format(mime)], **kwargs) elif isinstance(outdef, QgsProcessingOutputFile): # Try to get a corresponding inputFileDefinition mime = None if alg: inputdef = alg.parameterDefinition(outdef.name()) if isinstance(inputdef, QgsProcessingParameterFileDestination): mime = mimetypes.types_map.get("." + inputdef.defaultFileExtension()) if mime is None: LOGGER.warning("Cannot set file type for output %s", outdef.name()) mime = "application/octet-stream" return ComplexOutput(supported_formats=[Format(mime)], **kwargs)
def test_point_input_wkt(): """ Test input point from wkt """ param = QgsProcessingParameterPoint("POINT") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.WKT) inp.data = 'CRS=EPSG:4326;POINT(6 10)' assert inp.data_format.mime_type == FORMATS.WKT.mime_type value = geometryio.input_to_point( inp ) assert isinstance( value, QgsReferencedPointXY )
def test_point_input_json(): """ Test input point from json """ param = QgsProcessingParameterPoint("POINT") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.GEOJSON) inp.data = '{"coordinates":[4.0,42.0],"type":"Point"}' assert inp.data_format.mime_type == FORMATS.GEOJSON.mime_type value = geometryio.input_to_point( inp ) assert isinstance( value, QgsGeometry )
def parse_response(value: Any, outdef: QgsProcessingOutputDefinition, out: WPSOutput, context: ProcessingContext) -> Optional[WPSOutput]: """ Map processing output to WPS """ if isinstance(outdef, QgsProcessingOutputHtml): out.output_format = mimetypes.types_map['.html'] return to_output_file(value, out, context) elif isinstance(outdef, QgsProcessingOutputFile): _, sfx = os.path.splitext(value) mime = mimetypes.types_map.get(sfx.lower()) LOGGER.debug("Return output file '%s' with mime type '%s'", value, mime) if mime is None: mime = "application/octet-stream" out.data_format = Format(mime) return to_output_file(value, out, context)
def test_point_input_gml(): """ Test input point from gml """ param = QgsProcessingParameterPoint("POINT") inp = parse_input_definition(param) assert isinstance(inp, ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.GML) inp.data = '<gml:Point srsName="EPSG:4326"><gml:coordinates>4,42</gml:coordinates></gml:Point>' assert inp.data_format.mime_type == FORMATS.GML.mime_type value = input_to_point(inp) assert isinstance(value, (QgsGeometry, QgsReferencedPointXY))
def test_multipoint_input_json(): """ Test input point from json """ param = QgsProcessingParameterPoint("GEOM") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.GEOJSON) inp.data = '{"coordinates":[[10, 40], [40, 30], [20, 20], [30, 10]],"type":"MultiPoint"}' assert inp.data_format.mime_type == FORMATS.GEOJSON.mime_type value = geometryio.input_to_geometry( inp ) assert isinstance( value, QgsGeometry ) assert value.wkbType() == QgsWkbTypes.MultiPoint
def test_multipoint_input_wkt(): """ Test input point from gml """ param = QgsProcessingParameterPoint("GEOM") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.WKT) inp.data = 'CRS=EPSG:4326;MULTIPOINT((3.5 5.6), (4.8 10.5))' assert inp.data_format.mime_type == FORMATS.WKT.mime_type value = geometryio.input_to_geometry( inp ) assert isinstance( value, QgsReferencedGeometry ) assert value.wkbType() == QgsWkbTypes.MultiPoint
def test_nocrs_input_wkt(): """ Test input point from wkt """ param = QgsProcessingParameterPoint("POINT") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.WKT) inp.data = 'POINT(6 10)' assert inp.data_format.mime_type == FORMATS.WKT.mime_type value = geometryio.input_to_point( inp ) assert isinstance( value, QgsGeometry ) assert value.wkbType() == QgsWkbTypes.Point
def parse_response(value: Any, outdef: QgsProcessingOutputDefinition, out: WPSOutput, context: QgsProcessingContext) -> Optional[WPSOutput]: """ Process processing response to WPS output """ if not isinstance(outdef, OUTPUT_LAYER_TYPES): return out.data_format = Format("application/x-ogc-wms") output_url = context.wms_url result = add_layer_to_load_on_completion(value, outdef, context) if result: result = ','.join(result) out.url = output_url + '&' + urlencode((('layers', result), )) else: out.url = output_url return out
def test_linestring_input_gml(): """ Test input point from gml """ param = QgsProcessingParameterGeometry("GEOM") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.GML) inp.data = ('<gml:LineString srsName="EPSG:4326">' '<gml:coordinates>45.67,88.56 55.56,89.44</gml:coordinates>' '</gml:LineString>') assert inp.data_format.mime_type == FORMATS.GML.mime_type value = geometryio.input_to_geometry( inp ) assert isinstance( value, QgsReferencedGeometry ) assert value.wkbType() == QgsWkbTypes.LineString
def test_geometry_crs_json(): """ Test passing crs from json """ param = QgsProcessingParameterGeometry("GEOM") inp = parse_input_definition(param) assert isinstance(inp,ComplexInput) assert inp.as_reference == False inp.data_format = Format.from_definition(FORMATS.GEOJSON) inp.data = ('{ "geometry": {"coordinates":[445277.96, 5160979.44],"type":"Point"},' ' "crs": { ' ' "type": "name", ' ' "properties": { "name": "EPSG:3785" }' '}}') assert inp.data_format.mime_type == FORMATS.GEOJSON.mime_type value = geometryio.input_to_geometry( inp ) assert isinstance( value, QgsReferencedGeometry ) assert value.crs().authid() == "EPSG:3785" assert value.wkbType() == QgsWkbTypes.Point
def json(self, value): """init this request from json back again :param value: the json (not string) representation """ self.operation = value['operation'] self.version = value['version'] self.language = value['language'] self.identifiers = value['identifiers'] self.store_execute = value['store_execute'] self.status = value['store_execute'] self.lineage = value['lineage'] self.outputs = value['outputs'] self.raw = value['raw'] self.inputs = {} for identifier in value['inputs']: inpt = None inpt_defs = value['inputs'][identifier] for inpt_def in inpt_defs: if inpt_def['type'] == 'complex': inpt = ComplexInput( identifier=inpt_def['identifier'], title=inpt_def.get('title'), abstract=inpt_def.get('abstract'), data_format=Format( schema=inpt_def['data_format'].get('schema'), extension=inpt_def['data_format'].get('extension'), mime_type=inpt_def['data_format']['mime_type'], encoding=inpt_def['data_format'].get('encoding')), supported_formats=[ Format(schema=infrmt.get('schema'), extension=infrmt.get('extension'), mime_type=infrmt['mime_type'], encoding=infrmt.get('encoding')) for infrmt in inpt_def['supported_formats'] ], mode=MODE.NONE) inpt.file = inpt_def['file'] elif inpt_def['type'] == 'literal': allowed_values = [] for allowed_value in inpt_def['allowed_values']: if allowed_value['type'] == 'anyvalue': allowed_values.append(AnyValue()) elif allowed_value['type'] == 'novalue': allowed_values.append(NoValue()) elif allowed_value['type'] == 'valuesreference': allowed_values.append(ValuesReference()) elif allowed_value['type'] == 'allowedvalue': allowed_values.append( AllowedValue( allowed_type=allowed_value['allowed_type'], value=allowed_value['value'], minval=allowed_value['minval'], maxval=allowed_value['maxval'], spacing=allowed_value['spacing'], range_closure=allowed_value[ 'range_closure'])) inpt = LiteralInput(identifier=inpt_def['identifier'], title=inpt_def.get('title'), abstract=inpt_def.get('abstract'), data_type=inpt_def.get('data_type'), allowed_values=AnyValue, uoms=inpt_def.get('uoms'), mode=inpt_def.get('mode')) inpt.uom = inpt_def.get('uom') inpt.data = inpt_def.get('data') elif inpt_def['type'] == 'bbox': inpt = BBoxInput(identifier=inpt_def['identifier'], title=inpt_def['title'], abstract=inpt_def['abstract'], crss=inpt_def['crs'], dimensions=inpt_def['dimensions'], mode=inpt_def['mode']) inpt.ll = inpt_def['bbox'][0] inpt.ur = inpt_def['bbox'][1] if identifier in self.inputs: self.inputs[identifier].append(inpt) else: self.inputs[identifier] = [inpt]
# Map processing source types to string SourceTypes = { QgsProcessing.TypeMapLayer: 'TypeMapLayer', QgsProcessing.TypeVectorAnyGeometry: 'TypeVectorAnyGeometry', QgsProcessing.TypeVectorPoint: 'TypeVectorPoint', QgsProcessing.TypeVectorLine: 'TypeVectorLine', QgsProcessing.TypeVectorPolygon: 'TypeVectorPolygon', QgsProcessing.TypeRaster: 'TypeRaster', QgsProcessing.TypeFile: 'TypeFile', QgsProcessing.TypeVector: 'TypeVector', QgsProcessing.TypeMesh: 'TypeMesh', } # Allowed inputs formats RASTER_INPUT_FORMATS = (Format.from_definition(FORMATS.NETCDF), Format.from_definition(FORMATS.GEOTIFF)) VECTOR_INPUT_FORMATS = (Format.from_definition(FORMATS.GEOJSON), Format.from_definition(FORMATS.GML), Format.from_definition(FORMATS.SHP)) # ------------------------------------ # Processing parameters -> WPS input # ------------------------------------ def get_layers_type(param: QgsProcessingParameterDefinition, kwargs) -> None: """ Set datatype as metadata """ datatypes = []
def get_data_format(mime_type): return Format(mime_type=mime_type, validate=get_validator(mime_type))