Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/apify/_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@ async def start(
token: str | None = None,
content_type: str | None = None,
build: str | None = None,
max_items: int | None = None,
max_total_charge_usd: Decimal | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
Expand All @@ -955,6 +956,8 @@ async def start(
content_type: The content type of the input.
build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
the run uses the build specified in the default run configuration for the Actor (typically latest).
max_items: Maximum number of dataset items you are charged for, for pay-per-result Actors. It caps the
charge, not the output, so the run can return fewer or more items than this.
Comment on lines +959 to +960

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Afaik this is a legacy-only option for the PPE Actors (that have been migrated from PPR, which is not a thing anymore).

iirc it only does something in case your Actor has the apify-default-dataset-item event. For other PPE / free Actors, this is no-op. This can imo be surprising, given the very human-friendly name (max_items), which might suggest otherwise.

run = Actor.start('a-ppe-actor', max_items=50) # returns 50 items, as it was PPR before
run = Actor.start('b-ppe-actor', max_items=50) # returns 1000 items, as it implements other events

Can we be perhaps more vocal about this in the docstring (and propose max_total_charge_usd as the better / more modern option)?

Alternatively, we could drop it from the Python SDK altogether, if we haven't released yet 😅

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

max_total_charge_usd: A limit on the total charged amount for pay-per-event Actors.
restart_on_error: If true, the Actor run process will be restarted whenever it exits with
a non-zero status code.
Expand Down Expand Up @@ -988,6 +991,7 @@ async def start(
run_input=run_input,
content_type=content_type,
build=build,
max_items=max_items,
max_total_charge_usd=max_total_charge_usd,
restart_on_error=restart_on_error,
memory_mbytes=memory_mbytes,
Expand Down Expand Up @@ -1042,6 +1046,7 @@ async def call(
token: str | None = None,
content_type: str | None = None,
build: str | None = None,
max_items: int | None = None,
max_total_charge_usd: Decimal | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
Expand All @@ -1062,6 +1067,8 @@ async def call(
content_type: The content type of the input.
build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
the run uses the build specified in the default run configuration for the Actor (typically latest).
max_items: Maximum number of dataset items you are charged for, for pay-per-result Actors. It caps the
charge, not the output, so the run can return fewer or more items than this.
max_total_charge_usd: A limit on the total charged amount for pay-per-event Actors.
restart_on_error: If true, the Actor run process will be restarted whenever it exits with
a non-zero status code.
Expand Down Expand Up @@ -1099,6 +1106,7 @@ async def call(
run_input=run_input,
content_type=content_type,
build=build,
max_items=max_items,
max_total_charge_usd=max_total_charge_usd,
restart_on_error=restart_on_error,
memory_mbytes=memory_mbytes,
Expand All @@ -1121,6 +1129,7 @@ async def call_task(
task_input: dict | None = None,
*,
build: str | None = None,
max_items: int | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
timeout: timedelta | Literal['inherit'] | None = None,
Expand All @@ -1141,6 +1150,8 @@ async def call_task(
token: The Apify API token to use for this request (defaults to the `APIFY_TOKEN` environment variable).
build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
the run uses the build specified in the default run configuration for the Actor (typically latest).
max_items: Maximum number of dataset items you are charged for, for pay-per-result Actors. It caps the
charge, not the output, so the run can return fewer or more items than this.
restart_on_error: If true, the Task run process will be restarted whenever it exits with
a non-zero status code.
memory_mbytes: Memory limit for the run, in megabytes. By default, the run uses a memory limit specified
Expand Down Expand Up @@ -1171,6 +1182,7 @@ async def call_task(
run = await task_client.call(
task_input=task_input,
build=build,
max_items=max_items,
restart_on_error=restart_on_error,
memory_mbytes=memory_mbytes,
run_timeout=task_call_timeout,
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/actor/test_actor_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,30 @@ async def test_start_actor(apify_client_async_patcher: ApifyClientAsyncPatcher,
assert apify_client_async_patcher.calls['actor']['start'][0][0][0].resource_id == actor_id


@pytest.mark.parametrize(
('client_resource', 'client_method', 'sdk_method'),
[
pytest.param('actor', 'start', 'start', id='start'),
pytest.param('actor', 'call', 'call', id='call'),
pytest.param('task', 'call', 'call_task', id='call_task'),
],
)
async def test_max_items_forwarded_to_client(
apify_client_async_patcher: ApifyClientAsyncPatcher,
fake_actor_run: Run,
client_resource: str,
client_method: str,
sdk_method: str,
) -> None:
"""`max_items` passed to `Actor.start`, `Actor.call` or `Actor.call_task` reaches the API client."""
apify_client_async_patcher.patch(client_resource, client_method, return_value=fake_actor_run)

async with Actor:
await getattr(Actor, sdk_method)('some-id', max_items=42)

assert apify_client_async_patcher.calls[client_resource][client_method][0][1]['max_items'] == 42


async def test_abort_actor_run(apify_client_async_patcher: ApifyClientAsyncPatcher, fake_actor_run: Run) -> None:
apify_client_async_patcher.patch('run', 'abort', return_value=fake_actor_run)
run_id = 'some-run-id'
Expand Down
Loading