Skip to content

Commit

Permalink
Geospatial - added missing allowDimensionalityMismatch parameter (#1531)
Browse files Browse the repository at this point in the history
  • Loading branch information
skepticalcat authored Jan 8, 2024
1 parent 5eeaac4 commit d8c40dd
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 11 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ Changes are grouped as follows
- `Fixed` for any bug fixes.
- `Security` in case of vulnerabilities.


## [7.10.0] - 2024-01-08
### Added
- `geospatial.search_features` and `geospatial.stream_features` now accept the `allow_dimensionality_mismatch` parameter.

## [7.9.0] - 2024-01-05
### Added
- You can now enable or disable user profiles for your CDF project with `client.iam.user_profiles.[enable/disable]`.
Expand Down
22 changes: 17 additions & 5 deletions cognite/client/_api/geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ def search_features(
limit: int = DEFAULT_LIMIT_READ,
order_by: Sequence[OrderSpec] | None = None,
allow_crs_transformation: bool = False,
allow_dimensionality_mismatch: bool = False,
) -> FeatureList:
"""`Search for features`
<https://developer.cognite.com/api#tag/Geospatial/operation/searchFeatures>
Expand All @@ -542,6 +543,7 @@ def search_features(
limit (int): Maximum number of results
order_by (Sequence[OrderSpec] | None): The order specification
allow_crs_transformation (bool): If true, then input geometries will be transformed into the Coordinate Reference System defined in the feature type specification. When it is false, then requests with geometries in Coordinate Reference System different from the ones defined in the feature type will result in CogniteAPIError exception.
allow_dimensionality_mismatch (bool): Indicating if the spatial filter operators allow input geometries with a different dimensionality than the properties they are applied to. Defaults to False.
Returns:
FeatureList: the filtered features
Expand Down Expand Up @@ -578,6 +580,14 @@ def search_features(
... properties={"temperature": {}, "pressure": {}}
... )
Search for features and do CRS conversion on an output property:
>>> res = c.geospatial.search_features(
... feature_type_external_id=my_feature_type,
... filter={},
... properties={"location": {"srid": 3995}}
... )
Search for features and order results:
>>> res = c.geospatial.search_features(
Expand Down Expand Up @@ -631,7 +641,8 @@ def search_features(
"limit": limit,
"output": {"properties": properties},
"sort": order,
"allowCrsTransformation": (True if allow_crs_transformation else None),
"allowCrsTransformation": allow_crs_transformation,
"allowDimensionalityMismatch": allow_dimensionality_mismatch,
},
)
return FeatureList.load(res.json()["items"], cognite_client=self._cognite_client)
Expand All @@ -642,6 +653,7 @@ def stream_features(
filter: dict[str, Any] | None = None,
properties: dict[str, Any] | None = None,
allow_crs_transformation: bool = False,
allow_dimensionality_mismatch: bool = False,
) -> Iterator[Feature]:
"""`Stream features`
<https://developer.cognite.com/api#tag/Geospatial/operation/searchFeaturesStreaming>
Expand All @@ -655,6 +667,7 @@ def stream_features(
filter (dict[str, Any] | None): the search filter
properties (dict[str, Any] | None): the output property selection
allow_crs_transformation (bool): If true, then input geometries will be transformed into the Coordinate Reference System defined in the feature type specification. When it is false, then requests with geometries in Coordinate Reference System different from the ones defined in the feature type will result in CogniteAPIError exception.
allow_dimensionality_mismatch (bool): Indicating if the spatial filter operators allow input geometries with a different dimensionality than the properties they are applied to. Defaults to False.
Yields:
Feature: a generator for the filtered features
Expand Down Expand Up @@ -690,11 +703,10 @@ def stream_features(
payload = {
"filter": filter or {},
"output": {"properties": properties, "jsonStreamFormat": "NEW_LINE_DELIMITED"},
"allowCrsTransformation": allow_crs_transformation,
"allowDimensionalityMismatch": allow_dimensionality_mismatch,
}
params = {"allowCrsTransformation": "true"} if allow_crs_transformation else None
res = self._do_request(
"POST", url_path=resource_path, json=payload, timeout=self._config.timeout, stream=True, params=params
)
res = self._do_request("POST", url_path=resource_path, json=payload, timeout=self._config.timeout, stream=True)

try:
for line in res.iter_lines():
Expand Down
2 changes: 1 addition & 1 deletion cognite/client/_version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import annotations

__version__ = "7.9.0"
__version__ = "7.10.0"
__api_subversion__ = "V20220125"
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[tool.poetry]
name = "cognite-sdk"

version = "7.9.0"

version = "7.10.0"
description = "Cognite Python SDK"
readme = "README.md"
documentation = "https://cognite-sdk-python.readthedocs-hosted.com"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ def test_retrieve_nodes_and_edges(
assert set(retrieved.nodes.as_ids()) == set(movie_nodes.as_ids())
assert set(retrieved.edges.as_ids()) == set(movie_edges.as_ids())

@pytest.mark.xfail # TODO: Unknown ids should not raise
def test_retrieve_multiple_with_missing(self, cognite_client: CogniteClient, movie_nodes: NodeList) -> None:
# Arrange
ids_without_missing = movie_nodes.as_ids()
Expand All @@ -300,6 +301,7 @@ def test_retrieve_multiple_with_missing(self, cognite_client: CogniteClient, mov
# Assert
assert retrieved.nodes.as_ids() == ids_without_missing

@pytest.mark.xfail # TODO: Unknown ids should not raise
def test_retrieve_non_existent(self, cognite_client: CogniteClient) -> None:
assert cognite_client.data_modeling.instances.retrieve(("myNonExistingSpace", "myImaginaryNode")).nodes == []

Expand Down
61 changes: 57 additions & 4 deletions tests/tests_integration/test_api/test_geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,34 @@ def test_search_single_feature(self, cognite_client, test_feature_type, test_fea
)
assert len(res) == 0

def test_search_feature_dimensionality_mismatch(self, cognite_client, test_feature_type, test_feature):
polygon_z = "POLYGONZ((2.276 48.858 3,2.278 48.859 3,2.2759 48.859 3,2.276 48.858 3))"
polygon = "POLYGON((2.276 48.858,2.278 48.859,2.275 48.859,2.276 48.858))"
res = cognite_client.geospatial.search_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon}}},
limit=10,
)
assert res[0].external_id == test_feature.external_id

with pytest.raises(CogniteAPIError):
res = cognite_client.geospatial.search_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon_z}}},
limit=10,
)

