apify-client 3.2.1b4__tar.gz → 3.2.2b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/CHANGELOG.md +14 -2
  2. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/PKG-INFO +2 -2
  3. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/README.md +1 -1
  4. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/pyproject.toml +3 -2
  5. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/pyproject.toml.orig +6 -2
  6. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_consts.py +9 -0
  7. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_models.py +10 -0
  8. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor.py +89 -20
  9. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/key_value_store.py +18 -8
  10. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/run.py +8 -2
  11. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/task.py +57 -14
  12. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/encoding.py +28 -31
  13. apify_client-3.2.2b2/src/apify_client/_utils/wait_for_resources.py +82 -0
  14. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_clients/__init__.py +2 -0
  15. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_clients/_base.py +119 -32
  16. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_clients/_httpx2.py +3 -2
  17. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_clients/_impit.py +3 -2
  18. apify_client-3.2.2b2/src/apify_client/http_clients/_streamed_body.py +355 -0
  19. apify_client-3.2.2b2/src/apify_client/types.py +98 -0
  20. apify_client-3.2.1b4/src/apify_client/types.py +0 -53
  21. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/CONTRIBUTING.md +0 -0
  22. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/LICENSE +0 -0
  23. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/__init__.py +0 -0
  24. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_apify_client.py +0 -0
  25. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_client_registry.py +0 -0
  26. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_docs.py +0 -0
  27. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_literals.py +0 -0
  28. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_logging.py +0 -0
  29. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_pagination.py +0 -0
  30. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/__init__.py +0 -0
  31. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/_resource_client.py +0 -0
  32. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor_collection.py +0 -0
  33. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor_env_var.py +0 -0
  34. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor_env_var_collection.py +0 -0
  35. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor_version.py +0 -0
  36. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/actor_version_collection.py +0 -0
  37. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/build.py +0 -0
  38. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/build_collection.py +0 -0
  39. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/dataset.py +0 -0
  40. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/dataset_collection.py +0 -0
  41. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/key_value_store_collection.py +0 -0
  42. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/log.py +0 -0
  43. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/request_queue.py +0 -0
  44. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/request_queue_collection.py +0 -0
  45. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/run_collection.py +0 -0
  46. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/schedule.py +0 -0
  47. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/schedule_collection.py +0 -0
  48. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/store_collection.py +0 -0
  49. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/task_collection.py +0 -0
  50. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/user.py +0 -0
  51. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/webhook.py +0 -0
  52. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/webhook_collection.py +0 -0
  53. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/webhook_dispatch.py +0 -0
  54. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_resource_clients/webhook_dispatch_collection.py +0 -0
  55. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_statistics.py +0 -0
  56. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_status_message_watcher.py +0 -0
  57. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_streamed_log.py +0 -0
  58. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_typeddicts.py +0 -0
  59. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/__init__.py +0 -0
  60. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/crypto.py +0 -0
  61. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/errors.py +0 -0
  62. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/http.py +0 -0
  63. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/time.py +0 -0
  64. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/_utils/try_import.py +0 -0
  65. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/errors.py +0 -0
  66. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_compressors/__init__.py +0 -0
  67. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_compressors/_base.py +0 -0
  68. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_compressors/_brotli.py +0 -0
  69. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_compressors/_gzip.py +0 -0
  70. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/http_compressors/_resolve.py +0 -0
  71. {apify_client-3.2.1b4 → apify_client-3.2.2b2}/src/apify_client/py.typed +0 -0
@@ -3,7 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
5
  <!-- git-cliff-unreleased-start -->
