Skip to content

Commit 3aa630c

Browse files
committedJun 1, 2018
Added QgsDataProvider::ProviderOptions to the bindings
1 parent 0fa88e6 commit 3aa630c

File tree

5 files changed

+30
-88
lines changed

5 files changed

+30
-88
lines changed
 

‎python/core/auto_generated/qgsprovidermetadata.sip.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ no library is involved.
5050

5151
Py_BEGIN_ALLOW_THREADS
5252

53-
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource ) -> QgsDataProvider*
53+
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource, const QgsDataProvider::ProviderOptions &providerOptions ) -> QgsDataProvider*
5454
{
5555
QgsDataProvider *provider;
5656
provider = nullptr;
5757
PyObject *sipResObj;
5858
SIP_BLOCK_THREADS
5959

60-
sipResObj = sipCallMethod( NULL, a2, "D", new QString( dataSource ), sipType_QString, NULL );
60+
sipResObj = sipCallMethod( NULL, a2, "DD", new QString( dataSource ), sipType_QString, NULL, new QgsDataProvider::ProviderOptions( providerOptions ), sipType_QgsDataProvider_ProviderOptions, NULL );
6161

6262
if ( sipResObj )
6363
{

‎python/core/auto_generated/qgsproviderregistry.sip.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ Returns a string containing the available protocol drivers
182182

183183
void registerProvider( QgsProviderMetadata *providerMetadata /Transfer/ );
184184
%Docstring
185-
register a new vector data provider from its ``providerMetadata``
185+
register a new vector data provider from its ``providerMetadata``
186186

187187
.. note::
188188

‎src/core/qgsprovidermetadata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ class CORE_EXPORT QgsProviderMetadata
7171

7272
Py_BEGIN_ALLOW_THREADS
7373

74-
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource ) -> QgsDataProvider*
74+
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource, const QgsDataProvider::ProviderOptions &providerOptions ) -> QgsDataProvider*
7575
{
7676
QgsDataProvider *provider;
7777
provider = nullptr;
7878
PyObject *sipResObj;
7979
SIP_BLOCK_THREADS
8080

81-
sipResObj = sipCallMethod( NULL, a2, "D", new QString( dataSource ), sipType_QString, NULL );
81+
sipResObj = sipCallMethod( NULL, a2, "DD", new QString( dataSource ), sipType_QString, NULL, new QgsDataProvider::ProviderOptions( providerOptions ), sipType_QgsDataProvider_ProviderOptions, NULL );
8282

8383
if ( sipResObj )
8484
{

‎tests/src/python/provider_python.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
QgsProviderMetadata,
4747
QgsGeometryEngine,
4848
QgsSpatialIndex,
49+
QgsDataProvider,
4950
)
5051

5152
from qgis.PyQt.QtCore import QVariant
@@ -54,7 +55,7 @@
5455
class PyFeatureIterator(QgsAbstractFeatureIterator):
5556

5657
def __init__(self, source, request):
57-
super(PyFeatureIterator, self).__init__(request)
58+
super().__init__(request)
5859
self._request = request if request is not None else QgsFeatureRequest()
5960
self._source = source
6061
self._index = 0
@@ -187,13 +188,13 @@ def description(cls):
187188
return 'Python Test Provider'
188189

189190
@classmethod
190-
def createProvider(cls, uri):
191-
return PyProvider(uri)
191+
def createProvider(cls, uri, providerOptions):
192+
return PyProvider(uri, providerOptions)
192193

193194
# Implementation of functions from QgsVectorDataProvider
194195

195-
def __init__(self, uri=''):
196-
super(PyProvider, self).__init__(uri)
196+
def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()):
197+
super().__init__(uri)
197198
# Use the memory layer to parse the uri
198199
mlayer = QgsVectorLayer(uri, 'ml', 'memory')
199200
self.setNativeTypes(mlayer.dataProvider().nativeTypes())
@@ -206,6 +207,7 @@ def __init__(self, uri=''):
206207
self._subset_string = ''
207208
self._crs = mlayer.crs()
208209
self._spatialindex = None
210+
self._provider_options = providerOptions
209211
if 'index=yes'in self._uri:
210212
self.createSpatialIndex()
211213

