From 59005d5becb0e3152bbab903480d76280ff942e3 Mon Sep 17 00:00:00 2001 From: Auto Implementor Date: Tue, 17 Mar 2026 13:01:23 +0000 Subject: [PATCH] feat(gooddata-sdk): [AUTO] add read_result_binary method for Arrow API format support Expose the new BETA retrieveResultBinary endpoint (GET /result/{resultId}/binary) through BareExecutionResponse and Execution wrapper classes. The method accepts an optional cancel token but deliberately omits paging parameters (offset/limit/ excludedTotalDimensions) which are not supported on the binary endpoint. Co-Authored-By: Claude Sonnet 4.6 --- .../gooddata_sdk/compute/model/execution.py | 31 +++++++ .../tests/compute/test_execution_binary.py | 86 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 packages/gooddata-sdk/tests/compute/test_execution_binary.py diff --git a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py index a81b807ac..aa38f88ac 100644 --- a/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py +++ b/packages/gooddata-sdk/src/gooddata_sdk/compute/model/execution.py @@ -372,6 +372,26 @@ def read_result( ) return ExecutionResult(execution_result) + def read_result_binary( + self, + x_gdc_cancel_token: str | None = None, + ) -> Any: + """ + Reads the execution result in Apache Arrow IPC binary format. + + Note: This is a BETA endpoint. Unlike read_result(), it does not support paging parameters. + """ + kwargs: dict[str, Any] = {"_check_return_type": False} + if x_gdc_cancel_token is not None: + kwargs["x_gdc_cancel_token"] = x_gdc_cancel_token + elif self.cancel_token is not None: + kwargs["x_gdc_cancel_token"] = self.cancel_token + return self._actions_api.retrieve_result_binary( + workspace_id=self._workspace_id, + result_id=self.result_id, + **kwargs, + ) + def cancel(self) -> None: """ Cancels the execution backing this execution result. @@ -464,6 +484,17 @@ def read_result( ) -> ExecutionResult: return self.bare_exec_response.read_result(limit, offset, timeout) + def read_result_binary( + self, + x_gdc_cancel_token: str | None = None, + ) -> Any: + """ + Reads the execution result in Apache Arrow IPC binary format. + + Note: This is a BETA endpoint. Unlike read_result(), it does not support paging parameters. + """ + return self.bare_exec_response.read_result_binary(x_gdc_cancel_token=x_gdc_cancel_token) + def cancel(self) -> None: """ Cancels the execution. diff --git a/packages/gooddata-sdk/tests/compute/test_execution_binary.py b/packages/gooddata-sdk/tests/compute/test_execution_binary.py new file mode 100644 index 000000000..2b9731155 --- /dev/null +++ b/packages/gooddata-sdk/tests/compute/test_execution_binary.py @@ -0,0 +1,86 @@ +# (C) 2026 GoodData Corporation +from __future__ import annotations + +from unittest.mock import MagicMock, patch + +from gooddata_sdk.compute.model.execution import BareExecutionResponse + + +def _make_bare_exec_response(cancel_token: str | None = None) -> BareExecutionResponse: + """Build a BareExecutionResponse with a mocked API client.""" + api_client = MagicMock() + execution_response = { + "execution_response": { + "links": {"executionResult": "result-123"}, + "dimensions": [], + } + } + return BareExecutionResponse( + api_client=api_client, + workspace_id="ws-1", + execution_response=execution_response, + cancel_token=cancel_token, + ) + + +def test_read_result_binary_no_cancel_token(): + """read_result_binary passes no cancel token when neither provided nor stored.""" + resp = _make_bare_exec_response(cancel_token=None) + mock_binary = MagicMock() + resp._actions_api.retrieve_result_binary.return_value = mock_binary + + result = resp.read_result_binary() + + resp._actions_api.retrieve_result_binary.assert_called_once_with( + workspace_id="ws-1", + result_id="result-123", + _check_return_type=False, + ) + assert result is mock_binary + + +def test_read_result_binary_with_stored_cancel_token(): + """read_result_binary forwards the stored cancel token when no explicit token given.""" + resp = _make_bare_exec_response(cancel_token="stored-token") + mock_binary = MagicMock() + resp._actions_api.retrieve_result_binary.return_value = mock_binary + + result = resp.read_result_binary() + + resp._actions_api.retrieve_result_binary.assert_called_once_with( + workspace_id="ws-1", + result_id="result-123", + _check_return_type=False, + x_gdc_cancel_token="stored-token", + ) + assert result is mock_binary + + +def test_read_result_binary_with_explicit_cancel_token(): + """read_result_binary uses explicit cancel token, overriding the stored one.""" + resp = _make_bare_exec_response(cancel_token="stored-token") + mock_binary = MagicMock() + resp._actions_api.retrieve_result_binary.return_value = mock_binary + + result = resp.read_result_binary(x_gdc_cancel_token="explicit-token") + + resp._actions_api.retrieve_result_binary.assert_called_once_with( + workspace_id="ws-1", + result_id="result-123", + _check_return_type=False, + x_gdc_cancel_token="explicit-token", + ) + assert result is mock_binary + + +def test_read_result_binary_does_not_pass_paging_params(): + """read_result_binary must NOT pass offset, limit, or excludedTotalDimensions.""" + resp = _make_bare_exec_response() + resp._actions_api.retrieve_result_binary.return_value = MagicMock() + + resp.read_result_binary() + + call_kwargs = resp._actions_api.retrieve_result_binary.call_args[1] + assert "offset" not in call_kwargs + assert "limit" not in call_kwargs + assert "excluded_total_dimensions" not in call_kwargs