6
- ## 3.2.1 - **not yet released**
6
+ ## 3.2.2 - **not yet released**
7
+
8
+ ### 🚀 Features
9
+
10
+ - Stream request bodies from files, iterables, and responses ([#1060](https://github.com/apify/apify-client-python/pull/1060)) ([9be215b](https://github.com/apify/apify-client-python/commit/9be215b23a13de0abc4a255a18450cc764e7a6c7)) by [@vdusek](https://github.com/vdusek), closes [#972](https://github.com/apify/apify-client-python/issues/972)
11
+ - Retry starting a run on memory and concurrent-runs limits ([#1081](https://github.com/apify/apify-client-python/pull/1081)) ([3dd8ca5](https://github.com/apify/apify-client-python/commit/3dd8ca5fe4d2537cb009cb310ba12b39927a9558)) by [@vdusek](https://github.com/vdusek), closes [#1071](https://github.com/apify/apify-client-python/issues/1071)
12
+
13
+ ### 🐛 Bug Fixes
14
+
15
+ - Add missing `readme` field to `Profile` model ([#1086](https://github.com/apify/apify-client-python/pull/1086)) ([ae17148](https://github.com/apify/apify-client-python/commit/ae1714891c4f70d66ab4964c1783fee0a96776f1)) by [@apify-service-account](https://github.com/apify-service-account)
16
+
17
+
18
+ <!-- git-cliff-unreleased-end -->
19
+ ## [3.2.1](https://github.com/apify/apify-client-python/releases/tag/v3.2.1) (2026-09-25)
7
20
 
8
21
  ### 🐛 Bug Fixes
9
22
 
@@ -12,7 +25,6 @@ All notable changes to this project will be documented in this file.
12
25
  - Make `JsonSerializable` type alias read-only ([#1072](https://github.com/apify/apify-client-python/pull/1072)) ([bd82a26](https://github.com/apify/apify-client-python/commit/bd82a2645d3c64f0e4a30de3a016c16d92d48340)) by [@Pijukatel](https://github.com/Pijukatel)
13
26
 
14
27
 
15
- <!-- git-cliff-unreleased-end -->
16
28
  ## [3.2.0](https://github.com/apify/apify-client-python/releases/tag/v3.2.0) (2026-09-03)
17
29
 
18
30
  ### 🚀 Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apify_client
3
- Version: 3.2.1b4
3
+ Version: 3.2.2b2
4
4
  Summary: Apify API client for Python
5
5
  Keywords: apify,api,client,automation,crawling,scraping
6
6
  Author: Apify Technologies s.r.o.
@@ -170,7 +170,7 @@ For a guided walkthrough — authenticating, running an Actor, and reading its r
170
170
  - **Fully typed responses** — every method returns a [Pydantic](https://docs.pydantic.dev/) model generated from the Apify OpenAPI spec, with IDE autocomplete and runtime validation ([Typed models](https://docs.apify.com/api/client/python/docs/concepts/typed-models)).
171
171
  - **Automatic retries** — exponential backoff for network errors, HTTP 429, and 5xx responses, configurable per client ([Retries](https://docs.apify.com/api/client/python/docs/concepts/retries)).
172
172
  - **Tiered timeouts** — short / medium / long tiers picked per endpoint, overridable per call ([Timeouts](https://docs.apify.com/api/client/python/docs/concepts/timeouts)).
173
- - **Pagination and streaming** — iterate datasets, key-value store keys, or live logs without manual paging or buffering ([Pagination](https://docs.apify.com/api/client/python/docs/concepts/pagination), [Streaming](https://docs.apify.com/api/client/python/docs/concepts/streaming-resources)).
173
+ - **Pagination and streaming** — iterate datasets, key-value store keys, or live logs without manual paging or buffering, and upload large records straight from a file or another stream ([Pagination](https://docs.apify.com/api/client/python/docs/concepts/pagination), [Streaming](https://docs.apify.com/api/client/python/docs/concepts/streaming-resources)).
174
174
  - **Convenience methods** — `call()`, `wait_for_finish()`, nested resource access, and other shortcuts that hide platform quirks ([Convenience methods](https://docs.apify.com/api/client/python/docs/concepts/convenience-methods)).
175
175
  - **Pluggable HTTP layer** — use the default [Impit](https://github.com/apify/impit)-based client, opt in to the built-in [HTTPX2](https://github.com/pydantic/httpx2) client, or plug in any custom implementation ([HTTP clients](https://docs.apify.com/api/client/python/docs/concepts/custom-http-clients)).
176
176
  - **Structured errors** — every API error surfaces as an [`ApifyApiError`](https://docs.apify.com/api/client/python/reference/class/ApifyApiError) with HTTP-specific subclasses for precise handling ([Error handling](https://docs.apify.com/api/client/python/docs/concepts/error-handling)).
@@ -133,7 +133,7 @@ For a guided walkthrough — authenticating, running an Actor, and reading its r
133
133
  - **Fully typed responses** — every method returns a [Pydantic](https://docs.pydantic.dev/) model generated from the Apify OpenAPI spec, with IDE autocomplete and runtime validation ([Typed models](https://docs.apify.com/api/client/python/docs/concepts/typed-models)).
134
134
  - **Automatic retries** — exponential backoff for network errors, HTTP 429, and 5xx responses, configurable per client ([Retries](https://docs.apify.com/api/client/python/docs/concepts/retries)).
135
135
  - **Tiered timeouts** — short / medium / long tiers picked per endpoint, overridable per call ([Timeouts](https://docs.apify.com/api/client/python/docs/concepts/timeouts)).
136
- - **Pagination and streaming** — iterate datasets, key-value store keys, or live logs without manual paging or buffering ([Pagination](https://docs.apify.com/api/client/python/docs/concepts/pagination), [Streaming](https://docs.apify.com/api/client/python/docs/concepts/streaming-resources)).
136
+ - **Pagination and streaming** — iterate datasets, key-value store keys, or live logs without manual paging or buffering, and upload large records straight from a file or another stream ([Pagination](https://docs.apify.com/api/client/python/docs/concepts/pagination), [Streaming](https://docs.apify.com/api/client/python/docs/concepts/streaming-resources)).
137
137
  - **Convenience methods** — `call()`, `wait_for_finish()`, nested resource access, and other shortcuts that hide platform quirks ([Convenience methods](https://docs.apify.com/api/client/python/docs/concepts/convenience-methods)).
138
138
  - **Pluggable HTTP layer** — use the default [Impit](https://github.com/apify/impit)-based client, opt in to the built-in [HTTPX2](https://github.com/pydantic/httpx2) client, or plug in any custom implementation ([HTTP clients](https://docs.apify.com/api/client/python/docs/concepts/custom-http-clients)).
139
139
  - **Structured errors** — every API error surfaces as an [`ApifyApiError`](https://docs.apify.com/api/client/python/reference/class/ApifyApiError) with HTTP-specific subclasses for precise handling ([Error handling](https://docs.apify.com/api/client/python/docs/concepts/error-handling)).
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "apify_client"
7
- version = "3.2.1b4"
7
+ version = "3.2.2b2"
8
8
  description = "Apify API client for Python"
9
9
  license = "Apache-2.0"
10
10
  license-files = ["LICENSE"]
@@ -178,6 +178,7 @@ indent-style = "space"
178
178
  addopts = "-r a --verbose --dist worksteal"
179
179
  asyncio_default_fixture_loop_scope = "function"
180
180
  asyncio_mode = "auto"
181
+ filterwarnings = ["ignore:Streaming a request body is experimental:UserWarning"]
181
182
  pythonpath = ["."]
182
183
  timeout = 1800
183
184
 
@@ -245,7 +246,7 @@ disable_timestamp = true
245
246
  keep_model_order = true
246
247
 
247
248
  [tool.apify.openapi-spec]
248
- version = "v2-2026-08-31T125154Z"
249
+ version = "v2-2026-10-01T153946Z"
249
250
 
250
251
  [tool.uv]
251
252
  exclude-newer = "24 hours"
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "apify_client"
7
- version = "3.2.1b4"
7
+ version = "3.2.2b2"
8
8
  description = "Apify API client for Python"
9
9
  authors = [{ name = "Apify Technologies s.r.o.", email = "support@apify.com" }]
10
10
  license = "Apache-2.0"
@@ -187,6 +187,10 @@ max-branches = 18
187
187
  addopts = "-r a --verbose --dist worksteal"
188
188
  asyncio_default_fixture_loop_scope = "function"
189
189
  asyncio_mode = "auto"
190
+ filterwarnings = [
191
+ # The tests stream request bodies throughout, and the warning has a unit test of its own.
192
+ "ignore:Streaming a request body is experimental:UserWarning",
193
+ ]
190
194
  pythonpath = ["."]
191
195
  timeout = 1800
192
196
 
@@ -246,7 +250,7 @@ keep_model_order = true
246
250
  # workflow committing nothing unless the models changed. A local regeneration that only moves this line is that
247
251
  # same case - drop it rather than committing it alone.
248
252
  [tool.apify.openapi-spec]
249
- version = "v2-2026-08-31T125154Z"
253
+ version = "v2-2026-10-01T153946Z"
250
254
 
251
255
  [tool.uv]
252
256
  # Minimal defense against supply-chain atatcks.
@@ -42,6 +42,15 @@ A smaller body already fits in a single network packet, so compressing it costs
42
42
  saving a round trip.
43
43
  """
44
44
 
45
+ STREAMED_BODY_CHUNK_SIZE = 64 * 1024
46
+ """Size of the chunks a streamed request body reads from an `io.IOBase` source, in bytes from a binary stream and in
47
+ characters from a text-mode one.
48
+
49
+ A chunk is the most of a streamed body that is in memory at once, and in the asynchronous client every chunk costs
50
+ one worker-thread hop, so the size balances memory against per-chunk overhead. It matches the buffer size the
51
+ standard library and common HTTP libraries use to copy files.
52
+ """
53
+
45
54
  ALREADY_COMPRESSED_MEDIA_TYPE_PREFIXES = ('audio/', 'image/', 'video/')
46
55
  """Media type prefixes whose payloads carry their own compression, so compressing the request body is wasted work."""
47
56
 
@@ -595,6 +595,12 @@ class Build(BaseModel):
595
595
  build_number: Annotated[
596
596
  str, Field(examples=['0.1.1'], pattern='^([0-9]|[1-9][0-9])\\.([0-9]|[1-9][0-9])(\\.[1-9][0-9]{0,4})$')
597
597
  ]
598
+ image_digest: Annotated[
599
+ str | None, Field(examples=['1b2f1e8c0d5a4c7f9e3b6a2d8c4e0f7a5b9d3c1e6f8a2b4d0c7e9f1a3b5d7c9e'])
600
+ ] = None
601
+ """
602
+ Digest of the built Docker image manifest, without the `sha256:` prefix. Compare digests of two builds to find out whether their image contents differ. `null` if the digest is not available.
603
+ """
598
604
  act_version: Annotated[ActVersion | None, Field(title='BuildActVersion')] = None
599
605
  """
600
606
  Snapshot of the Actor version that this build was created from.
@@ -2280,6 +2286,10 @@ class Profile(BaseModel):
2280
2286
  alias_generator=to_camel,
2281
2287
  )
2282
2288
  bio: Annotated[str | None, Field(examples=['I started web scraping in 1985 using Altair BASIC.'])] = None
2289
+ readme: Annotated[str | None, Field(examples=['### Hello world 👋🏻\nI build web scrapers.'])] = None
2290
+ """
2291
+ Markdown README shown on the user's public profile page.
2292
+ """
2283
2293
  name: Annotated[str | None, Field(examples=['Jane Doe'])] = None
2284
2294
  picture_url: Annotated[AnyUrl | None, Field(examples=['https://apify.com/img/anonymous_user_picture.png'])] = None
2285
2295
  github_username: Annotated[str | None, Field(examples=['torvalds.'])] = None
@@ -26,6 +26,11 @@ from apify_client._resource_clients._resource_client import ResourceClient, Reso
26
26
  from apify_client._utils.encoding import encode_key_value_store_record_value, encode_webhooks_to_base64
27
27
  from apify_client._utils.http import response_to_dict
28
28
  from apify_client._utils.time import to_seconds
29
+ from apify_client._utils.wait_for_resources import (
30
+ prepare_resendable_body,
31
+ start_waiting_for_resources,
32
+ start_waiting_for_resources_async,
33
+ )
29
34
 
30
35
  if TYPE_CHECKING:
31
36
  from datetime import timedelta
@@ -229,6 +234,7 @@ class ActorClient(ResourceClient):
229
234
  force_permission_level: ActorPermissionLevel | None = None,
230
235
  wait_for_finish: int | None = None,
231
236
  webhooks: WebhooksList | None = None,
237
+ wait_for_resources: bool | timedelta = False,
232
238
  timeout: Timeout = 'medium',
233
239
  ) -> Run:
234
240
  """Start the Actor and immediately return the Run object.
@@ -236,7 +242,10 @@ class ActorClient(ResourceClient):
236
242
  https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor
237
243
 
238
244
  Args:
239
- run_input: The input to pass to the Actor run.
245
+ run_input: The input to pass to the Actor run. Accepts the same values as
246
+ `KeyValueStoreClient.set_record`, including an `io.IOBase` stream such as an open file, an iterable
247
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
248
+ memory. Streaming is experimental, and its behavior may change in future versions.
240
249
  content_type: The content type of the input.
241
250
  build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
242
251
  the run uses the build specified in the default run configuration for the Actor (typically latest).
@@ -260,12 +269,21 @@ class ActorClient(ResourceClient):
260
269
  * `event_types`: List of `WebhookEventType` values which trigger the webhook.
261
270
  * `request_url`: URL to which to send the webhook HTTP request.
262
271
  * `payload_template`: Optional template for the request payload.
272
+ wait_for_resources: Retry the start while the account lacks the memory or a concurrent-run slot for the run,
273
+ that is while the API rejects it with an `ApifyApiError` of type `actor-memory-limit-exceeded` or
274
+ `concurrent-runs-limit-exceeded`. Both clear as other runs or builds finish. The start is retried
275
+ every 10 seconds, and any other error is raised right away. `True` retries until the run starts, a
276
+ `timedelta` stops retrying after that long and raises the last error. A run that requests more memory
277
+ than the whole memory limit of the account is rejected with `actor-memory-limit-exceeded` as well and
278
+ never starts, so `True` retries it forever. A streamed `run_input` that cannot be rewound, such as a
279
+ generator, is sent only once, so its start is not retried.
263
280
  timeout: Timeout for the API HTTP request.
264
281
 
265
282
  Returns:
266
283
  The run object.
267
284
  """
268
285
  run_input, content_type = encode_key_value_store_record_value(run_input, content_type=content_type)
286
+ run_input, wait_for_resources = prepare_resendable_body(run_input, wait_for_resources=wait_for_resources)
269
287
 
270
288
  request_params = self._build_params(
271
289
  build=build,
@@ -279,13 +297,16 @@ class ActorClient(ResourceClient):
279
297
  webhooks=encode_webhooks_to_base64(webhooks),
280
298
  )
281
299
 
282
- response = self._http_client.call(
283
- url=self._build_url('runs'),
284
- method='POST',
285
- headers={'content-type': content_type},
286
- data=run_input,
287
- params=request_params,
288
- timeout=timeout,
300
+ response = start_waiting_for_resources(
301
+ lambda: self._http_client.call(
302
+ url=self._build_url('runs'),
303
+ method='POST',
304
+ headers={'content-type': content_type},
305
+ data=run_input,
306
+ params=request_params,
307
+ timeout=timeout,
308
+ ),
309
+ wait_for_resources=wait_for_resources,
289
310
  )
290
311
 
291
312
  result = response_to_dict(response)
@@ -305,6 +326,7 @@ class ActorClient(ResourceClient):
305
326
  webhooks: WebhooksList | None = None,
306
327
  force_permission_level: ActorPermissionLevel | None = None,
307
328
  wait_duration: timedelta | None = None,
329
+ wait_for_resources: bool | timedelta = False,
308
330
  logger: Logger | Literal['default'] | None = 'default',
309
331
  timeout: Timeout = 'no_timeout',
310
332
  ) -> Run | None:
@@ -315,7 +337,10 @@ class ActorClient(ResourceClient):
315
337
  https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor
316
338
 
317
339
  Args:
318
- run_input: The input to pass to the Actor run.
340
+ run_input: The input to pass to the Actor run. Accepts the same values as
341
+ `KeyValueStoreClient.set_record`, including an `io.IOBase` stream such as an open file, an iterable
342
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
343
+ memory. Streaming is experimental, and its behavior may change in future versions.
319
344
  content_type: The content type of the input.
320
345
  build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
321
346
  the run uses the build specified in the default run configuration for the Actor (typically latest).
@@ -335,6 +360,14 @@ class ActorClient(ResourceClient):
335
360
  a webhook set up for the Actor, you do not have to add it again here.
336
361
  wait_duration: The maximum time the server waits for the run to finish. If not provided,
337
362
  waits indefinitely.
363
+ wait_for_resources: Retry the start while the account lacks the memory or a concurrent-run slot for the run,
364
+ that is while the API rejects it with an `ApifyApiError` of type `actor-memory-limit-exceeded` or
365
+ `concurrent-runs-limit-exceeded`. Both clear as other runs or builds finish. The start is retried
366
+ every 10 seconds, and any other error is raised right away. `True` retries until the run starts, a
367
+ `timedelta` stops retrying after that long and raises the last error. A run that requests more memory
368
+ than the whole memory limit of the account is rejected with `actor-memory-limit-exceeded` as well and
369
+ never starts, so `True` retries it forever. The time spent retrying doesn't count toward
370
+ `wait_duration`.
338
371
  logger: Logger used to redirect logs from the Actor run. Using "default" literal means that a predefined
339
372
  default logger will be used. Setting `None` will disable any log propagation. Passing custom logger
340
373
  will redirect logs to the provided logger. The logger is also used to capture status and status message
@@ -355,6 +388,7 @@ class ActorClient(ResourceClient):
355
388
  run_timeout=run_timeout,
356
389
  webhooks=webhooks,
357
390
  force_permission_level=force_permission_level,
391
+ wait_for_resources=wait_for_resources,
358
392
  timeout=timeout,
359
393
  )
360
394
  run_client = self._client_registry.run_client(
@@ -540,7 +574,10 @@ class ActorClient(ResourceClient):
540
574
  """Validate an input for the Actor that defines an input schema.
541
575
 
542
576
  Args:
543
- run_input: The input to validate.
577
+ run_input: The input to validate. Accepts the same values as `KeyValueStoreClient.set_record`,
578
+ including an `io.IOBase` stream such as an open file, an iterable of byte chunks, or a streamed
579
+ `HttpResponse`, which are uploaded in chunks without being held in memory. Streaming is experimental,
580
+ and its behavior may change in future versions.
544
581
  build_tag: The Actor's build tag.
545
582
  content_type: The content type of the input.
546
583
  timeout: Timeout for the API HTTP request.
@@ -731,6 +768,7 @@ class ActorClientAsync(ResourceClientAsync):
731
768
  force_permission_level: ActorPermissionLevel | None = None,
732
769
  wait_for_finish: int | None = None,
733
770
  webhooks: WebhooksList | None = None,
771
+ wait_for_resources: bool | timedelta = False,
734
772
  timeout: Timeout = 'medium',
735
773
  ) -> Run:
736
774
  """Start the Actor and immediately return the Run object.
@@ -738,7 +776,10 @@ class ActorClientAsync(ResourceClientAsync):
738
776
  https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor
739
777
 
740
778
  Args:
741
- run_input: The input to pass to the Actor run.
779
+ run_input: The input to pass to the Actor run. Accepts the same values as
780
+ `KeyValueStoreClientAsync.set_record`, including an `io.IOBase` stream such as an open file, an iterable
781
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
782
+ memory. Streaming is experimental, and its behavior may change in future versions.
742
783
  content_type: The content type of the input.
743
784
  build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
744
785
  the run uses the build specified in the default run configuration for the Actor (typically latest).
@@ -762,12 +803,21 @@ class ActorClientAsync(ResourceClientAsync):
762
803
  * `event_types`: List of `WebhookEventType` values which trigger the webhook.
763
804
  * `request_url`: URL to which to send the webhook HTTP request.
764
805
  * `payload_template`: Optional template for the request payload.
806
+ wait_for_resources: Retry the start while the account lacks the memory or a concurrent-run slot for the run,
807
+ that is while the API rejects it with an `ApifyApiError` of type `actor-memory-limit-exceeded` or
808
+ `concurrent-runs-limit-exceeded`. Both clear as other runs or builds finish. The start is retried
809
+ every 10 seconds, and any other error is raised right away. `True` retries until the run starts, a
810
+ `timedelta` stops retrying after that long and raises the last error. A run that requests more memory
811
+ than the whole memory limit of the account is rejected with `actor-memory-limit-exceeded` as well and
812
+ never starts, so `True` retries it forever. A streamed `run_input` that cannot be rewound, such as a
813
+ generator, is sent only once, so its start is not retried.
765
814
  timeout: Timeout for the API HTTP request.
766
815
 
767
816
  Returns:
768
817
  The run object.
769
818
  """
770
819
  run_input, content_type = encode_key_value_store_record_value(run_input, content_type=content_type)
820
+ run_input, wait_for_resources = prepare_resendable_body(run_input, wait_for_resources=wait_for_resources)
771
821
 
772
822
  request_params = self._build_params(
773
823
  build=build,
@@ -781,13 +831,16 @@ class ActorClientAsync(ResourceClientAsync):
781
831
  webhooks=encode_webhooks_to_base64(webhooks),
782
832
  )
783
833
 
784
- response = await self._http_client.call(
785
- url=self._build_url('runs'),
786
- method='POST',
787
- headers={'content-type': content_type},
788
- data=run_input,
789
- params=request_params,
790
- timeout=timeout,
834
+ response = await start_waiting_for_resources_async(
835
+ lambda: self._http_client.call(
836
+ url=self._build_url('runs'),
837
+ method='POST',
838
+ headers={'content-type': content_type},
839
+ data=run_input,
840
+ params=request_params,
841
+ timeout=timeout,
842
+ ),
843
+ wait_for_resources=wait_for_resources,
791
844
  )
792
845
 
793
846
  result = response_to_dict(response)
@@ -807,6 +860,7 @@ class ActorClientAsync(ResourceClientAsync):
807
860
  webhooks: WebhooksList | None = None,
808
861
  force_permission_level: ActorPermissionLevel | None = None,
809
862
  wait_duration: timedelta | None = None,
863
+ wait_for_resources: bool | timedelta = False,
810
864
  logger: Logger | Literal['default'] | None = 'default',
811
865
  timeout: Timeout = 'no_timeout',
812
866
  ) -> Run | None:
@@ -817,7 +871,10 @@ class ActorClientAsync(ResourceClientAsync):
817
871
  https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor
818
872
 
819
873
  Args:
820
- run_input: The input to pass to the Actor run.
874
+ run_input: The input to pass to the Actor run. Accepts the same values as
875
+ `KeyValueStoreClientAsync.set_record`, including an `io.IOBase` stream such as an open file, an iterable
876
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
877
+ memory. Streaming is experimental, and its behavior may change in future versions.
821
878
  content_type: The content type of the input.
822
879
  build: Specifies the Actor build to run. It can be either a build tag or build number. By default,
823
880
  the run uses the build specified in the default run configuration for the Actor (typically latest).
@@ -837,6 +894,14 @@ class ActorClientAsync(ResourceClientAsync):
837
894
  a webhook set up for the Actor, you do not have to add it again here.
838
895
  wait_duration: The maximum time the server waits for the run to finish. If not provided,
839
896
  waits indefinitely.
897
+ wait_for_resources: Retry the start while the account lacks the memory or a concurrent-run slot for the run,
898
+ that is while the API rejects it with an `ApifyApiError` of type `actor-memory-limit-exceeded` or
899
+ `concurrent-runs-limit-exceeded`. Both clear as other runs or builds finish. The start is retried
900
+ every 10 seconds, and any other error is raised right away. `True` retries until the run starts, a
901
+ `timedelta` stops retrying after that long and raises the last error. A run that requests more memory
902
+ than the whole memory limit of the account is rejected with `actor-memory-limit-exceeded` as well and
903
+ never starts, so `True` retries it forever. The time spent retrying doesn't count toward
904
+ `wait_duration`.
840
905
  logger: Logger used to redirect logs from the Actor run. Using "default" literal means that a predefined
841
906
  default logger will be used. Setting `None` will disable any log propagation. Passing custom logger
842
907
  will redirect logs to the provided logger. The logger is also used to capture status and status message
@@ -857,6 +922,7 @@ class ActorClientAsync(ResourceClientAsync):
857
922
  run_timeout=run_timeout,
858
923
  webhooks=webhooks,
859
924
  force_permission_level=force_permission_level,
925
+ wait_for_resources=wait_for_resources,
860
926
  timeout=timeout,
861
927
  )
862
928
 
@@ -1043,7 +1109,10 @@ class ActorClientAsync(ResourceClientAsync):
1043
1109
  """Validate an input for the Actor that defines an input schema.
1044
1110
 
1045
1111
  Args:
1046
- run_input: The input to validate.
1112
+ run_input: The input to validate. Accepts the same values as `KeyValueStoreClientAsync.set_record`,
1113
+ including an `io.IOBase` stream such as an open file, an iterable of byte chunks, or a streamed
1114
+ `HttpResponse`, which are uploaded in chunks without being held in memory. Streaming is experimental,
1115
+ and its behavior may change in future versions.
1047
1116
  build_tag: The Actor's build tag.
1048
1117
  content_type: The content type of the input.
1049
1118
  timeout: Timeout for the API HTTP request.
@@ -369,14 +369,19 @@ class KeyValueStoreClient(ResourceClient):
369
369
 
370
370
  Args:
371
371
  key: The key of the record to save the value to.
372
- value: The value to save into the record.
372
+ value: The value to save into the record. An `io.IOBase` stream such as an open file, an iterable of byte
373
+ chunks, or a streamed `HttpResponse` is uploaded in chunks as it is read, without being held in memory
374
+ whole or compressed. Any other object with a callable `read` is read whole and sent uncompressed. Only
375
+ a seekable `io.IOBase` value can be retried; any other streamed value gets a single attempt. See
376
+ `StreamedRequestBody` for details. Streaming is experimental, and its behavior may change in future
377
+ versions.
373
378
  content_type: The content type of the saved value.
374
379
  content_encoding: The encoding already applied to `value`, sent as the `Content-Encoding` header. Pass it
375
380
  to upload a pre-compressed value - the client then forwards the bytes as they are instead of
376
381
  compressing them itself. The API accepts `gzip`, `br`, `deflate`, and `identity`, and stores the
377
- record exactly as uploaded, so this also becomes the encoding the record is served with. Only a
378
- bytes-like `value`, or a file-like one that reads into bytes, can carry a compression - anything
379
- else raises `TypeError` instead of being stored under a header that misdescribes it.
382
+ record exactly as uploaded, so this also becomes the encoding the record is served with. A `str`, a
383
+ JSON-serializable object, or a text-mode file cannot be carrying a compression and raises
384
+ `TypeError`; a streamed value is taken at its word, since its bytes are only seen as they are sent.
380
385
  timeout: Timeout for the API HTTP request.
381
386
  """
382
387
  value, content_type = encode_key_value_store_record_value(
@@ -802,14 +807,19 @@ class KeyValueStoreClientAsync(ResourceClientAsync):
802
807
 
803
808
  Args:
804
809
  key: The key of the record to save the value to.
805
- value: The value to save into the record.
810
+ value: The value to save into the record. An `io.IOBase` stream such as an open file, an iterable of byte
811
+ chunks, or a streamed `HttpResponse` is uploaded in chunks as it is read, without being held in memory
812
+ whole or compressed. Any other object with a callable `read` is read whole and sent uncompressed. Only
813
+ a seekable `io.IOBase` value can be retried; any other streamed value gets a single attempt. See
814
+ `StreamedRequestBody` for details. Streaming is experimental, and its behavior may change in future
815
+ versions.
806
816
  content_type: The content type of the saved value.
807
817
  content_encoding: The encoding already applied to `value`, sent as the `Content-Encoding` header. Pass it
808
818
  to upload a pre-compressed value - the client then forwards the bytes as they are instead of
809
819
  compressing them itself. The API accepts `gzip`, `br`, `deflate`, and `identity`, and stores the
810
- record exactly as uploaded, so this also becomes the encoding the record is served with. Only a
811
- bytes-like `value`, or a file-like one that reads into bytes, can carry a compression - anything
812
- else raises `TypeError` instead of being stored under a header that misdescribes it.
820
+ record exactly as uploaded, so this also becomes the encoding the record is served with. A `str`, a
821
+ JSON-serializable object, or a text-mode file cannot be carrying a compression and raises
822
+ `TypeError`; a streamed value is taken at its word, since its bytes are only seen as they are sent.
813
823
  timeout: Timeout for the API HTTP request.
814
824
  """
815
825
  value, content_type = encode_key_value_store_record_value(
@@ -180,7 +180,10 @@ class RunClient(ResourceClient):
180
180
  target_actor_build: The build of the target Actor. It can be either a build tag or build number.
181
181
  By default, the run uses the build specified in the default run configuration for the target Actor
182
182
  (typically the latest build).
183
- run_input: The input to pass to the new run.
183
+ run_input: The input to pass to the new run. Accepts the same values as
184
+ `KeyValueStoreClient.set_record`, including an `io.IOBase` stream such as an open file, an iterable
185
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
186
+ memory. Streaming is experimental, and its behavior may change in future versions.
184
187
  content_type: The content type of the input.
185
188
  timeout: Timeout for the API HTTP request.
186
189
 
@@ -608,7 +611,10 @@ class RunClientAsync(ResourceClientAsync):
608
611
  target_actor_build: The build of the target Actor. It can be either a build tag or build number.
609
612
  By default, the run uses the build specified in the default run configuration for the target Actor
610
613
  (typically the latest build).
611
- run_input: The input to pass to the new run.
614
+ run_input: The input to pass to the new run. Accepts the same values as
615
+ `KeyValueStoreClientAsync.set_record`, including an `io.IOBase` stream such as an open file, an iterable
616
+ of byte chunks, or a streamed `HttpResponse`, which are uploaded in chunks without being held in
617
+ memory. Streaming is experimental, and its behavior may change in future versions.
612
618
  content_type: The content type of the input.
613
619
  timeout: Timeout for the API HTTP request.
614
620