def test_fes20_c5_example2(): """A simple non-spatial filter comparing a property value to a literal. In this case, the DEPTH is checked to find instances where it is less than 30 - possibly to identify areas that need dredging. """ xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsLessThan> <fes:ValueReference>DEPTH</fes:ValueReference> <fes:Literal>30</fes:Literal> </fes:PropertyIsLessThan> </fes:Filter> """.strip() expected = Filter( BinaryComparisonOperator( BinaryComparisonName.PropertyIsLessThan, expression=(ValueReference("DEPTH"), Literal("30")), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[Q(DEPTH__lt=30)]), repr(query)
def test_fes10_no_namespace(leading_whitespace): """Test that omitting a namespace still parses the object.""" xml_text = """ <Filter> <PropertyIsEqualTo> <ValueReference>SomeProperty</ValueReference> <Literal>100</Literal> </PropertyIsEqualTo> </Filter> """ if leading_whitespace: xml_text = xml_text.strip() expected = Filter(predicate=BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="SomeProperty"), Literal(raw_value="100"), ), matchCase=True, matchAction=MatchAction.Any, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}"
def test_fes20_c5_example10(): """This example encodes a filter using the LIKE operation to perform a pattern matching comparison. In this case, the filter identifies all features where the value of the property named LAST_NAME begins with the letters "JOHN".""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsLike wildCard="*" singleChar="#" escapeChar="!"> <fes:ValueReference>LAST_NAME</fes:ValueReference> <fes:Literal>JOHN*</fes:Literal> </fes:PropertyIsLike> </fes:Filter> """.strip() expected = Filter(predicate=LikeOperator( expression=( ValueReference(xpath="LAST_NAME"), Literal(raw_value="JOHN*"), ), wildCard="*", singleChar="#", escapeChar="!", )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[Q( LAST_NAME__fes_like="JOHN%")]), repr(query)
def test_fes20_c5_example8(): """This example encodes a filter using the BETWEEN operator. The filter identifies all features where the DEPTH is between 100 m and 200 m.""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsBetween> <fes:ValueReference>DEPTH</fes:ValueReference> <fes:LowerBoundary> <fes:Literal>100</fes:Literal> </fes:LowerBoundary> <fes:UpperBoundary> <fes:Literal>200</fes:Literal> </fes:UpperBoundary> </fes:PropertyIsBetween> </fes:Filter> """.strip() expected = Filter(predicate=BetweenComparisonOperator( expression=ValueReference(xpath="DEPTH"), lowerBoundary=Literal(raw_value="100"), upperBoundary=Literal(raw_value="200"), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[Q(DEPTH__range=(100, 200))]), repr(query)
def test_fes20_c5_example1(): """A simple non-spatial filter checking to see if SomeProperty is equal to 100.""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsEqualTo> <fes:ValueReference>SomeProperty</fes:ValueReference> <fes:Literal>100</fes:Literal> </fes:PropertyIsEqualTo> </fes:Filter> """.strip() expected = Filter( BinaryComparisonOperator( BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference("SomeProperty"), Literal("100"), ), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[Q( SomeProperty__exact=100)]), repr(query)
def test_fes20_c5_example14(): """This example restricts the active set of objects to those instances of the Person type that are older than 50 years old and live in Toronto. This filter expression uses an XPath (as given in W3C XML Path Language) expression to reference the complex attributes of the Person type. """ xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:And> <fes:PropertyIsGreaterThan> <fes:ValueReference>Person/age</fes:ValueReference> <fes:Literal>50</fes:Literal> </fes:PropertyIsGreaterThan> <fes:PropertyIsEqualTo> <fes:ValueReference>Person/mailAddress/Address/city</fes:ValueReference> <fes:Literal>Toronto</fes:Literal> </fes:PropertyIsEqualTo> </fes:And> </fes:Filter> """.strip() result = Filter.from_string(xml_text) expected = Filter(predicate=BinaryLogicOperator( operands=[ BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsGreaterThan, expression=( ValueReference(xpath="Person/age"), Literal(raw_value="50"), ), matchCase=True, matchAction=MatchAction.Any, ), BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="Person/mailAddress/Address/city"), Literal(raw_value="Toronto"), ), matchCase=True, matchAction=MatchAction.Any, ), ], operatorType=BinaryLogicType.And, )) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(Person__age__gt=50) & Q(Person__mailAddress__Address__city__exact="Toronto") ]), repr(query)
def test_fes20_c5_example3(): """This example encodes a simple spatial filter. In this case, one is finding all features that have a geometry that spatially interacts with the specified bounding box. The expression NOT DISJOINT is used to exclude all features that do not interact with the bounding box; in other words identify all the features that interact with the bounding box in some way. """ xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"> <fes:Not> <fes:Disjoint> <fes:ValueReference>Geometry</fes:ValueReference> <gml:Envelope srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:lowerCorner>13.0983 31.5899</gml:lowerCorner> <gml:upperCorner>35.5472 42.8143</gml:upperCorner> </gml:Envelope> </fes:Disjoint> </fes:Not> </fes:Filter> """.strip() expected = Filter(predicate=UnaryLogicOperator( operands=BinarySpatialOperator( operatorType=SpatialOperatorName.Disjoint, operand1=ValueReference(xpath="Geometry"), operand2=GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, ), ), ), operatorType=UnaryLogicType.Not, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ ~Q(Geometry__disjoint=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, )) ]), repr(query)
def test_fes20_c5_example7(): """This example assumes that the server advertises support for a function called "Add" in its filter capabilities document. The example encodes a filter that includes an arithmetic expression. This filter is equivalent to the expression PROPA = PROPB + 100. """ @function_registry.register( name="Add", arguments=dict(value1=XsdTypes.double, value2=XsdTypes.double), returns=XsdTypes.double, ) def fes_add(value1: F, value2: str): # value1 is already an F value (thanks to ValueReference) return value1 + value2 xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsEqualTo> <fes:ValueReference>PROPA</fes:ValueReference> <fes:Function name="Add"> <fes:ValueReference>PROPB</fes:ValueReference> <fes:Literal>100</fes:Literal> </fes:Function> </fes:PropertyIsEqualTo> </fes:Filter> """.strip() expected = Filter(predicate=BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="PROPA"), Function( name="Add", arguments=[ ValueReference(xpath="PROPB"), Literal(raw_value="100") ], ), ), matchCase=True, matchAction=MatchAction.Any, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating # Testing against repr() because CombinedExpression / Value doesn't do __eq__ testing. query = result.compile_query() assert repr(query) == repr( CompiledQuery(lookups=[Q(PROPA__exact=F("PROPB") + 100)])), repr(query)
def test_fes10_add_sub(): """A simple non-spatial filter checking to see if SomeProperty is equal to 100.""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsEqualTo> <fes:ValueReference>SomeProperty</fes:ValueReference> <fes:Add> <fes:Sub> <fes:Literal>100</fes:Literal> <fes:Literal>50</fes:Literal> </fes:Sub> <fes:Literal>200</fes:Literal> </fes:Add> </fes:PropertyIsEqualTo> </fes:Filter> """.strip() expected = Filter(predicate=BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="SomeProperty"), BinaryOperator( _operatorType=BinaryOperatorType.Add, expression=( BinaryOperator( _operatorType=BinaryOperatorType.Sub, expression=( Literal(raw_value="100"), Literal(raw_value="50"), ), ), Literal(raw_value="200"), ), ), ), matchCase=True, matchAction=MatchAction.Any, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() integer_field = models.IntegerField() assert query == CompiledQuery(lookups=[ Q(SomeProperty__exact=(Value(100, output_field=integer_field) - Value(50, output_field=integer_field) + Value(200, output_field=integer_field))) ]), repr(query)
def test_fes20_c5_example6(): """The following filter includes the encoding of a function. This filter identifies all features where the sine() of the property named DISPERSION_ANGLE is 1. """ @function_registry.register( name="SIN", arguments=dict(value1="xsd:double"), returns="xsd:double", ) def fes_sin(value1): return Sin(value1) xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsEqualTo> <fes:Function name="SIN"> <fes:ValueReference>DISPERSION_ANGLE</fes:ValueReference> </fes:Function> <fes:Literal>1</fes:Literal> </fes:PropertyIsEqualTo> </fes:Filter> """.strip() expected = Filter(predicate=BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( Function( name="SIN", arguments=[ValueReference(xpath="DISPERSION_ANGLE")], ), Literal(raw_value="1"), ), matchCase=True, matchAction=MatchAction.Any, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery( annotations={"a1": Sin(F("DISPERSION_ANGLE"))}, lookups=[Q(a1__exact=1)]), repr(query)
def test_fes20_c5_example11_b(): """Although GML 3.2 is the canonical GML version supported by this International Standard, the filter schemas have been crafted is such a way as to support any version of GML. For example, here is the same filter expression expect that it GML 2.1.2 to encoding the geometry rather than GML 3.2:""" xml_text = """ <?xml version="1.0"?> <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://www.pvretano.com/schemas/filter/2.0/filterAll.xsd http://www.opengis.net/gml http://www.pvretano.com/schemas/gml/2.1.2/geometry.xsd"> <fes:Overlaps> <fes:ValueReference>Geometry</fes:ValueReference> <gml:Polygon srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:outerBoundaryIs> <gml:LinearRing> <gml:coordinates>10,10 20,20 30,30 40,40 10,10</gml:coordinates> </gml:LinearRing> </gml:outerBoundaryIs> </gml:Polygon> </fes:Overlaps> </fes:Filter> """.strip() expected = Filter(predicate=BinarySpatialOperator( operatorType=SpatialOperatorName.Overlaps, operand1=ValueReference(xpath="Geometry"), operand2=geometries.GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326), ), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(Geometry__overlaps=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326)) ]), repr(query)
def test_fes20_c5_example3_b(): """An alternative encoding of this filter could have used to fes:BBOX element""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"> <fes:BBOX> <fes:ValueReference>Geometry</fes:ValueReference> <gml:Envelope srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:lowerCorner>13.0983 31.5899</gml:lowerCorner> <gml:upperCorner>35.5472 42.8143</gml:upperCorner> </gml:Envelope> </fes:BBOX> </fes:Filter> """.strip() expected = Filter(predicate=BinarySpatialOperator( operatorType=SpatialOperatorName.BBOX, operand1=ValueReference(xpath="Geometry"), operand2=GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, ), ), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(Geometry__intersects=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, )) ]), repr(query)
def test_fes20_c5_example11(): """This example encodes a spatial filter that identifies all features whose geometry property, named Geometry in this example, overlap a polygonal area of interest.""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"> <fes:Overlaps> <fes:ValueReference>Geometry</fes:ValueReference> <gml:Polygon gml:id="P1" srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:exterior> <gml:LinearRing> <gml:posList>10 10 20 20 30 30 40 40 10 10</gml:posList> </gml:LinearRing> </gml:exterior> </gml:Polygon> </fes:Overlaps> </fes:Filter> """.strip() expected = Filter(predicate=BinarySpatialOperator( operatorType=SpatialOperatorName.Overlaps, operand1=ValueReference(xpath="Geometry"), operand2=geometries.GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326), ), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(Geometry__overlaps=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326)) ]), repr(query)
def test_fes20_c5_example5(): """A fes:Filter element can also be used to identify an enumerated set of feature instances or feature components. In this case, any operation that included this filter block would be limited to the feature instances or feature components listed within the fes:Filter element. A filter applied to a GML version 3 data store: """ xml_text = """ <?xml version="1.0"?> <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:ResourceId rid="TREESA_1M.1234"/> <fes:ResourceId rid="TREESA_1M.5678"/> <fes:ResourceId rid="TREESA_1M.9012"/> <fes:ResourceId rid="INWATERA_1M.3456"/> <fes:ResourceId rid="INWATERA_1M.7890"/> <fes:ResourceId rid="BUILTUPA_1M.4321"/> </fes:Filter> """.strip() expected = Filter( IdOperator([ ResourceId(rid="TREESA_1M.1234"), ResourceId(rid="TREESA_1M.5678"), ResourceId(rid="TREESA_1M.9012"), ResourceId(rid="INWATERA_1M.3456"), ResourceId(rid="INWATERA_1M.7890"), ResourceId(rid="BUILTUPA_1M.4321"), ])) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery( typed_lookups={ "BUILTUPA_1M": [Q(pk="4321")], "INWATERA_1M": [Q(pk="3456") | Q(pk="7890")], "TREESA_1M": [Q(pk="1234") | Q(pk="5678") | Q(pk="9012")], }), repr(query)
def test_fes20_c5_example9(): """This example is similar to Example 8, except that in this case, the filter is checking to see if the SAMPLE_DATE property is within a specified date range.""" xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:PropertyIsBetween> <fes:ValueReference>SAMPLE_DATE</fes:ValueReference> <fes:LowerBoundary> <fes:Literal>2001-01-15T20:07:48.11</fes:Literal> </fes:LowerBoundary> <fes:UpperBoundary> <fes:Literal>2001-03-06T12:00:00.00</fes:Literal> </fes:UpperBoundary> </fes:PropertyIsBetween> </fes:Filter> """.strip() expected = Filter(predicate=BetweenComparisonOperator( expression=ValueReference(xpath="SAMPLE_DATE"), lowerBoundary=Literal(raw_value="2001-01-15T20:07:48.11"), upperBoundary=Literal(raw_value="2001-03-06T12:00:00.00"), )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(SAMPLE_DATE__range=( datetime(2001, 1, 15, 20, 7, 48, 110000), datetime(2001, 3, 6, 12, 0), )) ]), repr(query)
def test_fes20_c5_example13(): """Spatial and non-spatial predicates can be encoded in a single filter expression. In this example, a spatial predicate checks to see if the geometric property WKB_GEOMlies within a region of interest defined by a polygon and a scalar predicate check to see if the scalar property DEPTH lies within a specified range. This example encoding is equivalent to the expression: (wkb_geom WITHIN "some polygon") AND (depth BETWEEN 400 AND 800) """ xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/gml/3.2 http://schemas.opengis.net/gml/3.2.1/gml.xsd"> <fes:And> <fes:Within> <fes:ValueReference>WKB_GEOM</fes:ValueReference> <gml:Polygon gml:id="P1" srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:exterior> <gml:LinearRing> <gml:posList>10 10 20 20 30 30 40 40 10 10</gml:posList> </gml:LinearRing> </gml:exterior> </gml:Polygon> </fes:Within> <fes:PropertyIsBetween> <fes:ValueReference>DEPTH</fes:ValueReference> <fes:LowerBoundary> <fes:Literal>400</fes:Literal> </fes:LowerBoundary> <fes:UpperBoundary> <fes:Literal>800</fes:Literal> </fes:UpperBoundary> </fes:PropertyIsBetween> </fes:And> </fes:Filter> """.strip() expected = Filter(predicate=BinaryLogicOperator( operands=[ BinarySpatialOperator( operatorType=SpatialOperatorName.Within, operand1=ValueReference(xpath="WKB_GEOM"), operand2=geometries.GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326), ), ), BetweenComparisonOperator( expression=ValueReference(xpath="DEPTH"), lowerBoundary=Literal(raw_value="400"), upperBoundary=Literal(raw_value="800"), ), ], operatorType=BinaryLogicType.And, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(WKB_GEOM__within=GEOSGeometry( "POLYGON ((10 10, 20 20, 30 30, 40 40, 10 10))", srid=4326)) & Q(DEPTH__range=(400, 800)) ]), repr(query)
def test_fes20_c5_example12(): """In this example, a more complex scalar predicate is encoded using the logical operators AND and OR. The example is equivalent to the expression: ((FIELD1=10 OR FIELD1=20) AND (STATUS="VALID")) """ xml_text = """ <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd"> <fes:And> <fes:Or> <fes:PropertyIsEqualTo> <fes:ValueReference>FIELD1</fes:ValueReference> <fes:Literal>10</fes:Literal> </fes:PropertyIsEqualTo> <fes:PropertyIsEqualTo> <fes:ValueReference>FIELD1</fes:ValueReference> <fes:Literal>20</fes:Literal> </fes:PropertyIsEqualTo> </fes:Or> <fes:PropertyIsEqualTo> <fes:ValueReference>STATUS</fes:ValueReference> <fes:Literal>VALID</fes:Literal> </fes:PropertyIsEqualTo> </fes:And> </fes:Filter> """.strip() expected = Filter(predicate=BinaryLogicOperator( operands=[ BinaryLogicOperator( operands=[ BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="FIELD1"), Literal(raw_value="10"), ), matchCase=True, matchAction=MatchAction.Any, ), BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="FIELD1"), Literal(raw_value="20"), ), matchCase=True, matchAction=MatchAction.Any, ), ], operatorType=BinaryLogicType.Or, ), BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsEqualTo, expression=( ValueReference(xpath="STATUS"), Literal(raw_value="VALID"), ), matchCase=True, matchAction=MatchAction.Any, ), ], operatorType=BinaryLogicType.And, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery( lookups=[(Q(FIELD1__exact=10) | Q(FIELD1__exact=20)) & Q(STATUS__exact="VALID")]), repr(query)
def test_fes20_c5_example4(): """In this example, Examples 2 and 3 are combined with the logical operator AND. The predicate is thus interpreted as seeking all features that interact with the specified bounding box and have a DEPTH value of less than 30 m.""" xml_text = """ <?xml version="1.0"?> <fes:Filter xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/fes/2.0 http://schemas.opengis.net/filter/2.0/filterAll.xsd http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/geometry.xsd"> <fes:And> <fes:PropertyIsLessThan> <fes:ValueReference>DEPTH</fes:ValueReference> <fes:Literal>30</fes:Literal> </fes:PropertyIsLessThan> <fes:Not> <fes:Disjoint> <fes:ValueReference>Geometry</fes:ValueReference> <gml:Envelope srsName="http://www.opengis.net/def/crs/epsg/0/4326"> <gml:lowerCorner>13.0983 31.5899</gml:lowerCorner> <gml:upperCorner>35.5472 42.8143</gml:upperCorner> </gml:Envelope> </fes:Disjoint> </fes:Not> </fes:And> </fes:Filter> """.strip() expected = Filter(predicate=BinaryLogicOperator( operands=[ BinaryComparisonOperator( operatorType=BinaryComparisonName.PropertyIsLessThan, expression=( ValueReference(xpath="DEPTH"), Literal(raw_value="30"), ), matchCase=True, matchAction=MatchAction.Any, ), UnaryLogicOperator( operands=BinarySpatialOperator( operatorType=SpatialOperatorName.Disjoint, operand1=ValueReference(xpath="Geometry"), operand2=GEOSGMLGeometry( srs=WGS84, geos_data=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, ), ), ), operatorType=UnaryLogicType.Not, ), ], operatorType=BinaryLogicType.And, )) result = Filter.from_string(xml_text) assert result == expected, f"result={result!r}" # Test SQL generating query = result.compile_query() assert query == CompiledQuery(lookups=[ Q(DEPTH__lt=30) & ~Q(Geometry__disjoint=GEOSGeometry( "POLYGON ((13.0983 31.5899, 35.5472 31.5899" ", 35.5472 42.8143, 13.0983 42.8143, 13.0983 31.5899))", srid=4326, )) ]), repr(query)