def testNoDanglingFileDescriptorAfterCloseVariant2(self): ''' Test that when closing the provider all file handles are released ''' temp_dbname = self.dbname + '.no_dangling_test2' shutil.copy(self.dbname, temp_dbname) vl = QgsVectorLayer("dbname=%s table=test_n (geometry)" % temp_dbname, "test_n", "spatialite") self.assertTrue(vl.isValid()) self.assertTrue(vl.isValid()) # Consume all features. myiter = vl.getFeatures() for feature in myiter: pass # The iterator is closed if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(temp_dbname), 2) # Should release one file descriptor del vl # Non portable, but Windows testing is done with trying to unlink if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(temp_dbname), 0) # Check that deletion works well (can only fail on Windows) os.unlink(temp_dbname) self.assertFalse(os.path.exists(temp_dbname))
def testCreateUniqueValue(self): """ test creating a unique value """ layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # bad field indices self.assertFalse(QgsVectorLayerUtils.createUniqueValue(layer, -10)) self.assertFalse(QgsVectorLayerUtils.createUniqueValue(layer, 10)) # integer field self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 1), 128) # double field self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 2), 3.0) # string field self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 0), 'test_4') self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 0, 'test_1'), 'test_4') self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 0, 'seed'), 'seed') self.assertEqual(QgsVectorLayerUtils.createUniqueValue(layer, 0, 'superpig'), 'superpig_1')
def testNoDanglingFileDescriptorAfterCloseVariant2(self): ''' Test that when closing the provider all file handles are released ''' datasource = os.path.join(self.basetestpath, 'testNoDanglingFileDescriptorAfterCloseVariant2.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,\n') f.write('2,POINT(2 49)\n') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') self.assertTrue(vl.isValid()) # Consume all features. myiter = vl.getFeatures() for feature in myiter: pass # The iterator is closed, but the corresponding connection still not closed if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(datasource), 2) # Should release one file descriptor del vl # Non portable, but Windows testing is done with trying to unlink if sys.platform.startswith('linux'): self.assertEqual(count_opened_filedescriptors(datasource), 0) # Check that deletion works well (can only fail on Windows) os.unlink(datasource) self.assertFalse(os.path.exists(datasource))
def testSkipConstraintCheck(self): vl = QgsVectorLayer("dbname=%s table=test_autoincrement" % self.dbname, "test_autoincrement", "spatialite") self.assertTrue(vl.isValid()) self.assertTrue(vl.dataProvider().skipConstraintCheck(0, QgsFieldConstraints.ConstraintUnique, str("Autogenerate"))) self.assertFalse(vl.dataProvider().skipConstraintCheck(0, QgsFieldConstraints.ConstraintUnique, 123))
def checkRepaintNonLabeledLayerDoesNotInvalidateLabelCache(self, job_type): layer = QgsVectorLayer("Point?field=fldtxt:string", "layer1", "memory") settings = QgsMapSettings() settings.setExtent(QgsRectangle(5, 25, 25, 45)) settings.setOutputSize(QSize(600, 400)) settings.setLayers([layer]) # with cache - first run should populate cache cache = QgsMapRendererCache() job = job_type(settings) job.setCache(cache) job.start() job.waitForFinished() self.assertFalse(job.usedCachedLabels()) self.assertTrue(cache.hasCacheImage('_labels_')) self.assertTrue(cache.hasCacheImage(layer.id())) self.assertEqual(cache.dependentLayers('_labels_'), []) # trigger repaint on layer - should not invalidate label cache because layer is not labeled layer.triggerRepaint() self.assertTrue(cache.hasCacheImage('_labels_')) self.assertFalse(cache.hasCacheImage(layer.id())) self.assertTrue(job.takeLabelingResults()) # second job should still use label cache job = job_type(settings) job.setCache(cache) job.start() job.waitForFinished() self.assertTrue(job.usedCachedLabels()) self.assertTrue(cache.hasCacheImage('_labels_')) self.assertTrue(job.takeLabelingResults())
def test_ValueMap_representValue(self): layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string", "layer", "memory") assert layer.isValid() QgsMapLayerRegistry.instance().addMapLayer(layer) f = QgsFeature() f.setAttributes([2, 2.5, 'NULL', None, None, None]) assert layer.dataProvider().addFeatures([f]) reg = QgsEditorWidgetRegistry.instance() factory = reg.factory("ValueMap") self.assertIsNotNone(factory) # Tests with different value types occurring in the value map config = {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL', 'nothing': self.VALUEMAP_NULL_TEXT} self.assertEqual(factory.representValue(layer, 0, config, None, 2), 'two') self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), 'twoandhalf') self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), 'NULL text') # Tests with null values of different types, if value map contains null self.assertEqual(factory.representValue(layer, 3, config, None, None), 'nothing') self.assertEqual(factory.representValue(layer, 4, config, None, None), 'nothing') self.assertEqual(factory.representValue(layer, 5, config, None, None), 'nothing') # Tests with fallback display for different value types config = {} self.assertEqual(factory.representValue(layer, 0, config, None, 2), '(2)') self.assertEqual(factory.representValue(layer, 1, config, None, 2.5), '(2.50000)') self.assertEqual(factory.representValue(layer, 2, config, None, 'NULL'), '(NULL)') # Tests with fallback display for null in different types of fields self.assertEqual(factory.representValue(layer, 3, config, None, None), '(NULL)') self.assertEqual(factory.representValue(layer, 4, config, None, None), '(NULL)') self.assertEqual(factory.representValue(layer, 5, config, None, None), '(NULL)') QgsMapLayerRegistry.instance().removeAllMapLayers()
def testKey(lyr, key, kfnames): self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.import_test') uri = '%s table="qgis_test"."import_test" (g)' % self.dbconn if key is not None: uri += ' key=\'%s\'' % key err = QgsVectorLayerExporter.exportLayer(lyr, uri, "postgres", lyr.crs()) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) olyr = QgsVectorLayer(uri, "y", "postgres") self.assertTrue(olyr.isValid()) flds = lyr.fields() oflds = olyr.fields() if key is None: # if the pkey was not given, it will create a pkey self.assertEqual(oflds.size(), flds.size() + 1) self.assertEqual(oflds[0].name(), kfnames[0]) for i in range(flds.size()): self.assertEqual(oflds[i + 1].name(), flds[i].name()) else: # pkey was given, no extra field generated self.assertEqual(oflds.size(), flds.size()) for i in range(oflds.size()): self.assertEqual(oflds[i].name(), flds[i].name()) pks = olyr.pkAttributeList() self.assertEqual(len(pks), len(kfnames)) for i in range(0, len(kfnames)): self.assertEqual(oflds[pks[i]].name(), kfnames[i])
def testFilter(self): """ test calculating aggregate with filter """ layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) agg = QgsAggregateCalculator(layer) filter_string = "fldint > 2" agg.setFilter(filter_string) self.assertEqual(agg.filter(), filter_string) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 20) # remove filter and retest agg.setFilter(None) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint') self.assertTrue(ok) self.assertEqual(val, 24)
def createLayer(cls): vl = QgsVectorLayer( 'Point?crs=epsg:4326&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk', 'test', 'pythonprovider') assert (vl.isValid()) f1 = QgsFeature() f1.setAttributes([5, -200, NULL, 'NuLl', '5']) f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)')) f2 = QgsFeature() f2.setAttributes([3, 300, 'Pear', 'PEaR', '3']) f3 = QgsFeature() f3.setAttributes([1, 100, 'Orange', 'oranGe', '1']) f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)')) f4 = QgsFeature() f4.setAttributes([2, 200, 'Apple', 'Apple', '2']) f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)')) f5 = QgsFeature() f5.setAttributes([4, 400, 'Honey', 'Honey', '4']) f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)')) vl.dataProvider().addFeatures([f1, f2, f3, f4, f5]) return vl
def testSaveLoadProject(self): schema_uri = encode_uri(self.ds_uri, 'qgis_test') project_uri = encode_uri(self.ds_uri, 'qgis_test', 'abc') self.dropProjectsTable() # make sure we have a clean start prj = QgsProject() uri = self.vl.source() vl1 = QgsVectorLayer(uri, 'test', 'postgres') self.assertEqual(vl1.isValid(), True) prj.addMapLayer(vl1) prj_storage = QgsApplication.projectStorageRegistry().projectStorageFromType("postgresql") self.assertTrue(prj_storage) lst0 = prj_storage.listProjects(schema_uri) self.assertEqual(lst0, []) # try to save project in the database prj.setFileName(project_uri) res = prj.write() self.assertTrue(res) lst1 = prj_storage.listProjects(schema_uri) self.assertEqual(lst1, ["abc"]) # now try to load the project back prj2 = QgsProject() prj2.setFileName(project_uri) res = prj2.read() self.assertTrue(res) self.assertEqual(len(prj2.mapLayers()), 1) self.assertEqual(prj2.baseName(), "abc") self.assertEqual(prj2.absoluteFilePath(), "") # path not supported for project storages self.assertTrue(abs(prj2.lastModified().secsTo(QDateTime.currentDateTime())) < 10) # try to see project's metadata res, metadata = prj_storage.readProjectStorageMetadata(project_uri) self.assertTrue(res) self.assertEqual(metadata.name, "abc") time_project = metadata.lastModified time_now = QDateTime.currentDateTime() time_diff = time_now.secsTo(time_project) self.assertTrue(abs(time_diff) < 10) # try to remove the project res = prj_storage.removeProject(project_uri) self.assertTrue(res) lst2 = prj_storage.listProjects(schema_uri) self.assertEqual(lst2, []) self.dropProjectsTable() # make sure we have a clean finish... "leave no trace"
def aoiExtent(cls): """Area of interest extent, which matches output aspect ratio""" uri = QgsDataSourceUri() uri.setDatabase(cls._PalFeaturesDb) uri.setDataSource('', 'aoi', 'geometry') aoilayer = QgsVectorLayer(uri.uri(), 'aoi', 'spatialite') return aoilayer.extent()
def runTestForLayer(self, layer, testname): tempdir = tempfile.mkdtemp() layer = QgsVectorLayer(layer, 'Layer', 'ogr') QgsProject.instance().addMapLayer(layer) self.iface.mapCanvas().setExtent(layer.extent()) geom = next(layer.getFeatures()).geometry() highlight = QgsHighlight(self.iface.mapCanvas(), geom, layer) color = QColor(Qt.red) highlight.setColor(color) highlight.setWidth(2) color.setAlpha(50) highlight.setFillColor(color) highlight.show() image = QImage(QSize(400, 400), QImage.Format_ARGB32) image.fill(Qt.white) painter = QPainter() painter.begin(image) self.iface.mapCanvas().render(painter) painter.end() control_image = os.path.join(tempdir, 'highlight_{}.png'.format(testname)) image.save(control_image) checker = QgsRenderChecker() checker.setControlPathPrefix("highlight") checker.setControlName("expected_highlight_{}".format(testname)) checker.setRenderedImage(control_image) self.assertTrue(checker.compareImages("highlight_{}".format(testname))) shutil.rmtree(tempdir)
def setUp(self): self.iface = get_iface() polys_shp = os.path.join(TEST_DATA_DIR, 'polys.shp') points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.polys_layer = QgsVectorLayer(polys_shp, 'Polygons', 'ogr') self.points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsProject.instance().addMapLayer(self.polys_layer) QgsProject.instance().addMapLayer(self.lines_layer) QgsProject.instance().addMapLayer(self.points_layer) # Create style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) sym2 = QgsLineSymbol.createSimple({'color': '#fdbf6f'}) sym3 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) self.polys_layer.setRenderer(QgsSingleSymbolRenderer(sym1)) self.lines_layer.setRenderer(QgsSingleSymbolRenderer(sym2)) self.points_layer.setRenderer(QgsSingleSymbolRenderer(sym3)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-133, 22, -70, 52))
def __init__(self, name='', description='', options=[], default=None, isSource=False, multiple=False, optional=False): Parameter.__init__(self, name, description, default, optional) self.multiple = multiple isSource = parseBool(isSource) self.options = options if isSource: self.options = [] layer = QgsVectorLayer(options[0], "layer", "ogr") if layer.isValid(): try: index = resolveFieldIndex(layer, options[1]) feats = QgsProcessingUtils.getFeatures(layer, dataobjects.createContext()) for feature in feats: self.options.append(str(feature.attributes()[index])) except ValueError: pass elif isinstance(self.options, str): self.options = self.options.split(";") # compute options as (value, text) options = [] for i, option in enumerate(self.options): if option is None or isinstance(option, basestring): options.append((i, option)) else: options.append((option[0], option[1])) self.options = options self.values = [option[0] for option in options] self.value = None
def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp') layer = QgsVectorLayer(myShpFile, 'Points', 'ogr') QgsProject.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbol.createSimple({'color': '#fdbf6f', 'outline_color': 'black'}) sym2 = QgsFillSymbol.createSimple({'color': '#71bd6c', 'outline_color': 'black'}) sym3 = QgsFillSymbol.createSimple({'color': '#1f78b4', 'outline_color': 'black'}) self.r1 = QgsRuleBasedRenderer.Rule(sym1, 0, 0, '"id" = 1') self.r2 = QgsRuleBasedRenderer.Rule(sym2, 0, 0, '"id" = 2') self.r3 = QgsRuleBasedRenderer.Rule(sym3, 0, 0, 'ELSE') rootrule = QgsRuleBasedRenderer.Rule(None) rootrule.appendChild(self.r1) rootrule.appendChild(self.r2) rootrule.appendChild(self.r3) layer.setRenderer(QgsRuleBasedRenderer(rootrule)) self.mapsettings = QgsMapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) rendered_layers = [layer] self.mapsettings.setLayers(rendered_layers)
def _round_trip(value, field, version='1.1.0'): """Set a value on fid 22 and field and check it back""" encoded_data = post_data.format(field=field, value=value, version=version).encode('utf8') # Strip the field if NULL if value is None: encoded_data = encoded_data.replace(b'<wfs:Value>None</wfs:Value>', b'') header, body = self._execute_request("?MAP=%s&SERVICE=WFS&VERSION=%s" % ( self.testdata_path + 'test_project_wms_grouped_layers.qgs', version), QgsServerRequest.PostMethod, encoded_data) if version == '1.0.0': self.assertTrue(b'<SUCCESS/>' in body, body) else: self.assertTrue(b'<TotalUpdated>1</TotalUpdated>' in body, body) header, body = self._execute_request("?MAP=%s&SERVICE=WFS&REQUEST=GetFeature&TYPENAME=cdb_lines&FEATUREID=cdb_lines.22" % ( self.testdata_path + 'test_project_wms_grouped_layers.qgs')) if value is not None: xml_value = '<qgs:{0}>{1}</qgs:{0}>'.format(field, value).encode('utf8') self.assertTrue(xml_value in body, "%s not found in body" % xml_value) else: xml_value = '<qgs:{0}>'.format(field).encode('utf8') self.assertFalse(xml_value in body) # Check the backend vl = QgsVectorLayer( self.testdata_path + 'test_project_wms_grouped_layers.gpkg|layername=cdb_lines', 'vl', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual( str(vl.getFeature(22)[field]), value if value is not None else 'NULL')
def test_expressionRequiresFormScope(self): res = list(QgsValueRelationFieldFormatter.expressionFormAttributes("current_value('ONE') AND current_value('TWO')")) res = sorted(res) self.assertEqual(res, ['ONE', 'TWO']) res = list(QgsValueRelationFieldFormatter.expressionFormVariables("@current_geometry")) self.assertEqual(res, ['current_geometry']) self.assertFalse(QgsValueRelationFieldFormatter.expressionRequiresFormScope("")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value('TWO')")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value ( 'TWO' )")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("@current_geometry")) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", QgsFeature())) layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string", "layer", "memory") self.assertTrue(layer.isValid()) QgsProject.instance().addMapLayer(layer) f = QgsFeature(layer.fields()) f.setAttributes([1, 'value']) point = QgsGeometry.fromPointXY(QgsPointXY(123, 456)) f.setGeometry(point) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_geometry", f)) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'pkid' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry current_value ( 'pkid' )", f)) QgsProject.instance().removeMapLayer(layer.id())
def testUniqueValues(self): ProcessingConfig.initialize() # disable check for geometry validity prevInvalidGeoms = ProcessingConfig.getSetting(ProcessingConfig.FILTER_INVALID_GEOMETRIES) ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, 0) test_data = points() test_layer = QgsVectorLayer(test_data, 'test', 'ogr') # field by index v = vector.uniqueValues(test_layer, 2) self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([2, 1, 0])) # field by name v = vector.uniqueValues(test_layer, 'id2') self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([2, 1, 0])) # test with selected features previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True) test_layer.selectByIds([2, 4, 6]) v = vector.uniqueValues(test_layer, 'id') self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([5, 7, 3])) ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value) ProcessingConfig.setSettingValue(ProcessingConfig.FILTER_INVALID_GEOMETRIES, prevInvalidGeoms)
def test_representValue(self): QgsSettings().setValue("qgis/nullValue", "NULL") layer = QgsVectorLayer("none?field=number1:integer&field=number2:double&field=text1:string&field=number3:integer&field=number4:double&field=text2:string", "layer", "memory") self.assertTrue(layer.isValid()) QgsProject.instance().addMapLayer(layer) f = QgsFeature() f.setAttributes([2, 2.5, 'NULL', None, None, None]) layer.dataProvider().addFeatures([f]) fieldFormatter = QgsValueMapFieldFormatter() # Tests with different value types occurring in the value map config = {'map': {'two': '2', 'twoandhalf': '2.5', 'NULL text': 'NULL', 'nothing': self.VALUEMAP_NULL_TEXT}} self.assertEqual(fieldFormatter.representValue(layer, 0, config, None, 2), 'two') self.assertEqual(fieldFormatter.representValue(layer, 1, config, None, 2.5), 'twoandhalf') self.assertEqual(fieldFormatter.representValue(layer, 2, config, None, 'NULL'), 'NULL text') # Tests with null values of different types, if value map contains null self.assertEqual(fieldFormatter.representValue(layer, 3, config, None, None), 'nothing') self.assertEqual(fieldFormatter.representValue(layer, 4, config, None, None), 'nothing') self.assertEqual(fieldFormatter.representValue(layer, 5, config, None, None), 'nothing') # Tests with fallback display for different value types config = {} self.assertEqual(fieldFormatter.representValue(layer, 0, config, None, 2), '(2)') self.assertEqual(fieldFormatter.representValue(layer, 1, config, None, 2.5), '(2.50000)') self.assertEqual(fieldFormatter.representValue(layer, 2, config, None, 'NULL'), '(NULL)') # Tests with fallback display for null in different types of fields self.assertEqual(fieldFormatter.representValue(layer, 3, config, None, None), '(NULL)') self.assertEqual(fieldFormatter.representValue(layer, 4, config, None, None), '(NULL)') self.assertEqual(fieldFormatter.representValue(layer, 5, config, None, None), '(NULL)') QgsProject.instance().removeAllMapLayers()
def testSettingFeature(self): """ test that feature is set when item moves """ a = QgsTextAnnotation() a.setFrameSizeMm(QSizeF(300 / 3.7795275, 200 / 3.7795275)) a.setFrameOffsetFromReferencePointMm(QPointF(40 / 3.7795275, 50 / 3.7795275)) a.setHasFixedMapPosition(True) a.setMapPosition(QgsPointXY(12, 34)) a.setMapPositionCrs(QgsCoordinateReferenceSystem(4326)) canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) i = QgsMapCanvasAnnotationItem(a, canvas) # NOQA layer = QgsVectorLayer("Point?crs=EPSG:4326&field=station:string&field=suburb:string", 'test', "memory") canvas.setLayers([layer]) f = QgsFeature(layer.fields()) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(14, 31))) f.setValid(True) f.setAttributes(['hurstbridge', 'somewhere']) self.assertTrue(layer.dataProvider().addFeatures([f])) a.setMapLayer(layer) self.assertFalse(a.associatedFeature().isValid()) a.setMapPosition(QgsPointXY(14, 31)) self.assertTrue(a.associatedFeature().isValid()) self.assertEqual(a.associatedFeature().attributes()[0], 'hurstbridge') a.setMapPosition(QgsPointXY(17, 31)) self.assertFalse(a.associatedFeature().isValid())
def __init__(self, name='', description='', options=[], default=None, isSource=False, optional=False): Parameter.__init__(self, name, description, default, optional) isSource = parseBool(isSource) self.options = options if isSource: self.options = [] layer = QgsVectorLayer(options[0], "layer", "ogr") if layer.isValid(): try: index = resolveFieldIndex(layer, options[1]) feats = features(layer) for feature in feats: self.options.append(unicode(feature.attributes()[index])) except ValueError: pass elif isinstance(self.options, basestring): self.options = self.options.split(";") if default is not None: try: self.default = int(default) except: self.default = 0 self.value = self.default
def testTriangleTINPolyhedralSurface(self): """ Test support for Triangles (mapped to Polygons) """ testsets = ( ("Triangle((0 0, 0 1, 1 1, 0 0))", QgsWkbTypes.Triangle, "Triangle ((0 0, 0 1, 1 1, 0 0))"), ("Triangle Z((0 0 1, 0 1 2, 1 1 3, 0 0 1))", QgsWkbTypes.TriangleZ, "TriangleZ ((0 0 1, 0 1 2, 1 1 3, 0 0 1))"), ("Triangle M((0 0 4, 0 1 5, 1 1 6, 0 0 4))", QgsWkbTypes.TriangleM, "TriangleM ((0 0 4, 0 1 5, 1 1 6, 0 0 4))"), ("Triangle ZM((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))", QgsWkbTypes.TriangleZM, "TriangleZM ((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))"), ("TIN (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("TIN Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("TIN M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("TIN ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))"), ("PolyhedralSurface (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("PolyhedralSurface Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("PolyhedralSurface M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("PolyhedralSurface ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))") ) for row in testsets: datasource = os.path.join(self.basetestpath, 'test.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,"%s"' % row[0]) vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), row[1]) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest(1)).nextFeature(f)) self.assertTrue(f.geometry()) self.assertEqual(f.geometry().constGet().asWkt(), row[2])
def testWriteWithBinaryField(self): """ Test writing with a binary field :return: """ basetestpath = tempfile.mkdtemp() tmpfile = os.path.join(basetestpath, 'binaryfield.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('binfield', ogr.OFTBinary)) lyr.CreateField(ogr.FieldDefn('binfield2', ogr.OFTBinary)) f = None ds = None vl = QgsVectorLayer(tmpfile) self.assertTrue(vl.isValid()) # check that 1 of its fields is a bool fields = vl.fields() self.assertEqual(fields.at(fields.indexFromName('binfield')).type(), QVariant.ByteArray) dp = vl.dataProvider() f = QgsFeature(fields) bin_1 = b'xxx' bin_2 = b'yyy' bin_val1 = QByteArray(bin_1) bin_val2 = QByteArray(bin_2) f.setAttributes([1, 'str', 100, bin_val1, bin_val2]) self.assertTrue(dp.addFeature(f)) # write a gpkg package with a binary field filename = os.path.join(str(QDir.tempPath()), 'with_bin_field') rc, errmsg = QgsVectorFileWriter.writeAsVectorFormat(vl, filename, 'utf-8', vl.crs(), 'GPKG') self.assertEqual(rc, QgsVectorFileWriter.NoError) # open the resulting geopackage vl = QgsVectorLayer(filename + '.gpkg', '', 'ogr') self.assertTrue(vl.isValid()) fields = vl.fields() # test type of converted field idx = fields.indexFromName('binfield') self.assertEqual(fields.at(idx).type(), QVariant.ByteArray) idx2 = fields.indexFromName('binfield2') self.assertEqual(fields.at(idx2).type(), QVariant.ByteArray) # test values self.assertEqual(vl.getFeature(1).attributes()[idx], bin_val1) self.assertEqual(vl.getFeature(1).attributes()[idx2], bin_val2) del vl os.unlink(filename + '.gpkg')
def getSource(self): # create temporary table for edit tests self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.edit_data') self.execSQLCommand( """CREATE TABLE qgis_test.edit_data (pk INTEGER PRIMARY KEY,cnt integer, name nvarchar(max), name2 nvarchar(max), num_char nvarchar(max), geom geometry)""") vl = QgsVectorLayer( self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POINT table="qgis_test"."edit_data" (geom) sql=', 'test', 'mssql') self.assertTrue(vl.isValid(), vl.dataProvider().error().message()) f1 = QgsFeature() f1.setAttributes([5, -200, NULL, 'NuLl', '5']) f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)')) f2 = QgsFeature() f2.setAttributes([3, 300, 'Pear', 'PEaR', '3']) f3 = QgsFeature() f3.setAttributes([1, 100, 'Orange', 'oranGe', '1']) f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)')) f4 = QgsFeature() f4.setAttributes([2, 200, 'Apple', 'Apple', '2']) f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)')) f5 = QgsFeature() f5.setAttributes([4, 400, 'Honey', 'Honey', '4']) f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)')) self.assertTrue(vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])) return vl
def testUniqueValues(self): ProcessingConfig.initialize() test_data = points() test_layer = QgsVectorLayer(test_data, 'test', 'ogr') # field by index v = vector.uniqueValues(test_layer, 2) self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([2, 1, 0])) # field by name v = vector.uniqueValues(test_layer, 'id2') self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([2, 1, 0])) # test with selected features previous_value = ProcessingConfig.getSetting(ProcessingConfig.USE_SELECTED) ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, True) test_layer.selectByIds([2, 4, 6]) v = vector.uniqueValues(test_layer, 'id') self.assertEqual(len(v), len(set(v))) self.assertEqual(set(v), set([5, 7, 3])) ProcessingConfig.setSettingValue(ProcessingConfig.USE_SELECTED, previous_value)
def testBool(self): vl = QgsVectorLayer( 'Point?crs=epsg:4326&field=f1:integer&field=f2:bool', 'test', 'memory') self.assertTrue(vl.isValid()) dp = vl.dataProvider() fields = dp.fields() self.assertEqual([f.name() for f in fields], ['f1', 'f2']) self.assertEqual([f.type() for f in fields], [QVariant.Int, QVariant.Bool]) self.assertEqual([f.typeName() for f in fields], ['integer', 'boolean']) f = QgsFeature(dp.fields()) f.setAttributes([1, True]) f2 = QgsFeature(dp.fields()) f2.setAttributes([2, False]) f3 = QgsFeature(dp.fields()) f3.setAttributes([3, NULL]) self.assertTrue(dp.addFeatures([f, f2, f3])) self.assertEqual([f.attributes() for f in dp.getFeatures()], [[1, True], [2, False], [3, NULL]]) # add boolean field self.assertTrue(dp.addAttributes([QgsField('boolfield2', QVariant.Bool, 'Boolean')])) fields = dp.fields() bool2_field = fields[fields.lookupField('boolfield2')] self.assertEqual(bool2_field.type(), QVariant.Bool) self.assertEqual(bool2_field.typeName(), 'Boolean') f = QgsFeature(fields) f.setAttributes([2, NULL, True]) self.assertTrue(dp.addFeature(f)) self.assertEqual([f.attributes() for f in dp.getFeatures()], [[1, True, NULL], [2, False, NULL], [3, NULL, NULL], [2, NULL, True]])
def get_layer(layer_path): """Get layer from path. .. versionadded:: 3.2 :param layer_path: User inputs. :type layer_path: CommandLineArguments :returns: Vector or Raster layer depending on input arguments. :rtype: QgsVectorLayer, QgsRasterLayer :raises: Exception """ layer = None try: if os.path.splitext(layer_path)[1] == ".shp": layer_base = join_if_relative(layer_path) layer = QgsVectorLayer(layer_base, "cli_vector_hazard", "ogr") elif os.path.splitext(layer_path)[1] in [".asc", ".tif", ".tiff"]: layer_base = join_if_relative(layer_path) layer = QgsRasterLayer(layer_base, "cli_raster_hazard") else: print "Unknown filetype " + layer_path if layer is not None and layer.isValid(): print "layer is VALID" else: print "layer is NOT VALID" print "Perhaps run-env-linux.sh /usr" return layer except Exception as exception: print exception.message print exception.__doc__
def testSurfaces(self): vl = QgsVectorLayer('%s table="QGIS"."POLY_DATA" (GEOM) srid=4326 type=POLYGON sql=' % (self.dbconn), "testpoly", "oracle") self.assertTrue(vl.isValid()) features = {f['pk']: f for f in vl.getFeatures()} self.assertTrue(compareWkt(features[1].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2))', 0.00001), features[1].geometry().asWkt()) self.assertTrue(compareWkt(features[2].geometry().asWkt(), 'PolygonZ ((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3))', 0.00001), features[2].geometry().asWkt()) self.assertTrue( compareWkt(features[3].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2),(5 6, 8 9, 8 6, 5 6),(3 4, 5 6, 3 6, 3 4))', 0.00001), features[3].geometry().asWkt()) self.assertTrue( compareWkt(features[4].geometry().asWkt(), 'PolygonZ ((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3),(5 6 1, 8 9 -1, 8 6 2, 5 6 1))', 0.00001), features[4].geometry().asWkt()) self.assertTrue( compareWkt(features[5].geometry().asWkt(), 'Polygon ((1 2, 11 2, 11 22, 1 22, 1 2))', 0.00001), features[5].geometry().asWkt()) self.assertTrue( compareWkt(features[6].geometry().asWkt(), 'CurvePolygon (CircularString (6.76923076923076916 22.82875364393326834, 17.98259979777942519 11.61538461538461497, 6.76923076923076916 0.40201558683595984, -4.44413825931788598 11.61538461538461497, 6.76923076923076916 22.82875364393326834))', 0.00001), features[6].geometry().asWkt()) self.assertTrue( compareWkt(features[7].geometry().asWkt(), 'MultiPolygon (((1 2, 11 2, 11 22, 1 22, 1 2)),((1 2, 11 2, 11 22, 1 22, 1 2),(5 6, 8 9, 8 6, 5 6),(3 4, 5 6, 3 6, 3 4)))', 0.00001), features[7].geometry().asWkt()) self.assertTrue( compareWkt(features[8].geometry().asWkt(), 'MultiPolygonZ (((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3)),((1 2 3, 11 2 13, 11 22 15, 1 22 7, 1 2 3),(5 6 1, 8 9 -1, 8 6 2, 5 6 1)))', 0.00001), features[8].geometry().asWkt()) self.assertTrue( compareWkt(features[9].geometry().asWkt(), 'CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3))', 0.00001), features[9].geometry().asWkt()) self.assertTrue( compareWkt(features[10].geometry().asWkt(), 'CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3),CircularString (3.1 3.3, 3.3 3.5, 3.4 3.7, 3.7 3.3, 3.1 3.3))', 0.00001), features[10].geometry().asWkt()) self.assertTrue( compareWkt(features[11].geometry().asWkt(), 'CurvePolygon(CompoundCurve ((-1 -5, 1 2),CircularString (1 2, 5 4, 7 2.20, 10 0.1, 13 4),(13 4, 17 -6),CircularString (17 -6, 5 -7, -1 -5)))', 0.00001), features[11].geometry().asWkt()) self.assertTrue( compareWkt(features[12].geometry().asWkt(), 'MultiSurface (CurvePolygon (CircularString (1 3, 3 5, 4 7, 7 3, 1 3)),CurvePolygon (CircularString (11 3, 13 5, 14 7, 17 3, 11 3)))', 0.00001), features[12].geometry().asWkt())
def testReplaceLayerWhileOpen(self): ''' Replace an existing geopackage layer whilst it's open in the project''' tmpfile = os.path.join(self.basetestpath, 'testGeopackageReplaceOpenLayer.gpkg') ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile) lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('attr2', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)')) lyr.CreateFeature(f) f = None vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr') p = QgsProject() p.addMapLayer(vl1) request = QgsFeatureRequest().setSubsetOfAttributes([0]) features = [f for f in vl1.getFeatures(request)] self.assertEqual(len(features), 1) # now, overwrite the layer with a different geometry type and fields ds.DeleteLayer('layer1') lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbLineString) lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('LineString(0 0, 1 1)')) lyr.CreateFeature(f) f = None vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer2', u'ogr') p.addMapLayer(vl2) features = [f for f in vl1.getFeatures(request)] self.assertEqual(len(features), 1)
def testSetupProxy(self): """Test proxy setup""" settings = QgsSettings() settings.setValue("proxy/proxyEnabled", True) settings.setValue("proxy/proxyPort", '1234') settings.setValue("proxy/proxyHost", 'myproxyhostname.com') settings.setValue("proxy/proxyUser", 'username') settings.setValue("proxy/proxyPassword", 'password') settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com") QgsNetworkAccessManager.instance().setupDefaultProxyAndCache() vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com:1234") self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username:password") settings.setValue("proxy/proxyEnabled", True) settings.remove("proxy/proxyPort") settings.setValue("proxy/proxyHost", 'myproxyhostname.com') settings.setValue("proxy/proxyUser", 'username') settings.remove("proxy/proxyPassword") settings.setValue("proxy/proxyExcludedUrls", "http://www.myhost.com|http://www.myotherhost.com") QgsNetworkAccessManager.instance().setupDefaultProxyAndCache() vl = QgsVectorLayer(TEST_DATA_DIR + '/' + 'lines.shp', 'proxy_test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXY"), "myproxyhostname.com") self.assertEqual(gdal.GetConfigOption("GDAL_HTTP_PROXYUSERPWD"), "username")
class TestQgsPointDisplacementRenderer(unittest.TestCase): def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'points.shp') self.layer = QgsVectorLayer(myShpFile, 'Points', 'ogr') QgsProject.instance().addMapLayer(self.layer) self.renderer = QgsPointDisplacementRenderer() sym1 = QgsMarkerSymbol.createSimple({ 'color': '#ff00ff', 'size': '3', 'outline_style': 'no' }) renderer = QgsSingleSymbolRenderer(sym1) self.renderer.setEmbeddedRenderer(renderer) self.renderer.setCircleRadiusAddition(2) self.renderer.setCircleWidth(1) self.renderer.setCircleColor(QColor(0, 0, 0)) self.renderer.setCenterSymbol( QgsMarkerSymbol.createSimple({ 'color': '#ffff00', 'size': '3', 'outline_style': 'no' })) self.layer.setRenderer(self.renderer) rendered_layers = [self.layer] self.mapsettings = QgsMapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-123, 18, -70, 52)) self.mapsettings.setLayers(rendered_layers) def tearDown(self): QgsProject.instance().removeAllMapLayers() def _setProperties(self, r): """ set properties for a renderer for testing with _checkProperties""" r.setLabelAttributeName('name') f = QgsFontUtils.getStandardTestFont('Bold Oblique', 14) r.setLabelFont(f) r.setMinimumLabelScale(50000) r.setLabelColor(QColor(255, 0, 0)) r.setTolerance(5) r.setToleranceUnit(QgsUnitTypes.RenderMapUnits) r.setToleranceMapUnitScale(QgsMapUnitScale(5, 15)) r.setCircleWidth(15) r.setCircleColor(QColor(0, 255, 0)) r.setCircleRadiusAddition(2.5) r.setPlacement(QgsPointDisplacementRenderer.ConcentricRings) m = QgsMarkerSymbol() m.setColor(QColor(0, 255, 0)) r.setCenterSymbol(m) sym1 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRenderer(sym1) r.setEmbeddedRenderer(renderer) def _checkProperties(self, r): """ test properties of renderer against expected""" self.assertEqual(r.labelAttributeName(), 'name') f = QgsFontUtils.getStandardTestFont('Bold Oblique', 14) self.assertEqual(r.labelFont().styleName(), f.styleName()) self.assertEqual(r.minimumLabelScale(), 50000) self.assertEqual(r.labelColor(), QColor(255, 0, 0)) self.assertEqual(r.tolerance(), 5) self.assertEqual(r.toleranceUnit(), QgsUnitTypes.RenderMapUnits) self.assertEqual(r.toleranceMapUnitScale(), QgsMapUnitScale(5, 15)) self.assertEqual(r.circleWidth(), 15) self.assertEqual(r.circleColor(), QColor(0, 255, 0)) self.assertEqual(r.circleRadiusAddition(), 2.5) self.assertEqual(r.placement(), QgsPointDisplacementRenderer.ConcentricRings) self.assertEqual(r.centerSymbol().color(), QColor(0, 255, 0)) self.assertEqual(r.embeddedRenderer().symbol().color().name(), '#fdbf6f') def testGettersSetters(self): """ test getters and setters """ r = QgsPointDisplacementRenderer() self._setProperties(r) self._checkProperties(r) def testClone(self): """ test cloning renderer """ r = QgsPointDisplacementRenderer() self._setProperties(r) c = r.clone() self._checkProperties(c) def testSaveCreate(self): """ test saving and recreating from XML """ r = QgsPointDisplacementRenderer() self._setProperties(r) doc = QDomDocument("testdoc") elem = r.save(doc, QgsReadWriteContext()) c = QgsPointDisplacementRenderer.create(elem, QgsReadWriteContext()) self._checkProperties(c) def testConvert(self): """ test renderer conversion """ # same type, should clone r = QgsPointDisplacementRenderer() self._setProperties(r) c = QgsPointDisplacementRenderer.convertFromRenderer(r) self._checkProperties(c) # test conversion from cluster renderer r = QgsPointClusterRenderer() r.setTolerance(5) r.setToleranceUnit(QgsUnitTypes.RenderMapUnits) r.setToleranceMapUnitScale(QgsMapUnitScale(5, 15)) m = QgsMarkerSymbol() m.setColor(QColor(0, 255, 0)) r.setClusterSymbol(m) sym1 = QgsMarkerSymbol.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRenderer(sym1) r.setEmbeddedRenderer(renderer) # want to keep as many settings as possible when converting between cluster and displacement renderer d = QgsPointDisplacementRenderer.convertFromRenderer(r) self.assertEqual(d.tolerance(), 5) self.assertEqual(d.toleranceUnit(), QgsUnitTypes.RenderMapUnits) self.assertEqual(d.toleranceMapUnitScale(), QgsMapUnitScale(5, 15)) self.assertEqual(d.centerSymbol().color(), QColor(0, 255, 0)) self.assertEqual(d.embeddedRenderer().symbol().color().name(), '#fdbf6f') def testRenderNoCluster(self): self.layer.renderer().setTolerance(1) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_no_cluster') self.assertTrue(renderchecker.runTest('displacement_no_cluster')) def testRenderWithin(self): self.layer.renderer().setTolerance(10) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_cluster') self.assertTrue(renderchecker.runTest('expected_displacement_cluster')) def testRenderVariables(self): """ test rendering with expression variables in marker """ self.layer.renderer().setTolerance(10) old_marker = self.layer.renderer().centerSymbol().clone() new_marker = QgsMarkerSymbol.createSimple({ 'color': '#ffff00', 'size': '3', 'outline_style': 'no' }) new_marker.symbolLayer(0).setDataDefinedProperty( QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression('@cluster_color')) new_marker.symbolLayer(0).setDataDefinedProperty( QgsSymbolLayer.PropertySize, QgsProperty.fromExpression('@cluster_size*2')) self.layer.renderer().setCenterSymbol(new_marker) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_variables') result = renderchecker.runTest('expected_displacement_variables') self.layer.renderer().setCenterSymbol(old_marker) self.assertTrue(result) def testRenderGrid(self): self.layer.renderer().setTolerance(10) self.layer.renderer().setPlacement(QgsPointDisplacementRenderer.Grid) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_grid') self.assertTrue(renderchecker.runTest('expected_displacement_grid')) def testRenderGridAdjust(self): self.layer.renderer().setTolerance(10) self.layer.renderer().setCircleRadiusAddition(5) self.layer.renderer().setPlacement(QgsPointDisplacementRenderer.Grid) self.layer.renderer().setCircleColor(QColor()) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('displacement_renderer') renderchecker.setControlName('expected_displacement_adjust_grid') self.assertTrue( renderchecker.runTest('expected_displacement_adjust_grid'))
def test_signalConnection(self): # remove all layers QgsProject.instance().removeAllMapLayers() # set dependencies and add back layers self.pointsLayer = QgsVectorLayer( "dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite") assert (self.pointsLayer.isValid()) self.linesLayer = QgsVectorLayer( "dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite") assert (self.linesLayer.isValid()) self.pointsLayer2 = QgsVectorLayer( "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite") assert (self.pointsLayer2.isValid()) self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies( [QgsMapLayerDependency(self.pointsLayer.id())]) # this should update connections between layers QgsProject.instance().addMapLayers([self.pointsLayer]) QgsProject.instance().addMapLayers([self.linesLayer]) QgsProject.instance().addMapLayers([self.pointsLayer2]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings( self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) cfg.setIndividualLayerSettings( self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(4) geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is OK m = u.snapToMap(QPoint(75, 100 - 0)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.8, 0.0)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
class TestQgsRangeWidget(unittest.TestCase): @classmethod def setUpClass(cls): QgsGui.editorWidgetRegistry().initEditors() def setUp(self): """ create a layer with one feature """ self.layer = QgsVectorLayer( "Point?crs=EPSG:21781&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = self.layer.dataProvider() # NOQA f = QgsFeature() f.setAttributes(["Hello World", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(600000, 200000))) def __createRangeWidget(self, allownull=False): """ create a range widget """ reg = QgsGui.editorWidgetRegistry() configWdg = reg.createConfigWidget('Range', self.layer, 1, None) config = configWdg.config() config["Min"] = 0 # if null shall be allowed if allownull: config["AllowNull"] = allownull rangewidget = reg.create('Range', self.layer, 1, config, None, None) return rangewidget def test_range_widget_numbers(self): """ are the numbers being returned correctly """ rangewidget = self.__createRangeWidget() rangewidget.setValue(1) assert rangewidget.value() == 1 rangewidget.setValue(0) assert rangewidget.value() == 0 def test_range_widget_no_null(self): """ are None and NULL being returned as expected """ rangewidget = self.__createRangeWidget() rangewidget.setValue(NULL) assert rangewidget.value() == 0 rangewidget.setValue(None) assert rangewidget.value() == 0 def test_range_widget_null_allowed(self): """ are None and NULL being returned as expected """ rangewidget = self.__createRangeWidget(True) rangewidget.setValue(NULL) self.assertEqual(rangewidget.value(), NULL) rangewidget.setValue(None) self.assertEqual(rangewidget.value(), NULL) rangewidget.setValue(0) self.assertEqual(rangewidget.value(), 0)
def testProjectStorage(self): # New project without fileName p0 = QgsProject() self.assertTrue(p0.auxiliaryStorage().isValid()) # Create new layers with key otherwise auxiliary layers are not # automacially created when added in project vl0 = createLayer() vl0Shp = writeShape(vl0, 'vl0.shp') vl1 = createLayer() vl1Shp = writeShape(vl1, 'vl1.shp') vl0 = QgsVectorLayer(vl0Shp, 'points', 'ogr') self.assertTrue(vl0.isValid()) vl1 = QgsVectorLayer(vl1Shp, 'points', 'ogr') self.assertTrue(vl1.isValid()) # Add layers to project and check underlying auxiliary layers p0.addMapLayers([vl0, vl1]) self.assertTrue(vl0.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'pk')) self.assertTrue(vl1.loadAuxiliaryLayer(p0.auxiliaryStorage(), 'num_char')) al0 = vl0.auxiliaryLayer() al1 = vl1.auxiliaryLayer() self.assertEqual(al0.joinInfo().targetFieldName(), 'pk') self.assertEqual(al1.joinInfo().targetFieldName(), 'num_char') # Add a field in auxiliary layers pdef0 = QgsPropertyDefinition('propname', QgsPropertyDefinition.DataTypeNumeric, '', '', 'ut') self.assertTrue(al0.addAuxiliaryField(pdef0)) pdef1 = QgsPropertyDefinition('propname1', QgsPropertyDefinition.DataTypeString, '', '', 'ut') self.assertTrue(al1.addAuxiliaryField(pdef1)) # Check auxiliary fields names af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, False) self.assertEqual(af0Name, 'ut_propname') af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, False) self.assertEqual(af1Name, 'ut_propname1') # Set value for auxiliary fields req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl0.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af0Name = QgsAuxiliaryLayer.nameFromProperty(pdef0, True) index0 = vl0.fields().indexOf(af0Name) vl0.changeAttributeValue(f.id(), index0, 333) req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) af1Name = QgsAuxiliaryLayer.nameFromProperty(pdef1, True) index1 = vl1.fields().indexOf(af1Name) vl1.changeAttributeValue(f.id(), index0, 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl1.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) vl1.changeAttributeValue(f.id(), index0, 'myvalue1') # Save the project in a zip file f = tmpPath() + '.qgz' p0.write(f) # Open the zip file with embedded auxiliary storage p1 = QgsProject() p1.read(f) # Check that auxiliary fields are well loaded in layers self.assertEqual(len(p1.mapLayers().values()), 2) for vl in p1.mapLayers().values(): al = vl.auxiliaryLayer() self.assertEqual(len(al.auxiliaryFields()), 1) af = al.auxiliaryFields()[0] afPropDef = QgsAuxiliaryLayer.propertyDefinitionFromField(af) self.assertEqual(afPropDef.origin(), 'ut') if vl.auxiliaryLayer().joinInfo().targetFieldName() == 'pk': self.assertEqual(afPropDef.name(), 'propname') self.assertEqual(al.featureCount(), 1) req = QgsFeatureRequest().setFilterExpression("name = 'Honey'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index0], 333.0) else: # num_char self.assertEqual(al.featureCount(), 2) self.assertEqual(afPropDef.name(), 'propname1') req = QgsFeatureRequest().setFilterExpression("name = 'Apple'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue') req = QgsFeatureRequest().setFilterExpression("name = 'Orange'") f = QgsFeature() vl.getFeatures(req).nextFeature(f) self.assertTrue(f.isValid()) self.assertEqual(f.attributes()[index1], 'myvalue1')
def testNumeric(self): """ Test calculation of aggregates on numeric fields""" layer = QgsVectorLayer("Point?field=fldint:integer&field=flddbl:double", "layer", "memory") pr = layer.dataProvider() # must be same length: int_values = [4, 2, 3, 2, 5, None, 8] dbl_values = [5.5, 3.5, 7.5, 5, 9, None, 7] self.assertEqual(len(int_values), len(dbl_values)) features = [] for i in range(len(int_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([int_values[i], dbl_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'fldint', 6], [QgsAggregateCalculator.Count, 'flddbl', 6], [QgsAggregateCalculator.Sum, 'fldint', 24], [QgsAggregateCalculator.Sum, 'flddbl', 37.5], [QgsAggregateCalculator.Mean, 'fldint', 4], [QgsAggregateCalculator.Mean, 'flddbl', 6.25], [QgsAggregateCalculator.StDev, 'fldint', 2.0816], [QgsAggregateCalculator.StDev, 'flddbl', 1.7969], [QgsAggregateCalculator.StDevSample, 'fldint', 2.2803], [QgsAggregateCalculator.StDevSample, 'flddbl', 1.9685], [QgsAggregateCalculator.Min, 'fldint', 2], [QgsAggregateCalculator.Min, 'flddbl', 3.5], [QgsAggregateCalculator.Max, 'fldint', 8], [QgsAggregateCalculator.Max, 'flddbl', 9], [QgsAggregateCalculator.Range, 'fldint', 6], [QgsAggregateCalculator.Range, 'flddbl', 5.5], [QgsAggregateCalculator.Median, 'fldint', 3.5], [QgsAggregateCalculator.Median, 'flddbl', 6.25], [QgsAggregateCalculator.CountDistinct, 'fldint', 5], [QgsAggregateCalculator.CountDistinct, 'flddbl', 6], [QgsAggregateCalculator.CountMissing, 'fldint', 1], [QgsAggregateCalculator.CountMissing, 'flddbl', 1], [QgsAggregateCalculator.FirstQuartile, 'fldint', 2], [QgsAggregateCalculator.FirstQuartile, 'flddbl', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'fldint', 5.0], [QgsAggregateCalculator.ThirdQuartile, 'flddbl', 7.5], [QgsAggregateCalculator.InterQuartileRange, 'fldint', 3.0], [QgsAggregateCalculator.InterQuartileRange, 'flddbl', 2.5], [QgsAggregateCalculator.ArrayAggregate, 'fldint', int_values], [QgsAggregateCalculator.ArrayAggregate, 'flddbl', dbl_values], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) if isinstance(t[2], (int, list)): self.assertEqual(val, t[2]) else: self.assertAlmostEqual(val, t[2], 3) # bad tests - the following stats should not be calculatable for numeric fields for t in [QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength]: val, ok = agg.calculate(t, 'fldint') self.assertFalse(ok) val, ok = agg.calculate(t, 'flddbl') self.assertFalse(ok)
def testExpression(self): """ test aggregate calculation using an expression """ # numeric layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory") pr = layer.dataProvider() int_values = [4, 2, 3, 2, 5, None, 8] features = [] for v in int_values: f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([v]) features.append(f) assert pr.addFeatures(features) # int agg = QgsAggregateCalculator(layer) val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2') self.assertTrue(ok) self.assertEqual(val, 48) # double val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 1.5') self.assertTrue(ok) self.assertEqual(val, 36) # datetime val, ok = agg.calculate(QgsAggregateCalculator.Max, "to_date('2012-05-04') + to_interval( fldint || ' day' )") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 12), QTime(0, 0, 0))) # date val, ok = agg.calculate(QgsAggregateCalculator.Min, "to_date(to_date('2012-05-04') + to_interval( fldint || ' day' ))") self.assertTrue(ok) self.assertEqual(val, QDateTime(QDate(2012, 5, 6), QTime(0, 0, 0))) # string val, ok = agg.calculate(QgsAggregateCalculator.Max, "fldint || ' oranges'") self.assertTrue(ok) self.assertEqual(val, '8 oranges') # geometry val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect, "make_point( coalesce(fldint,0), 2 )") self.assertTrue(ok) self.assertTrue(val.exportToWkt(), 'MultiPoint((4 2, 2 2, 3 2, 2 2,5 2, 0 2,8 2))') # try a bad expression val, ok = agg.calculate(QgsAggregateCalculator.Max, "not_a_field || ' oranges'") self.assertFalse(ok) val, ok = agg.calculate(QgsAggregateCalculator.Max, "5+") self.assertFalse(ok) # test expression context # check default context first # should have layer variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@layer_name") self.assertTrue(ok) self.assertEqual(val, 'layer') # but not custom variables: val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var") self.assertTrue(ok) self.assertEqual(val, NULL) # test with manual expression context scope = QgsExpressionContextScope() scope.setVariable('my_var', 5) context = QgsExpressionContext() context.appendScope(scope) val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var", context) self.assertTrue(ok) self.assertEqual(val, 5)
def testDateTime(self): """ Test calculation of aggregates on date/datetime fields""" layer = QgsVectorLayer("Point?field=flddate:date&field=flddatetime:datetime", "layer", "memory") pr = layer.dataProvider() # must be same length: datetime_values = [QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)), QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)), QDateTime(), QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)), QDateTime(), QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))] date_values = [QDate(2015, 3, 4), QDate(2015, 3, 4), QDate(2019, 12, 28), QDate(), QDate(1998, 1, 2), QDate(), QDate(2011, 1, 5), QDate(2011, 1, 5), QDate(2011, 1, 5)] self.assertEqual(len(datetime_values), len(date_values)) features = [] for i in range(len(datetime_values)): f = QgsFeature() f.setFields(layer.fields()) f.setAttributes([date_values[i], datetime_values[i]]) features.append(f) assert pr.addFeatures(features) tests = [[QgsAggregateCalculator.Count, 'flddatetime', 9], [QgsAggregateCalculator.Count, 'flddate', 9], [QgsAggregateCalculator.CountDistinct, 'flddatetime', 6], [QgsAggregateCalculator.CountDistinct, 'flddate', 5], [QgsAggregateCalculator.CountMissing, 'flddatetime', 2], [QgsAggregateCalculator.CountMissing, 'flddate', 2], [QgsAggregateCalculator.Min, 'flddatetime', QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54))], [QgsAggregateCalculator.Min, 'flddate', QDateTime(QDate(1998, 1, 2), QTime(0, 0, 0))], [QgsAggregateCalculator.Max, 'flddatetime', QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1))], [QgsAggregateCalculator.Max, 'flddate', QDateTime(QDate(2019, 12, 28), QTime(0, 0, 0))], [QgsAggregateCalculator.Range, 'flddatetime', QgsInterval(693871147)], [QgsAggregateCalculator.Range, 'flddate', QgsInterval(693792000)], [QgsAggregateCalculator.ArrayAggregate, 'flddatetime', [None if v.isNull() else v for v in datetime_values]], [QgsAggregateCalculator.ArrayAggregate, 'flddate', [None if v.isNull() else v for v in date_values]], ] agg = QgsAggregateCalculator(layer) for t in tests: val, ok = agg.calculate(t[0], t[1]) self.assertTrue(ok) self.assertEqual(val, t[2]) # bad tests - the following stats should not be calculatable for string fields for t in [QgsAggregateCalculator.Sum, QgsAggregateCalculator.Mean, QgsAggregateCalculator.Median, QgsAggregateCalculator.StDev, QgsAggregateCalculator.StDevSample, QgsAggregateCalculator.Minority, QgsAggregateCalculator.Majority, QgsAggregateCalculator.FirstQuartile, QgsAggregateCalculator.ThirdQuartile, QgsAggregateCalculator.InterQuartileRange, QgsAggregateCalculator.StringMinimumLength, QgsAggregateCalculator.StringMaximumLength, ]: val, ok = agg.calculate(t, 'flddatetime') self.assertFalse(ok)
def createReferencingLayer(): layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer", "referencinglayer", "memory") return layer
def testFidSupport(self): # We do not use @unittest.expectedFailure since the test might actually succeed # on Linux 64bit with GDAL 1.11, where "long" is 64 bit... # GDAL 2.0 is guaranteed to properly support it on all platforms version_num = int(gdal.VersionInfo('VERSION_NUM')) if version_num < GDAL_COMPUTE_VERSION(2, 0, 0): return tmpfile = os.path.join(self.basetestpath, 'testFidSupport.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString)) lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(12) f.SetField(0, 'foo') f.SetField(1, 123) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr') self.assertEqual(len(vl.fields()), 3) got = [(f.attribute('fid'), f.attribute('strfield'), f.attribute('intfield')) for f in vl.getFeatures()] self.assertEqual(got, [(12, 'foo', 123)]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "strfield = 'foo'"))] self.assertEqual(got, [(12, 'foo')]) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 12"))] self.assertEqual(got, [(12, 'foo')]) result = [ f['strfield'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest( ).setSubsetOfAttributes(['strfield'], vl.dataProvider().fields())) ] self.assertEqual(result, ['foo']) result = [ f['fid'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest( ).setSubsetOfAttributes(['fid'], vl.dataProvider().fields())) ] self.assertEqual(result, [12]) # Test that when the 'fid' field is not set, regular insertion is done f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([None, 'automatic_id']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 13) self.assertEqual(out_f[0].attribute('fid'), 13) self.assertEqual(out_f[0].attribute('strfield'), 'automatic_id') # Test that when the 'fid' field is set, it is really used to set the id f = QgsFeature() f.setFields(vl.fields()) f.setAttributes([9876543210, 'bar']) (res, out_f) = vl.dataProvider().addFeatures([f]) self.assertEqual(out_f[0].id(), 9876543210) self.assertEqual(out_f[0].attribute('fid'), 9876543210) self.assertEqual(out_f[0].attribute('strfield'), 'bar') got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'bar')]) self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 1: 'baz' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baz')]) self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 0: 9876543210, 1: 'baw' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Not allowed: changing the fid regular field self.assertTrue(vl.dataProvider().changeAttributeValues( {9876543210: { 0: 12, 1: 'baw' }})) got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression( "fid = 9876543210"))] self.assertEqual(got, [(9876543210, 'baw')]) # Cannot delete fid self.assertFalse(vl.dataProvider().deleteAttributes([0])) # Delete first "genuine" attribute self.assertTrue(vl.dataProvider().deleteAttributes([1])) got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures( QgsFeatureRequest().setFilterExpression("fid = 12"))] self.assertEqual(got, [(12, 123)])
def createReferencedLayer(): layer = QgsVectorLayer( "Point?field=x:string&field=y:integer&field=z:integer", "referencedlayer", "memory") return layer
def testCreateExpression(self): """ Test creating an expression using the widget""" layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddate:datetime", "test", "memory") parent = QWidget() w = QgsDefaultSearchWidgetWrapper(layer, 0) w.initWidget(parent) line_edit = w.lineEdit() line_edit.setText('test') case_sensitive = w.caseSensitiveCheckBox() case_sensitive.setChecked(False) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldtxt" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), 'lower("fldtxt")=lower(\'test\')') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), 'lower("fldtxt")<>lower(\'test\')') case_sensitive.setChecked(True) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'test\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldtxt"<>\'test\'') case_sensitive.setChecked(False) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.Contains), '"fldtxt" ILIKE \'%test%\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.DoesNotContain), 'NOT ("fldtxt" ILIKE \'%test%\')') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.StartsWith), '"fldtxt" ILIKE \'test%\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EndsWith), '"fldtxt" ILIKE \'%test\'') case_sensitive.setChecked(True) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.Contains), '"fldtxt" LIKE \'%test%\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.DoesNotContain), 'NOT ("fldtxt" LIKE \'%test%\')') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.StartsWith), '"fldtxt" LIKE \'test%\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EndsWith), '"fldtxt" LIKE \'%test\'') case_sensitive.setChecked(False) # numeric field parent = QWidget() w = QgsDefaultSearchWidgetWrapper(layer, 1) w.initWidget(parent) # may need updating if widget layout changes: line_edit = w.lineEdit() line_edit.setText('5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.GreaterThan), '"fldint">5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.LessThan), '"fldint"<5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.GreaterThanOrEqualTo), '"fldint">=5.5') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.LessThanOrEqualTo), '"fldint"<=5.5') # date/time/datetime parent = QWidget() w = QgsDefaultSearchWidgetWrapper(layer, 2) w.initWidget(parent) # may need updating if widget layout changes: line_edit = w.lineEdit() line_edit.setText('2015-06-03') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"flddate"=\'2015-06-03\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"flddate"<>\'2015-06-03\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.GreaterThan), '"flddate">\'2015-06-03\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.LessThan), '"flddate"<\'2015-06-03\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.GreaterThanOrEqualTo), '"flddate">=\'2015-06-03\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.LessThanOrEqualTo), '"flddate"<=\'2015-06-03\'')
def test_project_roundtrip(self): """Tests that a project with bad layers can be saved and restored""" p = QgsProject.instance() temp_dir = QTemporaryDir() for ext in ('shp', 'dbf', 'shx', 'prj'): copyfile(os.path.join(TEST_DATA_DIR, 'lines.%s' % ext), os.path.join(temp_dir.path(), 'lines.%s' % ext)) copyfile( os.path.join(TEST_DATA_DIR, 'raster', 'band1_byte_ct_epsg4326.tif'), os.path.join(temp_dir.path(), 'band1_byte_ct_epsg4326.tif')) copyfile( os.path.join(TEST_DATA_DIR, 'raster', 'band1_byte_ct_epsg4326.tif'), os.path.join(temp_dir.path(), 'band1_byte_ct_epsg4326_copy.tif')) l = QgsVectorLayer(os.path.join(temp_dir.path(), 'lines.shp'), 'lines', 'ogr') self.assertTrue(l.isValid()) rl = QgsRasterLayer( os.path.join(temp_dir.path(), 'band1_byte_ct_epsg4326.tif'), 'raster', 'gdal') self.assertTrue(rl.isValid()) rl_copy = QgsRasterLayer( os.path.join(temp_dir.path(), 'band1_byte_ct_epsg4326_copy.tif'), 'raster_copy', 'gdal') self.assertTrue(rl_copy.isValid()) self.assertTrue(p.addMapLayers([l, rl, rl_copy])) # Save project project_path = os.path.join(temp_dir.path(), 'project.qgs') self.assertTrue(p.write(project_path)) # Re-load the project, checking for the XML properties p.removeAllMapLayers() self.assertTrue(p.read(project_path)) vector = list(p.mapLayersByName('lines'))[0] raster = list(p.mapLayersByName('raster'))[0] raster_copy = list(p.mapLayersByName('raster_copy'))[0] self.assertTrue(vector.originalXmlProperties() != '') self.assertTrue(raster.originalXmlProperties() != '') self.assertTrue(raster_copy.originalXmlProperties() != '') # Test setter raster.setOriginalXmlProperties('pippo') self.assertEqual(raster.originalXmlProperties(), 'pippo') # Now create and invalid project: bad_project_path = os.path.join(temp_dir.path(), 'project_bad.qgs') with open(project_path, 'r') as infile: with open(bad_project_path, 'w+') as outfile: outfile.write(infile.read().replace( './lines.shp', './lines-BAD_SOURCE.shp').replace( 'band1_byte_ct_epsg4326_copy.tif', 'band1_byte_ct_epsg4326_copy-BAD_SOURCE.tif')) # Load the bad project p.removeAllMapLayers() self.assertTrue(p.read(bad_project_path)) # Check layer is invalid vector = list(p.mapLayersByName('lines'))[0] raster = list(p.mapLayersByName('raster'))[0] raster_copy = list(p.mapLayersByName('raster_copy'))[0] self.assertIsNotNone(vector.dataProvider()) self.assertIsNotNone(raster.dataProvider()) self.assertIsNotNone(raster_copy.dataProvider()) self.assertFalse(vector.isValid()) self.assertFalse(raster_copy.isValid()) # Try a getFeatures self.assertEqual([f for f in vector.getFeatures()], []) self.assertTrue(raster.isValid()) self.assertEqual(vector.providerType(), 'ogr') # Save the project bad_project_path2 = os.path.join(temp_dir.path(), 'project_bad2.qgs') p.write(bad_project_path2) # Re-save the project, with fixed paths good_project_path = os.path.join(temp_dir.path(), 'project_good.qgs') with open(bad_project_path2, 'r') as infile: with open(good_project_path, 'w+') as outfile: outfile.write(infile.read().replace( './lines-BAD_SOURCE.shp', './lines.shp').replace( 'band1_byte_ct_epsg4326_copy-BAD_SOURCE.tif', 'band1_byte_ct_epsg4326_copy.tif')) # Load the good project p.removeAllMapLayers() self.assertTrue(p.read(good_project_path)) # Check layer is valid vector = list(p.mapLayersByName('lines'))[0] raster = list(p.mapLayersByName('raster'))[0] raster_copy = list(p.mapLayersByName('raster_copy'))[0] self.assertTrue(vector.isValid()) self.assertTrue(raster.isValid()) self.assertTrue(raster_copy.isValid())
def testSubsetStringExtent_bug17863(self): """Check that the extent is correct when applied in the ctor and when modified after a subset string is set """ def _lessdigits(s): return re.sub(r'(\d+\.\d{3})\d+', r'\1', s) testPath = TEST_DATA_DIR + '/' + 'points.shp' subSetString = '"Class" = \'Biplane\'' subSet = '|layerid=0|subset=%s' % subSetString # unfiltered vl = QgsVectorLayer(testPath, 'test', 'ogr') self.assertTrue(vl.isValid()) unfiltered_extent = _lessdigits(vl.extent().toString()) del(vl) # filter after construction ... subSet_vl2 = QgsVectorLayer(testPath, 'test', 'ogr') self.assertEqual(_lessdigits(subSet_vl2.extent().toString()), unfiltered_extent) # ... apply filter now! subSet_vl2.setSubsetString(subSetString) self.assertEqual(subSet_vl2.subsetString(), subSetString) self.assertNotEqual(_lessdigits(subSet_vl2.extent().toString()), unfiltered_extent) filtered_extent = _lessdigits(subSet_vl2.extent().toString()) del(subSet_vl2) # filtered in constructor subSet_vl = QgsVectorLayer(testPath + subSet, 'subset_test', 'ogr') self.assertEqual(subSet_vl.subsetString(), subSetString) self.assertTrue(subSet_vl.isValid()) # This was failing in bug 17863 self.assertEqual(_lessdigits(subSet_vl.extent().toString()), filtered_extent) self.assertNotEqual(_lessdigits(subSet_vl.extent().toString()), unfiltered_extent)
def test_exceptions(self): ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") assert ml.isValid() fields = ml.fields() # check no error fields.remove(1) # check exceptions raised with self.assertRaises(KeyError): fields.remove(-1) with self.assertRaises(KeyError): fields.remove(111) fields = ml.fields() # check no error self.assertEqual("value", fields[1].name()) self.assertEqual("value", fields[-1].name()) # check exceptions raised with self.assertRaises(IndexError): fields[111] # check no error fields.at(1) # check exceptions raised with self.assertRaises(KeyError): fields.at(-1) with self.assertRaises(KeyError): fields.at(111) # check no error fields.field(1) # check exceptions raised with self.assertRaises(KeyError): fields.field(-1) with self.assertRaises(KeyError): fields.field(111) # check no error fields.field('value') # check exceptions raised with self.assertRaises(KeyError): fields.field('bad') # check no error fields.fieldOrigin(1) # check exceptions raised with self.assertRaises(KeyError): fields.fieldOrigin(-1) with self.assertRaises(KeyError): fields.fieldOrigin(111) # check no error fields.fieldOriginIndex(1) # check exceptions raised with self.assertRaises(KeyError): fields.fieldOriginIndex(-1) with self.assertRaises(KeyError): fields.fieldOriginIndex(111) # check no error fields.iconForField(1) # check exceptions raised with self.assertRaises(KeyError): fields.iconForField(-1) with self.assertRaises(KeyError): fields.iconForField(111)
def testDeleteShapes(self): ''' Test fix for #11007 ''' tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') feature_count = vl.featureCount() # Start an iterator that will open a new connection iterator = vl.getFeatures() next(iterator) # Delete a feature self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(1)) self.assertTrue(vl.commitChanges()) # Test the content of the shapefile while it is still opened ds = osgeo.ogr.Open(datasource) # Test repacking has been done self.assertTrue(ds.GetLayer(0).GetFeatureCount() == feature_count - 1) ds = None # Delete another feature while in update mode self.assertTrue(2 == 2) vl.dataProvider().enterUpdateMode() vl.dataProvider().deleteFeatures([0]) # Test that repacking has not been done (since in update mode) ds = osgeo.ogr.Open(datasource) self.assertTrue(ds.GetLayer(0).GetFeatureCount() == feature_count - 1) ds = None # Test that repacking was performed when leaving updateMode vl.dataProvider().leaveUpdateMode() ds = osgeo.ogr.Open(datasource) self.assertTrue(ds.GetLayer(0).GetFeatureCount() == feature_count - 2) ds = None vl = None
def testCreateExpression(self): """ Test creating an expression using the widget""" layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "test", "memory") # setup value relation parent_layer = QgsVectorLayer("Point?field=stringkey:string&field=intkey:integer&field=display:string", "parent", "memory") f1 = QgsFeature(parent_layer.fields(), 1) f1.setAttributes(['a', 1, 'value a']) f2 = QgsFeature(parent_layer.fields(), 2) f2.setAttributes(['b', 2, 'value b']) f3 = QgsFeature(parent_layer.fields(), 3) f3.setAttributes(['c', 3, 'value c']) parent_layer.dataProvider().addFeatures([f1, f2, f3]) QgsProject.instance().addMapLayers([layer, parent_layer]) config = {"Layer": parent_layer.id(), "Key": 'stringkey', "Value": 'display'} w = QgsValueRelationSearchWidgetWrapper(layer, 0) w.setConfig(config) c = w.widget() # first, set it to the "select value" item c.setCurrentIndex(0) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldtxt" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '') c.setCurrentIndex(1) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldtxt" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'a\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldtxt"<>\'a\'') c.setCurrentIndex(2) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldtxt" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldtxt" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldtxt"=\'b\'') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldtxt"<>\'b\'') # try with numeric field w = QgsValueRelationSearchWidgetWrapper(layer, 1) config['Key'] = 'intkey' w.setConfig(config) c = w.widget() c.setCurrentIndex(c.findText('value c')) self.assertEqual(c.currentIndex(), 3) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldint" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=3') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>3') # try with allow null set w = QgsValueRelationSearchWidgetWrapper(layer, 1) config['AllowNull'] = True w.setConfig(config) c = w.widget() c.setCurrentIndex(c.findText('value c')) self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldint" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=3') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>3') # try with line edit w = QgsValueRelationSearchWidgetWrapper(layer, 1) config['UseCompleter'] = True w.setConfig(config) l = w.widget() l.setText('value b') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNull), '"fldint" IS NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.IsNotNull), '"fldint" IS NOT NULL') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.EqualTo), '"fldint"=2') self.assertEqual(w.createExpression(QgsSearchWidgetWrapper.NotEqualTo), '"fldint"<>2')
def testreloadData(self): ''' Test reloadData() ''' tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl1 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') vl2 = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') self.assertTrue(vl1.startEditing()) self.assertTrue(vl1.deleteAttributes([1])) self.assertTrue(vl1.commitChanges()) self.assertEqual(len(vl1.fields()) + 1, len(vl2.fields())) # Reload vl2.reload() # And now check that fields are up-to-date self.assertEqual(len(vl1.fields()), len(vl2.fields()))
def testSubSetStringEditable_bug17795_but_with_modified_behavior(self): """Test that a layer is still editable after setting a subset""" testPath = TEST_DATA_DIR + '/' + 'lines.shp' isEditable = QgsVectorDataProvider.ChangeAttributeValues vl = QgsVectorLayer(testPath, 'subset_test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.dataProvider().capabilities() & isEditable) vl = QgsVectorLayer(testPath, 'subset_test', 'ogr') vl.setSubsetString('') self.assertTrue(vl.isValid()) self.assertTrue(vl.dataProvider().capabilities() & isEditable) vl = QgsVectorLayer(testPath, 'subset_test', 'ogr') vl.setSubsetString('"Name" = \'Arterial\'') self.assertTrue(vl.isValid()) self.assertTrue(vl.dataProvider().capabilities() & isEditable) vl.setSubsetString('') self.assertTrue(vl.dataProvider().capabilities() & isEditable)
def testUpdateMode(self): """ Test that on-the-fly re-opening in update/read-only mode works """ tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) self.assertTrue(caps & QgsVectorDataProvider.DeleteFeatures) self.assertTrue(caps & QgsVectorDataProvider.ChangeAttributeValues) self.assertTrue(caps & QgsVectorDataProvider.AddAttributes) self.assertTrue(caps & QgsVectorDataProvider.DeleteAttributes) self.assertTrue(caps & QgsVectorDataProvider.CreateSpatialIndex) self.assertTrue(caps & QgsVectorDataProvider.SelectAtId) self.assertTrue(caps & QgsVectorDataProvider.ChangeGeometries) # self.assertTrue(caps & QgsVectorDataProvider.ChangeFeatures) # We should be really opened in read-only mode even if write capabilities are declared self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Unbalanced call to leaveUpdateMode() self.assertFalse(vl.dataProvider().leaveUpdateMode()) # Test that startEditing() / commitChanges() plays with enterUpdateMode() / leaveUpdateMode() self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().isValid()) self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") self.assertTrue(vl.dataProvider().isValid()) # Manual enterUpdateMode() / leaveUpdateMode() with 2 depths self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") caps = vl.dataProvider().capabilities() self.assertTrue(caps & QgsVectorDataProvider.AddFeatures) f = QgsFeature() f.setAttributes([200]) f.setGeometry(QgsGeometry.fromWkt('Point (2 49)')) (ret, feature_list) = vl.dataProvider().addFeatures([f]) self.assertTrue(ret) fid = feature_list[0].id() features = [f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))] values = [f_iter['pk'] for f_iter in features] self.assertEqual(values, [200]) got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (2.0, 49.0)) self.assertTrue(vl.dataProvider().changeGeometryValues({fid: QgsGeometry.fromWkt('Point (3 50)')})) self.assertTrue(vl.dataProvider().changeAttributeValues({fid: {0: 100}})) features = [f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))] values = [f_iter['pk'] for f_iter in features] got_geom = [f_iter.geometry() for f_iter in features][0].constGet() self.assertEqual((got_geom.x(), got_geom.y()), (3.0, 50.0)) self.assertTrue(vl.dataProvider().deleteFeatures([fid])) # Check that it has really disappeared osgeo.gdal.PushErrorHandler('CPLQuietErrorHandler') features = [f_iter for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))] osgeo.gdal.PopErrorHandler() self.assertEqual(features, []) self.assertTrue(vl.dataProvider().addAttributes([QgsField("new_field", QVariant.Int, "integer")])) self.assertTrue(vl.dataProvider().deleteAttributes([len(vl.dataProvider().fields()) - 1])) self.assertTrue(vl.startEditing()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.commitChanges()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write") self.assertTrue(vl.dataProvider().leaveUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-only") # Test that update mode will be implictly enabled if doing an action # that requires update mode (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) self.assertTrue(ret) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "read-write")
def testRenameAttributes(self): ''' Test renameAttributes() ''' tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') provider = vl.dataProvider() # bad rename self.assertFalse(provider.renameAttributes({-1: 'not_a_field'})) self.assertFalse(provider.renameAttributes({100: 'not_a_field'})) # already exists self.assertFalse(provider.renameAttributes({2: 'cnt'})) # rename one field self.assertTrue(provider.renameAttributes({2: 'newname'})) self.assertEqual(provider.fields().at(2).name(), 'newname') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname') # rename two fields self.assertTrue(provider.renameAttributes({2: 'newname2', 3: 'another'})) self.assertEqual(provider.fields().at(2).name(), 'newname2') self.assertEqual(provider.fields().at(3).name(), 'another') vl.updateFields() fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname2') self.assertEqual(fet.fields()[3].name(), 'another') # close file and reopen, then recheck to confirm that changes were saved to file del vl vl = None vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') provider = vl.dataProvider() self.assertEqual(provider.fields().at(2).name(), 'newname2') self.assertEqual(provider.fields().at(3).name(), 'another') fet = next(vl.getFeatures()) self.assertEqual(fet.fields()[2].name(), 'newname2') self.assertEqual(fet.fields()[3].name(), 'another')
def test_SplitFeature(self): """Test sqlite feature can be split""" tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.sqlite') ds = ogr.GetDriverByName('SQlite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon) lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetGeometry(ogr.CreateGeometryFromWkt('POLYGON ((0 0,0 1,1 1,1 0,0 0))')) lyr.CreateFeature(f) f = None ds = None layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') # Check that pk field has unique constraint fields = layer.fields() pkfield = fields.at(0) self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique) self.assertTrue(layer.isValid()) self.assertTrue(layer.isSpatial()) self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))') layer.startEditing() self.assertEqual(layer.splitFeatures([QgsPointXY(0.5, 0), QgsPointXY(0.5, 1)], 0), 0) self.assertTrue(layer.commitChanges()) self.assertEqual(layer.featureCount(), 2) layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr') self.assertEqual(layer.featureCount(), 2) self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0.5 0, 0.5 1, 1 1, 1 0, 0.5 0))') self.assertEqual([f for f in layer.getFeatures()][1].geometry().asWkt(), 'Polygon ((0.5 1, 0.5 0, 0 0, 0 1, 0.5 1))')
def testUpdateModeFailedReopening(self): ''' Test that methods on provider don't crash after a failed reopening ''' # Windows doesn't like removing files opened by OGR, whatever # their open mode, so that makes it hard to test if sys.platform == 'win32': return tmpdir = tempfile.mkdtemp() self.dirs_to_cleanup.append(tmpdir) srcpath = os.path.join(TEST_DATA_DIR, 'provider') for file in glob.glob(os.path.join(srcpath, 'shapefile.*')): shutil.copy(os.path.join(srcpath, file), tmpdir) datasource = os.path.join(tmpdir, 'shapefile.shp') vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr') os.unlink(datasource) self.assertFalse(vl.dataProvider().enterUpdateMode()) self.assertFalse(vl.dataProvider().enterUpdateMode()) self.assertEqual(vl.dataProvider().property("_debug_open_mode"), "invalid") self.assertFalse(vl.dataProvider().isValid()) self.assertEqual(len([f for f in vl.dataProvider().getFeatures()]), 0) self.assertEqual(len(vl.dataProvider().subLayers()), 0) self.assertFalse(vl.dataProvider().setSubsetString('TRUE')) (ret, _) = vl.dataProvider().addFeatures([QgsFeature()]) self.assertFalse(ret) self.assertFalse(vl.dataProvider().deleteFeatures([1])) self.assertFalse(vl.dataProvider().addAttributes([QgsField()])) self.assertFalse(vl.dataProvider().deleteAttributes([1])) self.assertFalse(vl.dataProvider().changeGeometryValues({0: QgsGeometry.fromWkt('Point (3 50)')})) self.assertFalse(vl.dataProvider().changeAttributeValues({0: {0: 0}})) self.assertFalse(vl.dataProvider().createSpatialIndex()) self.assertFalse(vl.dataProvider().createAttributeIndex(0))
class TestQgsSymbolExpressionVariables(unittest.TestCase): def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsProject.instance().addMapLayer(self.layer) self.iface = get_iface() rendered_layers = [self.layer] self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) self.mapsettings.setLayers(rendered_layers) def tearDown(self): QgsProject.instance().removeAllMapLayers() def testPartNum(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({ 'color': '#fdbf6f', 'outline_color': 'black' }) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols( QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty( QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression( 'color_rgb( (@geometry_part_num - 1) * 200, 0, 0 )')) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_num') result = renderchecker.runTest('part_geometry_part_num') self.assertTrue(result) def testPartCount(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({ 'color': '#fdbf6f', 'outline_color': 'black' }) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols( QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty( QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression( 'color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )')) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_count') result = renderchecker.runTest('part_geometry_part_count') self.assertTrue(result) def testSymbolColor(self): # Create rulebased style sym1 = QgsFillSymbol.createSimple({ 'color': '#ff0000', 'outline_color': 'black' }) renderer = QgsSingleSymbolRenderer(sym1) renderer.symbols( QgsRenderContext())[0].symbolLayers()[0].setDataDefinedProperty( QgsSymbolLayer.PropertyFillColor, QgsProperty.fromExpression( 'set_color_part( @symbol_color, \'value\', "Value" * 4)')) self.layer.setRenderer(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_symbol_color_variable') result = renderchecker.runTest('symbol_color_variable', 50) self.assertTrue(result)
def testRepack(self): vl = QgsVectorLayer('{}|layerid=0'.format(self.repackfile), 'test', 'ogr') ids = [f.id() for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('pk=1'))] vl.selectByIds(ids) self.assertEqual(vl.selectedFeatureIds(), ids) self.assertEqual(vl.featureCount(), 5) self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeature(3)) self.assertTrue(vl.commitChanges()) self.assertTrue(vl.selectedFeatureCount() == 0 or vl.selectedFeatures()[0]['pk'] == 1)
def create_shapefile_full_layer_data_provider(path, name, srid, attributes, types, values, coords): """ Creates a shapefile using the Shapefile Data Provider Parameters ---------- path : `str` folder where the shapefile is to be saved name : `str` name of the shapefile srid : `str` CRS of the newly created shapefile attributes: array_like list of attribute (field) names types : array_like list of types (field) types, in sync with the `attributes` parameter values : array_like coordinates and attribute data, one array for each feature (F, C + A), F for features, C for coordinates and A for attribute data coords : array_like indices of the coordinate values within the `values` array Returns ------- vl : `QgsVectorLayer` the newly-created layer """ # create new layer with given attributes filename = path + "/" + name + ".shp" # create an instance of vector file writer, which will create the vector file. writer = None options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = "ESRI Shapefile" options.fileEncoding = 'utf-8' if len(coords) == 2: type = 'point' writer = QgsVectorFileWriter.create(filename, QgsFields(), QgsWkbTypes.Point, srid, QgsCoordinateTransformContext(), options) elif len(coords) == 4: type = 'line' writer = QgsVectorFileWriter.create(filename, QgsFields(), QgsWkbTypes.LineString, srid, QgsCoordinateTransformContext(), options) if writer.hasError() != QgsVectorFileWriter.NoError: print("Error when creating shapefile: ", writer.hasError()) return None del writer # open the newly created file vl = QgsVectorLayer(filename, name, "ogr") pr = vl.dataProvider() # create the required fields for i, attr in enumerate(attributes): pr.addAttributes([QgsField(attr, types[i])]) vl.commitChanges() # add features by iterating the values feat = QgsFeature() for i, val in enumerate(values): # add geometry try: if type == 'point': geometry = QgsGeometry.fromPoint([QgsPoint(float(val[coords[0]]), float(val[coords[1]]))]) elif type == 'line': geometry = QgsGeometry.fromPolyline([QgsPoint(float(val[coords[0]]), float(val[coords[1]])), QgsPoint(float(val[coords[2]]), float(val[coords[3]]))]) feat.setGeometry(geometry) except: pass # add attributes attrs = [] for j, attr in enumerate(attributes): attrs.append(val[j]) feat.setAttributes(attrs) pr.addFeature(feat) vl.updateExtents() vl = QgsVectorLayer(filename, name, "ogr") if not vl.isValid(): raise IOError("Layer could not be created") return None return vl
def testSubsetStringFids(self): """ - tests that feature ids are stable even if a subset string is set - tests that the subset string is correctly set on the ogr layer event when reloading the data source (issue #17122) """ tmpfile = os.path.join(self.basetestpath, 'subsetStringFids.sqlite') ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile) lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid']) lyr.CreateField(ogr.FieldDefn('type', ogr.OFTInteger)) lyr.CreateField(ogr.FieldDefn('value', ogr.OFTInteger)) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(0) f.SetField(0, 1) f.SetField(1, 11) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(1) f.SetField(0, 1) f.SetField(1, 12) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(2) f.SetField(0, 1) f.SetField(1, 13) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(3) f.SetField(0, 2) f.SetField(1, 14) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(4) f.SetField(0, 2) f.SetField(1, 15) lyr.CreateFeature(f) f = ogr.Feature(lyr.GetLayerDefn()) f.SetFID(5) f.SetField(0, 2) f.SetField(1, 16) lyr.CreateFeature(f) f = None ds = None vl = QgsVectorLayer(tmpfile + "|subset=type=2", 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid") req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertTrue(f.id() == 5) # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] while it.nextFeature(f): ids.append(f.id()) self.assertTrue(len(ids) == 3) self.assertTrue(3 in ids) self.assertTrue(4 in ids) self.assertTrue(5 in ids) # Check that subset string is correctly set on reload vl.reload() self.assertTrue(vl.fields().at(vl.fields().count() - 1).name() == "orig_ogc_fid")
class TestQgsBlendModes(TestCase): def __init__(self, methodName): """Run once on class initialisation.""" unittest.TestCase.__init__(self, methodName) # initialize class MapRegistry, Canvas, MapRenderer, Map and PAL self.mMapRegistry = QgsMapLayerRegistry.instance() # create point layer myShpFile = os.path.join(TEST_DATA_DIR, 'points.shp') self.mPointLayer = QgsVectorLayer(myShpFile, 'Points', 'ogr') self.mMapRegistry.addMapLayer(self.mPointLayer) self.mSimplifyMethod = QgsVectorSimplifyMethod() self.mSimplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod.NoSimplification) # create polygon layer myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') self.mPolygonLayer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr') self.mPolygonLayer.setSimplifyMethod(self.mSimplifyMethod) self.mMapRegistry.addMapLayer(self.mPolygonLayer) # create line layer myShpFile = os.path.join(TEST_DATA_DIR, 'lines.shp') self.mLineLayer = QgsVectorLayer(myShpFile, 'Lines', 'ogr') self.mLineLayer.setSimplifyMethod(self.mSimplifyMethod) self.mMapRegistry.addMapLayer(self.mLineLayer) # create two raster layers myRasterFile = os.path.join(TEST_DATA_DIR, 'landsat.tif') self.mRasterLayer1 = QgsRasterLayer(myRasterFile, "raster1") self.mRasterLayer2 = QgsRasterLayer(myRasterFile, "raster2") myMultiBandRenderer1 = QgsMultiBandColorRenderer( self.mRasterLayer1.dataProvider(), 2, 3, 4) self.mRasterLayer1.setRenderer(myMultiBandRenderer1) self.mMapRegistry.addMapLayer(self.mRasterLayer1) myMultiBandRenderer2 = QgsMultiBandColorRenderer( self.mRasterLayer2.dataProvider(), 2, 3, 4) self.mRasterLayer2.setRenderer(myMultiBandRenderer2) self.mMapRegistry.addMapLayer(self.mRasterLayer2) # to match blend modes test comparisons background self.mCanvas = CANVAS self.mCanvas.setCanvasColor(QColor(152, 219, 249)) self.mMap = self.mCanvas.map() self.mMap.resize(QSize(400, 400)) self.mapSettings = self.mCanvas.mapSettings() self.mapSettings.setOutputSize(QSize(400, 400)) def testVectorBlending(self): """Test that blend modes work for vector layers.""" #Add vector layers to map myLayers = [] myLayers.append(self.mLineLayer.id()) myLayers.append(self.mPolygonLayer.id()) self.mapSettings.setLayers(myLayers) self.mapSettings.setExtent(self.mPointLayer.extent()) #Set blending modes for both layers self.mLineLayer.setBlendMode(QPainter.CompositionMode_Difference) self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_Difference) checker = QgsMultiRenderChecker() checker.setControlName("expected_vector_blendmodes") checker.setMapSettings(self.mapSettings) checker.setColorTolerance(1) myResult = checker.runTest("vector_blendmodes", 20) myMessage = ('vector blending failed') assert myResult, myMessage #Reset layers self.mLineLayer.setBlendMode(QPainter.CompositionMode_SourceOver) self.mPolygonLayer.setBlendMode(QPainter.CompositionMode_SourceOver) def testVectorFeatureBlending(self): """Test that feature blend modes work for vector layers.""" #Add vector layers to map myLayers = [] myLayers.append(self.mLineLayer.id()) myLayers.append(self.mPolygonLayer.id()) self.mapSettings.setLayers(myLayers) self.mapSettings.setExtent(self.mPointLayer.extent()) #Set feature blending for line layer self.mLineLayer.setFeatureBlendMode(QPainter.CompositionMode_Plus) checker = QgsMultiRenderChecker() checker.setControlName("expected_vector_featureblendmodes") checker.setMapSettings(self.mapSettings) checker.setColorTolerance(1) myResult = checker.runTest("vector_featureblendmodes", 20) myMessage = ('vector feature blending failed') assert myResult, myMessage #Reset layers self.mLineLayer.setFeatureBlendMode( QPainter.CompositionMode_SourceOver) def testVectorLayerTransparency(self): """Test that layer transparency works for vector layers.""" #Add vector layers to map myLayers = [] myLayers.append(self.mLineLayer.id()) myLayers.append(self.mPolygonLayer.id()) self.mapSettings.setLayers(myLayers) self.mapSettings.setExtent(self.mPointLayer.extent()) #Set feature blending for line layer self.mLineLayer.setLayerTransparency(50) checker = QgsMultiRenderChecker() checker.setControlName("expected_vector_layertransparency") checker.setMapSettings(self.mapSettings) checker.setColorTolerance(1) myResult = checker.runTest("vector_layertransparency", 20) myMessage = ('vector layer transparency failed') assert myResult, myMessage def testRasterBlending(self): """Test that blend modes work for raster layers.""" #Add raster layers to map myLayers = [] myLayers.append(self.mRasterLayer1.id()) myLayers.append(self.mRasterLayer2.id()) self.mapSettings.setLayers(myLayers) self.mapSettings.setExtent(self.mRasterLayer1.extent()) #Set blending mode for top layer self.mRasterLayer1.setBlendMode(QPainter.CompositionMode_Plus) checker = QgsMultiRenderChecker() checker.setControlName("expected_raster_blendmodes") checker.setMapSettings(self.mapSettings) checker.setColorTolerance(1) checker.setColorTolerance(1) myResult = checker.runTest("raster_blendmodes", 20) myMessage = ('raster blending failed') assert myResult, myMessage
def create_layer(name): layer = QgsVectorLayer("Point?crs=EPSG:3111&field=fldtxt:string&field=fldint:integer", name, "memory") return layer
def load(fileName, name=None, crs=None, style=None): """Loads a layer/table into the current project, given its file. """ if fileName is None: return prjSetting = None settings = QgsSettings() if crs is not None: prjSetting = settings.value('/Projections/defaultBehavior') settings.setValue('/Projections/defaultBehavior', '') if name is None: name = os.path.split(fileName)[1] qgslayer = QgsVectorLayer(fileName, name, 'ogr') if qgslayer.isValid(): if crs is not None and qgslayer.crs() is None: qgslayer.setCrs(crs, False) if style is None: if qgslayer.geometryType() == QgsWkbTypes.PointGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POINT_STYLE) elif qgslayer.geometryType() == QgsWkbTypes.LineGeometry: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_LINE_STYLE) else: style = ProcessingConfig.getSetting( ProcessingConfig.VECTOR_POLYGON_STYLE) qgslayer.loadNamedStyle(style) QgsProject.instance().addMapLayers([qgslayer]) else: qgslayer = QgsRasterLayer(fileName, name) if qgslayer.isValid(): if crs is not None and qgslayer.crs() is None: qgslayer.setCrs(crs, False) if style is None: style = ProcessingConfig.getSetting( ProcessingConfig.RASTER_STYLE) qgslayer.loadNamedStyle(style) QgsProject.instance().addMapLayers([qgslayer]) else: if prjSetting: settings.setValue('/Projections/defaultBehavior', prjSetting) raise RuntimeError( 'Could not load layer: ' + str(fileName) + '\nCheck the processing framework log to look for errors') if prjSetting: settings.setValue('/Projections/defaultBehavior', prjSetting) return qgslayer
def testEdit(self): """Test `with edit(layer):` code""" ml = QgsVectorLayer("Point?crs=epsg:4236&field=id:integer&field=value:double", "test_data", "memory") # Data as list of x, y, id, value self.assertTrue(ml.isValid()) fields = ml.fields() # Check insert with edit(ml): feat = QgsFeature(fields) feat['id'] = 1 feat['value'] = 0.9 self.assertTrue(ml.addFeature(feat)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 0.9) # Check update with edit(ml): f = next(ml.getFeatures()) f['value'] = 9.9 self.assertTrue(ml.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) # Check for rollBack after exceptions with self.assertRaises(NameError): with edit(ml): f = next(ml.getFeatures()) f['value'] = 3.8 crashycrash() # NOQA self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 9.9) self.assertEqual(next(ml.getFeatures())['value'], 9.9) # Check for `as` with edit(ml) as l: f = next(l.getFeatures()) f['value'] = 10 self.assertTrue(l.updateFeature(f)) self.assertEqual(next(ml.dataProvider().getFeatures())['value'], 10) # Check that we get a QgsEditError exception when the commit fails with self.assertRaises(QgsEditError): with edit(ml) as l: l.rollBack()