Example #1
0
    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())
Example #2
0
    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())
Example #3
0
    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)
Example #4
0
    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))
Example #5
0
    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))
Example #6
0
    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())
Example #7
0
    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())
Example #8
0
    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())
Example #9
0
    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))
Example #10
0
    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))
Example #11
0
 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))
Example #12
0
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