diff --git a/python/CHANGELOG.md b/python/CHANGELOG.md index 8d6ca5617..16fab1cc9 100644 --- a/python/CHANGELOG.md +++ b/python/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Bugfixes +- Fix `assets.archive` raising `AttributeError` by reading the correct response field, `archived_run_ids`. + ## [v0.19.1] - July 27, 2026 ### What's New @@ -718,7 +721,7 @@ SiftClient has been updated to provide better support for RuleVersions and bette - Additional methods have been added to the SiftClient Rules resource to allow easy access to RuleVersions - Reports can now be generated from RuleVersions - The Jobs and Reports resources now have a `wait_until_complete` sync/async method, which provides a convenient way to wait until a job or report is complete, with configurable polling and timeout settings. -- When creating reports, SiftClient now returns a Job object, to signify that the report is still in progress. Waiting on the job with `wait_until_complete` will return the completed report once finished. The report_id can also still be accessed directly from the job object if needed. +- When creating reports, SiftClient now returns a Job object, to signify that the report is still in progress. Waiting on the job with `wait_until_complete` will return the completed report once finished. The report_id can also still be accessed directly from the job object if needed. ### Full Changelog - [Add more support for rule versions to SiftClient](https://github.com/sift-stack/sift/pull/479) @@ -735,8 +738,8 @@ SiftClient has been updated to provide better support for RuleVersions and bette ### DEPRECATION NOTICE -The `sift_py` module is deprecated as of **v0.10.0** and will be removed in **v1.0.0**. -Please use `sift_client` for all new development. Several minor releases will follow +The `sift_py` module is deprecated as of **v0.10.0** and will be removed in **v1.0.0**. +Please use `sift_client` for all new development. Several minor releases will follow before the major release to add features and give users time to migrate. ### What's New diff --git a/python/lib/sift_client/_internal/low_level_wrappers/assets.py b/python/lib/sift_client/_internal/low_level_wrappers/assets.py index 72da1adce..f7bdc35da 100644 --- a/python/lib/sift_client/_internal/low_level_wrappers/assets.py +++ b/python/lib/sift_client/_internal/low_level_wrappers/assets.py @@ -102,4 +102,4 @@ async def archive_asset(self, asset_id: str, archive_runs: bool = False) -> list request = ArchiveAssetRequest(asset_id=asset_id, archive_runs=archive_runs) response = await self._grpc_client.get_stub(AssetServiceStub).ArchiveAsset(request) response = cast("ArchiveAssetResponse", response) - return response.archived_runs + return list(response.archived_run_ids) diff --git a/python/lib/sift_client/_tests/_internal/low_level_wrappers/test_assets.py b/python/lib/sift_client/_tests/_internal/low_level_wrappers/test_assets.py new file mode 100644 index 000000000..3899e4e31 --- /dev/null +++ b/python/lib/sift_client/_tests/_internal/low_level_wrappers/test_assets.py @@ -0,0 +1,50 @@ +"""Tests for the assets low-level wrapper.""" + +from unittest.mock import AsyncMock, MagicMock + +import pytest +from sift.assets.v1 import assets_pb2 + +from sift_client._internal.low_level_wrappers.assets import AssetsLowLevelClient + + +def _client_with_stub(stub: MagicMock) -> AssetsLowLevelClient: + grpc = MagicMock() + grpc.get_stub.return_value = stub + return AssetsLowLevelClient(grpc) + + +class TestArchiveAsset: + @pytest.mark.asyncio + async def test_returns_archived_run_ids(self): + stub = MagicMock() + stub.ArchiveAsset = AsyncMock( + return_value=assets_pb2.ArchiveAssetResponse(archived_run_ids=["run-1", "run-2"]) + ) + client = _client_with_stub(stub) + + archived = await client.archive_asset("asset-1", archive_runs=True) + + assert archived == ["run-1", "run-2"] + + @pytest.mark.asyncio + async def test_returns_empty_when_no_runs_archived(self): + stub = MagicMock() + stub.ArchiveAsset = AsyncMock(return_value=assets_pb2.ArchiveAssetResponse()) + client = _client_with_stub(stub) + + archived = await client.archive_asset("asset-1") + + assert list(archived) == [] + + @pytest.mark.asyncio + async def test_request_carries_asset_id_and_archive_runs(self): + stub = MagicMock() + stub.ArchiveAsset = AsyncMock(return_value=assets_pb2.ArchiveAssetResponse()) + client = _client_with_stub(stub) + + await client.archive_asset("asset-1", archive_runs=True) + + request = stub.ArchiveAsset.call_args[0][0] + assert request.asset_id == "asset-1" + assert request.archive_runs is True