@@ -307,16 +309,21 @@ def addAttributes(self, attrs):
307309

308310
def renameAttributes(self, renamedAttributes):
309311
result = True
310-
for key, new_name in renamedAttributes:
311-
fieldIndex = key
312+
# We need to replace all fields because python bindings return a copy from [] and at()
313+
new_fields = [self._fields.at(i) for i in range(self._fields.count())]
314+
for fieldIndex, new_name in renamedAttributes.items():
312315
if fieldIndex < 0 or fieldIndex >= self._fields.count():
313316
result = False
314317
continue
315-
if new_name in self._fields.indexFromName(new_name) >= 0:
318+
if self._fields.indexFromName(new_name) >= 0:
316319
#field name already in use
317320
result = False
318321
continue
319-
self._fields[fieldIndex].setName(new_name)
322+
new_fields[fieldIndex].setName(new_name)
323+
if result:
324+
self._fields = QgsFields()
325+
for i in range(len(new_fields)):
326+
self._fields.append(new_fields[i])
320327
return result
321328

322329
def deleteAttributes(self, attributes):

‎tests/src/python/test_provider_python.py

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
"""QGIS Unit tests for the python layer provider.
2+
"""QGIS Unit tests for the python dataprovider.
33
44
.. note:: This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -144,13 +144,13 @@ def getEditableLayer(self):
144144
return self.createLayer()
145145

146146
def testGetFeaturesSubsetAttributes2(self):
147-
""" Override and skip this test for memory provider, as it's actually more efficient for the memory provider to return
147+
""" Override and skip this test for pythonprovider provider, as it's actually more efficient for the pythonprovider provider to return
148148
its features as direct copies (due to implicit sharing of QgsFeature)
149149
"""
150150
pass
151151

152152
def testGetFeaturesNoGeometry(self):
153-
""" Override and skip this test for memory provider, as it's actually more efficient for the memory provider to return
153+
""" Override and skip this test for pythonprovider provider, as it's actually more efficient for the pythonprovider provider to return
154154
its features as direct copies (due to implicit sharing of QgsFeature)
155155
"""
156156
pass
@@ -163,8 +163,8 @@ def testGetFeaturesDestinationCrs(self):
163163
def testCtors(self):
164164
testVectors = ["Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon", "None"]
165165
for v in testVectors:
166-
layer = QgsVectorLayer(v, "test", "memory")
167-
assert layer.isValid(), "Failed to create valid %s memory layer" % (v)
166+
layer = QgsVectorLayer(v, "test", "pythonprovider")
167+
assert layer.isValid(), "Failed to create valid %s pythonprovider layer" % (v)
168168

169169
def testLayerGeometry(self):
170170
testVectors = [("Point", QgsWkbTypes.PointGeometry, QgsWkbTypes.Point),
@@ -199,7 +199,7 @@ def testLayerGeometry(self):
199199
("MultiPolygon25D", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygon25D),
200200
("None", QgsWkbTypes.NullGeometry, QgsWkbTypes.NoGeometry)]
201201
for v in testVectors:
202-
layer = QgsVectorLayer(v[0], "test", "memory")
202+
layer = QgsVectorLayer(v[0], "test", "pythonprovider")
203203

204204
myMessage = ('Expected: %s\nGot: %s\n' %
205205
(v[1], layer.geometryType()))
@@ -210,7 +210,7 @@ def testLayerGeometry(self):
210210
assert layer.wkbType() == v[2], myMessage
211211

212212
def testAddFeatures(self):
213-
layer = QgsVectorLayer("Point", "test", "memory")
213+
layer = QgsVectorLayer("Point", "test", "pythonprovider")
214214
provider = layer.dataProvider()
215215

