diff --git a/CHANGELOG.md b/CHANGELOG.md index b5a23b26e..eb0dfdbd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,11 +17,16 @@ Changes are grouped as follows - `Fixed` for any bug fixes. - `Security` in case of vulnerabilities. +## [7.1.0] - 2023-11-16 +### Added +- The list method for asset mappings in the 3D API now supports `intersects_bounding_box`, allowing users to only + return asset mappings for assets whose bounding box intersects with the given bounding box. + ## [7.0.3] - 2023-11-15 ### Fixed -- Bug when `cognite.client.data_classes.filter` used with any `data_modeling` endpoint raised a `CogniteAPIError` for - snake_cased properties. This is now fixed. -- When calling `client.relationships.retrieve`, `.retrieve_multiple`, or `.list` with `fetch_resources=True`, the +- Bug when `cognite.client.data_classes.filter` used with any `data_modeling` endpoint raised a `CogniteAPIError` for + snake_cased properties. This is now fixed. +- When calling `client.relationships.retrieve`, `.retrieve_multiple`, or `.list` with `fetch_resources=True`, the `target` and `source` resources were not instantiated with a `cognite_client`. This is now fixed. ## [7.0.2] - 2023-11-15 diff --git a/cognite/client/_api/three_d.py b/cognite/client/_api/three_d.py index aeb6db58e..a50db778c 100644 --- a/cognite/client/_api/three_d.py +++ b/cognite/client/_api/three_d.py @@ -1,10 +1,12 @@ from __future__ import annotations +import json from typing import TYPE_CHECKING, Any, Iterator, Sequence, cast from cognite.client._api_client import APIClient from cognite.client._constants import DEFAULT_LIMIT_READ from cognite.client.data_classes import ( + BoundingBox3D, ThreeDAssetMapping, ThreeDAssetMappingList, ThreeDModel, @@ -559,6 +561,7 @@ def list( revision_id: int, node_id: int | None = None, asset_id: int | None = None, + intersects_bounding_box: BoundingBox3D | None = None, limit: int | None = DEFAULT_LIMIT_READ, ) -> ThreeDAssetMappingList: """`List 3D node asset mappings. `_ @@ -568,6 +571,7 @@ def list( revision_id (int): Id of the revision. node_id (int | None): List only asset mappings associated with this node. asset_id (int | None): List only asset mappings associated with this asset. + intersects_bounding_box (BoundingBox3D | None): If given, only return asset mappings for assets whose bounding box intersects with the given bounding box. limit (int | None): Maximum number of asset mappings to return. Defaults to 25. Set to -1, float("inf") or None to return all items. Returns: @@ -575,19 +579,29 @@ def list( Example: - List 3d node asset mappings:: + List 3d node asset mappings: >>> from cognite.client import CogniteClient >>> c = CogniteClient() >>> res = c.three_d.asset_mappings.list(model_id=1, revision_id=1) + + List 3d node asset mappings for assets whose bounding box intersects with a given bounding box: + + >>> from cognite.client.data_classes import BoundingBox3D + >>> bbox = BoundingBox3D(min=[0.0, 0.0, 0.0], max=[1.0, 1.0, 1.0]) + >>> res = c.three_d.asset_mappings.list( + ... model_id=1, revision_id=1, intersects_bounding_box=bbox) """ path = interpolate_and_url_encode(self._RESOURCE_PATH, model_id, revision_id) + flt: dict[str, str | int | None] = {"nodeId": node_id, "assetId": asset_id} + if intersects_bounding_box: + flt["intersectsBoundingBox"] = json.dumps(intersects_bounding_box.dump(camel_case=True)) return self._list( list_cls=ThreeDAssetMappingList, resource_cls=ThreeDAssetMapping, resource_path=path, method="GET", - filter={"nodeId": node_id, "assetId": asset_id}, + filter=flt, limit=limit, ) diff --git a/cognite/client/_version.py b/cognite/client/_version.py index 2fbab5dee..09d623b37 100644 --- a/cognite/client/_version.py +++ b/cognite/client/_version.py @@ -1,4 +1,4 @@ from __future__ import annotations -__version__ = "7.0.3" +__version__ = "7.1.0" __api_subversion__ = "V20220125" diff --git a/pyproject.toml b/pyproject.toml index 4b5c07238..c3412fbe7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [tool.poetry] name = "cognite-sdk" -version = "7.0.3" +version = "7.1.0" description = "Cognite Python SDK" readme = "README.md" documentation = "https://cognite-sdk-python.readthedocs-hosted.com" authors = [ "Erlend Vollset ", - "Håkon Treider ", + "Håkon Treider ", "Anders Albert " ] license = "Apache-2.0" diff --git a/tests/tests_unit/test_api/test_3d.py b/tests/tests_unit/test_api/test_3d.py index 57ed54ffb..42e396aca 100644 --- a/tests/tests_unit/test_api/test_3d.py +++ b/tests/tests_unit/test_api/test_3d.py @@ -1,4 +1,5 @@ import re +from urllib.parse import unquote_plus import pytest @@ -13,6 +14,7 @@ ThreeDModelUpdate, ThreeDNodeList, ) +from cognite.client.data_classes import BoundingBox3D from cognite.client.exceptions import CogniteAPIError from tests.utils import jsgz_load @@ -286,11 +288,25 @@ def mock_3d_asset_mappings_response(self, cognite_client, rsps): def test_list(self, cognite_client, mock_3d_asset_mappings_response): res = cognite_client.three_d.asset_mappings.list( - model_id=1, revision_id=1, node_id=None, asset_id=None, limit=None + model_id=1, revision_id=1, node_id=None, asset_id=None, intersects_bounding_box=None, limit=None ) assert isinstance(res, ThreeDAssetMappingList) assert mock_3d_asset_mappings_response.calls[0].response.json()["items"] == res.dump(camel_case=True) + url = mock_3d_asset_mappings_response.calls[0].request.url + assert "intersectsBoundingBox" not in unquote_plus(url) + + def test_list__with_intersects_bounding_box(self, cognite_client, mock_3d_asset_mappings_response): + bbox = BoundingBox3D(min=[0.0, 0.0, 0.0], max=[1.0, 1.0, 1.0]) + res = cognite_client.three_d.asset_mappings.list( + model_id=1, revision_id=1, node_id=None, asset_id=None, intersects_bounding_box=bbox, limit=None + ) + assert isinstance(res, ThreeDAssetMappingList) + assert mock_3d_asset_mappings_response.calls[0].response.json()["items"] == res.dump(camel_case=True) + + url = mock_3d_asset_mappings_response.calls[0].request.url + assert 'intersectsBoundingBox={"max": [1.0, 1.0, 1.0], "min": [0.0, 0.0, 0.0]}' in unquote_plus(url) + def test_create(self, cognite_client, mock_3d_asset_mappings_response): res = cognite_client.three_d.asset_mappings.create( model_id=1, revision_id=1, asset_mapping=ThreeDAssetMapping(node_id=1, asset_id=1)