Skip to content

Commit 4c8b159

Browse files
committed
[processing] Fix GDAL algorithms do not run with memory layer inputs
Breaks execution of mixed QGIS/GDAL algorithms
1 parent ce72536 commit 4c8b159

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

python/plugins/processing/algs/gdal/GdalAlgorithm.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def getOgrCompatibleSource(self, parameter_name, parameters, context, feedback,
7373
input_layer = self.parameterAsVectorLayer(parameters, parameter_name, context)
7474
ogr_data_path = None
7575
ogr_layer_name = None
76-
if input_layer is None:
76+
if input_layer is None or input_layer.dataProvider().name() == 'memory':
7777
if executing:
7878
# parameter is not a vector layer - try to convert to a source compatible with OGR
7979
# and extract selection if required

python/plugins/processing/tests/GdalAlgorithmsTest.py

+86-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,16 @@
2828
import AlgorithmsTestBase
2929
from processing.algs.gdal.OgrToPostGis import OgrToPostGis
3030
from processing.algs.gdal.GdalUtils import GdalUtils
31-
from qgis.core import QgsProcessingContext
31+
from qgis.core import (QgsProcessingContext,
32+
QgsProcessingFeedback,
33+
QgsApplication,
34+
QgsVectorLayer,
35+
QgsFeature,
36+
QgsGeometry,
37+
QgsPointXY,
38+
QgsProject,
39+
QgsProcessingUtils,
40+
QgsProcessingFeatureSourceDefinition)
3241
import nose2
3342
import os
3443
import shutil
@@ -59,6 +68,82 @@ def tearDownClass(cls):
5968
def test_definition_file(self):
6069
return 'gdal_algorithm_tests.yaml'
6170

71+
def testGetOgrCompatibleSourceFromMemoryLayer(self):
72+
# create a memory layer and add to project and context
73+
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
74+
"testmem", "memory")
75+
self.assertTrue(layer.isValid())
76+
pr = layer.dataProvider()
77+
f = QgsFeature()
78+
f.setAttributes(["test", 123])
79+
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
80+
f2 = QgsFeature()
81+
f2.setAttributes(["test2", 457])
82+
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
83+
self.assertTrue(pr.addFeatures([f, f2]))
84+
self.assertEqual(layer.featureCount(), 2)
85+
QgsProject.instance().addMapLayer(layer)
86+
context = QgsProcessingContext()
87+
context.setProject(QgsProject.instance())
88+
89+
alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
90+
self.assertIsNotNone(alg)
91+
parameters = {'INPUT': 'testmem'}
92+
feedback = QgsProcessingFeedback()
93+
# check that memory layer is automatically saved out to shape when required by GDAL algorithms
94+
ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback, executing=True)
95+
self.assertTrue(ogr_data_path)
96+
self.assertTrue(ogr_data_path.endswith('.shp'))
97+
self.assertTrue(os.path.exists(ogr_data_path))
98+
self.assertTrue(ogr_layer_name)
99+
100+
# make sure that layer has correct features
101+
res = QgsVectorLayer(ogr_data_path, 'res')
102+
self.assertTrue(res.isValid())
103+
self.assertEqual(res.featureCount(), 2)
104+
105+
QgsProject.instance().removeMapLayer(layer)
106+
107+
def testGetOgrCompatibleSourceFromFeatureSource(self):
108+
# create a memory layer and add to project and context
109+
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
110+
"testmem", "memory")
111+
self.assertTrue(layer.isValid())
112+
pr = layer.dataProvider()
113+
f = QgsFeature()
114+
f.setAttributes(["test", 123])
115+
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
116+
f2 = QgsFeature()
117+
f2.setAttributes(["test2", 457])
118+
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
119+
self.assertTrue(pr.addFeatures([f, f2]))
120+
self.assertEqual(layer.featureCount(), 2)
121+
# select first feature
122+
layer.selectByIds([next(layer.getFeatures()).id()])
123+
self.assertEqual(len(layer.selectedFeatureIds()), 1)
124+
QgsProject.instance().addMapLayer(layer)
125+
context = QgsProcessingContext()
126+
context.setProject(QgsProject.instance())
127+
128+
alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
129+
self.assertIsNotNone(alg)
130+
parameters = {'INPUT': QgsProcessingFeatureSourceDefinition('testmem', True)}
131+
feedback = QgsProcessingFeedback()
132+
# check that memory layer is automatically saved out to shape when required by GDAL algorithms
133+
ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback,
134+
executing=True)
135+
self.assertTrue(ogr_data_path)
136+
self.assertTrue(ogr_data_path.endswith('.shp'))
137+
self.assertTrue(os.path.exists(ogr_data_path))
138+
self.assertTrue(ogr_layer_name)
139+
140+
# make sure that layer has only selected feature
141+
res = QgsVectorLayer(ogr_data_path, 'res')
142+
self.assertTrue(res.isValid())
143+
self.assertEqual(res.featureCount(), 1)
144+
145+
QgsProject.instance().removeMapLayer(layer)
146+
62147
def testOgrLayerNameExtraction(self):
63148
outdir = tempfile.mkdtemp()
64149
self.cleanup_paths.append(outdir)

0 commit comments

Comments
 (0)