Skip to content

Commit 127d10e

Browse files
committed
docs: cover apify-client v3 changes in the v4 upgrading guide
Restructure the apify-client section of the v4 upgrading guide to mirror the client's "Upgrading to v3" guide, and document the changes that reach SDK users through it: - Split into "Built on apify-client v3", "Typed responses", and "Literal string aliases instead of StrEnum classes"; fix the typed-responses method list (start / abort / call / call_task; metamorph returns None). - Add "Actor pricing info models" - the pricing models are now thin apify-client subclasses; shape unchanged, fuller field set, event_price_usd optional. - Add "Using the client from Actor.new_client" - 404 raising NotFoundError on ambiguous endpoints, keyword-only arguments, and async iterate_* returning AsyncIterator.
1 parent b86be73 commit 127d10e

1 file changed

Lines changed: 68 additions & 4 deletions

File tree

docs/04_upgrading/upgrading_to_v4.md

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ This page summarizes the breaking changes between Apify Python SDK v3.x and v4.0
88

99
## Python 3.11+ required
1010

11-
Support for Python 3.10 has been dropped. Apify Python SDK v4.x requires Python 3.11 or later.
11+
Support for Python 3.10 has been dropped. Apify Python SDK v4.x now requires Python 3.11 or later — make sure your environment is on a compatible version before upgrading.
1212

13-
## `apify-client` v3 required
13+
## Built on `apify-client` v3
1414

15-
The SDK is now built on `apify-client` v3 and no longer depends on `apify-shared`. Three changes are user-visible:
15+
The SDK is now built on [`apify-client`](https://docs.apify.com/api/client/python) v3 and no longer depends on `apify-shared`. The sections below cover the user-visible consequences; see the client's [Upgrading to v3](https://docs.apify.com/api/client/python/docs/upgrading/upgrading-to-v3) guide for the full list of changes in the client itself.
16+
17+
## Typed responses
18+
19+
`Actor.start`, `Actor.abort`, `Actor.call`, and `Actor.call_task` now return `apify_client._models.Run` instead of the SDK-side `ActorRun`. Both are [Pydantic](https://docs.pydantic.dev/latest/) models with the same snake_case fields, so field access is unchanged — only the type and import path differ. The SDK no longer ships its own response models (`apify._models` has been removed); response shapes come from `apify-client`.
20+
21+
## Literal string aliases instead of StrEnum classes
22+
23+
Generated enum-like types are now [`Literal`](https://docs.python.org/3/library/typing.html#typing.Literal) string aliases instead of `StrEnum` classes. Pass plain strings instead of enum members.
1624

17-
- `Actor.start`, `Actor.call`, `Actor.call_task`, and `Actor.metamorph` return `apify_client._models.Run` instead of the SDK-side `ActorRun`. The shape is equivalent — only the import path changes.
1825
- `apify.WebhookEventType` is now a `Literal[...]` instead of a `StrEnum`. Use plain string values (`'ACTOR.RUN.FAILED'`) instead of enum members.
1926
- `apify_shared.consts.ActorEventTypes` (a `StrEnum`) is replaced by `apify.ActorEventTypes`, now a `Literal['systemInfo', 'persistState', 'migrating', 'aborting']`. For runtime values, use `apify.Event` (re-exported from Crawlee) instead of enum members.
2027

@@ -35,6 +42,10 @@ from apify import Actor, Event
3542
Actor.on(Event.SYSTEM_INFO, callback)
3643
```
3744

45+
## Actor pricing info models
46+
47+
The Actor pricing-info models exposed through `Actor.configuration.actor_pricing_info``FreeActorPricingInfo`, `FlatPricePerMonthActorPricingInfo`, `PricePerDatasetItemActorPricingInfo`, `PayPerEventActorPricingInfo`, and the nested `ActorChargeEvent` / `PricingPerEvent` — are now thin subclasses of the corresponding `apify-client` models instead of standalone SDK copies. The discriminated-union shape is unchanged, so existing access (`pricing_model`, per-event titles and prices) keeps working; the models now expose the full `apify-client` field set, and a charge event's `event_price_usd` is optional (it is unset for tier-priced events). `ChargingManager.get_pricing_info()` is unchanged.
48+
3849
## `Webhook` API simplified
3950

4051
The `Webhook` model has been slimmed down to only the fields a user sets when defining a webhook. Server-populated response fields (`id`, `created_at`, `modified_at`, `user_id`, `is_ad_hoc`, `condition`, `last_dispatch`, `stats`) and the unused `WebhookCondition` helper class have been removed. `Webhook` is now a plain `@dataclass` instead of a Pydantic `BaseModel` — construct it with snake_case kwargs; `.model_dump()` / `.model_validate()` are gone.
@@ -79,3 +90,56 @@ The `webhooks` argument on `Actor.start`, `Actor.call`, and `Actor.call_task` st
7990
## `Actor.new_client``timeout` scales all tiers
8091

8192
`apify-client` v3 split its single timeout into four tiers (short / medium / long / max). `Actor.new_client(timeout=...)` still takes a single `timedelta`; the SDK uses it as the medium-tier baseline and scales the other tiers proportionally (short = `timeout / 6`, long = `timeout * 12`, max = `timeout * 24`). The public signature is unchanged — no migration needed.
93+
94+
## Using the client from `Actor.new_client`
95+
96+
`Actor.new_client()` (and the `Actor.apify_client` property) now returns an `apify-client` v3 `ApifyClientAsync`. When you use that client directly, the client's v3 breaking changes apply — the most impactful ones are below. See the client's [Upgrading to v3](https://docs.apify.com/api/client/python/docs/upgrading/upgrading-to-v3) guide for the complete reference.
97+
98+
### 404 raises `NotFoundError` on ambiguous endpoints
99+
100+
Direct `.get(id)` and `.delete(id)` calls still swallow 404 into `None`. But where a 404 could mean either the parent or the sub-resource is missing, the client now raises `NotFoundError` instead of returning `None`.
101+
102+
**Before (v3.x):**
103+
104+
```python
105+
client = Actor.new_client()
106+
107+
# Returned None on 404.
108+
dataset = await client.run('some-run-id').dataset().get()
109+
```
110+
111+
**Now (v4.0):**
112+
113+
```python
114+
from apify_client.errors import NotFoundError
115+
116+
client = Actor.new_client()
117+
118+
# Raises NotFoundError; handle it explicitly.
119+
try:
120+
dataset = await client.run('some-run-id').dataset().get()
121+
except NotFoundError:
122+
dataset = None
123+
```
124+
125+
### Keyword-only arguments
126+
127+
Secondary parameters on several client methods can no longer be passed positionally.
128+
129+
**Before (v3.x):**
130+
131+
```python
132+
await client.key_value_store('my-store').set_record('my-key', {'data': 1}, 'application/json')
133+
await client.run('my-run').charge('my-event', 5)
134+
```
135+
136+
**Now (v4.0):**
137+
138+
```python
139+
await client.key_value_store('my-store').set_record('my-key', {'data': 1}, content_type='application/json')
140+
await client.run('my-run').charge('my-event', count=5)
141+
```
142+
143+
### Async `iterate_*` are no longer coroutine functions
144+
145+
`DatasetClientAsync.iterate_items()` and `KeyValueStoreClientAsync.iterate_keys()` are now plain `def` functions returning `AsyncIterator[T]`. Consumer code (`async for ...`) is unchanged; if you annotate the call's return value, change `AsyncGenerator[T, None]` to `AsyncIterator[T]`.

0 commit comments

Comments
 (0)