Skip to content
12 changes: 12 additions & 0 deletions cognite/client/_api/vision.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@
class VisionAPI(APIClient):
_RESOURCE_PATH = "/context/vision"

@staticmethod
def _deprecation_warning() -> None:
warnings.warn(
"The Vision API will be removed in a future version of the SDK. "
"Please migrate to the recommended alternative. "
"Read more at: https://docs.cognite.com/cdf/deprecated#deprecated-and-retired-features",
UserWarning,
stacklevel=3,
)

@staticmethod
def _process_file_ids(ids: list[int] | int | None, external_ids: list[str] | str | None) -> list:
"""
Expand Down Expand Up @@ -90,6 +100,7 @@ def extract(
>>> # Save predictions in CDF using Annotations API:
>>> extract_job.save_predictions()
"""
VisionAPI._deprecation_warning()
# Sanitize input(s)
assert_type(features, "features", [VisionFeature, list], allow_none=False)
if isinstance(features, list):
Expand Down Expand Up @@ -136,6 +147,7 @@ def get_extract_job(self, job_id: int) -> VisionExtractJob:
... predictions = item.predictions
... # do something with the predictions
"""
VisionAPI._deprecation_warning()
job = VisionExtractJob(
job_id=job_id,
status_path=f"{self._RESOURCE_PATH}/extract/",
Expand Down
7 changes: 5 additions & 2 deletions docs/source/contextualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ Convert to an interactive SVG where the provided annotations are highlighted
.. automethod:: cognite.client._api.diagrams.DiagramsAPI.convert


Vision
------
Vision (deprecated)
-------------------

.. warning::
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could also do something like this to really make it stand out?

Vision (deprecated)
-------------------
Image

The Vision API will be removed in a future version of the SDK. Please migrate to the recommended alternative. See the :doc:`deprecated` page for details.

The Vision API enable extraction of information from imagery data based on
their visual content. For example, you can can extract features such as text, asset tags or industrial objects from images using this service.
Expand Down
12 changes: 12 additions & 0 deletions docs/source/deprecated.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Deprecated
==========

Vision
------
Start vision extract job
^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.vision.VisionAPI.extract
:noindex:

Retrieve vision extract job
^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. automethod:: cognite.client._api.vision.VisionAPI.get_extract_job
:noindex:

Templates
---------
Create Template groups
Expand Down
37 changes: 28 additions & 9 deletions tests/tests_unit/test_api/test_vision_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,21 @@ def test_extract_unit(
error_message: str | None,
cognite_client: CogniteClient,
) -> None:
VAPI = cognite_client.vision
vision_api = cognite_client.vision
file_ids = [1, 2, 3]
file_external_ids = []
if error_message is not None:
with pytest.raises(TypeError, match=error_message):
# GET request will not be executed due to invalid parameters in POST
# thus relax the assertion requirements
mock_post_extract.assert_all_requests_are_fired = False
VAPI.extract(features=features, file_ids=file_ids, file_external_ids=file_external_ids)
vision_api.extract(features=features, file_ids=file_ids, file_external_ids=file_external_ids)
else:
is_beta_feature: bool = len([f for f in features if f in VisionFeature.beta_features()]) > 0
error_handling = UserWarning if is_beta_feature else does_not_raise()
# Job should be queued immediately after a successfully POST
with error_handling:
job = VAPI.extract(
job = vision_api.extract(
features=features, file_ids=file_ids, file_external_ids=file_external_ids, parameters=parameters
)
assert isinstance(job, VisionExtractJob)
Expand Down Expand Up @@ -226,16 +226,16 @@ def test_extract_unit(
def test_get_extract(
self, mock_post_extract: RequestsMock, mock_get_extract: RequestsMock, cognite_client: CogniteClient
) -> None:
VAPI = cognite_client.vision
vision_api = cognite_client.vision
file_ids = [1, 2, 3]
file_external_ids = []

job = VAPI.extract(
job = vision_api.extract(
features=VisionFeature.TEXT_DETECTION, file_ids=file_ids, file_external_ids=file_external_ids
)

# retrieved job should correspond to the started job:
retrieved_job = VAPI.get_extract_job(job_id=job.job_id)
retrieved_job = vision_api.get_extract_job(job_id=job.job_id)

assert isinstance(retrieved_job, VisionExtractJob)
assert retrieved_job.job_id == job.job_id
Expand All @@ -247,22 +247,41 @@ def test_get_extract(
assert f"/{job.job_id}" in call.request.url
assert 1 == num_get_requests

def test_extract_emits_deprecation_warning(
self, mock_post_extract: RequestsMock, mock_get_extract: RequestsMock, cognite_client: CogniteClient
) -> None:
mock_get_extract.assert_all_requests_are_fired = False # only POST (extract) is called
vision_api = cognite_client.vision
with pytest.warns(UserWarning, match=r"Vision API will be removed"):
job = vision_api.extract(features=VisionFeature.TEXT_DETECTION, file_ids=[1], file_external_ids=[])
assert isinstance(job, VisionExtractJob)

def test_get_extract_job_emits_deprecation_warning(
self, mock_post_extract: RequestsMock, mock_get_extract: RequestsMock, cognite_client: CogniteClient
) -> None:
mock_post_extract.assert_all_requests_are_fired = False # only GET (get_extract_job) is called
vision_api = cognite_client.vision
with pytest.warns(UserWarning, match=r"Vision API will be removed"):
job = vision_api.get_extract_job(job_id=1)
assert isinstance(job, VisionExtractJob)
assert job.job_id == 1

def test_save_empty_predictions(
self,
mock_post_extract: RequestsMock,
mock_get_extract_empty_predictions: RequestsMock,
cognite_client: CogniteClient,
) -> None:
VAPI = cognite_client.vision
vision_api = cognite_client.vision
file_ids = [1]
file_external_ids = []

job = VAPI.extract(
job = vision_api.extract(
features=VisionFeature.ASSET_TAG_DETECTION, file_ids=file_ids, file_external_ids=file_external_ids
)

# retrieved job should correspond to the started job:
retrieved_job = VAPI.get_extract_job(job_id=job.job_id)
retrieved_job = vision_api.get_extract_job(job_id=job.job_id)

assert isinstance(retrieved_job, VisionExtractJob)
assert retrieved_job.job_id == job.job_id
Expand Down