From 0bf14f56e0d062726e3338310e6487acd748d9f5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 09:24:48 +0000 Subject: [PATCH 1/2] feat: default last_run to the last successful run Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_017ocuALBprYy13aVai5MaVb --- src/apify_client/_resource_clients/actor.py | 10 ++-- src/apify_client/_resource_clients/task.py | 12 ++-- tests/unit/test_last_run_params.py | 64 +++++++++++++++++++++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/apify_client/_resource_clients/actor.py b/src/apify_client/_resource_clients/actor.py index f5d5a430..48c63bc2 100644 --- a/src/apify_client/_resource_clients/actor.py +++ b/src/apify_client/_resource_clients/actor.py @@ -536,7 +536,7 @@ def default_build( def last_run( self, *, - status: ActorJobStatus | None = None, + status: ActorJobStatus | None = 'SUCCEEDED', origin: RunOrigin | None = None, ) -> RunClient: """Retrieve the client for the last run of this Actor. @@ -544,7 +544,8 @@ def last_run( Last run is retrieved based on the start time of the runs. Args: - status: Consider only runs with this status. + status: Consider only runs with this status. Defaults to SUCCEEDED; pass None to consider runs + of any status. origin: Consider only runs started with this origin. Returns: @@ -1139,7 +1140,7 @@ async def default_build( def last_run( self, *, - status: ActorJobStatus | None = None, + status: ActorJobStatus | None = 'SUCCEEDED', origin: RunOrigin | None = None, ) -> RunClientAsync: """Retrieve the client for the last run of this Actor. @@ -1147,7 +1148,8 @@ def last_run( Last run is retrieved based on the start time of the runs. Args: - status: Consider only runs with this status. + status: Consider only runs with this status. Defaults to SUCCEEDED; pass None to consider runs + of any status. origin: Consider only runs started with this origin. Returns: diff --git a/src/apify_client/_resource_clients/task.py b/src/apify_client/_resource_clients/task.py index 178a7fe7..846da38d 100644 --- a/src/apify_client/_resource_clients/task.py +++ b/src/apify_client/_resource_clients/task.py @@ -429,13 +429,14 @@ def runs(self) -> RunCollectionClient: **self._base_client_kwargs, ) - def last_run(self, *, status: ActorJobStatus | None = None, origin: RunOrigin | None = None) -> RunClient: + def last_run(self, *, status: ActorJobStatus | None = 'SUCCEEDED', origin: RunOrigin | None = None) -> RunClient: """Retrieve the client for the last run of this task. Last run is retrieved based on the start time of the runs. Args: - status: Consider only runs with this status. + status: Consider only runs with this status. Defaults to SUCCEEDED; pass None to consider runs + of any status. origin: Consider only runs started with this origin. Returns: @@ -844,13 +845,16 @@ def runs(self) -> RunCollectionClientAsync: **self._base_client_kwargs, ) - def last_run(self, *, status: ActorJobStatus | None = None, origin: RunOrigin | None = None) -> RunClientAsync: + def last_run( + self, *, status: ActorJobStatus | None = 'SUCCEEDED', origin: RunOrigin | None = None + ) -> RunClientAsync: """Retrieve the client for the last run of this task. Last run is retrieved based on the start time of the runs. Args: - status: Consider only runs with this status. + status: Consider only runs with this status. Defaults to SUCCEEDED; pass None to consider runs + of any status. origin: Consider only runs started with this origin. Returns: diff --git a/tests/unit/test_last_run_params.py b/tests/unit/test_last_run_params.py index cb684f49..24677186 100644 --- a/tests/unit/test_last_run_params.py +++ b/tests/unit/test_last_run_params.py @@ -71,3 +71,67 @@ async def test_last_run_filters_propagate_to_chained_clients_async( request, _ = httpserver.log[-1] assert request.args.get('status') == 'SUCCEEDED' assert request.args.get('origin') == 'WEB' + + +@pytest.mark.parametrize( + ('resource', 'path_prefix'), + [ + pytest.param('actor', 'actors', id='actor'), + pytest.param('task', 'actor-tasks', id='task'), + ], +) +@pytest.mark.parametrize( + ('kwargs', 'expected_status'), + [ + pytest.param({}, 'SUCCEEDED', id='default'), + pytest.param({'status': 'FAILED'}, 'FAILED', id='explicit_status'), + pytest.param({'status': None}, None, id='any_status'), + ], +) +def test_last_run_defaults_to_succeeded( + httpserver: HTTPServer, + resource: str, + path_prefix: str, + kwargs: dict, + expected_status: str | None, +) -> None: + """`last_run()` asks for the last successful run unless the caller picks another status or opts out.""" + httpserver.expect_request(f'/v2/{path_prefix}/resource-id/runs/last').respond_with_json(_NOT_FOUND_BODY, status=404) + client = ApifyClient(token='test-token', api_url=httpserver.url_for('/').removesuffix('/')) + + assert getattr(client, resource)('resource-id').last_run(**kwargs).get() is None + + request, _ = httpserver.log[-1] + assert request.args.get('status') == expected_status + + +@pytest.mark.parametrize( + ('resource', 'path_prefix'), + [ + pytest.param('actor', 'actors', id='actor'), + pytest.param('task', 'actor-tasks', id='task'), + ], +) +@pytest.mark.parametrize( + ('kwargs', 'expected_status'), + [ + pytest.param({}, 'SUCCEEDED', id='default'), + pytest.param({'status': 'FAILED'}, 'FAILED', id='explicit_status'), + pytest.param({'status': None}, None, id='any_status'), + ], +) +async def test_last_run_defaults_to_succeeded_async( + httpserver: HTTPServer, + resource: str, + path_prefix: str, + kwargs: dict, + expected_status: str | None, +) -> None: + """Async variant of `test_last_run_defaults_to_succeeded`.""" + httpserver.expect_request(f'/v2/{path_prefix}/resource-id/runs/last').respond_with_json(_NOT_FOUND_BODY, status=404) + client = ApifyClientAsync(token='test-token', api_url=httpserver.url_for('/').removesuffix('/')) + + assert await getattr(client, resource)('resource-id').last_run(**kwargs).get() is None + + request, _ = httpserver.log[-1] + assert request.args.get('status') == expected_status From b92fa059487e3e8923e67a14ec0d9a818e84016f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Nov 2026 09:37:37 +0000 Subject: [PATCH 2/2] test: reword the last_run default test docstring Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_017ocuALBprYy13aVai5MaVb --- tests/unit/test_last_run_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_last_run_params.py b/tests/unit/test_last_run_params.py index 24677186..b00d3275 100644 --- a/tests/unit/test_last_run_params.py +++ b/tests/unit/test_last_run_params.py @@ -95,7 +95,7 @@ def test_last_run_defaults_to_succeeded( kwargs: dict, expected_status: str | None, ) -> None: - """`last_run()` asks for the last successful run unless the caller picks another status or opts out.""" + """`last_run()` asks for the last successful run unless the caller picks a different status or opts out.""" httpserver.expect_request(f'/v2/{path_prefix}/resource-id/runs/last').respond_with_json(_NOT_FOUND_BODY, status=404) client = ApifyClient(token='test-token', api_url=httpserver.url_for('/').removesuffix('/'))