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
204 changes: 130 additions & 74 deletions src/apify_client/_apify_client.py

Large diffs are not rendered by default.

8 changes: 0 additions & 8 deletions src/apify_client/_client_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,8 @@
ScheduleClientAsync,
ScheduleCollectionClient,
ScheduleCollectionClientAsync,
StatusMessageWatcherAsync,
StatusMessageWatcherSync,
StoreCollectionClient,
StoreCollectionClientAsync,
StreamedLogAsync,
StreamedLogSync,
TaskClient,
TaskClientAsync,
TaskCollectionClient,
Expand Down Expand Up @@ -87,8 +83,6 @@ class ClientRegistry:
key_value_store_client: type[KeyValueStoreClient]
key_value_store_collection_client: type[KeyValueStoreCollectionClient]
log_client: type[LogClient]
status_message_watcher: type[StatusMessageWatcherSync]
streamed_log: type[StreamedLogSync]
request_queue_client: type[RequestQueueClient]
request_queue_collection_client: type[RequestQueueCollectionClient]
run_client: type[RunClient]
Expand Down Expand Up @@ -126,8 +120,6 @@ class ClientRegistryAsync:
key_value_store_client: type[KeyValueStoreClientAsync]
key_value_store_collection_client: type[KeyValueStoreCollectionClientAsync]
log_client: type[LogClientAsync]
status_message_watcher: type[StatusMessageWatcherAsync]
streamed_log: type[StreamedLogAsync]
request_queue_client: type[RequestQueueClientAsync]
request_queue_collection_client: type[RequestQueueCollectionClientAsync]
run_client: type[RunClientAsync]
Expand Down
36 changes: 36 additions & 0 deletions src/apify_client/_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from __future__ import annotations

from collections.abc import Callable
from typing import Any, Literal, TypeVar

# The order of the rendered API groups is defined by GROUP_ORDER in website/transformDocs.js
# and applied via groupSort in website/docusaurus.config.js.
GroupName = Literal[
'Apify API clients',
'HTTP clients',
'Resource clients',
'Errors',
'Models',
'Other',
]

T = TypeVar('T', bound=Callable[..., Any])


def docs_group(group_name: GroupName) -> Callable[[T], T]: # noqa: ARG001
"""Mark a symbol for rendering and grouping in documentation.

This decorator is used solely for documentation purposes and does not modify the behavior
of the decorated callable.

Args:
group_name: The documentation group to which the symbol belongs.

Returns:
The original callable without modification.
"""

def wrapper(func: T) -> T:
return func

return wrapper
29 changes: 21 additions & 8 deletions src/apify_client/_http_clients/_http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import impit

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


@docs_group('HTTP clients')
class HttpClient(BaseHttpClient):
"""Synchronous HTTP client for Apify API with automatic retries and exponential backoff."""
"""Synchronous HTTP client for the Apify API.

Handles authentication, request serialization, and automatic retries with exponential backoff
for rate-limited (HTTP 429) and server error (HTTP 5xx) responses. Non-retryable errors
(e.g. HTTP 4xx client errors) are raised immediately.
"""