def test_search_feature_dimensionality_mismatch_flag_set(self, cognite_client, test_feature_type, test_feature):
polygon_z = "POLYGONZ((2.276 48.858 3,2.278 48.859 3,2.2759 48.859 3,2.276 48.858 3))"
res = cognite_client.geospatial.search_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon_z}}},
limit=10,
allow_dimensionality_mismatch=True,
)
assert len(res) == 1
assert res[0].external_id == test_feature.external_id

def test_retrieve_multiple_feature_types_by_external_id(
self, cognite_client, test_feature_type, another_test_feature_type
):
Expand Down Expand Up @@ -335,15 +363,12 @@ def test_search_multiple_features(self, cognite_client, test_feature_type, test_
assert res[0].external_id == test_feature.external_id

def test_search_wrong_crs(self, cognite_client, test_feature_type, test_feature):
try:
with pytest.raises(CogniteAPIError):
cognite_client.geospatial.search_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "location", "value": {"wkt": "", "srid": 3857}}},
limit=10,
)
raise pytest.fail("searching features using a geometry in invalid crs should have raised an exception")
except CogniteAPIError:
pass

def test_get_coordinate_reference_system(self, cognite_client):
res = cognite_client.geospatial.get_coordinate_reference_systems(srids=4326)
Expand Down Expand Up @@ -449,6 +474,34 @@ def test_stream_features(self, cognite_client, large_feature_type, many_features
feature_list = FeatureList(list(features))
assert len(feature_list) == len(many_features)

def test_stream_features_dimensionality_mismatch(self, cognite_client, test_feature_type, test_feature):
polygon_z = "POLYGONZ((2.276 48.858 3,2.278 48.859 3,2.2759 48.859 3,2.276 48.858 3))"
polygon = "POLYGON((2.276 48.858,2.278 48.859,2.275 48.859,2.276 48.858))"
stream_res = cognite_client.geospatial.stream_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon}}},
)
res = [x for x in stream_res]
assert res[0].external_id == test_feature.external_id

with pytest.raises(CogniteAPIError):
stream_res = cognite_client.geospatial.stream_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon_z}}},
)
_ = [x for x in stream_res]

def test_stream_features_dimensionality_mismatch_flag_set(self, cognite_client, test_feature_type, test_feature):
polygon_z = "POLYGONZ((2.276 48.858 3,2.278 48.859 3,2.2759 48.859 3,2.276 48.858 3))"
stream_res = cognite_client.geospatial.stream_features(
feature_type_external_id=test_feature_type.external_id,
filter={"stWithin": {"property": "position", "value": {"wkt": polygon_z}}},
allow_dimensionality_mismatch=True,
)
res = [x for x in stream_res]
assert len(res) == 1
assert res[0].external_id == test_feature.external_id

def test_list(self, cognite_client, test_feature_type, test_features):
with set_request_limit(cognite_client.geospatial, 2):
res = cognite_client.geospatial.list_features(
Expand Down

0 comments on commit d8c40dd

Please sign in to comment.