Skip to content

Commit 69571f0

Browse files
vdusekclaude
andauthored
docs: Improve API doc groups and polish docstrings (#638)
## Summary - Introduces the `@docs_group()` decorator (following the crawlee-python pattern) to organize all public symbols into clear documentation groups: **Apify API clients**, **Resource clients**, **HTTP clients**, **Models**, and **Errors** - Applies the decorator to all 260+ public classes across the codebase (2 API clients, 61 resource clients, 192 models, 2 HTTP clients, 3 errors) - Updates `website/transformDocs.js` to read group assignments from the decorator instead of hardcoded JS predicates - Improves and polishes all docstrings for Apify API clients, Resource clients, HTTP clients, and Errors with consistent patterns and helpful context ## Screenshot <img width="2880" height="6778" alt="image" src="https://github.com/user-attachments/assets/b4b101e8-6a6d-47a4-b096-04eff0267460" /> ## Issues - Closes: #637 ## Test plan - [x] CI passes 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 283d470 commit 69571f0

39 files changed

+772
-285
lines changed

src/apify_client/_apify_client.py

Lines changed: 130 additions & 74 deletions
Large diffs are not rendered by default.

src/apify_client/_client_registry.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,8 @@
4343
ScheduleClientAsync,
4444
ScheduleCollectionClient,
4545
ScheduleCollectionClientAsync,
46-
StatusMessageWatcherAsync,
47-
StatusMessageWatcherSync,
4846
StoreCollectionClient,
4947
StoreCollectionClientAsync,
50-
StreamedLogAsync,
51-
StreamedLogSync,
5248
TaskClient,
5349
TaskClientAsync,
5450
TaskCollectionClient,
@@ -87,8 +83,6 @@ class ClientRegistry:
8783
key_value_store_client: type[KeyValueStoreClient]
8884
key_value_store_collection_client: type[KeyValueStoreCollectionClient]
8985
log_client: type[LogClient]
90-
status_message_watcher: type[StatusMessageWatcherSync]
91-
streamed_log: type[StreamedLogSync]
9286
request_queue_client: type[RequestQueueClient]
9387
request_queue_collection_client: type[RequestQueueCollectionClient]
9488
run_client: type[RunClient]
@@ -126,8 +120,6 @@ class ClientRegistryAsync:
126120
key_value_store_client: type[KeyValueStoreClientAsync]
127121
key_value_store_collection_client: type[KeyValueStoreCollectionClientAsync]
128122
log_client: type[LogClientAsync]
129-
status_message_watcher: type[StatusMessageWatcherAsync]
130-
streamed_log: type[StreamedLogAsync]
131123
request_queue_client: type[RequestQueueClientAsync]
132124
request_queue_collection_client: type[RequestQueueCollectionClientAsync]
133125
run_client: type[RunClientAsync]

src/apify_client/_docs.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from __future__ import annotations
2+
3+
from collections.abc import Callable
4+
from typing import Any, Literal, TypeVar
5+
6+
# The order of the rendered API groups is defined by GROUP_ORDER in website/transformDocs.js
7+
# and applied via groupSort in website/docusaurus.config.js.
8+
GroupName = Literal[
9+
'Apify API clients',
10+
'HTTP clients',
11+
'Resource clients',
12+
'Errors',
13+
'Models',
14+
'Other',
15+
]
16+
17+
T = TypeVar('T', bound=Callable[..., Any])
18+
19+
20+
def docs_group(group_name: GroupName) -> Callable[[T], T]: # noqa: ARG001
21+
"""Mark a symbol for rendering and grouping in documentation.
22+
23+
This decorator is used solely for documentation purposes and does not modify the behavior
24+
of the decorated callable.
25+
26+
Args:
27+
group_name: The documentation group to which the symbol belongs.
28+
29+
Returns:
30+
The original callable without modification.
31+
"""
32+
33+
def wrapper(func: T) -> T:
34+
return func
35+
36+
return wrapper

src/apify_client/_http_clients/_http_client.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import impit
1212

1313
from apify_client._consts import DEFAULT_MAX_RETRIES, DEFAULT_MIN_DELAY_BETWEEN_RETRIES, DEFAULT_TIMEOUT
14+
from apify_client._docs import docs_group
1415
from apify_client._http_clients._base import BaseHttpClient
1516
from apify_client._logging import log_context, logger_name
1617
from apify_client._utils import to_seconds
@@ -27,8 +28,14 @@
2728
logger = logging.getLogger(logger_name)
2829

2930

31+
@docs_group('HTTP clients')
3032
class HttpClient(BaseHttpClient):
31-
"""Synchronous HTTP client for Apify API with automatic retries and exponential backoff."""
33+
"""Synchronous HTTP client for the Apify API.
34+
35+
Handles authentication, request serialization, and automatic retries with exponential backoff
36+
for rate-limited (HTTP 429) and server error (HTTP 5xx) responses. Non-retryable errors
37+
(e.g. HTTP 4xx client errors) are raised immediately.
38+
"""
3239

3340
def __init__(
3441
self,
@@ -44,9 +51,9 @@ def __init__(
4451
4552
Args:
4653
token: Apify API token for authentication.
47-
timeout: Request timeout.
48-
max_retries: Maximum number of retries for failed requests.
49-
min_delay_between_retries: Minimum delay between retries.
54+
timeout: Default timeout for HTTP requests.
55+
max_retries: Maximum number of retry attempts for failed requests.
56+
min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt).
5057
statistics: Statistics tracker for API calls. Created automatically if not provided.
5158
headers: Additional HTTP headers to include in all requests.
5259
"""
@@ -247,8 +254,14 @@ def stop_retrying() -> None:
247254
return func(stop_retrying, max_retries + 1)
248255

249256

257+
@docs_group('HTTP clients')
250258
class HttpClientAsync(BaseHttpClient):
251-
"""Asynchronous HTTP client for Apify API with automatic retries and exponential backoff."""
259+
"""Asynchronous HTTP client for the Apify API.
260+
261+
Handles authentication, request serialization, and automatic retries with exponential backoff
262+
for rate-limited (HTTP 429) and server error (HTTP 5xx) responses. Non-retryable errors
263+
(e.g. HTTP 4xx client errors) are raised immediately.
264+
"""
252265

253266
def __init__(
254267
self,
@@ -264,9 +277,9 @@ def __init__(
264277
265278
Args:
266279
token: Apify API token for authentication.
267-
timeout: Request timeout.
268-
max_retries: Maximum number of retries for failed requests.
269-
min_delay_between_retries: Minimum delay between retries.
280+
timeout: Default timeout for HTTP requests.
281+
max_retries: Maximum number of retry attempts for failed requests.
282+
min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt).
270283
statistics: Statistics tracker for API calls. Created automatically if not provided.
271284
headers: Additional HTTP headers to include in all requests.
272285
"""

src/apify_client/_resource_clients/__init__.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
from .run_collection import RunCollectionClient, RunCollectionClientAsync
1818
from .schedule import ScheduleClient, ScheduleClientAsync
1919
from .schedule_collection import ScheduleCollectionClient, ScheduleCollectionClientAsync
20-
from .status_message_watcher import StatusMessageWatcher, StatusMessageWatcherAsync, StatusMessageWatcherSync
2120
from .store_collection import StoreCollectionClient, StoreCollectionClientAsync
22-
from .streamed_log import StreamedLog, StreamedLogAsync, StreamedLogSync
2321
from .task import TaskClient, TaskClientAsync
2422
from .task_collection import TaskCollectionClient, TaskCollectionClientAsync
2523
from .user import UserClient, UserClientAsync
@@ -67,14 +65,8 @@
6765
'ScheduleClientAsync',
6866
'ScheduleCollectionClient',
6967
'ScheduleCollectionClientAsync',
70-
'StatusMessageWatcher',
71-
'StatusMessageWatcherAsync',
72-
'StatusMessageWatcherSync',
7368
'StoreCollectionClient',
7469
'StoreCollectionClientAsync',
75-
'StreamedLog',
76-
'StreamedLogAsync',
77-
'StreamedLogSync',
7870
'TaskClient',
7971
'TaskClientAsync',
8072
'TaskCollectionClient',

src/apify_client/_resource_clients/_resource_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import TYPE_CHECKING, Any
88

99
from apify_client._consts import DEFAULT_WAIT_FOR_FINISH, DEFAULT_WAIT_WHEN_JOB_NOT_EXIST, TERMINAL_STATUSES
10+
from apify_client._docs import docs_group
1011
from apify_client._internal_models import ActorJobResponse
1112
from apify_client._logging import WithLogDetailsClient
1213
from apify_client._utils import catch_not_found_or_throw, response_to_dict, to_safe_id, to_seconds
@@ -120,6 +121,7 @@ def _build_params(self, **kwargs: Any) -> dict:
120121
return {k: v for k, v in merged.items() if v is not None}
121122

122123

124+
@docs_group('Resource clients')
123125
class ResourceClient(ResourceClientBase):
124126
"""Base class for synchronous resource clients."""
125127

@@ -286,6 +288,7 @@ def _wait_for_finish(
286288
return actor_job
287289

288290

291+
@docs_group('Resource clients')
289292
class ResourceClientAsync(ResourceClientBase):
290293
"""Base class for asynchronous resource clients."""
291294

src/apify_client/_resource_clients/actor.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING, Any, Literal
44

5+
from apify_client._docs import docs_group
56
from apify_client._models import (
67
Actor,
78
ActorPermissionLevel,
@@ -47,8 +48,13 @@
4748
)
4849

4950

51+
@docs_group('Resource clients')
5052
class ActorClient(ResourceClient):
51-
"""Sub-client for manipulating a single Actor."""
53+
"""Sub-client for managing a specific Actor.
54+
55+
Provides methods to manage a specific Actor, e.g. update it, delete it, build it, or start runs. Obtain an instance
56+
via an appropriate method on the `ApifyClient` class.
57+
"""
5258

5359
def __init__(
5460
self,
@@ -506,8 +512,13 @@ def validate_input(
506512
return True
507513

508514

515+
@docs_group('Resource clients')
509516
class ActorClientAsync(ResourceClientAsync):
510-
"""Async sub-client for manipulating a single Actor."""
517+
"""Sub-client for managing a specific Actor.
518+
519+
Provides methods to manage a specific Actor, e.g. update it, delete it, build it, or start runs. Obtain an instance
520+
via an appropriate method on the `ApifyClientAsync` class.
521+
"""
511522

512523
def __init__(
513524
self,

src/apify_client/_resource_clients/actor_collection.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING, Any, Literal
44

5+
from apify_client._docs import docs_group
56
from apify_client._models import Actor, ActorResponse, ListOfActors, ListOfActorsResponse
67
from apify_client._representations import get_actor_repr
78
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
@@ -11,8 +12,13 @@
1112
from datetime import timedelta
1213

1314

15+
@docs_group('Resource clients')
1416
class ActorCollectionClient(ResourceClient):
15-
"""Sub-client for manipulating Actors."""
17+
"""Sub-client for the Actor collection.
18+
19+
Provides methods to manage the Actor collection, e.g. list or create Actors. Obtain an instance via an appropriate
20+
method on the `ApifyClient` class.
21+
"""
1622

1723
def __init__(self, *args: Any, **kwargs: Any) -> None:
1824
resource_path = kwargs.pop('resource_path', 'acts')
@@ -138,8 +144,13 @@ def create(
138144
return ActorResponse.model_validate(result).data
139145

140146

147+
@docs_group('Resource clients')
141148
class ActorCollectionClientAsync(ResourceClientAsync):
142-
"""Async sub-client for manipulating Actors."""
149+
"""Sub-client for the Actor collection.
150+
151+
Provides methods to manage the Actor collection, e.g. list or create Actors. Obtain an instance via an appropriate
152+
method on the `ApifyClientAsync` class.
153+
"""
143154

144155
def __init__(self, *args: Any, **kwargs: Any) -> None:
145156
resource_path = kwargs.pop('resource_path', 'acts')

src/apify_client/_resource_clients/actor_env_var.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import Any
44

5+
from apify_client._docs import docs_group
56
from apify_client._models import EnvVar, EnvVarResponse
67
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
78
from apify_client._utils import filter_none_values
@@ -21,8 +22,13 @@ def get_actor_env_var_representation(
2122
}
2223

2324

25+
@docs_group('Resource clients')
2426
class ActorEnvVarClient(ResourceClient):
25-
"""Sub-client for manipulating a single Actor environment variable."""
27+
"""Sub-client for managing a specific Actor environment variable.
28+
29+
Provides methods to manage a specific Actor environment variable, e.g. get, update, or delete it. Obtain an instance
30+
via an appropriate method on the `ActorVersionClient` class.
31+
"""
2632

2733
def __init__(self, *args: Any, **kwargs: Any) -> None:
2834
resource_path = kwargs.pop('resource_path', 'env-vars')
@@ -77,8 +83,13 @@ def delete(self) -> None:
7783
self._delete()
7884

7985

86+
@docs_group('Resource clients')
8087
class ActorEnvVarClientAsync(ResourceClientAsync):
81-
"""Async sub-client for manipulating a single Actor environment variable."""
88+
"""Sub-client for managing a specific Actor environment variable.
89+
90+
Provides methods to manage a specific Actor environment variable, e.g. get, update, or delete it. Obtain an instance
91+
via an appropriate method on the `ActorVersionClientAsync` class.
92+
"""
8293

8394
def __init__(self, *args: Any, **kwargs: Any) -> None:
8495
resource_path = kwargs.pop('resource_path', 'env-vars')

src/apify_client/_resource_clients/actor_env_var_collection.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22

33
from typing import Any
44

5+
from apify_client._docs import docs_group
56
from apify_client._models import EnvVar, EnvVarResponse, ListOfEnvVars, ListOfEnvVarsResponse
67
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
78
from apify_client._resource_clients.actor_env_var import get_actor_env_var_representation
89
from apify_client._utils import filter_none_values
910

1011

12+
@docs_group('Resource clients')
1113
class ActorEnvVarCollectionClient(ResourceClient):
12-
"""Sub-client for manipulating Actor env vars."""
14+
"""Sub-client for the Actor environment variable collection.
15+
16+
Provides methods to manage Actor environment variables, e.g. list or create them. Obtain an instance via an
17+
appropriate method on the `ActorVersionClient` class.
18+
"""
1319

1420
def __init__(self, *args: Any, **kwargs: Any) -> None:
1521
resource_path = kwargs.pop('resource_path', 'env-vars')
@@ -55,8 +61,13 @@ def create(
5561
return EnvVarResponse.model_validate(result).data
5662

5763

64+
@docs_group('Resource clients')
5865
class ActorEnvVarCollectionClientAsync(ResourceClientAsync):
59-
"""Async sub-client for manipulating Actor env vars."""
66+
"""Sub-client for the Actor environment variable collection.
67+
68+
Provides methods to manage Actor environment variables, e.g. list or create them. Obtain an instance via an
69+
appropriate method on the `ActorVersionClientAsync` class.
70+
"""
6071

6172
def __init__(self, *args: Any, **kwargs: Any) -> None:
6273
resource_path = kwargs.pop('resource_path', 'env-vars')

0 commit comments

Comments
 (0)