def __init__(
self,
Expand All @@ -44,9 +51,9 @@ def __init__(

Args:
token: Apify API token for authentication.
timeout: Request timeout.
max_retries: Maximum number of retries for failed requests.
min_delay_between_retries: Minimum delay between retries.
timeout: Default timeout for HTTP requests.
max_retries: Maximum number of retry attempts for failed requests.
min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt).
statistics: Statistics tracker for API calls. Created automatically if not provided.
headers: Additional HTTP headers to include in all requests.
"""
Expand Down Expand Up @@ -247,8 +254,14 @@ def stop_retrying() -> None:
return func(stop_retrying, max_retries + 1)


@docs_group('HTTP clients')
class HttpClientAsync(BaseHttpClient):
"""Asynchronous HTTP client for Apify API with automatic retries and exponential backoff."""
"""Asynchronous HTTP client for the Apify API.

Handles authentication, request serialization, and automatic retries with exponential backoff
for rate-limited (HTTP 429) and server error (HTTP 5xx) responses. Non-retryable errors
(e.g. HTTP 4xx client errors) are raised immediately.
"""

def __init__(
self,
Expand All @@ -264,9 +277,9 @@ def __init__(

Args:
token: Apify API token for authentication.
timeout: Request timeout.
max_retries: Maximum number of retries for failed requests.
min_delay_between_retries: Minimum delay between retries.
timeout: Default timeout for HTTP requests.
max_retries: Maximum number of retry attempts for failed requests.
min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt).
statistics: Statistics tracker for API calls. Created automatically if not provided.
headers: Additional HTTP headers to include in all requests.
"""
Expand Down
8 changes: 0 additions & 8 deletions src/apify_client/_resource_clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
from .run_collection import RunCollectionClient, RunCollectionClientAsync
from .schedule import ScheduleClient, ScheduleClientAsync
from .schedule_collection import ScheduleCollectionClient, ScheduleCollectionClientAsync
from .status_message_watcher import StatusMessageWatcher, StatusMessageWatcherAsync, StatusMessageWatcherSync
from .store_collection import StoreCollectionClient, StoreCollectionClientAsync
from .streamed_log import StreamedLog, StreamedLogAsync, StreamedLogSync
from .task import TaskClient, TaskClientAsync
from .task_collection import TaskCollectionClient, TaskCollectionClientAsync
from .user import UserClient, UserClientAsync
Expand Down Expand Up @@ -67,14 +65,8 @@
'ScheduleClientAsync',
'ScheduleCollectionClient',
'ScheduleCollectionClientAsync',
'StatusMessageWatcher',
'StatusMessageWatcherAsync',
'StatusMessageWatcherSync',
'StoreCollectionClient',
'StoreCollectionClientAsync',
'StreamedLog',
'StreamedLogAsync',
'StreamedLogSync',
'TaskClient',
'TaskClientAsync',
'TaskCollectionClient',
Expand Down
3 changes: 3 additions & 0 deletions src/apify_client/_resource_clients/_resource_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import TYPE_CHECKING, Any

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


@docs_group('Resource clients')
class ResourceClient(ResourceClientBase):
"""Base class for synchronous resource clients."""

Expand Down Expand Up @@ -286,6 +288,7 @@ def _wait_for_finish(
return actor_job


@docs_group('Resource clients')
class ResourceClientAsync(ResourceClientBase):
"""Base class for asynchronous resource clients."""

Expand Down
15 changes: 13 additions & 2 deletions src/apify_client/_resource_clients/actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TYPE_CHECKING, Any, Literal

from apify_client._docs import docs_group
from apify_client._models import (
Actor,
ActorPermissionLevel,
Expand Down Expand Up @@ -47,8 +48,13 @@
)


@docs_group('Resource clients')
class ActorClient(ResourceClient):
"""Sub-client for manipulating a single Actor."""
"""Sub-client for managing a specific Actor.

Provides methods to manage a specific Actor, e.g. update it, delete it, build it, or start runs. Obtain an instance
via an appropriate method on the `ApifyClient` class.
"""

def __init__(
self,
Expand Down Expand Up @@ -506,8 +512,13 @@ def validate_input(
return True


@docs_group('Resource clients')
class ActorClientAsync(ResourceClientAsync):
"""Async sub-client for manipulating a single Actor."""
"""Sub-client for managing a specific Actor.

Provides methods to manage a specific Actor, e.g. update it, delete it, build it, or start runs. Obtain an instance
via an appropriate method on the `ApifyClientAsync` class.
"""

def __init__(
self,
Expand Down
15 changes: 13 additions & 2 deletions src/apify_client/_resource_clients/actor_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TYPE_CHECKING, Any, Literal

from apify_client._docs import docs_group
from apify_client._models import Actor, ActorResponse, ListOfActors, ListOfActorsResponse
from apify_client._representations import get_actor_repr
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
Expand All @@ -11,8 +12,13 @@
from datetime import timedelta


@docs_group('Resource clients')
class ActorCollectionClient(ResourceClient):
"""Sub-client for manipulating Actors."""
"""Sub-client for the Actor collection.

Provides methods to manage the Actor collection, e.g. list or create Actors. Obtain an instance via an appropriate
method on the `ApifyClient` class.
"""

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


@docs_group('Resource clients')
class ActorCollectionClientAsync(ResourceClientAsync):
"""Async sub-client for manipulating Actors."""
"""Sub-client for the Actor collection.

Provides methods to manage the Actor collection, e.g. list or create Actors. Obtain an instance via an appropriate
method on the `ApifyClientAsync` class.
"""

def __init__(self, *args: Any, **kwargs: Any) -> None:
resource_path = kwargs.pop('resource_path', 'acts')
Expand Down
15 changes: 13 additions & 2 deletions src/apify_client/_resource_clients/actor_env_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import Any

from apify_client._docs import docs_group
from apify_client._models import EnvVar, EnvVarResponse
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
from apify_client._utils import filter_none_values
Expand All @@ -21,8 +22,13 @@ def get_actor_env_var_representation(
}


@docs_group('Resource clients')
class ActorEnvVarClient(ResourceClient):
"""Sub-client for manipulating a single Actor environment variable."""
"""Sub-client for managing a specific Actor environment variable.

Provides methods to manage a specific Actor environment variable, e.g. get, update, or delete it. Obtain an instance
via an appropriate method on the `ActorVersionClient` class.
"""

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


@docs_group('Resource clients')
class ActorEnvVarClientAsync(ResourceClientAsync):
"""Async sub-client for manipulating a single Actor environment variable."""
"""Sub-client for managing a specific Actor environment variable.

Provides methods to manage a specific Actor environment variable, e.g. get, update, or delete it. Obtain an instance
via an appropriate method on the `ActorVersionClientAsync` class.
"""

def __init__(self, *args: Any, **kwargs: Any) -> None:
resource_path = kwargs.pop('resource_path', 'env-vars')
Expand Down
15 changes: 13 additions & 2 deletions src/apify_client/_resource_clients/actor_env_var_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

from typing import Any

from apify_client._docs import docs_group
from apify_client._models import EnvVar, EnvVarResponse, ListOfEnvVars, ListOfEnvVarsResponse
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
from apify_client._resource_clients.actor_env_var import get_actor_env_var_representation
from apify_client._utils import filter_none_values


@docs_group('Resource clients')
class ActorEnvVarCollectionClient(ResourceClient):
"""Sub-client for manipulating Actor env vars."""
"""Sub-client for the Actor environment variable collection.

Provides methods to manage Actor environment variables, e.g. list or create them. Obtain an instance via an
appropriate method on the `ActorVersionClient` class.
"""

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


@docs_group('Resource clients')
class ActorEnvVarCollectionClientAsync(ResourceClientAsync):
"""Async sub-client for manipulating Actor env vars."""
"""Sub-client for the Actor environment variable collection.

Provides methods to manage Actor environment variables, e.g. list or create them. Obtain an instance via an
appropriate method on the `ActorVersionClientAsync` class.
"""

def __init__(self, *args: Any, **kwargs: Any) -> None:
resource_path = kwargs.pop('resource_path', 'env-vars')
Expand Down
15 changes: 13 additions & 2 deletions src/apify_client/_resource_clients/actor_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TYPE_CHECKING, Any

from apify_client._docs import docs_group
from apify_client._models import Version, VersionResponse, VersionSourceType
from apify_client._representations import get_actor_version_repr
from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync
Expand All @@ -16,8 +17,13 @@
)


@docs_group('Resource clients')
class ActorVersionClient(ResourceClient):
"""Sub-client for manipulating a single Actor version."""
"""Sub-client for managing a specific Actor version.

Provides methods to manage a specific Actor version, e.g. get, update, or delete it. Obtain an instance via an
appropriate method on the `ActorClient` class.
"""

def __init__(
self,
Expand Down Expand Up @@ -121,8 +127,13 @@ def env_var(self, env_var_name: str) -> ActorEnvVarClient:
)


@docs_group('Resource clients')
class ActorVersionClientAsync(ResourceClientAsync):
"""Async sub-client for manipulating a single Actor version."""
"""Sub-client for managing a specific Actor version.

Provides methods to manage a specific Actor version, e.g. get, update, or delete it. Obtain an instance via an
appropriate method on the `ActorClientAsync` class.
"""

def __init__(
self,
Expand Down
Loading