def test_optional_inputs(): not_optional_param = QgsProcessingParameterNumber( "TEST1", "LiteralInteger", type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=10) assert not _is_optional(not_optional_param) optional_param = QgsProcessingParameterNumber( "TEST2", "LiteralInteger", type=QgsProcessingParameterNumber.Integer, optional=True, minValue=1, defaultValue=10) assert _is_optional(optional_param) optional_input = parse_input_definition(optional_param) not_optional_input = parse_input_definition(not_optional_param) assert optional_input.min_occurs == 0 assert not_optional_input.min_occurs > 0
def test_bbox_input(): """ Test extent parameter """ param = QgsProcessingParameterExtent("BBOX") inp = parse_input_definition(param) assert isinstance(inp,BoundingBoxInput) assert inp.crss[0] == "EPSG:4326" inp.data = ['15', '50', '16', '51'] value = geometryio.input_to_extent( inp ) assert isinstance(value,QgsReferencedRectangle) assert isinstance(value,QgsRectangle) assert value.xMinimum() == 15; assert value.yMaximum() == 51; assert value.yMinimum() == 50; assert value.xMaximum() == 16; # Test CRS crs = value.crs() assert crs.isValid() assert crs.authid() == 'EPSG:4326'
def test_simple_algorithms(): """ Execute a simple algorithm """ alg = _find_algorithm('pyqgiswps_test:testsimplevalue') context = QgsProcessingContext() feedback = QgsProcessingFeedback() inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['PARAM1'][0].data = '1' inputs['PARAM2'][0].data = 'stuff' parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() ) assert parameters['PARAM1'] == 1 assert parameters['PARAM2'] == 'stuff' # Run algorithm results = Processing.runAlgorithm(alg, parameters=parameters, onFinish=handle_algorithm_results, feedback=feedback, context=context) assert results['OUTPUT'] == "1 stuff" write_outputs( alg, results, outputs ) assert outputs['OUTPUT'].data == "1 stuff"
def test_option_algorithms(): """ Execute a simple choice algorithm """ alg = _find_algorithm('pyqgiswps_test:testoptionvalue') context = QgsProcessingContext() feedback = QgsProcessingFeedback() inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['INPUT'][0].data = 'value1' parameters = dict( input_to_processing(ident, inp, alg, context) for ident, inp in inputs.items()) assert parameters['INPUT'] == 0 # Run algorithm results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context, outputs=outputs) assert results['OUTPUT'] == 'selection is 0' assert outputs['OUTPUT'].data == "selection is 0"
def test_parameter_abstract(): helpstr = """ This is a help text. It must appears in the 'abstract' field of wps """ title = "Parameter with help" param = QgsProcessingParameterNumber( "TEST", title, type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=10) param.setHelp(helpstr) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.identifier == "TEST" assert inp.title == title assert inp.abstract == helpstr
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 test_option_multi_algorithms(): """ Execute a multiple choice algorithm """ alg = _find_algorithm('pyqgiswps_test:testmultioptionvalue') context = QgsProcessingContext() feedback = QgsProcessingFeedback() inputs = { p.name(): parse_input_definition(p) for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } source = inputs['INPUT'] inputs['INPUT'] = [source.clone(),source.clone()] inputs['INPUT'][0].data = 'value1' inputs['INPUT'][1].data = 'value3' parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() ) assert parameters['INPUT'] == [0,2] # Run algorithm results = Processing.runAlgorithm(alg, parameters=parameters, onFinish=handle_algorithm_results, feedback=feedback, context=context) assert results['OUTPUT'] == 'selection is 0,2' write_outputs( alg, results, outputs ) assert outputs['OUTPUT'].data == "selection is 0,2"
def test_bbox_input_with_context(outputdir): """ Test extent parameter with context """ context = ProcessingContext(str(outputdir), 'france_parts_3857.qgs') project = context.project() project_crs = project.crs() assert project_crs.isValid() assert project_crs.authid() == 'EPSG:3857' param = QgsProcessingParameterExtent("BBOX") inp = parse_input_definition(param, context=context) assert isinstance(inp,BoundingBoxInput) assert inp.crss[0] == "EPSG:3857" # see create_bbox_inputs at L532 app/Service.py inp.data = ['15', '50', '16', '51'] value = geometryio.input_to_extent( inp ) assert isinstance(value,QgsReferencedRectangle) # Test CRS crs = value.crs() assert crs.isValid() assert crs.authid() == 'EPSG:3857'
def test_centroides_algorithms(outputdir, data): """ Execute an algorithm from a model """ alg = _find_algorithm('model:centroides') # Load source project source = QgsProject() rv = source.read(str(data / 'france_parts.qgs')) assert rv == True context = Context(source, outputdir) feedback = QgsProcessingFeedback() inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['input'][0].data = 'france_parts' inputs['native:centroids_1:OUTPUT'][0].data = 'output_layer' parameters = dict( input_to_processing(ident, inp, alg, context) for ident, inp in inputs.items()) assert isinstance(parameters['native:centroids_1:OUTPUT'], QgsProcessingOutputLayerDefinition) destination_name = parameters['native:centroids_1:OUTPUT'].destinationName assert destination_name == 'output_layer' # Destination project destination_project = get_valid_filename(alg.id()) context.wms_url = "http://localhost/wms/?MAP=test/{name}.qgs".format( name=destination_project) # Run algorithm with chdir(outputdir): results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context, outputs=outputs) assert context.destination_project.count() == 1 out = outputs.get('native:centroids_1:OUTPUT') assert out.data_format.mime_type == "application/x-ogc-wms" query = parse_qs(urlparse(out.url).query) assert query['layers'][0] == destination_name # Get the layer layers = context.destination_project.mapLayersByName(destination_name) assert len(layers) == 1
def test_selectfeatures_algorithm(outputdir, data): """ Test simple layer output """ alg = _find_algorithm('pyqgiswps_test:simplebuffer') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['INPUT'][0].data = 'layer:france_parts?' + urlencode( (('select', 'OBJECTID=2662 OR OBJECTID=2664'), )) inputs['OUTPUT_VECTOR'][0].data = 'buffer' inputs['DISTANCE'][0].data = 0.05 # 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()) assert isinstance(parameters['OUTPUT_VECTOR'], QgsProcessingOutputLayerDefinition) assert isinstance(parameters['DISTANCE'], float) 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) assert context.destination_project.count() == 1 out = outputs.get('OUTPUT_VECTOR') assert out.data_format.mime_type == "application/x-ogc-wms" destination_name = parameters['OUTPUT_VECTOR'].destinationName query = parse_qs(urlparse(out.url).query) assert query['layers'][0] == destination_name # Get the layer layers = context.destination_project.mapLayersByName(destination_name) assert len(layers) == 1 assert layers[0].featureCount() == 2
def test_output_vector_algorithm(outputdir, data): """ Test simple vector layer output """ alg = _find_algorithm('pyqgiswps_test:vectoroutput') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['INPUT'][0].data = 'france_parts' inputs['DISTANCE'][0].data = 0.05 # 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()) assert isinstance(parameters['DISTANCE'], float) 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) assert context.destination_project.count() == 1 out = outputs.get('OUTPUT') assert out.data_format.mime_type == "application/x-ogc-wms" output_name = 'my_output_vector' query = parse_qs(urlparse(out.url).query) assert query['layers'][0] == output_name # Get the layer srclayer = QgsProcessingUtils.mapLayerFromString('france_parts', context) assert srclayer is not None layers = context.destination_project.mapLayersByName(output_name) assert len(layers) == 1 assert layers[0].name() == 'my_output_vector' assert layers[0].featureCount() == srclayer.featureCount()
def test_source_types_metadata(): param = QgsProcessingParameterFeatureSource( "FSOURCE", '', [QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPoint]) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert get_metadata(inp,'processing:dataTypes')[0].href == 'TypeVectorLine,TypeVectorPoint'
def test_file_destination(): alg = _find_algorithm('pyqgiswps_test:testfiledestination') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } inputs['OUTPUT'][0].data = '/bad/..//path/to/file' context = QgsProcessingContext() parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() ) assert parameters['OUTPUT'] == 'file'
def test_freeform_metadata(): param = QgsProcessingParameterNumber("TEST", "LiteralInteger", type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=10) param.setMetadata({'meta1':'value1', 'meta2':'value2' }) inp = parse_input_definition(param) assert get_metadata(inp,'processing:meta:meta1')[0].href == 'value1' assert get_metadata(inp,'processing:meta:meta2')[0].href == 'value2'
def test_input_title(): param = QgsProcessingParameterNumber("Input_title", description="A short description", type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=10) inp = parse_input_definition(param) assert inp.title == "Input title" assert inp.abstract == "A short description"
def test_scale_input(): param = QgsProcessingParameterScale("TEST", "LiteralScale", defaultValue=2.0) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.identifier == "TEST" assert inp.data_type == "scale" assert len(inp.allowed_values) == 1 assert inp.default == param.defaultValue()
def test_optional_input(): param = QgsProcessingParameterField("XFIELD", 'X Field', parentLayerParameterName='INPUT', optional=True, type=QgsProcessingParameterField.Any) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.data_type == 'string' assert inp.min_occurs == 0
def test_buffer_algorithm(outputdir, data): """ Test simple layer output """ alg = _find_algorithm('pyqgiswps_test:simplebuffer') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['INPUT'][0].data = 'france_parts' inputs['OUTPUT_VECTOR'][0].data = 'buffer' inputs['DISTANCE'][0].data = 0.05 # Load source project source = QgsProject() rv = source.read(data.join('france_parts.qgs').strpath) assert rv == True workdir = outputdir.strpath context = Context(source, workdir) feedback = QgsProcessingFeedback() parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() ) assert isinstance( parameters['OUTPUT_VECTOR'], QgsProcessingOutputLayerDefinition) assert isinstance( parameters['DISTANCE'], float) # Run algorithm with chdir(outputdir.strpath): results = Processing.runAlgorithm(alg, parameters=parameters, onFinish=handle_algorithm_results, feedback=feedback, context=context) assert context.destination_project.count() == 1 handle_layer_outputs(results, context) assert results['OUTPUT_VECTOR'] == parameters['OUTPUT_VECTOR'].destinationName output_uri = "http://localhost/wms/?MAP=test/{name}.qgs".format(name=alg.name()) write_outputs( alg, results, outputs, output_uri, context ) out = outputs.get('OUTPUT_VECTOR') assert out.output_format == "application/x-ogc-wms" query = parse_qs(urlparse(out.url).query) assert query['layer'][0] == parameters['OUTPUT_VECTOR'].destinationName # Get the layer srclayer = QgsProcessingUtils.mapLayerFromString('france_parts', context) assert srclayer is not None layers = context.destination_project.mapLayersByName(results['OUTPUT_VECTOR']) assert len(layers) == 1 assert layers[0].featureCount() == srclayer.featureCount()
def test_field_input(): param = QgsProcessingParameterField("XFIELD", 'X Field', parentLayerParameterName='INPUT', type=QgsProcessingParameterField.Any) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.data_type == 'string' assert get_metadata(inp, 'processing:dataType')[0].href == 'Any' assert get_metadata( inp, 'processing:parentLayerParameterName')[0].href == 'INPUT'
def test_arbitrary_layer_scheme(): """ Test arbitrary layer scheme does not trig an error """ param = QgsProcessingParameterVectorLayer("LAYER", "") inp = parse_input_definition(param) inp.data = "foobar:layername" context = QgsProcessingContext() value = layersio.get_processing_value(param, [inp], context) assert value == "foobar:layername"
def test_layer_scheme(): """ Test layer scheme """ param = QgsProcessingParameterVectorLayer("LAYER", "") inp = parse_input_definition(param) inp.data = "layer:layername" context = QgsProcessingContext() value = layersio.get_processing_value(param, [inp], context) assert value == "layername"
def test_mesh_layer(): param = QgsProcessingParameterMeshLayer("LAYER", "") inp = parse_input_definition(param) inp.data = "layer:layername" assert get_metadata(inp, "processing:dataTypes")[0].href == "TypeMesh" context = QgsProcessingContext() value = layersio.get_processing_value(param, [inp], context) assert value == "layername"
def test_layer_destination(): param = QgsProcessingParameterVectorDestination( "LAYER", "", defaultValue=QgsProcessingOutputLayerDefinition('foo.shp')) inp = parse_input_definition(param) assert inp.default == "foo" metadata = layersio.get_metadata(inp, 'processing:extension') assert len(metadata) == 1 assert metadata[0] == 'shp' inp.data = "bar" context = QgsProcessingContext() context.destination_project = None inp.data = "bar" value = layersio.get_processing_value(param, [inp], context) assert isinstance(value, QgsProcessingOutputLayerDefinition) assert value.destinationName == 'bar' assert value.sink.staticValue() == './LAYER.shp' # Check unsafe option with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'): inp.data = "/foobar.csv" value = layersio.get_processing_value(param, [inp], context) assert value.destinationName == 'foobar' assert value.sink.staticValue() == 'foobar.csv' # Check unsafe option with default extension with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'): inp.data = "/foobar" value = layersio.get_processing_value(param, [inp], context) assert value.destinationName == 'foobar' assert value.sink.staticValue() == 'foobar.shp' # Check unsafe option with layername with chconfig('processing','unsafe.raw_destination_input_sink','yes'),\ chconfig('processing','destination_root_path','/unsafe'): inp.data = "file:/path/to/foobar.csv|layername=foobaz" value = layersio.get_processing_value(param, [inp], context) assert value.destinationName == 'foobaz' assert value.sink.staticValue() == '/unsafe/path/to/foobar.csv' # Check unsafe option with url with chconfig('processing', 'unsafe.raw_destination_input_sink', 'yes'): inp.data = "postgres://service=foobar|layername=foobaz" value = layersio.get_processing_value(param, [inp], context) assert value.destinationName == 'foobaz' assert value.sink.staticValue() == 'postgres://service=foobar'
def test_options_input(): options = ["opt0","opt1","opt2"] param = QgsProcessingParameterEnum("OPTION","Option", options=options, defaultValue=1) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.data_type == 'string' assert inp.allowed_values[0].value == options[0] assert inp.allowed_values[1].value == options[1] assert inp.allowed_values[2].value == options[2] assert inp.default == options[1]
def test_geometry_nomultipart(): """ Test geometry multipart Metadata """ # Single geometry param = QgsProcessingParameterGeometry("GEOM", geometryTypes=[QgsWkbTypes.LineGeometry], allowMultipart=False) inp = parse_input_definition(param) assert get_metadata(inp,'processing:geometryType')[0].href == "Line" # No multipart assert get_metadata(inp,'processing:allowMultipart', minOccurence=0) == []
def test_file_destination_io(): """ """ param = QgsProcessingParameterFileDestination("FILE", fileFilter="CSV Files (*.csv)") assert param.defaultFileExtension() == 'csv' inp = parse_input_definition(param) inp.data = "foobar" context = QgsProcessingContext() value = filesio.get_processing_value( param, [inp], context) assert value == 'foobar.csv'
def test_bbox_input(): """ Test extent parameter """ param = QgsProcessingParameterExtent("BBOX") inp = parse_input_definition(param) assert isinstance(inp,BoundingBoxInput) # see create_bbox_inputs at L532 app/Service.py inp.data = ['15', '50', '16', '51'] value = input_to_extent( [inp] ) assert isinstance(value,QgsReferencedRectangle)
def test_geometry_geometrytypes(): """ Test geometryTypes Metadata """ # Single geometry param = QgsProcessingParameterGeometry("GEOM", geometryTypes=[QgsWkbTypes.LineGeometry]) inp = parse_input_definition(param) assert get_metadata(inp,'processing:geometryType')[0].href == "Line" # Check allow multipart assert len(get_metadata(inp,'processing:allowMultipart')) == 1 # Multi Geometry param = QgsProcessingParameterGeometry("GEOM", geometryTypes=[QgsWkbTypes.LineGeometry,QgsWkbTypes.PointGeometry] ) inp = parse_input_definition(param) assert get_metadata(inp,'processing:geometryType',2)[0].href == "Line" assert get_metadata(inp,'processing:geometryType',2)[1].href == "Point" assert len(get_metadata(inp,'processing:allowMultipart')) == 1 # Test output XML xml = inp.describe_xml() def _get_geometryTypes(el): for metadata_el in xpath_ns(el, './ows:Metadata'): if metadata_el.attrib['{http://www.w3.org/1999/xlink}title'] == 'processing:geometryType': yield metadata_el.attrib['{http://www.w3.org/1999/xlink}href'] geomtypes = tuple(_get_geometryTypes(xml)) assert len(geomtypes) == 2 for type_ in geomtypes: assert type_ in ("Line","Point")
def test_literal_input(): param = QgsProcessingParameterNumber("TEST", "LiteralInteger", type=QgsProcessingParameterNumber.Integer, minValue=1, defaultValue=10) inp = parse_input_definition(param) assert isinstance(inp, LiteralInput) assert inp.identifier == "TEST" assert inp.data_type == "integer" assert len(inp.allowed_values) == 1 assert inp.allowed_values[0].allowed_type == ALLOWEDVALUETYPE.RANGE assert inp.allowed_values[0].minval == param.minimum() assert inp.allowed_values[0].maxval == param.maximum() assert inp.default == param.defaultValue()
def test_layer_algorithm(outputdir, data): """ Copy layer """ alg = _find_algorithm('pyqgiswps_test:testcopylayer') inputs = { p.name(): [parse_input_definition(p)] for p in alg.parameterDefinitions() } outputs = { p.name(): parse_output_definition(p) for p in alg.outputDefinitions() } inputs['INPUT'][0].data = 'france_parts' inputs['OUTPUT'][0].data = 'france_parts_2' # 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()) destination = get_valid_filename(alg.id()) assert isinstance(parameters['OUTPUT'], QgsProcessingOutputLayerDefinition) context.wms_url = "http://localhost/wms/MAP=test/{name}.qgs".format( name=destination) # Run algorithm with chdir(outputdir): results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context, outputs=outputs) output = parameters['OUTPUT'] assert output.destinationName == 'france_parts_2' assert output.sink.staticValue() == './OUTPUT.shp' assert context.destination_project.count() == 1