def testFilterExpression(self): req = QgsFeatureRequest().setFilterExpression('a=5') self.assertEqual(req.filterType(), QgsFeatureRequest.FilterExpression) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=5') self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) # filter rect doesn't affect fids filter req.setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=5') self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertTrue(req.referenceGeometry().isNull()) req.setFilterExpression('a=8') self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=8') self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertTrue(req.referenceGeometry().isNull())
def testFilterFids(self): req = QgsFeatureRequest().setFilterFids([5, 6]) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [5, 6]) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) # filter rect doesn't affect fids filter req.setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [5, 6]) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertTrue(req.referenceGeometry().isNull()) req.setFilterFids([8, 9]) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [8, 9]) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertTrue(req.referenceGeometry().isNull())
def testFilterRect(self): req = QgsFeatureRequest().setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertTrue(req.referenceGeometry().isNull()) # setting filter rect should not change attribute filter req = QgsFeatureRequest().setFilterFid(5).setFilterRect( QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterFid(), 5) self.assertFalse(req.filterFids()) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) # setting attribute filter should not change filter rect req = QgsFeatureRequest().setFilterRect(QgsRectangle( 1, 2, 3, 4)).setFilterFid(5) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterFid(), 5) self.assertFalse(req.filterFids()) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) # setting null rectangle should clear spatial filter req = QgsFeatureRequest().setFilterFid(5).setFilterRect( QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterFid(), 5) self.assertFalse(req.filterFids()) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) req.setFilterRect(QgsRectangle()) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertTrue(req.filterRect().isNull()) # setting distance within should override filter rect req = QgsFeatureRequest().setFilterRect(QgsRectangle(1, 2, 3, 4)) req.setDistanceWithin( QgsGeometry.fromWkt('LineString(0 0, 10 0, 11 2)'), 1.2) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.DistanceWithin) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.referenceGeometry().asWkt(), 'LineString (0 0, 10 0, 11 2)') self.assertEqual(req.distanceWithin(), 1.2)
def testAssignment(self): req = QgsFeatureRequest().setFilterFids([8, 9]).setFilterRect( QgsRectangle(1, 2, 3, 4)).setInvalidGeometryCheck( QgsFeatureRequest.GeometrySkipInvalid).setLimit(6).setFlags( QgsFeatureRequest.ExactIntersect).setSubsetOfAttributes( [1, 4]).setTimeout(6).setRequestMayBeNested(True) context = QgsExpressionContext() scope = QgsExpressionContextScope() scope.setVariable('a', 6) context.appendScope(scope) req.setExpressionContext(context) method = QgsSimplifyMethod() method.setMethodType(QgsSimplifyMethod.PreserveTopology) req.setSimplifyMethod(method) context = QgsCoordinateTransformContext() req.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3857'), context) req2 = QgsFeatureRequest(req) self.assertEqual(req2.limit(), 6) self.assertCountEqual(req2.filterFids(), [8, 9]) self.assertEqual(req2.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertEqual(req2.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req2.invalidGeometryCheck(), QgsFeatureRequest.GeometrySkipInvalid) self.assertEqual(req2.expressionContext().scopeCount(), 1) self.assertEqual(req2.expressionContext().variable('a'), 6) self.assertEqual( req2.flags(), QgsFeatureRequest.ExactIntersect | QgsFeatureRequest.SubsetOfAttributes) self.assertEqual(req2.subsetOfAttributes(), [1, 4]) self.assertEqual(req2.simplifyMethod().methodType(), QgsSimplifyMethod.PreserveTopology) self.assertEqual(req2.destinationCrs().authid(), 'EPSG:3857') self.assertEqual(req2.timeout(), 6) self.assertTrue(req2.requestMayBeNested()) # copy distance within request req = QgsFeatureRequest().setDistanceWithin( QgsGeometry.fromWkt('LineString( 0 0, 10 0, 11 2)'), 1.2) req2 = QgsFeatureRequest(req) self.assertEqual(req2.spatialFilterType(), Qgis.SpatialFilterType.DistanceWithin) self.assertEqual(req2.referenceGeometry().asWkt(), 'LineString (0 0, 10 0, 11 2)') self.assertEqual(req2.distanceWithin(), 1.2) self.assertEqual(req2.filterRect(), QgsRectangle(-1.2, -1.2, 12.2, 3.2))
def testFilterFid(self): req = QgsFeatureRequest().setFilterFid(5) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.filterFid(), 5) self.assertFalse(req.filterFids()) # filter rect doesn't affect fid filter req.setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.filterFid(), 5) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) req.setFilterFid(6) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.filterFid(), 6) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4))
def testDisableFilter(self): req = QgsFeatureRequest().setFilterFid(5).disableFilter() self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) req = QgsFeatureRequest().setFilterFids([5, 6]).disableFilter() self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) req = QgsFeatureRequest().setFilterExpression('a=5').disableFilter() self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertFalse(req.filterExpression()) # disable filter does not disable spatial filter req = QgsFeatureRequest().setFilterExpression('a=5').setFilterRect( QgsRectangle(1, 2, 3, 4)) req.disableFilter() self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4)) self.assertFalse(req.filterExpression())
def testCombineFilter(self): req = QgsFeatureRequest() req.combineFilterExpression('b=9') self.assertEqual(req.filterType(), QgsFeatureRequest.FilterExpression) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'b=9') self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) req.combineFilterExpression('a=11') self.assertEqual(req.filterType(), QgsFeatureRequest.FilterExpression) self.assertEqual(req.filterExpression().expression(), '(b=9) AND (a=11)') self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull())
def testConstructors(self): req = QgsFeatureRequest() self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) req = QgsFeatureRequest(55) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFid) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertEqual(req.filterFid(), 55) self.assertFalse(req.filterFids()) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) req = QgsFeatureRequest([55, 56]) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.NoFilter) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [55, 56]) self.assertTrue(req.filterRect().isNull()) self.assertTrue(req.referenceGeometry().isNull()) req = QgsFeatureRequest(QgsRectangle(55, 56, 57, 58)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterNone) self.assertEqual(req.spatialFilterType(), Qgis.SpatialFilterType.BoundingBox) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), []) self.assertEqual(req.filterRect(), QgsRectangle(55, 56, 57, 58)) self.assertTrue(req.referenceGeometry().isNull())
def testFilterFids(self): req = QgsFeatureRequest().setFilterFids([5, 6]) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [5, 6]) # filter rect doesn't affect fids filter req.setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [5, 6]) req.setFilterFids([8, 9]) self.assertEqual(req.filterType(), QgsFeatureRequest.FilterFids) self.assertEqual(req.filterFid(), -1) self.assertCountEqual(req.filterFids(), [8, 9]) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4))
def testFilterExpression(self): req = QgsFeatureRequest().setFilterExpression('a=5') self.assertEqual(req.filterType(), QgsFeatureRequest.FilterExpression) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=5') # filter rect doesn't affect fids filter req.setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=5') req.setFilterExpression('a=8') self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterExpression().expression(), 'a=8') self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4))
def testFilterRect(self): req = QgsFeatureRequest().setFilterRect(QgsRectangle(1, 2, 3, 4)) self.assertEqual(req.filterFid(), -1) self.assertFalse(req.filterFids()) self.assertEqual(req.filterRect(), QgsRectangle(1, 2, 3, 4))
def __get_qgis_features(qgis_layer, qgis_feature_request=None, bbox_filter=None, attribute_filters=None, search_filter=None, with_geometry=True, page=None, page_size=None, ordering=None, exclude_fields=None, extra_expression=None, extra_subset_string=None): """Private implementation for count and get""" if qgis_feature_request is None: qgis_feature_request = QgsFeatureRequest() if exclude_fields is not None: if exclude_fields == '__all__': qgis_feature_request.setNoAttributes() else: qgis_feature_request.setSubsetOfAttributes([ name for name in qgis_layer.fields().names() if name not in exclude_fields ], qgis_layer.fields()) expression_parts = [] if extra_expression is not None: expression_parts.append(extra_expression) if not with_geometry: qgis_feature_request.setFlags(QgsFeatureRequest.NoGeometry) if bbox_filter is not None: assert isinstance(bbox_filter, QgsRectangle) qgis_feature_request.setFilterRect(bbox_filter) # Ordering if ordering is not None: ascending = True if ordering.startswith('-'): ordering = ordering[1:] ascending = False order_by = QgsFeatureRequest.OrderBy( [QgsFeatureRequest.OrderByClause('"%s"' % ordering, ascending)]) qgis_feature_request.setOrderBy(order_by) # Search if search_filter is not None: exp_template = '"{field_name}" ILIKE \'%' + search_filter.replace( '\'', '\\\'') + '%\'' exp_parts = [] for f in qgis_layer.fields(): exp_parts.append( exp_template.format(field_name=f.name().replace('"', '\\"'))) expression_parts.append(' OR '.join(exp_parts)) # Attribute filters if attribute_filters is not None: exp_parts = [] for field_name, field_value in attribute_filters.items(): exp_parts.append('"{field_name}" ILIKE \'%{field_value}%\''.format( field_name=field_name.replace('"', '\\"'), field_value=str(field_value).replace('\'', '\\\''))) expression_parts.append(' AND '.join(exp_parts)) offset = 0 feature_count = qgis_layer.featureCount() if page is not None and page_size is not None: page_size = int(page_size) page = int(page) offset = page_size * (page - 1) feature_count = page_size * page # Set to max, without taking filters into account qgis_feature_request.setLimit(feature_count) else: page_size = None # make sure it's none # Fetch features if expression_parts: qgis_feature_request.combineFilterExpression( '(' + ') AND ('.join(expression_parts) + ')') logger.debug( 'Fetching features from layer {layer_name} - filter expression: {filter} - BBOX: {bbox}' .format(layer_name=qgis_layer.name(), filter=qgis_feature_request.filterExpression(), bbox=qgis_feature_request.filterRect())) features = [] original_subset_string = qgis_layer.subsetString() if extra_subset_string is not None: subset_string = original_subset_string if subset_string: qgis_layer.setSubsetString( "({original_subset_string}) AND ({extra_subset_string})". format(original_subset_string=original_subset_string, extra_subset_string=extra_subset_string)) else: qgis_layer.setSubsetString(extra_subset_string) iterator = qgis_layer.getFeatures(qgis_feature_request) try: for _ in range(offset): next(iterator) if page_size is not None: for __ in range(page_size): features.append(next(iterator)) else: while True: features.append(next(iterator)) except StopIteration: pass if extra_subset_string is not None: qgis_layer.setSubsetString(original_subset_string) return features