def execute_in_place_run(alg, active_layer, parameters, context=None, feedback=None, raise_exceptions=False): """Executes an algorithm modifying features in-place in the input layer. The input layer must be editable or an exception is raised. :param alg: algorithm to run :type alg: QgsProcessingAlgorithm :param active_layer: the editable layer :type active_layer: QgsVectoLayer :param parameters: parameters of the algorithm :type parameters: dict :param context: context, defaults to None :param context: QgsProcessingContext, optional :param feedback: feedback, defaults to None :param feedback: QgsProcessingFeedback, optional :raises QgsProcessingException: raised when the layer is not editable or the layer cannot be found in the current project :return: a tuple with true if success and results :rtype: tuple """ if feedback is None: feedback = QgsProcessingFeedback() if context is None: context = dataobjects.createContext(feedback) if active_layer is None or not active_layer.isEditable(): raise QgsProcessingException( tr("Layer is not editable or layer is None.")) if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException( tr("Selected algorithm and parameter configuration are not compatible with in-place modifications." )) parameters['OUTPUT'] = 'memory:' try: new_feature_ids = [] active_layer.beginEditCommand(alg.displayName()) req = QgsFeatureRequest(QgsExpression(r"$id < 0")) req.setFlags(QgsFeatureRequest.NoGeometry) req.setSubsetOfAttributes([]) # Checks whether the algorithm has a processFeature method if hasattr(alg, 'processFeature'): # in-place feature editing # Make a clone or it will crash the second time the dialog # is opened and run alg = alg.create() if not alg.prepare(parameters, context, feedback): raise QgsProcessingException( tr("Could not prepare selected algorithm.")) # Check again for compatibility after prepare if not alg.supportInPlaceEdit(active_layer): raise QgsProcessingException( tr("Selected algorithm and parameter configuration are not compatible with in-place modifications." )) field_idxs = range(len(active_layer.fields())) feature_iterator = active_layer.getFeatures( QgsFeatureRequest(active_layer.selectedFeatureIds()) ) if parameters[ 'INPUT'].selectedFeaturesOnly else active_layer.getFeatures() for f in feature_iterator: # need a deep copy, because python processFeature implementations may return # a shallow copy from processFeature input_feature = QgsFeature(f) new_features = alg.processFeature(input_feature, context, feedback) new_features = QgsVectorLayerUtils.makeFeaturesCompatible( new_features, active_layer) if len(new_features) == 0: active_layer.deleteFeature(f.id()) elif len(new_features) == 1: new_f = new_features[0] if not f.geometry().equals(new_f.geometry()): active_layer.changeGeometry(f.id(), new_f.geometry()) if f.attributes() != new_f.attributes(): active_layer.changeAttributeValues( f.id(), dict(zip(field_idxs, new_f.attributes())), dict(zip(field_idxs, f.attributes()))) new_feature_ids.append(f.id()) else: active_layer.deleteFeature(f.id()) # Get the new ids old_ids = set( [f.id() for f in active_layer.getFeatures(req)]) if not active_layer.addFeatures(new_features): raise QgsProcessingException( tr("Error adding processed features back into the layer." )) new_ids = set( [f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) results, ok = {}, True else: # Traditional 'run' with delete and add features cycle results, ok = alg.run(parameters, context, feedback) if ok: result_layer = QgsProcessingUtils.mapLayerFromString( results['OUTPUT'], context) # TODO: check if features have changed before delete/add cycle active_layer.deleteFeatures(active_layer.selectedFeatureIds()) new_features = [] for f in result_layer.getFeatures(): new_features.extend( QgsVectorLayerUtils.makeFeaturesCompatible( [f], active_layer)) # Get the new ids old_ids = set([f.id() for f in active_layer.getFeatures(req)]) if not active_layer.addFeatures(new_features): raise QgsProcessingException( tr("Error adding processed features back into the layer." )) new_ids = set([f.id() for f in active_layer.getFeatures(req)]) new_feature_ids += list(new_ids - old_ids) active_layer.endEditCommand() if ok and new_feature_ids: active_layer.selectByIds(new_feature_ids) elif not ok: active_layer.rollBack() return ok, results except QgsProcessingException as e: active_layer.endEditCommand() active_layer.rollBack() if raise_exceptions: raise e QgsMessageLog.logMessage(str(sys.exc_info()[0]), 'Processing', Qgis.Critical) if feedback is not None: feedback.reportError(getattr(e, 'msg', str(e))) return False, {}
def mergeDataSources2Vrt(self, dataSources, outFile, union=False, relative=False, schema=False, feedback=None): '''Function to do the work of merging datasources in a single vrt format @param data_sources: Array of path strings @param outfile: the output vrt file to generate @param relative: Write relative flag. DOES NOT relativise paths. They have to be already relative @param schema: Schema flag @return: vrt in string format ''' if feedback is None: feedback = QgsProcessingFeedback() vrt = '<OGRVRTDataSource>' if union: vrt += '<OGRVRTUnionLayer name="UnionedLayer">' total = 100.0 / len(dataSources) if dataSources else 1 for current, layer in enumerate(dataSources): if feedback.isCanceled(): break feedback.setProgress(int(current * total)) inFile = layer.source() srcDS = ogr.Open(inFile, 0) if srcDS is None: raise QgsProcessingException( self.tr('Invalid datasource: {}'.format(inFile))) if schema: inFile = '@dummy@' for layer in srcDS: layerDef = layer.GetLayerDefn() layerName = layerDef.GetName() vrt += '<OGRVRTLayer name="{}">'.format(self.XmlEsc(layerName)) vrt += '<SrcDataSource relativeToVRT="{}" shared="{}">{}</SrcDataSource>'.format(1 if relative else 0, not schema, self.XmlEsc(inFile)) if schema: vrt += '<SrcLayer>@dummy@</SrcLayer>' else: vrt += '<SrcLayer>{}</SrcLayer>'.format(self.XmlEsc(layerName)) vrt += '<GeometryType>{}</GeometryType>'.format(self.GeomType2Name(layerDef.GetGeomType())) crs = layer.GetSpatialRef() if crs is not None: vrt += '<LayerSRS>{}</LayerSRS>'.format(self.XmlEsc(crs.ExportToWkt())) # Process all the fields. for fieldIdx in range(layerDef.GetFieldCount()): fieldDef = layerDef.GetFieldDefn(fieldIdx) vrt += '<Field name="{}" type="{}"'.format(self.XmlEsc(fieldDef.GetName()), self.fieldType2Name(fieldDef.GetType())) if not schema: vrt += ' src="{}"'.format(self.XmlEsc(fieldDef.GetName())) if fieldDef.GetWidth() > 0: vrt += ' width="{}"'.format(fieldDef.GetWidth()) if fieldDef.GetPrecision() > 0: vrt += ' precision="{}"'.format(fieldDef.GetPrecision()) vrt += '/>' vrt += '</OGRVRTLayer>' srcDS.Destroy() if union: vrt += '</OGRVRTUnionLayer>' vrt += '</OGRVRTDataSource>' #TODO: pretty-print XML if outFile is not None: with codecs.open(outFile, 'w') as f: f.write(vrt) return vrt
def handleAlgorithmResults(alg, context, feedback=None, showResults=True): wrongLayers = [] if feedback is None: feedback = QgsProcessingFeedback() feedback.setProgressText( QCoreApplication.translate('Postprocessing', 'Loading resulting layers')) i = 0 for l, details in context.layersToLoadOnCompletion().items(): feedback.setProgress(100 * i / float(len(context.layersToLoadOnCompletion()))) try: layer = QgsProcessingUtils.mapLayerFromString(l, context) if layer is not None: layer.setName(details.name) details.project.addMapLayer( context.temporaryLayerStore().takeMapLayer(layer)) else: name = details.name if ProcessingConfig.getSetting( ProcessingConfig.USE_FILENAME_AS_LAYER_NAME): name = os.path.basename(l) dataobjects.load(l, name, alg.crs, RenderingStyles.getStyle(alg.id(), l)) except Exception: QgsMessageLog.logMessage( "Error loading result layer:\n" + traceback.format_exc(), 'Processing', QgsMessageLog.CRITICAL) #wrongLayers.append(out.description()) wrongLayers.append(l) # for out in alg.outputs: # feedback.setProgress(100 * i / float(len(alg.outputs))) # if out.flags() & QgsProcessingParameterDefinition.FlagHidden or not out.open: # continue # if isinstance(out, (OutputRaster, OutputVector, OutputTable)): # try: # layer = QgsProcessingUtils.mapLayerFromString(out.value, context) # if layer: # layer.setName(out.description) # QgsProject.instance().addMapLayer(context.temporaryLayerStore().takeMapLayer(layer)) # else: # if ProcessingConfig.getSetting( # ProcessingConfig.USE_FILENAME_AS_LAYER_NAME): # name = os.path.basename(out.value) # else: # name = out.description # # isRaster = True if isinstance(out, OutputRaster) else False # dataobjects.load(out.value, name, alg.crs, # RenderingStyles.getStyle(alg.id(), out.name), # isRaster) # except Exception: # QgsMessageLog.logMessage("Error loading result layer:\n" + traceback.format_exc(), 'Processing', QgsMessageLog.CRITICAL) # wrongLayers.append(out.description) # elif isinstance(out, OutputHTML): # resultsList.addResult(alg.icon(), out.description, out.value) # i += 1 QApplication.restoreOverrideCursor() if wrongLayers: msg = "The following layers were not correctly generated.<ul>" msg += "".join(["<li>%s</li>" % lay for lay in wrongLayers]) + "</ul>" msg += "You can check the log messages to find more information about the execution of the algorithm" feedback.reportError(msg) return len(wrongLayers) == 0
def runGdal(commands, feedback=None): if feedback is None: feedback = QgsProcessingFeedback() envval = os.getenv('PATH') # We need to give some extra hints to get things picked up on OS X isDarwin = False try: isDarwin = platform.system() == 'Darwin' except IOError: # https://travis-ci.org/m-kuhn/QGIS#L1493-L1526 pass if isDarwin and os.path.isfile( os.path.join(QgsApplication.prefixPath(), "bin", "gdalinfo")): # Looks like there's a bundled gdal. Let's use it. os.environ['PATH'] = "{}{}{}".format( os.path.join(QgsApplication.prefixPath(), "bin"), os.pathsep, envval) os.environ['DYLD_LIBRARY_PATH'] = os.path.join( QgsApplication.prefixPath(), "lib") else: # Other platforms should use default gdal finder codepath settings = QgsSettings() path = settings.value('/GdalTools/gdalPath', '') if not path.lower() in envval.lower().split(os.pathsep): envval += '{}{}'.format(os.pathsep, path) os.putenv('PATH', envval) fused_command = ' '.join([str(c) for c in commands]) QgsMessageLog.logMessage(fused_command, 'Processing', QgsMessageLog.INFO) feedback.pushInfo('GDAL command:') feedback.pushCommandInfo(fused_command) feedback.pushInfo('GDAL command output:') success = False retry_count = 0 while not success: loglines = [] loglines.append('GDAL execution console output') try: with subprocess.Popen( fused_command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.DEVNULL, stderr=subprocess.STDOUT, universal_newlines=True, ) as proc: for line in proc.stdout: feedback.pushConsoleInfo(line) loglines.append(line) success = True except IOError as e: if retry_count < 5: retry_count += 1 else: raise IOError( e.message + u'\nTried 5 times without success. Last iteration stopped after reading {} line(s).\nLast line(s):\n{}' .format(len(loglines), u'\n'.join(loglines[-10:]))) QgsMessageLog.logMessage('\n'.join(loglines), 'Processing', QgsMessageLog.INFO) GdalUtils.consoleOutput = loglines
def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=None): if isinstance(algOrName, QgsProcessingAlgorithm): alg = algOrName else: alg = QgsApplication.processingRegistry().createAlgorithmById( algOrName) if feedback is None: feedback = QgsProcessingFeedback() if alg is None: # fix_print_with_import print('Error: Algorithm not found\n') msg = Processing.tr('Error: Algorithm {0} not found\n').format( algOrName) feedback.reportError(msg) raise QgsProcessingException(msg) # check for any mandatory parameters which were not specified for param in alg.parameterDefinitions(): if param.name() not in parameters: if not param.flags( ) & QgsProcessingParameterDefinition.FlagOptional: # fix_print_with_import msg = Processing.tr( 'Error: Missing parameter value for parameter {0}.' ).format(param.name()) print('Error: Missing parameter value for parameter %s.' % param.name()) feedback.reportError(msg) raise QgsProcessingException(msg) if context is None: context = dataobjects.createContext(feedback) ok, msg = alg.checkParameterValues(parameters, context) if not ok: # fix_print_with_import print('Unable to execute algorithm\n' + str(msg)) msg = Processing.tr('Unable to execute algorithm\n{0}').format(msg) feedback.reportError(msg) raise QgsProcessingException(msg) if not alg.validateInputCrs(parameters, context): print('Warning: Not all input layers use the same CRS.\n' + 'This can cause unexpected results.') feedback.pushInfo( Processing. tr('Warning: Not all input layers use the same CRS.\nThis can cause unexpected results.' )) ret, results = execute(alg, parameters, context, feedback) if ret: feedback.pushInfo(Processing.tr('Results: {}').format(results)) if onFinish is not None: onFinish(alg, context, feedback) else: # auto convert layer references in results to map layers for out in alg.outputDefinitions(): if out.name() not in results: continue if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)): result = results[out.name()] if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( result ) # transfer layer ownership out of context if layer: results[out.name( )] = layer # replace layer string ref with actual layer (+ownership) elif isinstance(out, QgsProcessingOutputMultipleLayers): result = results[out.name()] if result: layers_result = [] for l in result: if not isinstance(result, QgsMapLayer): layer = context.takeResultLayer( l ) # transfer layer ownership out of context if layer: layers_result.append(layer) else: layers_result.append(l) else: layers_result.append(l) results[out.name( )] = layers_result # replace layers strings ref with actual layers (+ownership) else: msg = Processing.tr("There were errors executing the algorithm.") feedback.reportError(msg) raise QgsProcessingException(msg) if isinstance(feedback, MessageBarProgress): feedback.close() return results
def handleAlgorithmResults(alg, context, feedback=None, showResults=True): wrongLayers = [] if feedback is None: feedback = QgsProcessingFeedback() feedback.setProgressText( QCoreApplication.translate('Postprocessing', 'Loading resulting layers')) i = 0 for l, details in context.layersToLoadOnCompletion().items(): if feedback.isCanceled(): return False if len(context.layersToLoadOnCompletion()) > 2: # only show progress feedback if we're loading a bunch of layers feedback.setProgress( 100 * i / float(len(context.layersToLoadOnCompletion()))) try: layer = QgsProcessingUtils.mapLayerFromString(l, context) if layer is not None: if not ProcessingConfig.getSetting( ProcessingConfig.USE_FILENAME_AS_LAYER_NAME): layer.setName(details.name) style = None if details.outputName: style = RenderingStyles.getStyle(alg.id(), details.outputName) if style is None: if layer.type() == QgsMapLayer.RasterLayer: style = ProcessingConfig.getSetting( ProcessingConfig.RASTER_STYLE) else: if layer.geometryType() == QgsWkbTypes.PointGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POINT_STYLE) elif layer.geometryType() == QgsWkbTypes.LineGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_LINE_STYLE) else: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POLYGON_STYLE) if style: layer.loadNamedStyle(style) details.project.addMapLayer( context.temporaryLayerStore().takeMapLayer(layer)) else: wrongLayers.append(str(l)) except Exception: QgsMessageLog.logMessage( QCoreApplication.translate( 'Postprocessing', "Error loading result layer:") + "\n" + traceback.format_exc(), 'Processing', QgsMessageLog.CRITICAL) wrongLayers.append(str(l)) i += 1 feedback.setProgress(100) if wrongLayers: msg = QCoreApplication.translate( 'Postprocessing', "The following layers were not correctly generated.") msg += "<ul>" + "".join(["<li>%s</li>" % lay for lay in wrongLayers]) + "</ul>" msg += QCoreApplication.translate( 'Postprocessing', "You can check the 'Log Messages Panel' in QGIS main window to find more information about the execution of the algorithm." ) feedback.reportError(msg) return len(wrongLayers) == 0
def handleAlgorithmResults(alg, context, feedback=None, showResults=True, parameters={}): wrongLayers = [] if feedback is None: feedback = QgsProcessingFeedback() feedback.setProgressText( QCoreApplication.translate('Postprocessing', 'Loading resulting layers')) i = 0 for l, details in context.layersToLoadOnCompletion().items(): if feedback.isCanceled(): return False if len(context.layersToLoadOnCompletion()) > 2: # only show progress feedback if we're loading a bunch of layers feedback.setProgress( 100 * i / float(len(context.layersToLoadOnCompletion()))) try: layer = QgsProcessingUtils.mapLayerFromString( l, context, typeHint=details.layerTypeHint) if layer is not None: set_layer_name(layer, details) '''If running a model, the execution will arrive here when an algorithm that is part of that model is executed. We check if its output is a final otuput of the model, and adapt the output name accordingly''' outputName = details.outputName expcontext = QgsExpressionContext() scope = QgsExpressionContextScope() expcontext.appendScope(scope) for out in alg.outputDefinitions(): if out.name() not in parameters: continue outValue = parameters[out.name()] if hasattr(outValue, "sink"): outValue = outValue.sink.valueAsString(expcontext)[0] else: outValue = str(outValue) if outValue == l: outputName = out.name() break style = None if outputName: style = RenderingStyles.getStyle(alg.id(), outputName) if style is None: if layer.type() == QgsMapLayerType.RasterLayer: style = ProcessingConfig.getSetting( ProcessingConfig.RASTER_STYLE) else: if layer.geometryType() == QgsWkbTypes.PointGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POINT_STYLE) elif layer.geometryType() == QgsWkbTypes.LineGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_LINE_STYLE) else: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POLYGON_STYLE) if style: layer.loadNamedStyle(style) details.project.addMapLayer( context.temporaryLayerStore().takeMapLayer(layer)) if details.postProcessor(): details.postProcessor().postProcessLayer( layer, context, feedback) else: wrongLayers.append(str(l)) except Exception: QgsMessageLog.logMessage( QCoreApplication.translate( 'Postprocessing', "Error loading result layer:") + "\n" + traceback.format_exc(), 'Processing', Qgis.Critical) wrongLayers.append(str(l)) i += 1 feedback.setProgress(100) if wrongLayers: msg = QCoreApplication.translate( 'Postprocessing', "The following layers were not correctly generated.") msg += "<ul>" + "".join(["<li>%s</li>" % lay for lay in wrongLayers]) + "</ul>" msg += QCoreApplication.translate( 'Postprocessing', "You can check the 'Log Messages Panel' in QGIS main window to find more information about the execution of the algorithm." ) feedback.reportError(msg) return len(wrongLayers) == 0
def testOgr2PostGis(self): context = QgsProcessingContext() feedback = QgsProcessingFeedback() source = os.path.join(testDataPath, 'polys.gml') source_with_space = os.path.join(testDataPath, 'filename with spaces.gml') alg = OgrToPostGis() alg.initAlgorithm() self.assertEqual( alg.getConsoleCommands({'INPUT': source}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source_with_space}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 "' + source_with_space + '" filename_with_spaces ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.filename_with_spaces -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'HOST': 'google.com'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=google.com port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PORT': 3333}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=3333 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'USER': '******'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public user=kevin_bacon" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'DBNAME': 'secret_stuff'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 dbname=secret_stuff active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PASSWORD': '******'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 password=passw0rd active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SCHEMA': 'desktop'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=desktop" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln desktop.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'TABLE': 'out_table'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.out_table -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PK': ''}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PK': 'new_fid'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=new_fid -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PK': '', 'PRIMARY_KEY': 'objectid'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=objectid -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PK': 'new_id', 'PRIMARY_KEY': 'objectid'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=new_id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'GEOCOLUMN': 'my_geom'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=my_geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'DIM': 1}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=3 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SIMPLIFY': 5}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -simplify 5 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SEGMENTIZE': 4}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -segmentize 4 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SPAT': QgsRectangle(1, 2, 3, 4)}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -spat 1.0 2.0 3.0 4.0 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELDS': ['f1', 'f2']}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 -select "f1,f2" ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'WHERE': '0=1'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -where "0=1" -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'GT': 2}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -gt 2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'OVERWRITE': False}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'APPEND': True}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-append -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'ADDFIELDS': True}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-addfields -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'LAUNDER': True}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-lco LAUNDER=NO -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'INDEX': True}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-lco SPATIAL_INDEX=OFF -overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SKIPFAILURES': True}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -skipfailures -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PROMOTETOMULTI': False}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'PRECISION': False}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI -lco PRECISION=NO']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'OPTIONS': 'blah'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI blah']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'SHAPE_ENCODING': 'blah'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES --config SHAPE_ENCODING "blah" -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'GTYPE': 4}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -nlt LINESTRING -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'A_SRS': 'EPSG:3111'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'A_SRS': QgsCoordinateReferenceSystem('EPSG:3111')}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs' self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'A_SRS': custom_crs}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -a_srs EPSG:20936 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'T_SRS': 'EPSG:3111'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'T_SRS': QgsCoordinateReferenceSystem('EPSG:3111')}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs' self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'T_SRS': custom_crs}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -t_srs EPSG:20936 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'S_SRS': 'EPSG:3111'}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'S_SRS': QgsCoordinateReferenceSystem('EPSG:3111')}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:3111 -nlt PROMOTE_TO_MULTI']) custom_crs = 'proj4: +proj=utm +zone=36 +south +a=6378249.145 +b=6356514.966398753 +towgs84=-143,-90,-294,0,0,0,0 +units=m +no_defs' self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'S_SRS': custom_crs}, context, feedback), ['ogr2ogr', '-progress --config PG_USE_COPY YES -f PostgreSQL "PG:host=localhost port=5432 active_schema=public" ' '-lco DIM=2 ' + source + ' polys2 ' '-overwrite -lco GEOMETRY_NAME=geom -lco FID=id -nln public.polys2 -s_srs EPSG:20936 -nlt PROMOTE_TO_MULTI'])
def testDissolve(self): context = QgsProcessingContext() feedback = QgsProcessingFeedback() source = os.path.join(testDataPath, 'polys.gml') source_with_space = os.path.join(testDataPath, 'filename with spaces.gml') alg = Dissolve() alg.initAlgorithm() with tempfile.TemporaryDirectory() as outdir: self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry FROM \\"polys2\\"" ' + '-f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'total population', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"total population\\" FROM \\"polys2\\" ' + 'GROUP BY \\"total population\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source_with_space, 'FIELD': 'my_field', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + '"' + source_with_space + '" ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"filename_with_spaces\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'GEOMETRY': 'the_geom', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'KEEP_ATTRIBUTES': False, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'KEEP_ATTRIBUTES': False, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry FROM \\"polys2\\"" ' + '-f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'EXPLODE_COLLECTIONS': True, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -explodecollections -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COUNT_FEATURES': True, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\", COUNT(geometry) AS count FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COUNT_FEATURES': True, 'GEOMETRY': 'the_geom', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, \\"my_field\\", COUNT(the_geom) AS count FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COMPUTE_AREA': True, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\", SUM(ST_Area(geometry)) AS area, ' + 'ST_Perimeter(ST_Union(geometry)) AS perimeter FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COMPUTE_AREA': True, 'GEOMETRY': 'the_geom', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(the_geom) AS the_geom, \\"my_field\\", SUM(ST_Area(the_geom)) AS area, ' + 'ST_Perimeter(ST_Union(the_geom)) AS perimeter FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COMPUTE_STATISTICS': True, 'STATISTICS_ATTRIBUTE': 'my_val', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\", ' + 'SUM(\\"my_val\\") AS sum, MIN(\\"my_val\\") AS min, MAX(\\"my_val\\") AS max, AVG(\\"my_val\\") AS avg FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'test field', 'COMPUTE_STATISTICS': True, 'STATISTICS_ATTRIBUTE': 'total population', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"test field\\", ' + 'SUM(\\"total population\\") AS sum, MIN(\\"total population\\") AS min, MAX(\\"total population\\") AS max, ' + 'AVG(\\"total population\\") AS avg FROM \\"polys2\\" ' + 'GROUP BY \\"test field\\"" -f "ESRI Shapefile"']) # compute stats without stats attribute, and vice versa (should be ignored) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'COMPUTE_STATISTICS': True, 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'STATISTICS_ATTRIBUTE': 'my_val', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" -f "ESRI Shapefile"']) self.assertEqual( alg.getConsoleCommands({'INPUT': source, 'FIELD': 'my_field', 'OPTIONS': 'my opts', 'OUTPUT': outdir + '/check.shp'}, context, feedback), ['ogr2ogr', outdir + '/check.shp ' + source + ' ' + '-nlt PROMOTE_TO_MULTI -dialect sqlite -sql "SELECT ST_Union(geometry) AS geometry, \\"my_field\\" FROM \\"polys2\\" ' + 'GROUP BY \\"my_field\\"" "my opts" -f "ESRI Shapefile"'])