mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-18 00:03:05 -04:00
Added QgsDataProvider::ProviderOptions to the bindings
This commit is contained in:
parent
0fa88e6faf
commit
3aa630ca25
@ -50,14 +50,14 @@ no library is involved.
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource ) -> QgsDataProvider*
|
||||
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource, const QgsDataProvider::ProviderOptions &providerOptions ) -> QgsDataProvider*
|
||||
{
|
||||
QgsDataProvider *provider;
|
||||
provider = nullptr;
|
||||
PyObject *sipResObj;
|
||||
SIP_BLOCK_THREADS
|
||||
|
||||
sipResObj = sipCallMethod( NULL, a2, "D", new QString( dataSource ), sipType_QString, NULL );
|
||||
sipResObj = sipCallMethod( NULL, a2, "DD", new QString( dataSource ), sipType_QString, NULL, new QgsDataProvider::ProviderOptions( providerOptions ), sipType_QgsDataProvider_ProviderOptions, NULL );
|
||||
|
||||
if ( sipResObj )
|
||||
{
|
||||
|
@ -182,7 +182,7 @@ Returns a string containing the available protocol drivers
|
||||
|
||||
void registerProvider( QgsProviderMetadata *providerMetadata /Transfer/ );
|
||||
%Docstring
|
||||
register a new vector data provider from its ``providerMetadata``
|
||||
register a new vector data provider from its ``providerMetadata``
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -71,14 +71,14 @@ class CORE_EXPORT QgsProviderMetadata
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource ) -> QgsDataProvider*
|
||||
sipCpp = new QgsProviderMetadata( *a0, *a1, [a2]( const QString &dataSource, const QgsDataProvider::ProviderOptions &providerOptions ) -> QgsDataProvider*
|
||||
{
|
||||
QgsDataProvider *provider;
|
||||
provider = nullptr;
|
||||
PyObject *sipResObj;
|
||||
SIP_BLOCK_THREADS
|
||||
|
||||
sipResObj = sipCallMethod( NULL, a2, "D", new QString( dataSource ), sipType_QString, NULL );
|
||||
sipResObj = sipCallMethod( NULL, a2, "DD", new QString( dataSource ), sipType_QString, NULL, new QgsDataProvider::ProviderOptions( providerOptions ), sipType_QgsDataProvider_ProviderOptions, NULL );
|
||||
|
||||
if ( sipResObj )
|
||||
{
|
||||
|
@ -46,6 +46,7 @@ from qgis.core import (
|
||||
QgsProviderMetadata,
|
||||
QgsGeometryEngine,
|
||||
QgsSpatialIndex,
|
||||
QgsDataProvider,
|
||||
)
|
||||
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
@ -54,7 +55,7 @@ from qgis.PyQt.QtCore import QVariant
|
||||
class PyFeatureIterator(QgsAbstractFeatureIterator):
|
||||
|
||||
def __init__(self, source, request):
|
||||
super(PyFeatureIterator, self).__init__(request)
|
||||
super().__init__(request)
|
||||
self._request = request if request is not None else QgsFeatureRequest()
|
||||
self._source = source
|
||||
self._index = 0
|
||||
@ -187,13 +188,13 @@ class PyProvider(QgsVectorDataProvider):
|
||||
return 'Python Test Provider'
|
||||
|
||||
@classmethod
|
||||
def createProvider(cls, uri):
|
||||
return PyProvider(uri)
|
||||
def createProvider(cls, uri, providerOptions):
|
||||
return PyProvider(uri, providerOptions)
|
||||
|
||||
# Implementation of functions from QgsVectorDataProvider
|
||||
|
||||
def __init__(self, uri=''):
|
||||
super(PyProvider, self).__init__(uri)
|
||||
def __init__(self, uri='', providerOptions=QgsDataProvider.ProviderOptions()):
|
||||
super().__init__(uri)
|
||||
# Use the memory layer to parse the uri
|
||||
mlayer = QgsVectorLayer(uri, 'ml', 'memory')
|
||||
self.setNativeTypes(mlayer.dataProvider().nativeTypes())
|
||||
@ -206,6 +207,7 @@ class PyProvider(QgsVectorDataProvider):
|
||||
self._subset_string = ''
|
||||
self._crs = mlayer.crs()
|
||||
self._spatialindex = None
|
||||
self._provider_options = providerOptions
|
||||
if 'index=yes'in self._uri:
|
||||
self.createSpatialIndex()
|
||||
|
||||
@ -307,16 +309,21 @@ class PyProvider(QgsVectorDataProvider):
|
||||
|
||||
def renameAttributes(self, renamedAttributes):
|
||||
result = True
|
||||
for key, new_name in renamedAttributes:
|
||||
fieldIndex = key
|
||||
# We need to replace all fields because python bindings return a copy from [] and at()
|
||||
new_fields = [self._fields.at(i) for i in range(self._fields.count())]
|
||||
for fieldIndex, new_name in renamedAttributes.items():
|
||||
if fieldIndex < 0 or fieldIndex >= self._fields.count():
|
||||
result = False
|
||||
continue
|
||||
if new_name in self._fields.indexFromName(new_name) >= 0:
|
||||
if self._fields.indexFromName(new_name) >= 0:
|
||||
#field name already in use
|
||||
result = False
|
||||
continue
|
||||
self._fields[fieldIndex].setName(new_name)
|
||||
new_fields[fieldIndex].setName(new_name)
|
||||
if result:
|
||||
self._fields = QgsFields()
|
||||
for i in range(len(new_fields)):
|
||||
self._fields.append(new_fields[i])
|
||||
return result
|
||||
|
||||
def deleteAttributes(self, attributes):
|
||||
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for the python layer provider.
|
||||
"""QGIS Unit tests for the python dataprovider.
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -144,13 +144,13 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
return self.createLayer()
|
||||
|
||||
def testGetFeaturesSubsetAttributes2(self):
|
||||
""" Override and skip this test for memory provider, as it's actually more efficient for the memory provider to return
|
||||
""" Override and skip this test for pythonprovider provider, as it's actually more efficient for the pythonprovider provider to return
|
||||
its features as direct copies (due to implicit sharing of QgsFeature)
|
||||
"""
|
||||
pass
|
||||
|
||||
def testGetFeaturesNoGeometry(self):
|
||||
""" Override and skip this test for memory provider, as it's actually more efficient for the memory provider to return
|
||||
""" Override and skip this test for pythonprovider provider, as it's actually more efficient for the pythonprovider provider to return
|
||||
its features as direct copies (due to implicit sharing of QgsFeature)
|
||||
"""
|
||||
pass
|
||||
@ -163,8 +163,8 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
def testCtors(self):
|
||||
testVectors = ["Point", "LineString", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon", "None"]
|
||||
for v in testVectors:
|
||||
layer = QgsVectorLayer(v, "test", "memory")
|
||||
assert layer.isValid(), "Failed to create valid %s memory layer" % (v)
|
||||
layer = QgsVectorLayer(v, "test", "pythonprovider")
|
||||
assert layer.isValid(), "Failed to create valid %s pythonprovider layer" % (v)
|
||||
|
||||
def testLayerGeometry(self):
|
||||
testVectors = [("Point", QgsWkbTypes.PointGeometry, QgsWkbTypes.Point),
|
||||
@ -199,7 +199,7 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
("MultiPolygon25D", QgsWkbTypes.PolygonGeometry, QgsWkbTypes.MultiPolygon25D),
|
||||
("None", QgsWkbTypes.NullGeometry, QgsWkbTypes.NoGeometry)]
|
||||
for v in testVectors:
|
||||
layer = QgsVectorLayer(v[0], "test", "memory")
|
||||
layer = QgsVectorLayer(v[0], "test", "pythonprovider")
|
||||
|
||||
myMessage = ('Expected: %s\nGot: %s\n' %
|
||||
(v[1], layer.geometryType()))
|
||||
@ -210,7 +210,7 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
assert layer.wkbType() == v[2], myMessage
|
||||
|
||||
def testAddFeatures(self):
|
||||
layer = QgsVectorLayer("Point", "test", "memory")
|
||||
layer = QgsVectorLayer("Point", "test", "pythonprovider")
|
||||
provider = layer.dataProvider()
|
||||
|
||||
res = provider.addAttributes([QgsField("name", QVariant.String),
|
||||
@ -260,7 +260,7 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
assert compareWkt(str(geom.asWkt()), "Point (10 10)"), myMessage
|
||||
|
||||
def testGetFields(self):
|
||||
layer = QgsVectorLayer("Point", "test", "memory")
|
||||
layer = QgsVectorLayer("Point", "test", "pythonprovider")
|
||||
provider = layer.dataProvider()
|
||||
|
||||
provider.addAttributes([QgsField("name", QVariant.String),
|
||||
@ -345,7 +345,7 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
assert f == importedFields.field(f.name())
|
||||
|
||||
def testRenameAttributes(self):
|
||||
layer = QgsVectorLayer("Point", "test", "memory")
|
||||
layer = QgsVectorLayer("Point", "test", "pythonprovider")
|
||||
provider = layer.dataProvider()
|
||||
|
||||
res = provider.addAttributes([QgsField("name", QVariant.String),
|
||||
@ -382,71 +382,6 @@ class TestPyQgsPythonProvider(unittest.TestCase, ProviderTestCase):
|
||||
self.assertEqual(fet.fields()[1].name(), 'mapinfo_is_the_stone_age')
|
||||
self.assertEqual(fet.fields()[2].name(), 'super_size')
|
||||
|
||||
def testUniqueSource(self):
|
||||
"""
|
||||
Similar memory layers should have unique source - some code checks layer source to identify
|
||||
matching layers
|
||||
"""
|
||||
layer = QgsVectorLayer("Point", "test", "memory")
|
||||
layer2 = QgsVectorLayer("Point", "test2", "memory")
|
||||
self.assertNotEqual(layer.source(), layer2.source())
|
||||
|
||||
def testCreateMemoryLayer(self):
|
||||
"""
|
||||
Test QgsMemoryProviderUtils.createMemoryLayer()
|
||||
"""
|
||||
|
||||
# no fields
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertEqual(layer.name(), 'my name')
|
||||
self.assertTrue(layer.fields().isEmpty())
|
||||
|
||||
# similar layers should have unique sources
|
||||
layer2 = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields())
|
||||
self.assertNotEqual(layer.source(), layer2.source())
|
||||
|
||||
# geometry type
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.Point)
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM)
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
|
||||
|
||||
# crs
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', QgsFields(), QgsWkbTypes.PolygonZM, QgsCoordinateReferenceSystem.fromEpsgId(3111))
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
|
||||
self.assertTrue(layer.crs().isValid())
|
||||
self.assertEqual(layer.crs().authid(), 'EPSG:3111')
|
||||
|
||||
# fields
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField("string", QVariant.String))
|
||||
fields.append(QgsField("long", QVariant.LongLong))
|
||||
fields.append(QgsField("double", QVariant.Double))
|
||||
fields.append(QgsField("integer", QVariant.Int))
|
||||
fields.append(QgsField("date", QVariant.Date))
|
||||
fields.append(QgsField("datetime", QVariant.DateTime))
|
||||
fields.append(QgsField("time", QVariant.Time))
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertFalse(layer.fields().isEmpty())
|
||||
self.assertEqual(len(layer.fields()), len(fields))
|
||||
for i in range(len(fields)):
|
||||
self.assertEqual(layer.fields()[i].name(), fields[i].name())
|
||||
self.assertEqual(layer.fields()[i].type(), fields[i].type())
|
||||
|
||||
# unsupported field type
|
||||
fields = QgsFields()
|
||||
fields.append(QgsField("rect", QVariant.RectF))
|
||||
layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
|
||||
self.assertTrue(layer.isValid())
|
||||
self.assertFalse(layer.fields().isEmpty())
|
||||
self.assertEqual(layer.fields()[0].name(), 'rect')
|
||||
self.assertEqual(layer.fields()[0].type(), QVariant.String) # should be mapped to string
|
||||
|
||||
def testThreadSafetyWithIndex(self):
|
||||
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',
|
||||
'test', 'pythonprovider')
|
||||
|
Loading…
x
Reference in New Issue
Block a user