Skip to content

Commit

Permalink
[processing] Fix GDAL algorithms do not run with memory layer inputs
Browse files Browse the repository at this point in the history
Breaks execution of mixed QGIS/GDAL algorithms

(cherry-picked from 4c8b159)
  • Loading branch information
nyalldawson committed Apr 9, 2018
1 parent cb067f8 commit f7b27d6
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/gdal/GdalAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def getOgrCompatibleSource(self, parameter_name, parameters, context, feedback,
input_layer = self.parameterAsVectorLayer(parameters, parameter_name, context)
ogr_data_path = None
ogr_layer_name = None
if input_layer is None:
if input_layer is None or input_layer.dataProvider().name() == 'memory':
if executing:
# parameter is not a vector layer - try to convert to a source compatible with OGR
# and extract selection if required
Expand Down
87 changes: 86 additions & 1 deletion python/plugins/processing/tests/GdalAlgorithmsTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@
import AlgorithmsTestBase
from processing.algs.gdal.OgrToPostGis import OgrToPostGis
from processing.algs.gdal.GdalUtils import GdalUtils
from qgis.core import QgsProcessingContext
from qgis.core import (QgsProcessingContext,
QgsProcessingFeedback,
QgsApplication,
QgsVectorLayer,
QgsFeature,
QgsGeometry,
QgsPointXY,
QgsProject,
QgsProcessingUtils,
QgsProcessingFeatureSourceDefinition)
import nose2
import os
import shutil
Expand Down Expand Up @@ -59,6 +68,82 @@ def tearDownClass(cls):
def test_definition_file(self):
return 'gdal_algorithm_tests.yaml'

def testGetOgrCompatibleSourceFromMemoryLayer(self):
# create a memory layer and add to project and context
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
"testmem", "memory")
self.assertTrue(layer.isValid())
pr = layer.dataProvider()
f = QgsFeature()
f.setAttributes(["test", 123])
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
f2 = QgsFeature()
f2.setAttributes(["test2", 457])
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
self.assertTrue(pr.addFeatures([f, f2]))
self.assertEqual(layer.featureCount(), 2)
QgsProject.instance().addMapLayer(layer)
context = QgsProcessingContext()
context.setProject(QgsProject.instance())

alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
self.assertIsNotNone(alg)
parameters = {'INPUT': 'testmem'}
feedback = QgsProcessingFeedback()
# check that memory layer is automatically saved out to shape when required by GDAL algorithms
ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback, executing=True)
self.assertTrue(ogr_data_path)
self.assertTrue(ogr_data_path.endswith('.shp'))
self.assertTrue(os.path.exists(ogr_data_path))
self.assertTrue(ogr_layer_name)

# make sure that layer has correct features
res = QgsVectorLayer(ogr_data_path, 'res')
self.assertTrue(res.isValid())
self.assertEqual(res.featureCount(), 2)

QgsProject.instance().removeMapLayer(layer)

def testGetOgrCompatibleSourceFromFeatureSource(self):
# create a memory layer and add to project and context
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
"testmem", "memory")
self.assertTrue(layer.isValid())
pr = layer.dataProvider()
f = QgsFeature()
f.setAttributes(["test", 123])
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
f2 = QgsFeature()
f2.setAttributes(["test2", 457])
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
self.assertTrue(pr.addFeatures([f, f2]))
self.assertEqual(layer.featureCount(), 2)
# select first feature
layer.selectByIds([next(layer.getFeatures()).id()])
self.assertEqual(len(layer.selectedFeatureIds()), 1)
QgsProject.instance().addMapLayer(layer)
context = QgsProcessingContext()
context.setProject(QgsProject.instance())

alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
self.assertIsNotNone(alg)
parameters = {'INPUT': QgsProcessingFeatureSourceDefinition('testmem', True)}
feedback = QgsProcessingFeedback()
# check that memory layer is automatically saved out to shape when required by GDAL algorithms
ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback,
executing=True)
self.assertTrue(ogr_data_path)
self.assertTrue(ogr_data_path.endswith('.shp'))
self.assertTrue(os.path.exists(ogr_data_path))
self.assertTrue(ogr_layer_name)

# make sure that layer has only selected feature
res = QgsVectorLayer(ogr_data_path, 'res')
self.assertTrue(res.isValid())
self.assertEqual(res.featureCount(), 1)

QgsProject.instance().removeMapLayer(layer)

def testOgrLayerNameExtraction(self):
outdir = tempfile.mkdtemp()
self.cleanup_paths.append(outdir)
Expand Down

0 comments on commit f7b27d6

Please sign in to comment.