216216
res = provider.addAttributes([QgsField("name", QVariant.String),
@@ -260,7 +260,7 @@ def testAddFeatures(self):
260260
assert compareWkt(str(geom.asWkt()), "Point (10 10)"), myMessage
261261

262262
def testGetFields(self):
263-
layer = QgsVectorLayer("Point", "test", "memory")
263+
layer = QgsVectorLayer("Point", "test", "pythonprovider")
264264
provider = layer.dataProvider()
265265

266266
provider.addAttributes([QgsField("name", QVariant.String),
@@ -345,7 +345,7 @@ def testSaveFields(self):
345345
assert f == importedFields.field(f.name())
346346

347347
def testRenameAttributes(self):
348-
layer = QgsVectorLayer("Point", "test", "memory")
348+
layer = QgsVectorLayer("Point", "test", "pythonprovider")
349349
provider = layer.dataProvider()
350350

351351
res = provider.addAttributes([QgsField("name", QVariant.String),
@@ -382,71 +382,6 @@ def testRenameAttributes(self):
382382
self.assertEqual(fet.fields()[1].name(), 'mapinfo_is_the_stone_age')
383383
self.assertEqual(fet.fields()[2].name(), 'super_size')
384384

385-
def testUniqueSource(self):
386-
"""
387-
Similar memory layers should have unique source - some code checks layer source to identify
388-
matching layers
389-
"""
390-
layer = QgsVectorLayer("Point", "test", "memory")
391-
layer2 = QgsVectorLayer("Point", "test2", "memory")
392-
self.assertNotEqual(layer.source(), layer2.source())
393-
394-
def testCreateMemoryLayer(self):
395-
"""
396-
Test QgsMemoryProviderUtils.createMemoryLayer()
397-
"""
398-
399-
# no fields
400-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
401-
self.assertTrue(layer.isValid())
402-
self.assertEqual(layer.name(), 'my name')
403-
self.assertTrue(layer.fields().isEmpty())
404-
405-
# similar layers should have unique sources
406-
layer2 = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
407-
self.assertNotEqual(layer.source(), layer2.source())
408-
409-
# geometry type
410-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.Point)
411-
self.assertTrue(layer.isValid())
412-
self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
413-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM)
414-
self.assertTrue(layer.isValid())
415-
self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
416-
417-
# crs
418-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM, QgsCoordinateReferenceSystem.fromEpsgId(3111))
419-
self.assertTrue(layer.isValid())
420-
self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
421-
self.assertTrue(layer.crs().isValid())
422-
self.assertEqual(layer.crs().authid(), 'EPSG:3111')
423-
424-
# fields
425-
fields = QgsFields()
426-
fields.append(QgsField("string", QVariant.String))
427-
fields.append(QgsField("long", QVariant.LongLong))
428-
fields.append(QgsField("double", QVariant.Double))
429-
fields.append(QgsField("integer", QVariant.Int))
430-
fields.append(QgsField("date", QVariant.Date))
431-
fields.append(QgsField("datetime", QVariant.DateTime))
432-
fields.append(QgsField("time", QVariant.Time))
433-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
434-
self.assertTrue(layer.isValid())
435-
self.assertFalse(layer.fields().isEmpty())
436-
self.assertEqual(len(layer.fields()), len(fields))
437-
for i in range(len(fields)):
438-
self.assertEqual(layer.fields()[i].name(), fields[i].name())
439-
self.assertEqual(layer.fields()[i].type(), fields[i].type())
440-
441-
# unsupported field type
442-
fields = QgsFields()
443-
fields.append(QgsField("rect", QVariant.RectF))
444-
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
445-
self.assertTrue(layer.isValid())
446-
self.assertFalse(layer.fields().isEmpty())
447-
self.assertEqual(layer.fields()[0].name(), 'rect')
448-
self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string
449-
450385
def testThreadSafetyWithIndex(self):
451386
layer = QgsVectorLayer('Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:int8&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
452387
'test', 'pythonprovider')

0 commit comments

Comments
 (0)
Please sign in to comment.