Skip to content

Commit 5cae1e4

Browse files
committed
Add validate_input endpoint
Update `run_input` for actor start Deprecate `content_type` for actor start
1 parent 636dc52 commit 5cae1e4

File tree

2 files changed

+68
-11
lines changed

2 files changed

+68
-11
lines changed

src/apify_client/_utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ def encode_key_value_store_record_value(value: Any, content_type: str | None = N
143143
content_type = 'application/json; charset=utf-8'
144144

145145
if 'application/json' in content_type and not is_file_or_bytes(value) and not isinstance(value, str):
146-
value = json.dumps(value, ensure_ascii=False, indent=2, allow_nan=False, default=str).encode('utf-8')
146+
value = _to_json(value).encode('utf-8')
147147

148-
return (value, content_type)
148+
return value, content_type
149+
150+
151+
def _to_json(value: Any) -> str:
152+
return json.dumps(value, ensure_ascii=False, indent=2, allow_nan=False, default=str)

src/apify_client/clients/resource_clients/actor.py

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
import logging
34
from typing import TYPE_CHECKING, Any
45

56
from apify_shared.utils import (
@@ -9,7 +10,7 @@
910
parse_date_fields,
1011
)
1112

12-
from apify_client._utils import encode_key_value_store_record_value, encode_webhook_list_to_base64, pluck_data
13+
from apify_client._utils import _to_json, encode_webhook_list_to_base64, pluck_data
1314
from apify_client.clients.base import ResourceClient, ResourceClientAsync
1415
from apify_client.clients.resource_clients.actor_version import ActorVersionClient, ActorVersionClientAsync
1516
from apify_client.clients.resource_clients.actor_version_collection import (
@@ -30,6 +31,8 @@
3031

3132
from apify_shared.consts import ActorJobStatus, MetaOrigin
3233

34+
logger = logging.getLogger(__name__)
35+
3336

3437
def get_actor_representation(
3538
*,
@@ -216,7 +219,7 @@ def delete(self) -> None:
216219
def start(
217220
self,
218221
*,
219-
run_input: Any = None,
222+
run_input: str | dict | None = None,
220223
content_type: str | None = None,
221224
build: str | None = None,
222225
max_items: int | None = None,
@@ -232,7 +235,7 @@ def start(
232235
233236
Args:
234237
run_input: The input to pass to the Actor run.
235-
content_type: The content type of the input.
238+
content_type: Deprecated.
236239
build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
237240
the run uses the build specified in the default run configuration for the Actor (typically latest).
238241
max_items: Maximum number of results that will be returned by this run. If the Actor is charged
@@ -255,7 +258,11 @@ def start(
255258
Returns:
256259
The run object.
257260
"""
258-
run_input, content_type = encode_key_value_store_record_value(run_input, content_type)
261+
if content_type:
262+
logger.warning('`content_type` is deprecated and not used anymore.')
263+
264+
if not isinstance(run_input, str):
265+
run_input = _to_json(run_input)
259266

260267
request_params = self._params(
261268
build=build,
@@ -270,7 +277,7 @@ def start(
270277
response = self.http_client.call(
271278
url=self._url('runs'),
272279
method='POST',
273-
headers={'content-type': content_type},
280+
headers={'content-type': 'application/json'},
274281
data=run_input,
275282
params=request_params,
276283
)
@@ -459,6 +466,27 @@ def webhooks(self) -> WebhookCollectionClient:
459466
"""Retrieve a client for webhooks associated with this Actor."""
460467
return WebhookCollectionClient(**self._sub_resource_init_options())
461468

469+
def validate_input(self, run_input: str | bytes | dict | None = None) -> bool:
470+
"""Validate the input for the Actor.
471+
472+
Args:
473+
run_input: The input to validate. Either dictionary or json in bytes or str.
474+
475+
Returns:
476+
True if the input is valid, else raise an exception with validation error details.
477+
"""
478+
if not isinstance(run_input, str):
479+
run_input = _to_json(run_input)
480+
481+
self.http_client.call(
482+
url=self._url('validate-input'),
483+
method='POST',
484+
headers={'content-type': 'application/json'},
485+
data=run_input,
486+
)
487+
488+
return True
489+
462490

463491
class ActorClientAsync(ResourceClientAsync):
464492
"""Async sub-client for manipulating a single Actor."""
@@ -583,7 +611,7 @@ async def delete(self) -> None:
583611
async def start(
584612
self,
585613
*,
586-
run_input: Any = None,
614+
run_input: str | dict | None = None,
587615
content_type: str | None = None,
588616
build: str | None = None,
589617
max_items: int | None = None,
@@ -599,7 +627,7 @@ async def start(
599627
600628
Args:
601629
run_input: The input to pass to the Actor run.
602-
content_type: The content type of the input.
630+
content_type: Deprecated.
603631
build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
604632
the run uses the build specified in the default run configuration for the Actor (typically latest).
605633
max_items: Maximum number of results that will be returned by this run. If the Actor is charged
@@ -622,7 +650,11 @@ async def start(
622650
Returns:
623651
The run object.
624652
"""
625-
run_input, content_type = encode_key_value_store_record_value(run_input, content_type)
653+
if content_type:
654+
logger.warning('`content_type` is deprecated and not used anymore.')
655+
656+
if not isinstance(run_input, str):
657+
run_input = _to_json(run_input)
626658

627659
request_params = self._params(
628660
build=build,
@@ -637,7 +669,7 @@ async def start(
637669
response = await self.http_client.call(
638670
url=self._url('runs'),
639671
method='POST',
640-
headers={'content-type': content_type},
672+
headers={'content-type': 'application/json'},
641673
data=run_input,
642674
params=request_params,
643675
)
@@ -829,3 +861,24 @@ def version(self, version_number: str) -> ActorVersionClientAsync:
829861
def webhooks(self) -> WebhookCollectionClientAsync:
830862
"""Retrieve a client for webhooks associated with this Actor."""
831863
return WebhookCollectionClientAsync(**self._sub_resource_init_options())
864+
865+
async def validate_input(self, run_input: str | dict | None = None) -> bool:
866+
"""Validate the input for the Actor.
867+
868+
Args:
869+
run_input: The input to validate. Either json string or a dictionary.
870+
871+
Returns:
872+
True if the input is valid, else raise an exception with validation error details.
873+
"""
874+
if not isinstance(run_input, str):
875+
run_input = _to_json(run_input)
876+
877+
await self.http_client.call(
878+
url=self._url('validate-input'),
879+
method='POST',
880+
headers={'content-type': 'application/json'},
881+
data=run_input,
882+
)
883+
884+
return True

0 commit comments

Comments
 (0)