From 6c9078a8b63d1d60fc4bac1e50716a6ec0e3f98b Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 10:23:24 +0100 Subject: [PATCH 1/7] docs: Improve API reference with docs_group decorator Add @docs_group decorator to organize public symbols into clear documentation sections (Apify API clients, Resource clients, HTTP clients, Models, Errors) instead of generic predicate-based grouping. Update transformDocs.js to read group names from the decorator. Closes #637 Co-Authored-By: Claude Opus 4.6 --- src/apify_client/_apify_client.py | 3 + src/apify_client/_docs.py | 34 +++ .../_http_clients/_http_client.py | 3 + src/apify_client/_models.py | 194 ++++++++++++++++++ src/apify_client/_resource_clients/actor.py | 3 + .../_resource_clients/actor_collection.py | 3 + .../_resource_clients/actor_env_var.py | 3 + .../actor_env_var_collection.py | 3 + .../_resource_clients/actor_version.py | 3 + .../actor_version_collection.py | 3 + src/apify_client/_resource_clients/build.py | 3 + .../_resource_clients/build_collection.py | 3 + src/apify_client/_resource_clients/dataset.py | 4 + .../_resource_clients/dataset_collection.py | 3 + .../_resource_clients/key_value_store.py | 3 + .../key_value_store_collection.py | 3 + src/apify_client/_resource_clients/log.py | 3 + .../_resource_clients/request_queue.py | 3 + .../request_queue_collection.py | 3 + src/apify_client/_resource_clients/run.py | 3 + .../_resource_clients/run_collection.py | 3 + .../_resource_clients/schedule.py | 3 + .../_resource_clients/schedule_collection.py | 3 + .../status_message_watcher.py | 4 + .../_resource_clients/store_collection.py | 3 + .../_resource_clients/streamed_log.py | 5 + src/apify_client/_resource_clients/task.py | 3 + .../_resource_clients/task_collection.py | 3 + src/apify_client/_resource_clients/user.py | 3 + src/apify_client/_resource_clients/webhook.py | 3 + .../_resource_clients/webhook_collection.py | 3 + .../_resource_clients/webhook_dispatch.py | 3 + .../webhook_dispatch_collection.py | 3 + src/apify_client/errors.py | 5 + website/transformDocs.js | 51 +++-- 35 files changed, 366 insertions(+), 15 deletions(-) create mode 100644 src/apify_client/_docs.py diff --git a/src/apify_client/_apify_client.py b/src/apify_client/_apify_client.py index 93f68f1a..268cb424 100644 --- a/src/apify_client/_apify_client.py +++ b/src/apify_client/_apify_client.py @@ -12,6 +12,7 @@ DEFAULT_MIN_DELAY_BETWEEN_RETRIES, DEFAULT_TIMEOUT, ) +from apify_client._docs import docs_group from apify_client._http_clients import HttpClient, HttpClientAsync from apify_client._resource_clients import ( ActorClient, @@ -79,6 +80,7 @@ from datetime import timedelta +@docs_group('Apify API clients') class ApifyClient: """The Apify API client.""" @@ -340,6 +342,7 @@ def store(self) -> StoreCollectionClient: return StoreCollectionClient(**self._base_kwargs) +@docs_group('Apify API clients') class ApifyClientAsync: """The asynchronous version of the Apify API client.""" diff --git a/src/apify_client/_docs.py b/src/apify_client/_docs.py new file mode 100644 index 00000000..da26df6a --- /dev/null +++ b/src/apify_client/_docs.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +from collections.abc import Callable +from typing import Any, Literal, TypeVar + +# The order of the rendered API groups is defined in the website/docusaurus.config.js file. +GroupName = Literal[ + 'Apify API clients', + 'Resource clients', + 'HTTP clients', + 'Models', + 'Errors', +] + +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 diff --git a/src/apify_client/_http_clients/_http_client.py b/src/apify_client/_http_clients/_http_client.py index 291fac3f..fd406a86 100644 --- a/src/apify_client/_http_clients/_http_client.py +++ b/src/apify_client/_http_clients/_http_client.py @@ -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 @@ -27,6 +28,7 @@ logger = logging.getLogger(logger_name) +@docs_group('HTTP clients') class HttpClient(BaseHttpClient): """Synchronous HTTP client for Apify API with automatic retries and exponential backoff.""" @@ -247,6 +249,7 @@ 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.""" diff --git a/src/apify_client/_models.py b/src/apify_client/_models.py index 26231768..9f6edad8 100644 --- a/src/apify_client/_models.py +++ b/src/apify_client/_models.py @@ -9,7 +9,10 @@ from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, EmailStr, Field +from apify_client._docs import docs_group + +@docs_group('Models') class PaginationResponse(BaseModel): """Common pagination fields for list responses.""" @@ -38,6 +41,7 @@ class PaginationResponse(BaseModel): """ +@docs_group('Models') class ActorStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -54,6 +58,7 @@ class ActorStats(BaseModel): ] = None +@docs_group('Models') class ActorShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -67,6 +72,7 @@ class ActorShort(BaseModel): stats: ActorStats | None = None +@docs_group('Models') class ListOfActors(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -74,6 +80,7 @@ class ListOfActors(PaginationResponse): items: list[ActorShort] +@docs_group('Models') class ListOfActorsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -81,6 +88,7 @@ class ListOfActorsResponse(BaseModel): data: ListOfActors +@docs_group('Models') class Error(BaseModel): model_config = ConfigDict( extra='allow', @@ -89,6 +97,7 @@ class Error(BaseModel): message: Annotated[str, Field(examples=['Actor run did not succeed (run ID: 55uatRrZib4xbZs, status: FAILED)'])] +@docs_group('Models') class ErrorResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -96,6 +105,7 @@ class ErrorResponse(BaseModel): error: Error +@docs_group('Models') class VersionSourceType(StrEnum): SOURCE_FILES = 'SOURCE_FILES' GIT_REPO = 'GIT_REPO' @@ -103,6 +113,7 @@ class VersionSourceType(StrEnum): GITHUB_GIST = 'GITHUB_GIST' +@docs_group('Models') class EnvVar(BaseModel): model_config = ConfigDict( extra='allow', @@ -112,11 +123,13 @@ class EnvVar(BaseModel): is_secret: Annotated[bool | None, Field(alias='isSecret', examples=[False])] = None +@docs_group('Models') class SourceCodeFileFormat(StrEnum): BASE64 = 'BASE64' TEXT = 'TEXT' +@docs_group('Models') class SourceCodeFile(BaseModel): model_config = ConfigDict( extra='allow', @@ -126,6 +139,7 @@ class SourceCodeFile(BaseModel): name: Annotated[str, Field(examples=['src/main.js'])] +@docs_group('Models') class SourceCodeFolder(BaseModel): """Represents a folder in the Actor's source code structure. Distinguished from SourceCodeFile by the presence of the `folder` property set to `true`. @@ -145,6 +159,7 @@ class SourceCodeFolder(BaseModel): """ +@docs_group('Models') class Version(BaseModel): model_config = ConfigDict( extra='allow', @@ -171,6 +186,7 @@ class Version(BaseModel): """ +@docs_group('Models') class CommonActorPricingInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -192,6 +208,7 @@ class CommonActorPricingInfo(BaseModel): reason_for_change: Annotated[str | None, Field(alias='reasonForChange')] = None +@docs_group('Models') class PricingModel(StrEnum): PAY_PER_EVENT = 'PAY_PER_EVENT' PRICE_PER_DATASET_ITEM = 'PRICE_PER_DATASET_ITEM' @@ -199,6 +216,7 @@ class PricingModel(StrEnum): FREE = 'FREE' +@docs_group('Models') class ActorChargeEvent(BaseModel): model_config = ConfigDict( extra='allow', @@ -208,6 +226,7 @@ class ActorChargeEvent(BaseModel): event_description: Annotated[str, Field(alias='eventDescription')] +@docs_group('Models') class PricingPerEvent(BaseModel): model_config = ConfigDict( extra='allow', @@ -215,6 +234,7 @@ class PricingPerEvent(BaseModel): actor_charge_events: Annotated[dict[str, ActorChargeEvent] | None, Field(alias='actorChargeEvents')] = None +@docs_group('Models') class PayPerEventActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -224,6 +244,7 @@ class PayPerEventActorPricingInfo(CommonActorPricingInfo): minimal_max_total_charge_usd: Annotated[float | None, Field(alias='minimalMaxTotalChargeUsd')] = None +@docs_group('Models') class PricePerDatasetItemActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -236,6 +257,7 @@ class PricePerDatasetItemActorPricingInfo(CommonActorPricingInfo): price_per_unit_usd: Annotated[float, Field(alias='pricePerUnitUsd')] +@docs_group('Models') class FlatPricePerMonthActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -251,6 +273,7 @@ class FlatPricePerMonthActorPricingInfo(CommonActorPricingInfo): """ +@docs_group('Models') class FreeActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -258,6 +281,7 @@ class FreeActorPricingInfo(CommonActorPricingInfo): pricing_model: Annotated[Literal['FREE'], Field(alias='pricingModel')] +@docs_group('Models') class DefaultRunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -268,6 +292,7 @@ class DefaultRunOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None +@docs_group('Models') class CreateActorRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -294,6 +319,7 @@ class CreateActorRequest(BaseModel): default_run_options: Annotated[DefaultRunOptions | None, Field(alias='defaultRunOptions')] = None +@docs_group('Models') class ActorPermissionLevel(StrEnum): """Determines permissions that the Actor requires to run. For more information, see the [Actor permissions documentation](https://docs.apify.com/platform/actors/development/permissions).""" @@ -301,6 +327,7 @@ class ActorPermissionLevel(StrEnum): FULL_PERMISSIONS = 'FULL_PERMISSIONS' +@docs_group('Models') class ExampleRunInput(BaseModel): model_config = ConfigDict( extra='allow', @@ -309,6 +336,7 @@ class ExampleRunInput(BaseModel): content_type: Annotated[str, Field(alias='contentType', examples=['application/json; charset=utf-8'])] +@docs_group('Models') class TaggedBuildInfo(BaseModel): """Information about a tagged build.""" @@ -331,6 +359,7 @@ class TaggedBuildInfo(BaseModel): """ +@docs_group('Models') class Actor(BaseModel): model_config = ConfigDict( extra='allow', @@ -369,6 +398,7 @@ class Actor(BaseModel): """ +@docs_group('Models') class ActorResponse(BaseModel): """Response containing Actor data.""" @@ -378,6 +408,7 @@ class ActorResponse(BaseModel): data: Actor +@docs_group('Models') class CreateOrUpdateVersionRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -404,6 +435,7 @@ class CreateOrUpdateVersionRequest(BaseModel): """ +@docs_group('Models') class BuildTag(BaseModel): model_config = ConfigDict( extra='allow', @@ -411,6 +443,7 @@ class BuildTag(BaseModel): build_id: Annotated[str, Field(alias='buildId')] +@docs_group('Models') class UpdateActorRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -483,6 +516,7 @@ class UpdateActorRequest(BaseModel): """ +@docs_group('Models') class ListOfVersions(BaseModel): model_config = ConfigDict( extra='allow', @@ -491,6 +525,7 @@ class ListOfVersions(BaseModel): items: list[Version] +@docs_group('Models') class ListOfVersionsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -498,6 +533,7 @@ class ListOfVersionsResponse(BaseModel): data: ListOfVersions +@docs_group('Models') class VersionResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -505,6 +541,7 @@ class VersionResponse(BaseModel): data: Version +@docs_group('Models') class ListOfEnvVars(BaseModel): model_config = ConfigDict( extra='allow', @@ -513,6 +550,7 @@ class ListOfEnvVars(BaseModel): items: list[EnvVar] +@docs_group('Models') class ListOfEnvVarsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -520,6 +558,7 @@ class ListOfEnvVarsResponse(BaseModel): data: ListOfEnvVars +@docs_group('Models') class EnvVarResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -527,6 +566,7 @@ class EnvVarResponse(BaseModel): data: EnvVar +@docs_group('Models') class WebhookEventType(StrEnum): """Type of event that triggers the webhook.""" @@ -544,6 +584,7 @@ class WebhookEventType(StrEnum): TEST = 'TEST' +@docs_group('Models') class WebhookCondition(BaseModel): model_config = ConfigDict( extra='allow', @@ -553,6 +594,7 @@ class WebhookCondition(BaseModel): actor_run_id: Annotated[str | None, Field(alias='actorRunId', examples=['hgdKZtadYvn4mBpoi'])] = None +@docs_group('Models') class WebhookDispatchStatus(StrEnum): """Status of the webhook dispatch indicating whether the HTTP request was successful.""" @@ -561,6 +603,7 @@ class WebhookDispatchStatus(StrEnum): FAILED = 'FAILED' +@docs_group('Models') class ExampleWebhookDispatch(BaseModel): model_config = ConfigDict( extra='allow', @@ -571,6 +614,7 @@ class ExampleWebhookDispatch(BaseModel): ) +@docs_group('Models') class WebhookStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -578,6 +622,7 @@ class WebhookStats(BaseModel): total_dispatches: Annotated[int, Field(alias='totalDispatches', examples=[1])] +@docs_group('Models') class WebhookShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -597,6 +642,7 @@ class WebhookShort(BaseModel): stats: WebhookStats | None = None +@docs_group('Models') class ListOfWebhooks(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -604,6 +650,7 @@ class ListOfWebhooks(PaginationResponse): items: list[WebhookShort] +@docs_group('Models') class ListOfWebhooksResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -611,6 +658,7 @@ class ListOfWebhooksResponse(BaseModel): data: ListOfWebhooks +@docs_group('Models') class ActorJobStatus(StrEnum): """Status of an Actor job (run or build).""" @@ -624,6 +672,7 @@ class ActorJobStatus(StrEnum): ABORTED = 'ABORTED' +@docs_group('Models') class RunOrigin(StrEnum): DEVELOPMENT = 'DEVELOPMENT' WEB = 'WEB' @@ -636,6 +685,7 @@ class RunOrigin(StrEnum): STANDBY = 'STANDBY' +@docs_group('Models') class BuildsMeta(BaseModel): model_config = ConfigDict( extra='allow', @@ -651,6 +701,7 @@ class BuildsMeta(BaseModel): """ +@docs_group('Models') class BuildShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -666,6 +717,7 @@ class BuildShort(BaseModel): meta: BuildsMeta | None = None +@docs_group('Models') class ListOfBuilds(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -673,6 +725,7 @@ class ListOfBuilds(PaginationResponse): items: list[BuildShort] +@docs_group('Models') class ListOfBuildsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -680,6 +733,7 @@ class ListOfBuildsResponse(BaseModel): data: ListOfBuilds +@docs_group('Models') class BuildStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -689,6 +743,7 @@ class BuildStats(BaseModel): compute_units: Annotated[float, Field(alias='computeUnits', examples=[0.0126994444444444])] +@docs_group('Models') class BuildOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -699,6 +754,7 @@ class BuildOptions(BaseModel): disk_mbytes: Annotated[int | None, Field(alias='diskMbytes', examples=[2048])] = None +@docs_group('Models') class BuildUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -706,6 +762,7 @@ class BuildUsage(BaseModel): actor_compute_units: Annotated[float | None, Field(alias='ACTOR_COMPUTE_UNITS', examples=[0.08])] = None +@docs_group('Models') class Storages(BaseModel): model_config = ConfigDict( extra='allow', @@ -716,6 +773,7 @@ class Storages(BaseModel): """ +@docs_group('Models') class ActorDefinition(BaseModel): """The definition of the Actor, the full specification of this field can be found in [Apify docs](https://docs.apify.com/platform/actors/development/actor-definition/actor-json)""" @@ -781,6 +839,7 @@ class ActorDefinition(BaseModel): """ +@docs_group('Models') class Build(BaseModel): model_config = ConfigDict( extra='allow', @@ -807,6 +866,7 @@ class Build(BaseModel): actor_definition: Annotated[ActorDefinition | None, Field(alias='actorDefinition')] = None +@docs_group('Models') class BuildResponse(BaseModel): """Response containing Actor build data.""" @@ -816,6 +876,7 @@ class BuildResponse(BaseModel): data: Build +@docs_group('Models') class RunMeta(BaseModel): model_config = ConfigDict( extra='allow', @@ -839,6 +900,7 @@ class RunMeta(BaseModel): """ +@docs_group('Models') class RunShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -860,6 +922,7 @@ class RunShort(BaseModel): default_request_queue_id: Annotated[str, Field(alias='defaultRequestQueueId', examples=['so93g2shcDzK3pA85'])] +@docs_group('Models') class ListOfRuns(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -867,6 +930,7 @@ class ListOfRuns(PaginationResponse): items: list[RunShort] +@docs_group('Models') class ListOfRunsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -874,6 +938,7 @@ class ListOfRunsResponse(BaseModel): data: ListOfRuns +@docs_group('Models') class RunStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -897,6 +962,7 @@ class RunStats(BaseModel): compute_units: Annotated[float, Field(alias='computeUnits', examples=[0.13804], ge=0.0)] +@docs_group('Models') class RunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -909,6 +975,7 @@ class RunOptions(BaseModel): max_total_charge_usd: Annotated[float | None, Field(alias='maxTotalChargeUsd', examples=[5], ge=0.0)] = None +@docs_group('Models') class GeneralAccess(StrEnum): """Defines the general access level for the resource.""" @@ -918,6 +985,7 @@ class GeneralAccess(StrEnum): RESTRICTED = 'RESTRICTED' +@docs_group('Models') class RunUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -942,6 +1010,7 @@ class RunUsage(BaseModel): proxy_serps: Annotated[int | None, Field(alias='PROXY_SERPS', examples=[3])] = None +@docs_group('Models') class RunUsageUsd(BaseModel): """Resource usage costs in USD. All values are monetary amounts in US dollars.""" @@ -968,6 +1037,7 @@ class RunUsageUsd(BaseModel): proxy_serps: Annotated[float | None, Field(alias='PROXY_SERPS', examples=[0.003])] = None +@docs_group('Models') class Metamorph(BaseModel): """Information about a metamorph event that occurred during the run.""" @@ -992,6 +1062,7 @@ class Metamorph(BaseModel): """ +@docs_group('Models') class Run(BaseModel): """Represents an Actor run and its associated data.""" @@ -1126,6 +1197,7 @@ class Run(BaseModel): """ +@docs_group('Models') class RunResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1133,6 +1205,7 @@ class RunResponse(BaseModel): data: Run +@docs_group('Models') class TaskStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1140,6 +1213,7 @@ class TaskStats(BaseModel): total_runs: Annotated[int | None, Field(alias='totalRuns', examples=[15])] = None +@docs_group('Models') class TaskShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -1156,6 +1230,7 @@ class TaskShort(BaseModel): stats: TaskStats | None = None +@docs_group('Models') class ListOfTasks(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1163,6 +1238,7 @@ class ListOfTasks(PaginationResponse): items: list[TaskShort] +@docs_group('Models') class ListOfTasksResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1170,6 +1246,7 @@ class ListOfTasksResponse(BaseModel): data: ListOfTasks +@docs_group('Models') class TaskOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -1180,6 +1257,7 @@ class TaskOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None +@docs_group('Models') class TaskInput(BaseModel): """The input configuration for the Actor task. This is a user-defined JSON object that will be passed to the Actor when the task is run. @@ -1191,6 +1269,7 @@ class TaskInput(BaseModel): ) +@docs_group('Models') class CreateTaskRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1201,6 +1280,7 @@ class CreateTaskRequest(BaseModel): input: TaskInput | None = None +@docs_group('Models') class Task(BaseModel): model_config = ConfigDict( extra='allow', @@ -1219,6 +1299,7 @@ class Task(BaseModel): standby_url: Annotated[AnyUrl | None, Field(alias='standbyUrl')] = None +@docs_group('Models') class TaskResponse(BaseModel): """Response containing Actor task data.""" @@ -1228,6 +1309,7 @@ class TaskResponse(BaseModel): data: Task +@docs_group('Models') class UpdateTaskRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1245,6 +1327,7 @@ class UpdateTaskRequest(BaseModel): input: TaskInput | None = None +@docs_group('Models') class Webhook(BaseModel): model_config = ConfigDict( extra='allow', @@ -1271,6 +1354,7 @@ class Webhook(BaseModel): stats: WebhookStats | None = None +@docs_group('Models') class UpdateRunRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1281,6 +1365,7 @@ class UpdateRunRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None +@docs_group('Models') class ChargeRunRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1289,11 +1374,13 @@ class ChargeRunRequest(BaseModel): count: Annotated[int, Field(examples=[1])] +@docs_group('Models') class StorageOwnership(StrEnum): OWNED_BY_ME = 'ownedByMe' SHARED_WITH_ME = 'sharedWithMe' +@docs_group('Models') class KeyValueStoreStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1305,6 +1392,7 @@ class KeyValueStoreStats(BaseModel): s3_storage_bytes: Annotated[int | None, Field(alias='s3StorageBytes', examples=[18])] = None +@docs_group('Models') class KeyValueStore(BaseModel): model_config = ConfigDict( extra='allow', @@ -1340,6 +1428,7 @@ class KeyValueStore(BaseModel): stats: KeyValueStoreStats | None = None +@docs_group('Models') class ListOfKeyValueStores(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1347,6 +1436,7 @@ class ListOfKeyValueStores(PaginationResponse): items: list[KeyValueStore] +@docs_group('Models') class ListOfKeyValueStoresResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1354,6 +1444,7 @@ class ListOfKeyValueStoresResponse(BaseModel): data: ListOfKeyValueStores +@docs_group('Models') class KeyValueStoreResponse(BaseModel): """Response containing key-value store data.""" @@ -1363,6 +1454,7 @@ class KeyValueStoreResponse(BaseModel): data: KeyValueStore +@docs_group('Models') class UpdateStoreRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1371,6 +1463,7 @@ class UpdateStoreRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None +@docs_group('Models') class KeyValueStoreKey(BaseModel): model_config = ConfigDict( extra='allow', @@ -1389,6 +1482,7 @@ class KeyValueStoreKey(BaseModel): """ +@docs_group('Models') class ListOfKeys(BaseModel): model_config = ConfigDict( extra='allow', @@ -1401,6 +1495,7 @@ class ListOfKeys(BaseModel): next_exclusive_start_key: Annotated[str | None, Field(alias='nextExclusiveStartKey', examples=['third-key'])] = None +@docs_group('Models') class ListOfKeysResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1408,6 +1503,7 @@ class ListOfKeysResponse(BaseModel): data: ListOfKeys +@docs_group('Models') class RecordResponse(BaseModel): """The response body contains the value of the record. The content type of the response is determined by the Content-Type header stored with the record. @@ -1419,6 +1515,7 @@ class RecordResponse(BaseModel): ) +@docs_group('Models') class PutRecordRequest(BaseModel): """The request body contains the value to store in the record. The content type should be specified in the Content-Type header. @@ -1430,6 +1527,7 @@ class PutRecordRequest(BaseModel): ) +@docs_group('Models') class DatasetListItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -1446,6 +1544,7 @@ class DatasetListItem(BaseModel): act_run_id: Annotated[str | None, Field(alias='actRunId')] = None +@docs_group('Models') class ListOfDatasets(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1453,6 +1552,7 @@ class ListOfDatasets(PaginationResponse): items: list[DatasetListItem] +@docs_group('Models') class ListOfDatasetsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1460,6 +1560,7 @@ class ListOfDatasetsResponse(BaseModel): data: ListOfDatasets +@docs_group('Models') class DatasetStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1469,6 +1570,7 @@ class DatasetStats(BaseModel): storage_bytes: Annotated[int, Field(alias='storageBytes', examples=[783])] +@docs_group('Models') class Dataset(BaseModel): model_config = ConfigDict( extra='allow', @@ -1530,6 +1632,7 @@ class Dataset(BaseModel): stats: DatasetStats | None = None +@docs_group('Models') class DatasetResponse(BaseModel): """Response containing dataset metadata.""" @@ -1539,6 +1642,7 @@ class DatasetResponse(BaseModel): data: Dataset +@docs_group('Models') class UpdateDatasetRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1547,6 +1651,7 @@ class UpdateDatasetRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None +@docs_group('Models') class PutItemsRequest(BaseModel): """The request body containing the item(s) to add to the dataset. Can be a single object or an array of objects. Each object represents one dataset item. @@ -1558,6 +1663,7 @@ class PutItemsRequest(BaseModel): ) +@docs_group('Models') class ValidationError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1584,6 +1690,7 @@ class ValidationError(BaseModel): """ +@docs_group('Models') class InvalidItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -1598,6 +1705,7 @@ class InvalidItem(BaseModel): """ +@docs_group('Models') class SchemaValidationErrorData(BaseModel): model_config = ConfigDict( extra='allow', @@ -1608,6 +1716,7 @@ class SchemaValidationErrorData(BaseModel): """ +@docs_group('Models') class DatasetSchemaValidationError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1623,6 +1732,7 @@ class DatasetSchemaValidationError(BaseModel): data: SchemaValidationErrorData | None = None +@docs_group('Models') class PutItemResponseError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1630,6 +1740,7 @@ class PutItemResponseError(BaseModel): error: DatasetSchemaValidationError +@docs_group('Models') class DatasetFieldStatistics(BaseModel): model_config = ConfigDict( extra='allow', @@ -1652,6 +1763,7 @@ class DatasetFieldStatistics(BaseModel): """ +@docs_group('Models') class DatasetStatistics(BaseModel): model_config = ConfigDict( extra='allow', @@ -1662,6 +1774,7 @@ class DatasetStatistics(BaseModel): """ +@docs_group('Models') class DatasetStatisticsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1669,6 +1782,7 @@ class DatasetStatisticsResponse(BaseModel): data: DatasetStatistics +@docs_group('Models') class RequestQueueShort(BaseModel): """A shortened request queue object for list responses.""" @@ -1733,6 +1847,7 @@ class RequestQueueShort(BaseModel): """ +@docs_group('Models') class ListOfRequestQueues(PaginationResponse): """A paginated list of request queues.""" @@ -1745,6 +1860,7 @@ class ListOfRequestQueues(PaginationResponse): """ +@docs_group('Models') class ListOfRequestQueuesResponse(BaseModel): """Response containing a list of request queues.""" @@ -1754,6 +1870,7 @@ class ListOfRequestQueuesResponse(BaseModel): data: ListOfRequestQueues +@docs_group('Models') class RequestQueueStats(BaseModel): """Statistics about request queue operations and storage.""" @@ -1782,6 +1899,7 @@ class RequestQueueStats(BaseModel): """ +@docs_group('Models') class RequestQueue(BaseModel): """A request queue object containing metadata and statistics.""" @@ -1838,6 +1956,7 @@ class RequestQueue(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None +@docs_group('Models') class RequestQueueResponse(BaseModel): """Response containing request queue data.""" @@ -1847,6 +1966,7 @@ class RequestQueueResponse(BaseModel): data: RequestQueue +@docs_group('Models') class UpdateRequestQueueRequest(BaseModel): """Request object for updating a request queue.""" @@ -1860,6 +1980,7 @@ class UpdateRequestQueueRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None +@docs_group('Models') class RequestDraft(BaseModel): """A request that failed to be processed during a request queue operation and can be retried.""" @@ -1884,6 +2005,7 @@ class RequestDraft(BaseModel): """ +@docs_group('Models') class AddedRequest(BaseModel): """Information about a request that was successfully added to a request queue.""" @@ -1908,6 +2030,7 @@ class AddedRequest(BaseModel): """ +@docs_group('Models') class BatchAddResult(BaseModel): """Result of a batch add operation containing successfully processed and failed requests.""" @@ -1924,6 +2047,7 @@ class BatchAddResult(BaseModel): """ +@docs_group('Models') class BatchAddResponse(BaseModel): """Response containing the result of a batch add operation.""" @@ -1933,6 +2057,7 @@ class BatchAddResponse(BaseModel): data: BatchAddResult +@docs_group('Models') class DeletedRequest(BaseModel): """Confirmation of a request that was successfully deleted from a request queue.""" @@ -1949,6 +2074,7 @@ class DeletedRequest(BaseModel): """ +@docs_group('Models') class BatchDeleteResult(BaseModel): """Result of a batch delete operation containing successfully deleted and failed requests.""" @@ -1965,6 +2091,7 @@ class BatchDeleteResult(BaseModel): """ +@docs_group('Models') class BatchDeleteResponse(BaseModel): """Response containing the result of a batch delete operation.""" @@ -1974,6 +2101,7 @@ class BatchDeleteResponse(BaseModel): data: BatchDeleteResult +@docs_group('Models') class UnlockRequestsResult(BaseModel): """Result of unlocking requests in the request queue.""" @@ -1986,6 +2114,7 @@ class UnlockRequestsResult(BaseModel): """ +@docs_group('Models') class UnlockRequestsResponse(BaseModel): """Response containing the result of unlocking requests.""" @@ -1995,6 +2124,7 @@ class UnlockRequestsResponse(BaseModel): data: UnlockRequestsResult +@docs_group('Models') class RequestUserData(BaseModel): """Custom user data attached to the request. Can contain arbitrary fields.""" @@ -2011,6 +2141,7 @@ class RequestUserData(BaseModel): """ +@docs_group('Models') class Request(BaseModel): """A request stored in the request queue, including its metadata and processing state.""" @@ -2064,6 +2195,7 @@ class Request(BaseModel): """ +@docs_group('Models') class ListOfRequests(BaseModel): """A paginated list of requests from the request queue.""" @@ -2088,6 +2220,7 @@ class ListOfRequests(BaseModel): """ +@docs_group('Models') class ListOfRequestsResponse(BaseModel): """Response containing a list of requests from the request queue.""" @@ -2097,6 +2230,7 @@ class ListOfRequestsResponse(BaseModel): data: ListOfRequests +@docs_group('Models') class RequestRegistration(BaseModel): """Result of registering a request in the request queue, either by adding a new request or updating an existing one.""" @@ -2117,6 +2251,7 @@ class RequestRegistration(BaseModel): """ +@docs_group('Models') class AddRequestResponse(BaseModel): """Response containing the result of adding a request to the request queue.""" @@ -2126,6 +2261,7 @@ class AddRequestResponse(BaseModel): data: RequestRegistration +@docs_group('Models') class RequestResponse(BaseModel): """Response containing a single request from the request queue.""" @@ -2135,6 +2271,7 @@ class RequestResponse(BaseModel): data: Request +@docs_group('Models') class UpdateRequestResponse(BaseModel): """Response containing the result of updating a request in the request queue.""" @@ -2144,6 +2281,7 @@ class UpdateRequestResponse(BaseModel): data: RequestRegistration +@docs_group('Models') class HeadRequest(BaseModel): """A request from the request queue head without lock information.""" @@ -2172,6 +2310,7 @@ class HeadRequest(BaseModel): """ +@docs_group('Models') class RequestQueueHead(BaseModel): """A batch of requests from the request queue head without locking.""" @@ -2196,6 +2335,7 @@ class RequestQueueHead(BaseModel): """ +@docs_group('Models') class HeadResponse(BaseModel): """Response containing requests from the request queue head without locking.""" @@ -2205,6 +2345,7 @@ class HeadResponse(BaseModel): data: RequestQueueHead +@docs_group('Models') class LockedHeadRequest(BaseModel): """A request from the request queue head that has been locked for processing.""" @@ -2237,6 +2378,7 @@ class LockedHeadRequest(BaseModel): """ +@docs_group('Models') class LockedRequestQueueHead(BaseModel): """A batch of locked requests from the request queue head.""" @@ -2273,6 +2415,7 @@ class LockedRequestQueueHead(BaseModel): """ +@docs_group('Models') class HeadAndLockResponse(BaseModel): """Response containing locked requests from the request queue head.""" @@ -2282,6 +2425,7 @@ class HeadAndLockResponse(BaseModel): data: LockedRequestQueueHead +@docs_group('Models') class RequestLockInfo(BaseModel): """Information about a request lock.""" @@ -2294,6 +2438,7 @@ class RequestLockInfo(BaseModel): """ +@docs_group('Models') class ProlongRequestLockResponse(BaseModel): """Response containing updated lock information after prolonging a request lock.""" @@ -2303,6 +2448,7 @@ class ProlongRequestLockResponse(BaseModel): data: RequestLockInfo +@docs_group('Models') class WebhookCreate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2324,6 +2470,7 @@ class WebhookCreate(BaseModel): should_interpolate_strings: Annotated[bool | None, Field(alias='shouldInterpolateStrings', examples=[False])] = None +@docs_group('Models') class WebhookResponse(BaseModel): """Response containing webhook data.""" @@ -2333,6 +2480,7 @@ class WebhookResponse(BaseModel): data: Webhook +@docs_group('Models') class WebhookUpdate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2355,6 +2503,7 @@ class WebhookUpdate(BaseModel): should_interpolate_strings: Annotated[bool | None, Field(alias='shouldInterpolateStrings', examples=[False])] = None +@docs_group('Models') class EventData(BaseModel): model_config = ConfigDict( extra='allow', @@ -2363,6 +2512,7 @@ class EventData(BaseModel): actor_run_id: Annotated[str, Field(alias='actorRunId', examples=['JgwXN9BdwxGcu9MMF'])] +@docs_group('Models') class Call(BaseModel): model_config = ConfigDict( extra='allow', @@ -2376,6 +2526,7 @@ class Call(BaseModel): response_body: Annotated[str | None, Field(alias='responseBody', examples=['{"foo": "bar"}'])] = None +@docs_group('Models') class WebhookDispatch(BaseModel): model_config = ConfigDict( extra='allow', @@ -2390,6 +2541,7 @@ class WebhookDispatch(BaseModel): calls: Annotated[list[Call] | None, Field(title='calls')] = None +@docs_group('Models') class TestWebhookResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2397,6 +2549,7 @@ class TestWebhookResponse(BaseModel): data: WebhookDispatch +@docs_group('Models') class ListOfWebhookDispatches(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2404,6 +2557,7 @@ class ListOfWebhookDispatches(PaginationResponse): items: list[WebhookDispatch] +@docs_group('Models') class WebhookDispatchList(BaseModel): model_config = ConfigDict( extra='allow', @@ -2411,6 +2565,7 @@ class WebhookDispatchList(BaseModel): data: ListOfWebhookDispatches | None = None +@docs_group('Models') class WebhookDispatchResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2418,6 +2573,7 @@ class WebhookDispatchResponse(BaseModel): data: WebhookDispatch +@docs_group('Models') class ScheduleActionType(StrEnum): """Type of action to perform when the schedule triggers.""" @@ -2425,6 +2581,7 @@ class ScheduleActionType(StrEnum): RUN_ACTOR_TASK = 'RUN_ACTOR_TASK' +@docs_group('Models') class ScheduleAction(BaseModel): model_config = ConfigDict( extra='allow', @@ -2434,6 +2591,7 @@ class ScheduleAction(BaseModel): actor_id: Annotated[str, Field(alias='actorId', examples=['HKhKmiCMrDgu9eXeE'])] +@docs_group('Models') class ScheduleShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -2452,6 +2610,7 @@ class ScheduleShort(BaseModel): actions: list[ScheduleAction] +@docs_group('Models') class ListOfSchedules(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2459,6 +2618,7 @@ class ListOfSchedules(PaginationResponse): items: list[ScheduleShort] +@docs_group('Models') class ListOfSchedulesResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2466,6 +2626,7 @@ class ListOfSchedulesResponse(BaseModel): data: ListOfSchedules +@docs_group('Models') class ScheduleActionsRunInput(BaseModel): model_config = ConfigDict( extra='allow', @@ -2474,6 +2635,7 @@ class ScheduleActionsRunInput(BaseModel): content_type: Annotated[str | None, Field(alias='contentType', examples=['application/json; charset=utf-8'])] = None +@docs_group('Models') class ScheduleActionsRunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2484,6 +2646,7 @@ class ScheduleActionsRunOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None +@docs_group('Models') class ScheduleCreateActions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2494,6 +2657,7 @@ class ScheduleCreateActions(BaseModel): run_options: Annotated[ScheduleActionsRunOptions | None, Field(alias='runOptions')] = None +@docs_group('Models') class ScheduleCreate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2507,6 +2671,7 @@ class ScheduleCreate(BaseModel): actions: list[ScheduleCreateActions] | None = None +@docs_group('Models') class ScheduleActions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2518,6 +2683,7 @@ class ScheduleActions(BaseModel): run_options: Annotated[ScheduleActionsRunOptions | None, Field(alias='runOptions')] = None +@docs_group('Models') class Schedule(BaseModel): model_config = ConfigDict( extra='allow', @@ -2537,6 +2703,7 @@ class Schedule(BaseModel): actions: list[ScheduleActions] +@docs_group('Models') class ScheduleResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2544,6 +2711,7 @@ class ScheduleResponse(BaseModel): data: Schedule +@docs_group('Models') class ScheduleInvoked(BaseModel): model_config = ConfigDict( extra='allow', @@ -2553,6 +2721,7 @@ class ScheduleInvoked(BaseModel): created_at: Annotated[AwareDatetime, Field(alias='createdAt', examples=['2019-03-26T12:28:00.370Z'])] +@docs_group('Models') class ScheduleLogResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2560,6 +2729,7 @@ class ScheduleLogResponse(BaseModel): data: list[ScheduleInvoked] +@docs_group('Models') class CurrentPricingInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2567,6 +2737,7 @@ class CurrentPricingInfo(BaseModel): pricing_model: Annotated[str, Field(alias='pricingModel', examples=['FREE'])] +@docs_group('Models') class StoreListActor(BaseModel): model_config = ConfigDict( extra='allow', @@ -2594,6 +2765,7 @@ class StoreListActor(BaseModel): """ +@docs_group('Models') class ListOfStoreActors(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2601,6 +2773,7 @@ class ListOfStoreActors(PaginationResponse): items: list[StoreListActor] +@docs_group('Models') class ListOfActorsInStoreResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2608,6 +2781,7 @@ class ListOfActorsInStoreResponse(BaseModel): data: ListOfStoreActors +@docs_group('Models') class Profile(BaseModel): model_config = ConfigDict( extra='allow', @@ -2622,6 +2796,7 @@ class Profile(BaseModel): twitter_username: Annotated[str | None, Field(alias='twitterUsername', examples=['@BillGates'])] = None +@docs_group('Models') class UserPublicInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2630,6 +2805,7 @@ class UserPublicInfo(BaseModel): profile: Profile +@docs_group('Models') class PublicUserDataResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2637,6 +2813,7 @@ class PublicUserDataResponse(BaseModel): data: UserPublicInfo +@docs_group('Models') class ProxyGroup(BaseModel): model_config = ConfigDict( extra='allow', @@ -2646,6 +2823,7 @@ class ProxyGroup(BaseModel): available_count: Annotated[int, Field(alias='availableCount', examples=[10])] +@docs_group('Models') class Proxy(BaseModel): model_config = ConfigDict( extra='allow', @@ -2654,6 +2832,7 @@ class Proxy(BaseModel): groups: list[ProxyGroup] +@docs_group('Models') class Plan(BaseModel): model_config = ConfigDict( extra='allow', @@ -2693,6 +2872,7 @@ class Plan(BaseModel): available_add_ons: Annotated[list[str], Field(alias='availableAddOns', examples=[[]])] +@docs_group('Models') class EffectivePlatformFeature(BaseModel): model_config = ConfigDict( extra='allow', @@ -2714,6 +2894,7 @@ class EffectivePlatformFeature(BaseModel): ] = None +@docs_group('Models') class EffectivePlatformFeatures(BaseModel): model_config = ConfigDict( extra='allow', @@ -2730,6 +2911,7 @@ class EffectivePlatformFeatures(BaseModel): actors_public_developer: Annotated[EffectivePlatformFeature, Field(alias='ACTORS_PUBLIC_DEVELOPER')] +@docs_group('Models') class UserPrivateInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2745,6 +2927,7 @@ class UserPrivateInfo(BaseModel): is_paying: Annotated[bool, Field(alias='isPaying', examples=[True])] +@docs_group('Models') class PrivateUserDataResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2752,6 +2935,7 @@ class PrivateUserDataResponse(BaseModel): data: UserPrivateInfo +@docs_group('Models') class UsageCycle(BaseModel): model_config = ConfigDict( extra='allow', @@ -2760,6 +2944,7 @@ class UsageCycle(BaseModel): end_at: Annotated[AwareDatetime, Field(alias='endAt', examples=['2022-11-01T23:59:59.999Z'])] +@docs_group('Models') class PriceTiers(BaseModel): model_config = ConfigDict( extra='allow', @@ -2771,6 +2956,7 @@ class PriceTiers(BaseModel): price_usd: Annotated[float, Field(alias='priceUsd', examples=[0])] +@docs_group('Models') class UsageItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -2784,6 +2970,7 @@ class UsageItem(BaseModel): price_tiers: Annotated[list[PriceTiers] | None, Field(alias='priceTiers')] = None +@docs_group('Models') class DailyServiceUsages(BaseModel): model_config = ConfigDict( extra='allow', @@ -2793,6 +2980,7 @@ class DailyServiceUsages(BaseModel): total_usage_credits_usd: Annotated[float, Field(alias='totalUsageCreditsUsd', examples=[0.0474385791970591])] +@docs_group('Models') class MonthlyUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -2808,6 +2996,7 @@ class MonthlyUsage(BaseModel): ] +@docs_group('Models') class MonthlyUsageResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2815,6 +3004,7 @@ class MonthlyUsageResponse(BaseModel): data: MonthlyUsage +@docs_group('Models') class Limits(BaseModel): model_config = ConfigDict( extra='allow', @@ -2836,6 +3026,7 @@ class Limits(BaseModel): data_retention_days: Annotated[int, Field(alias='dataRetentionDays', examples=[90])] +@docs_group('Models') class Current(BaseModel): model_config = ConfigDict( extra='allow', @@ -2854,6 +3045,7 @@ class Current(BaseModel): team_account_seat_count: Annotated[int, Field(alias='teamAccountSeatCount', examples=[5])] +@docs_group('Models') class AccountLimits(BaseModel): model_config = ConfigDict( extra='allow', @@ -2863,6 +3055,7 @@ class AccountLimits(BaseModel): current: Current +@docs_group('Models') class LimitsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2870,6 +3063,7 @@ class LimitsResponse(BaseModel): data: AccountLimits +@docs_group('Models') class UpdateLimitsRequest(BaseModel): model_config = ConfigDict( extra='allow', diff --git a/src/apify_client/_resource_clients/actor.py b/src/apify_client/_resource_clients/actor.py index 5e3594aa..2ff920a7 100644 --- a/src/apify_client/_resource_clients/actor.py +++ b/src/apify_client/_resource_clients/actor.py @@ -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, @@ -47,6 +48,7 @@ ) +@docs_group('Resource clients') class ActorClient(ResourceClient): """Sub-client for manipulating a single Actor.""" @@ -506,6 +508,7 @@ def validate_input( return True +@docs_group('Resource clients') class ActorClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single Actor.""" diff --git a/src/apify_client/_resource_clients/actor_collection.py b/src/apify_client/_resource_clients/actor_collection.py index 7a2a6c63..62dec62d 100644 --- a/src/apify_client/_resource_clients/actor_collection.py +++ b/src/apify_client/_resource_clients/actor_collection.py @@ -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 @@ -11,6 +12,7 @@ from datetime import timedelta +@docs_group('Resource clients') class ActorCollectionClient(ResourceClient): """Sub-client for manipulating Actors.""" @@ -138,6 +140,7 @@ def create( return ActorResponse.model_validate(result).data +@docs_group('Resource clients') class ActorCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating Actors.""" diff --git a/src/apify_client/_resource_clients/actor_env_var.py b/src/apify_client/_resource_clients/actor_env_var.py index e4b9e985..19c7bcd7 100644 --- a/src/apify_client/_resource_clients/actor_env_var.py +++ b/src/apify_client/_resource_clients/actor_env_var.py @@ -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 @@ -21,6 +22,7 @@ def get_actor_env_var_representation( } +@docs_group('Resource clients') class ActorEnvVarClient(ResourceClient): """Sub-client for manipulating a single Actor environment variable.""" @@ -77,6 +79,7 @@ def delete(self) -> None: self._delete() +@docs_group('Resource clients') class ActorEnvVarClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single Actor environment variable.""" diff --git a/src/apify_client/_resource_clients/actor_env_var_collection.py b/src/apify_client/_resource_clients/actor_env_var_collection.py index 5bdd8f2f..6e5f9144 100644 --- a/src/apify_client/_resource_clients/actor_env_var_collection.py +++ b/src/apify_client/_resource_clients/actor_env_var_collection.py @@ -2,12 +2,14 @@ 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.""" @@ -55,6 +57,7 @@ def create( return EnvVarResponse.model_validate(result).data +@docs_group('Resource clients') class ActorEnvVarCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating Actor env vars.""" diff --git a/src/apify_client/_resource_clients/actor_version.py b/src/apify_client/_resource_clients/actor_version.py index f4ea03a2..c54b0a30 100644 --- a/src/apify_client/_resource_clients/actor_version.py +++ b/src/apify_client/_resource_clients/actor_version.py @@ -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 @@ -16,6 +17,7 @@ ) +@docs_group('Resource clients') class ActorVersionClient(ResourceClient): """Sub-client for manipulating a single Actor version.""" @@ -121,6 +123,7 @@ 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.""" diff --git a/src/apify_client/_resource_clients/actor_version_collection.py b/src/apify_client/_resource_clients/actor_version_collection.py index 40c69c03..2cb18761 100644 --- a/src/apify_client/_resource_clients/actor_version_collection.py +++ b/src/apify_client/_resource_clients/actor_version_collection.py @@ -2,6 +2,7 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ( ListOfVersions, ListOfVersionsResponse, @@ -14,6 +15,7 @@ from apify_client._utils import filter_none_values +@docs_group('Resource clients') class ActorVersionCollectionClient(ResourceClient): """Sub-client for manipulating Actor versions.""" @@ -85,6 +87,7 @@ def create( return VersionResponse.model_validate(result).data +@docs_group('Resource clients') class ActorVersionCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating Actor versions.""" diff --git a/src/apify_client/_resource_clients/build.py b/src/apify_client/_resource_clients/build.py index ef8f7ef6..d87c5cd3 100644 --- a/src/apify_client/_resource_clients/build.py +++ b/src/apify_client/_resource_clients/build.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import Build, BuildResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import response_to_dict @@ -12,6 +13,7 @@ from apify_client._resource_clients import LogClient, LogClientAsync +@docs_group('Resource clients') class BuildClient(ResourceClient): """Sub-client for manipulating a single Actor build.""" @@ -109,6 +111,7 @@ def log(self) -> LogClient: ) +@docs_group('Resource clients') class BuildClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single Actor build.""" diff --git a/src/apify_client/_resource_clients/build_collection.py b/src/apify_client/_resource_clients/build_collection.py index 3daee7aa..ed5c9c66 100644 --- a/src/apify_client/_resource_clients/build_collection.py +++ b/src/apify_client/_resource_clients/build_collection.py @@ -2,10 +2,12 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ListOfBuilds, ListOfBuildsResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +@docs_group('Resource clients') class BuildCollectionClient(ResourceClient): """Sub-client for listing Actor builds.""" @@ -40,6 +42,7 @@ def list( return ListOfBuildsResponse.model_validate(result).data +@docs_group('Resource clients') class BuildCollectionClientAsync(ResourceClientAsync): """Async sub-client for listing Actor builds.""" diff --git a/src/apify_client/_resource_clients/dataset.py b/src/apify_client/_resource_clients/dataset.py index e0534743..4f413ec3 100644 --- a/src/apify_client/_resource_clients/dataset.py +++ b/src/apify_client/_resource_clients/dataset.py @@ -7,6 +7,7 @@ from urllib.parse import urlencode, urlparse, urlunparse from apify_client._consts import FAST_OPERATION_TIMEOUT, STANDARD_OPERATION_TIMEOUT +from apify_client._docs import docs_group from apify_client._models import Dataset, DatasetResponse, DatasetStatistics, DatasetStatisticsResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import ( @@ -28,6 +29,7 @@ from apify_client._models import GeneralAccess +@docs_group('Models') @dataclass class DatasetItemsPage: """A page of dataset items returned by the `list_items` method. @@ -56,6 +58,7 @@ class DatasetItemsPage: """Whether the items are sorted in descending order.""" +@docs_group('Resource clients') class DatasetClient(ResourceClient): """Sub-client for manipulating a single dataset.""" @@ -672,6 +675,7 @@ def create_items_public_url( return urlunparse(items_public_url) +@docs_group('Resource clients') class DatasetClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single dataset.""" diff --git a/src/apify_client/_resource_clients/dataset_collection.py b/src/apify_client/_resource_clients/dataset_collection.py index 1effcdd0..4a6cc160 100644 --- a/src/apify_client/_resource_clients/dataset_collection.py +++ b/src/apify_client/_resource_clients/dataset_collection.py @@ -2,11 +2,13 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import Dataset, DatasetResponse, ListOfDatasets, ListOfDatasetsResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import filter_none_values +@docs_group('Resource clients') class DatasetCollectionClient(ResourceClient): """Sub-client for manipulating datasets.""" @@ -54,6 +56,7 @@ def get_or_create(self, *, name: str | None = None, schema: dict | None = None) return DatasetResponse.model_validate(result).data +@docs_group('Resource clients') class DatasetCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating datasets.""" diff --git a/src/apify_client/_resource_clients/key_value_store.py b/src/apify_client/_resource_clients/key_value_store.py index d6490108..b998a9eb 100644 --- a/src/apify_client/_resource_clients/key_value_store.py +++ b/src/apify_client/_resource_clients/key_value_store.py @@ -7,6 +7,7 @@ from urllib.parse import urlencode, urlparse, urlunparse from apify_client._consts import FAST_OPERATION_TIMEOUT, STANDARD_OPERATION_TIMEOUT +from apify_client._docs import docs_group from apify_client._models import ( KeyValueStore, KeyValueStoreKey, @@ -68,6 +69,7 @@ def _parse_get_record_response(response: Response) -> Any: return response_data +@docs_group('Resource clients') class KeyValueStoreClient(ResourceClient): """Sub-client for manipulating a single key-value store.""" @@ -447,6 +449,7 @@ def create_keys_public_url( return urlunparse(keys_public_url) +@docs_group('Resource clients') class KeyValueStoreClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single key-value store.""" diff --git a/src/apify_client/_resource_clients/key_value_store_collection.py b/src/apify_client/_resource_clients/key_value_store_collection.py index abf5a87f..012c2b25 100644 --- a/src/apify_client/_resource_clients/key_value_store_collection.py +++ b/src/apify_client/_resource_clients/key_value_store_collection.py @@ -2,6 +2,7 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ( KeyValueStore, KeyValueStoreResponse, @@ -12,6 +13,7 @@ from apify_client._utils import filter_none_values +@docs_group('Resource clients') class KeyValueStoreCollectionClient(ResourceClient): """Sub-client for manipulating key-value stores.""" @@ -64,6 +66,7 @@ def get_or_create( return KeyValueStoreResponse.model_validate(result).data +@docs_group('Resource clients') class KeyValueStoreCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating key-value stores.""" diff --git a/src/apify_client/_resource_clients/log.py b/src/apify_client/_resource_clients/log.py index b214c114..af186630 100644 --- a/src/apify_client/_resource_clients/log.py +++ b/src/apify_client/_resource_clients/log.py @@ -3,6 +3,7 @@ from contextlib import asynccontextmanager, contextmanager from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import catch_not_found_or_throw from apify_client.errors import ApifyApiError @@ -13,6 +14,7 @@ import impit +@docs_group('Resource clients') class LogClient(ResourceClient): """Sub-client for manipulating logs.""" @@ -100,6 +102,7 @@ def stream(self, *, raw: bool = False) -> Iterator[impit.Response | None]: response.close() +@docs_group('Resource clients') class LogClientAsync(ResourceClientAsync): """Async sub-client for manipulating logs.""" diff --git a/src/apify_client/_resource_clients/request_queue.py b/src/apify_client/_resource_clients/request_queue.py index 2a7ac991..d2b1e13e 100644 --- a/src/apify_client/_resource_clients/request_queue.py +++ b/src/apify_client/_resource_clients/request_queue.py @@ -10,6 +10,7 @@ from more_itertools import constrained_batches from apify_client._consts import FAST_OPERATION_TIMEOUT, STANDARD_OPERATION_TIMEOUT +from apify_client._docs import docs_group from apify_client._models import ( AddedRequest, AddRequestResponse, @@ -51,6 +52,7 @@ _SAFETY_BUFFER_PERCENT = 0.01 / 100 # 0.01% +@docs_group('Resource clients') class RequestQueueClient(ResourceClient): """Sub-client for manipulating a single request queue.""" @@ -456,6 +458,7 @@ def unlock_requests(self: RequestQueueClient) -> UnlockRequestsResult: return UnlockRequestsResponse.model_validate(result).data +@docs_group('Resource clients') class RequestQueueClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single request queue.""" diff --git a/src/apify_client/_resource_clients/request_queue_collection.py b/src/apify_client/_resource_clients/request_queue_collection.py index 177450f5..ce179ea8 100644 --- a/src/apify_client/_resource_clients/request_queue_collection.py +++ b/src/apify_client/_resource_clients/request_queue_collection.py @@ -2,6 +2,7 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ( ListOfRequestQueues, ListOfRequestQueuesResponse, @@ -11,6 +12,7 @@ from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +@docs_group('Resource clients') class RequestQueueCollectionClient(ResourceClient): """Sub-client for manipulating request queues.""" @@ -57,6 +59,7 @@ def get_or_create(self, *, name: str | None = None) -> RequestQueue: return RequestQueueResponse.model_validate(result).data +@docs_group('Resource clients') class RequestQueueCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating request queues.""" diff --git a/src/apify_client/_resource_clients/run.py b/src/apify_client/_resource_clients/run.py index c545ebd6..8e38fb24 100644 --- a/src/apify_client/_resource_clients/run.py +++ b/src/apify_client/_resource_clients/run.py @@ -7,6 +7,7 @@ from datetime import timedelta from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._logging import create_redirect_logger from apify_client._models import Run, RunResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync @@ -39,6 +40,7 @@ ) +@docs_group('Resource clients') class RunClient(ResourceClient): """Sub-client for manipulating a single Actor run.""" @@ -423,6 +425,7 @@ def get_status_message_watcher( ) +@docs_group('Resource clients') class RunClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single Actor run.""" diff --git a/src/apify_client/_resource_clients/run_collection.py b/src/apify_client/_resource_clients/run_collection.py index cdded09d..be75ec59 100644 --- a/src/apify_client/_resource_clients/run_collection.py +++ b/src/apify_client/_resource_clients/run_collection.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import ListOfRuns, ListOfRunsResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import enum_to_value @@ -12,6 +13,7 @@ from apify_client._consts import ActorJobStatus +@docs_group('Resource clients') class RunCollectionClient(ResourceClient): """Sub-client for listing Actor runs.""" @@ -61,6 +63,7 @@ def list( return ListOfRunsResponse.model_validate(result).data +@docs_group('Resource clients') class RunCollectionClientAsync(ResourceClientAsync): """Async sub-client for listing Actor runs.""" diff --git a/src/apify_client/_resource_clients/schedule.py b/src/apify_client/_resource_clients/schedule.py index b87e3a17..3cb85942 100644 --- a/src/apify_client/_resource_clients/schedule.py +++ b/src/apify_client/_resource_clients/schedule.py @@ -2,6 +2,7 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import Schedule, ScheduleInvoked, ScheduleLogResponse, ScheduleResponse from apify_client._representations import get_schedule_repr from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync @@ -9,6 +10,7 @@ from apify_client.errors import ApifyApiError +@docs_group('Resource clients') class ScheduleClient(ResourceClient): """Sub-client for manipulating a single schedule.""" @@ -104,6 +106,7 @@ def get_log(self) -> list[ScheduleInvoked] | None: return None +@docs_group('Resource clients') class ScheduleClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single schedule.""" diff --git a/src/apify_client/_resource_clients/schedule_collection.py b/src/apify_client/_resource_clients/schedule_collection.py index ff69a2d5..7565d7f8 100644 --- a/src/apify_client/_resource_clients/schedule_collection.py +++ b/src/apify_client/_resource_clients/schedule_collection.py @@ -2,12 +2,14 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ListOfSchedules, ListOfSchedulesResponse, Schedule, ScheduleResponse from apify_client._representations import get_schedule_repr from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync from apify_client._utils import filter_none_values +@docs_group('Resource clients') class ScheduleCollectionClient(ResourceClient): """Sub-client for manipulating schedules.""" @@ -86,6 +88,7 @@ def create( return ScheduleResponse.model_validate(result).data +@docs_group('Resource clients') class ScheduleCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating schedules.""" diff --git a/src/apify_client/_resource_clients/status_message_watcher.py b/src/apify_client/_resource_clients/status_message_watcher.py index 33f760b8..c27fe756 100644 --- a/src/apify_client/_resource_clients/status_message_watcher.py +++ b/src/apify_client/_resource_clients/status_message_watcher.py @@ -8,6 +8,7 @@ from threading import Thread from typing import TYPE_CHECKING, Self +from apify_client._docs import docs_group from apify_client._utils import to_seconds if TYPE_CHECKING: @@ -18,6 +19,7 @@ from apify_client._resource_clients import RunClient, RunClientAsync +@docs_group('Resource clients') class StatusMessageWatcher: """Utility class for logging status messages from another Actor run. @@ -66,6 +68,7 @@ def _log_run_data(self, run_data: Run | None) -> bool: return True +@docs_group('Resource clients') class StatusMessageWatcherAsync(StatusMessageWatcher): """Async variant of `StatusMessageWatcher` that is logging in task.""" @@ -123,6 +126,7 @@ async def _log_changed_status_message(self) -> None: await asyncio.sleep(self._check_period) +@docs_group('Resource clients') class StatusMessageWatcherSync(StatusMessageWatcher): """Sync variant of `StatusMessageWatcher` that is logging in thread.""" diff --git a/src/apify_client/_resource_clients/store_collection.py b/src/apify_client/_resource_clients/store_collection.py index ffa7f9b6..2140ee61 100644 --- a/src/apify_client/_resource_clients/store_collection.py +++ b/src/apify_client/_resource_clients/store_collection.py @@ -2,10 +2,12 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ListOfActorsInStoreResponse, ListOfStoreActors from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +@docs_group('Resource clients') class StoreCollectionClient(ResourceClient): """Sub-client for Apify store.""" @@ -53,6 +55,7 @@ def list( return ListOfActorsInStoreResponse.model_validate(result).data +@docs_group('Resource clients') class StoreCollectionClientAsync(ResourceClientAsync): """Async sub-client for Apify store.""" diff --git a/src/apify_client/_resource_clients/streamed_log.py b/src/apify_client/_resource_clients/streamed_log.py index edc83304..95e7851e 100644 --- a/src/apify_client/_resource_clients/streamed_log.py +++ b/src/apify_client/_resource_clients/streamed_log.py @@ -9,12 +9,15 @@ from threading import Thread from typing import TYPE_CHECKING, Self, cast +from apify_client._docs import docs_group + if TYPE_CHECKING: from types import TracebackType from apify_client._resource_clients import LogClient, LogClientAsync +@docs_group('Resource clients') class StreamedLog: """Utility class for streaming logs from another Actor. @@ -94,6 +97,7 @@ def _guess_log_level_from_message(message: str) -> int: return logging.INFO +@docs_group('Resource clients') class StreamedLogSync(StreamedLog): """Sync variant of `StreamedLog` that is logging in threads.""" @@ -146,6 +150,7 @@ def _stream_log(self) -> None: return +@docs_group('Resource clients') class StreamedLogAsync(StreamedLog): """Async variant of `StreamedLog` that is logging in tasks.""" diff --git a/src/apify_client/_resource_clients/task.py b/src/apify_client/_resource_clients/task.py index a380510c..3d209e92 100644 --- a/src/apify_client/_resource_clients/task.py +++ b/src/apify_client/_resource_clients/task.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import Run, RunOrigin, RunResponse, Task, TaskResponse from apify_client._representations import get_task_repr from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync @@ -29,6 +30,7 @@ ) +@docs_group('Resource clients') class TaskClient(ResourceClient): """Sub-client for manipulating a single task.""" @@ -317,6 +319,7 @@ def webhooks(self) -> WebhookCollectionClient: return self._client_registry.webhook_collection_client(**self._base_client_kwargs) +@docs_group('Resource clients') class TaskClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single task.""" diff --git a/src/apify_client/_resource_clients/task_collection.py b/src/apify_client/_resource_clients/task_collection.py index e55b0d46..a09cec5e 100644 --- a/src/apify_client/_resource_clients/task_collection.py +++ b/src/apify_client/_resource_clients/task_collection.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import ListOfTasks, ListOfTasksResponse, Task, TaskResponse from apify_client._representations import get_task_repr from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync @@ -11,6 +12,7 @@ from datetime import timedelta +@docs_group('Resource clients') class TaskCollectionClient(ResourceClient): """Sub-client for manipulating tasks.""" @@ -110,6 +112,7 @@ def create( return TaskResponse.model_validate(result).data +@docs_group('Resource clients') class TaskCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating tasks.""" diff --git a/src/apify_client/_resource_clients/user.py b/src/apify_client/_resource_clients/user.py index af6e6357..2b9cd188 100644 --- a/src/apify_client/_resource_clients/user.py +++ b/src/apify_client/_resource_clients/user.py @@ -4,6 +4,7 @@ from pydantic import ValidationError +from apify_client._docs import docs_group from apify_client._models import ( AccountLimits, LimitsResponse, @@ -19,6 +20,7 @@ from apify_client.errors import ApifyApiError +@docs_group('Resource clients') class UserClient(ResourceClient): """Sub-client for querying user data.""" @@ -118,6 +120,7 @@ def update_limits( ) +@docs_group('Resource clients') class UserClientAsync(ResourceClientAsync): """Async sub-client for querying user data.""" diff --git a/src/apify_client/_resource_clients/webhook.py b/src/apify_client/_resource_clients/webhook.py index ecf906de..cfaec8d1 100644 --- a/src/apify_client/_resource_clients/webhook.py +++ b/src/apify_client/_resource_clients/webhook.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import ( TestWebhookResponse, Webhook, @@ -18,6 +19,7 @@ from apify_client._resource_clients import WebhookDispatchCollectionClient, WebhookDispatchCollectionClientAsync +@docs_group('Resource clients') class WebhookClient(ResourceClient): """Sub-client for manipulating a single webhook.""" @@ -135,6 +137,7 @@ def dispatches(self) -> WebhookDispatchCollectionClient: ) +@docs_group('Resource clients') class WebhookClientAsync(ResourceClientAsync): """Async sub-client for manipulating a single webhook.""" diff --git a/src/apify_client/_resource_clients/webhook_collection.py b/src/apify_client/_resource_clients/webhook_collection.py index 82c90781..7b508e15 100644 --- a/src/apify_client/_resource_clients/webhook_collection.py +++ b/src/apify_client/_resource_clients/webhook_collection.py @@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Any +from apify_client._docs import docs_group from apify_client._models import ListOfWebhooks, ListOfWebhooksResponse, Webhook, WebhookResponse from apify_client._representations import get_webhook_repr from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync @@ -11,6 +12,7 @@ from apify_client._models import WebhookEventType +@docs_group('Resource clients') class WebhookCollectionClient(ResourceClient): """Sub-client for manipulating webhooks.""" @@ -97,6 +99,7 @@ def create( return WebhookResponse.model_validate(result).data +@docs_group('Resource clients') class WebhookCollectionClientAsync(ResourceClientAsync): """Async sub-client for manipulating webhooks.""" diff --git a/src/apify_client/_resource_clients/webhook_dispatch.py b/src/apify_client/_resource_clients/webhook_dispatch.py index 9ee80cbb..61abda9d 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch.py +++ b/src/apify_client/_resource_clients/webhook_dispatch.py @@ -2,10 +2,12 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import WebhookDispatch, WebhookDispatchResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +@docs_group('Resource clients') class WebhookDispatchClient(ResourceClient): """Sub-client for querying information about a webhook dispatch.""" @@ -27,6 +29,7 @@ def get(self) -> WebhookDispatch | None: return WebhookDispatchResponse.model_validate(result).data +@docs_group('Resource clients') class WebhookDispatchClientAsync(ResourceClientAsync): """Async sub-client for querying information about a webhook dispatch.""" diff --git a/src/apify_client/_resource_clients/webhook_dispatch_collection.py b/src/apify_client/_resource_clients/webhook_dispatch_collection.py index 941db91a..cee09cd4 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch_collection.py +++ b/src/apify_client/_resource_clients/webhook_dispatch_collection.py @@ -2,10 +2,12 @@ from typing import Any +from apify_client._docs import docs_group from apify_client._models import ListOfWebhookDispatches, WebhookDispatchList from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +@docs_group('Resource clients') class WebhookDispatchCollectionClient(ResourceClient): """Sub-client for listing webhook dispatches.""" @@ -36,6 +38,7 @@ def list( return WebhookDispatchList.model_validate(result).data +@docs_group('Resource clients') class WebhookDispatchCollectionClientAsync(ResourceClientAsync): """Async sub-client for listing webhook dispatches.""" diff --git a/src/apify_client/errors.py b/src/apify_client/errors.py index bd4e2205..db019c39 100644 --- a/src/apify_client/errors.py +++ b/src/apify_client/errors.py @@ -2,14 +2,18 @@ from typing import TYPE_CHECKING +from apify_client._docs import docs_group + if TYPE_CHECKING: import impit +@docs_group('Errors') class ApifyClientError(Exception): """Base class for errors specific to the Apify API Client.""" +@docs_group('Errors') class ApifyApiError(ApifyClientError): """Error from Apify API responses (rate limits, validation errors, internal errors). @@ -55,6 +59,7 @@ def __init__(self, response: impit.Response, attempt: int, method: str = 'GET') self.http_method = method +@docs_group('Errors') class InvalidResponseBodyError(ApifyClientError): """Error when response body cannot be parsed (e.g., partial JSON). diff --git a/website/transformDocs.js b/website/transformDocs.js index e1c993c2..ebcddb62 100644 --- a/website/transformDocs.js +++ b/website/transformDocs.js @@ -55,11 +55,10 @@ const TYPEDOC_KINDS = { } const GROUP_ORDER = [ - 'Main Classes', - 'Main Clients', - 'Resource Clients', - 'Async Resource Clients', - 'Helper Classes', + 'Apify API clients', + 'Resource clients', + 'HTTP clients', + 'Models', 'Errors', 'Constructors', 'Methods', @@ -75,14 +74,24 @@ const groupSort = (g1, g2) => { return g1.localeCompare(g2); }; +// Extract the docs_group name from a docspec member's decorators +function getDocsGroup(member) { + const decoration = member.decorations?.find(d => d.name === 'docs_group'); + if (decoration?.args) { + const match = decoration.args.match(/['"](.+?)['"]/); + if (match) return match[1]; + } + return undefined; +} + function getGroupName(object) { + // If a docs_group was extracted from the Python decorator, use it + if (object.docsGroup) { + return object.docsGroup; + } + + // Fallback grouping for sub-members (methods, properties, etc.) inside classes const groupPredicates = { - 'Errors': (x) => x.name.toLowerCase().includes('error'), - 'Main Classes': (x) => ['Actor', 'Dataset', 'KeyValueStore', 'RequestQueue'].includes(x.name), - 'Main Clients': (x) => ['ApifyClient', 'ApifyClientAsync'].includes(x.name), - 'Async Resource Clients': (x) => x.name.toLowerCase().includes('async'), - 'Resource Clients': (x) => x.kindString === 'Class' && x.name.toLowerCase().includes('client'), - 'Helper Classes': (x) => x.kindString === 'Class', 'Methods': (x) => x.kindString === 'Method', 'Constructors': (x) => x.kindString === 'Constructor', 'Properties': (x) => x.kindString === 'Property', @@ -90,11 +99,11 @@ function getGroupName(object) { 'Enumeration Members': (x) => x.kindString === 'Enumeration Member', }; - const [group] = Object.entries(groupPredicates).find( + const found = Object.entries(groupPredicates).find( ([_, predicate]) => predicate(object) ); - return group; + return found ? found[0] : 'Other'; } // Strips the Optional[] type from the type string, and replaces generic types with just the main type @@ -158,9 +167,17 @@ function extractArgsAndReturns(docstring) { return { parameters, returns }; } -// Objects with decorators named 'ignore_docs' or with empty docstrings will be ignored +// Objects with decorators named 'ignore_docs' or without docstrings will be ignored, +// unless they have a 'docs_group' decorator which explicitly marks them for documentation function isHidden(member) { - return member.decorations?.some(d => d.name === 'ignore_docs') || member.name === 'ignore_docs' || !member.docstring?.content; + if (member.decorations?.some(d => d.name === 'ignore_docs') || member.name === 'ignore_docs') { + return true; + } + // Members with @docs_group are always visible (even without docstrings) + if (member.decorations?.some(d => d.name === 'docs_group')) { + return false; + } + return !member.docstring?.content; } // Each object in the Typedoc structure has an unique ID, @@ -205,11 +222,15 @@ function convertObject(obj, parent, module) { moduleName = moduleShortcuts[fullName].replace(`.${member.name}`, ''); } + // Extract docs_group from the Python decorator (if present) + const docsGroup = getDocsGroup(member); + // Create the Typedoc member object let typedocMember = { id: oid++, name: member.name, module: moduleName, // This is an extension to the original Typedoc structure, to support showing where the member is exported from + docsGroup, ...typedocKind, flags: {}, comment: member.docstring ? { From 622b4921cc934c9511f6c36f32f61557c4b041f0 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 10:36:09 +0100 Subject: [PATCH 2/7] docs: Improve and polish docstrings for all public classes Improve class-level docstrings for Apify API clients, resource clients, HTTP clients, and error classes to be more descriptive and consistent. Resource client docstrings now describe key operations and reference how to obtain an instance via the parent client. Co-Authored-By: Claude Opus 4.6 --- src/apify_client/_apify_client.py | 148 ++++++++++-------- .../_http_clients/_http_client.py | 26 ++- src/apify_client/_resource_clients/actor.py | 12 +- .../_resource_clients/actor_collection.py | 10 +- .../_resource_clients/actor_env_var.py | 12 +- .../actor_env_var_collection.py | 12 +- .../_resource_clients/actor_version.py | 12 +- .../actor_version_collection.py | 12 +- src/apify_client/_resource_clients/build.py | 12 +- .../_resource_clients/build_collection.py | 10 +- src/apify_client/_resource_clients/dataset.py | 12 +- .../_resource_clients/dataset_collection.py | 10 +- .../_resource_clients/key_value_store.py | 12 +- .../key_value_store_collection.py | 12 +- src/apify_client/_resource_clients/log.py | 10 +- .../_resource_clients/request_queue.py | 12 +- .../request_queue_collection.py | 12 +- src/apify_client/_resource_clients/run.py | 12 +- .../_resource_clients/run_collection.py | 10 +- .../_resource_clients/schedule.py | 12 +- .../_resource_clients/schedule_collection.py | 10 +- .../status_message_watcher.py | 8 +- .../_resource_clients/store_collection.py | 10 +- .../_resource_clients/streamed_log.py | 16 +- src/apify_client/_resource_clients/task.py | 12 +- .../_resource_clients/task_collection.py | 10 +- src/apify_client/_resource_clients/user.py | 12 +- src/apify_client/_resource_clients/webhook.py | 12 +- .../_resource_clients/webhook_collection.py | 10 +- .../_resource_clients/webhook_dispatch.py | 10 +- .../webhook_dispatch_collection.py | 10 +- src/apify_client/errors.py | 42 +++-- 32 files changed, 389 insertions(+), 153 deletions(-) diff --git a/src/apify_client/_apify_client.py b/src/apify_client/_apify_client.py index 268cb424..1200c701 100644 --- a/src/apify_client/_apify_client.py +++ b/src/apify_client/_apify_client.py @@ -82,7 +82,14 @@ @docs_group('Apify API clients') class ApifyClient: - """The Apify API client.""" + """Synchronous client for the Apify API. + + This is the main entry point for interacting with the Apify platform. It provides methods to access + resource-specific sub-clients for managing Actors, runs, datasets, key-value stores, request queues, + schedules, webhooks, and more. + + The client automatically handles retries with exponential backoff for failed or rate-limited requests. + """ _OVERRIDABLE_DEFAULT_HEADERS: ClassVar[set[str]] = {'Accept', 'Authorization', 'Accept-Encoding', 'User-Agent'} @@ -97,18 +104,19 @@ def __init__( timeout: timedelta = DEFAULT_TIMEOUT, headers: dict[str, str] | None = None, ) -> None: - """Initialize a new instance. + """Initialize the Apify API client. Args: - token: The Apify API token. - api_url: The URL of the Apify API server to which to connect. Defaults to https://api.apify.com. It can - be an internal URL that is not globally accessible, in such case `api_public_url` should be set as well. - api_public_url: The globally accessible URL of the Apify API server. It should be set only if the `api_url` + token: The Apify API token. You can find your token on the + [Integrations](https://console.apify.com/account/integrations) page in the Apify Console. + api_url: The URL of the Apify API server to connect to. Defaults to https://api.apify.com. It can + be an internal URL that is not globally accessible, in which case `api_public_url` should be set + as well. + api_public_url: The globally accessible URL of the Apify API server. Should be set only if `api_url` is an internal URL that is not globally accessible. Defaults to https://api.apify.com. - max_retries: How many times to retry a failed request at most. - min_delay_between_retries: How long will the client wait between retrying requests - (increases exponentially from this value). - timeout: The socket timeout of the HTTP requests sent to the Apify API. + max_retries: Maximum number of retry attempts for failed requests. + min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt). + timeout: Timeout for HTTP requests sent to the Apify API. headers: Additional HTTP headers to include in all API requests. """ # We need to do this because of mocking in tests and default mutable arguments. @@ -201,7 +209,7 @@ def token(self) -> str | None: return self._token def actor(self, actor_id: str) -> ActorClient: - """Retrieve the sub-client for manipulating a single Actor. + """Get the sub-client for a specific Actor. Args: actor_id: ID of the Actor to be manipulated. @@ -209,11 +217,11 @@ def actor(self, actor_id: str) -> ActorClient: return ActorClient(resource_id=actor_id, **self._base_kwargs) def actors(self) -> ActorCollectionClient: - """Retrieve the sub-client for manipulating Actors.""" + """Get the sub-client for the Actor collection, allowing to list and create Actors.""" return ActorCollectionClient(**self._base_kwargs) def build(self, build_id: str) -> BuildClient: - """Retrieve the sub-client for manipulating a single Actor build. + """Get the sub-client for a specific Actor build. Args: build_id: ID of the Actor build to be manipulated. @@ -221,11 +229,11 @@ def build(self, build_id: str) -> BuildClient: return BuildClient(resource_id=build_id, **self._base_kwargs) def builds(self) -> BuildCollectionClient: - """Retrieve the sub-client for querying multiple builds of a user.""" + """Get the sub-client for the build collection, allowing to list builds.""" return BuildCollectionClient(**self._base_kwargs) def run(self, run_id: str) -> RunClient: - """Retrieve the sub-client for manipulating a single Actor run. + """Get the sub-client for a specific Actor run. Args: run_id: ID of the Actor run to be manipulated. @@ -233,11 +241,11 @@ def run(self, run_id: str) -> RunClient: return RunClient(resource_id=run_id, **self._base_kwargs) def runs(self) -> RunCollectionClient: - """Retrieve the sub-client for querying multiple Actor runs of a user.""" + """Get the sub-client for the run collection, allowing to list Actor runs.""" return RunCollectionClient(**self._base_kwargs) def dataset(self, dataset_id: str) -> DatasetClient: - """Retrieve the sub-client for manipulating a single dataset. + """Get the sub-client for a specific dataset. Args: dataset_id: ID of the dataset to be manipulated. @@ -245,11 +253,11 @@ def dataset(self, dataset_id: str) -> DatasetClient: return DatasetClient(resource_id=dataset_id, **self._base_kwargs) def datasets(self) -> DatasetCollectionClient: - """Retrieve the sub-client for manipulating datasets.""" + """Get the sub-client for the dataset collection, allowing to list and create datasets.""" return DatasetCollectionClient(**self._base_kwargs) def key_value_store(self, key_value_store_id: str) -> KeyValueStoreClient: - """Retrieve the sub-client for manipulating a single key-value store. + """Get the sub-client for a specific key-value store. Args: key_value_store_id: ID of the key-value store to be manipulated. @@ -257,11 +265,11 @@ def key_value_store(self, key_value_store_id: str) -> KeyValueStoreClient: return KeyValueStoreClient(resource_id=key_value_store_id, **self._base_kwargs) def key_value_stores(self) -> KeyValueStoreCollectionClient: - """Retrieve the sub-client for manipulating key-value stores.""" + """Get the sub-client for the key-value store collection, allowing to list and create key-value stores.""" return KeyValueStoreCollectionClient(**self._base_kwargs) def request_queue(self, request_queue_id: str, *, client_key: str | None = None) -> RequestQueueClient: - """Retrieve the sub-client for manipulating a single request queue. + """Get the sub-client for a specific request queue. Args: request_queue_id: ID of the request queue to be manipulated. @@ -270,11 +278,11 @@ def request_queue(self, request_queue_id: str, *, client_key: str | None = None) return RequestQueueClient(resource_id=request_queue_id, client_key=client_key, **self._base_kwargs) def request_queues(self) -> RequestQueueCollectionClient: - """Retrieve the sub-client for manipulating request queues.""" + """Get the sub-client for the request queue collection, allowing to list and create request queues.""" return RequestQueueCollectionClient(**self._base_kwargs) def webhook(self, webhook_id: str) -> WebhookClient: - """Retrieve the sub-client for manipulating a single webhook. + """Get the sub-client for a specific webhook. Args: webhook_id: ID of the webhook to be manipulated. @@ -282,11 +290,11 @@ def webhook(self, webhook_id: str) -> WebhookClient: return WebhookClient(resource_id=webhook_id, **self._base_kwargs) def webhooks(self) -> WebhookCollectionClient: - """Retrieve the sub-client for querying multiple webhooks of a user.""" + """Get the sub-client for the webhook collection, allowing to list and create webhooks.""" return WebhookCollectionClient(**self._base_kwargs) def webhook_dispatch(self, webhook_dispatch_id: str) -> WebhookDispatchClient: - """Retrieve the sub-client for accessing a single webhook dispatch. + """Get the sub-client for a specific webhook dispatch. Args: webhook_dispatch_id: ID of the webhook dispatch to access. @@ -294,11 +302,11 @@ def webhook_dispatch(self, webhook_dispatch_id: str) -> WebhookDispatchClient: return WebhookDispatchClient(resource_id=webhook_dispatch_id, **self._base_kwargs) def webhook_dispatches(self) -> WebhookDispatchCollectionClient: - """Retrieve the sub-client for querying multiple webhook dispatches of a user.""" + """Get the sub-client for the webhook dispatch collection, allowing to list webhook dispatches.""" return WebhookDispatchCollectionClient(**self._base_kwargs) def schedule(self, schedule_id: str) -> ScheduleClient: - """Retrieve the sub-client for manipulating a single schedule. + """Get the sub-client for a specific schedule. Args: schedule_id: ID of the schedule to be manipulated. @@ -306,11 +314,11 @@ def schedule(self, schedule_id: str) -> ScheduleClient: return ScheduleClient(resource_id=schedule_id, **self._base_kwargs) def schedules(self) -> ScheduleCollectionClient: - """Retrieve the sub-client for manipulating schedules.""" + """Get the sub-client for the schedule collection, allowing to list and create schedules.""" return ScheduleCollectionClient(**self._base_kwargs) def log(self, build_or_run_id: str) -> LogClient: - """Retrieve the sub-client for retrieving logs. + """Get the sub-client for retrieving logs of an Actor build or run. Args: build_or_run_id: ID of the Actor build or run for which to access the log. @@ -318,7 +326,7 @@ def log(self, build_or_run_id: str) -> LogClient: return LogClient(resource_id=build_or_run_id, **self._base_kwargs) def task(self, task_id: str) -> TaskClient: - """Retrieve the sub-client for manipulating a single task. + """Get the sub-client for a specific Actor task. Args: task_id: ID of the task to be manipulated. @@ -326,11 +334,11 @@ def task(self, task_id: str) -> TaskClient: return TaskClient(resource_id=task_id, **self._base_kwargs) def tasks(self) -> TaskCollectionClient: - """Retrieve the sub-client for manipulating tasks.""" + """Get the sub-client for the task collection, allowing to list and create Actor tasks.""" return TaskCollectionClient(**self._base_kwargs) def user(self, user_id: str | None = None) -> UserClient: - """Retrieve the sub-client for querying users. + """Get the sub-client for querying user data. Args: user_id: ID of user to be queried. If None, queries the user belonging to the token supplied to the client. @@ -338,13 +346,20 @@ def user(self, user_id: str | None = None) -> UserClient: return UserClient(resource_id=user_id, **self._base_kwargs) def store(self) -> StoreCollectionClient: - """Retrieve the sub-client for Apify store.""" + """Get the sub-client for the Apify Store, allowing to list Actors published in the store.""" return StoreCollectionClient(**self._base_kwargs) @docs_group('Apify API clients') class ApifyClientAsync: - """The asynchronous version of the Apify API client.""" + """Asynchronous client for the Apify API. + + This is the main entry point for interacting with the Apify platform using async/await. It provides + methods to access resource-specific sub-clients for managing Actors, runs, datasets, key-value stores, + request queues, schedules, webhooks, and more. + + The client automatically handles retries with exponential backoff for failed or rate-limited requests. + """ _OVERRIDABLE_DEFAULT_HEADERS: ClassVar[set[str]] = {'Accept', 'Authorization', 'Accept-Encoding', 'User-Agent'} @@ -359,18 +374,19 @@ def __init__( timeout: timedelta = DEFAULT_TIMEOUT, headers: dict[str, str] | None = None, ) -> None: - """Initialize a new instance. + """Initialize the Apify API client. Args: - token: The Apify API token. - api_url: The URL of the Apify API server to which to connect. Defaults to https://api.apify.com. It can - be an internal URL that is not globally accessible, in such case `api_public_url` should be set as well. - api_public_url: The globally accessible URL of the Apify API server. It should be set only if the `api_url` + token: The Apify API token. You can find your token on the + [Integrations](https://console.apify.com/account/integrations) page in the Apify Console. + api_url: The URL of the Apify API server to connect to. Defaults to https://api.apify.com. It can + be an internal URL that is not globally accessible, in which case `api_public_url` should be set + as well. + api_public_url: The globally accessible URL of the Apify API server. Should be set only if `api_url` is an internal URL that is not globally accessible. Defaults to https://api.apify.com. - max_retries: How many times to retry a failed request at most. - min_delay_between_retries: How long will the client wait between retrying requests - (increases exponentially from this value). - timeout: The socket timeout of the HTTP requests sent to the Apify API. + max_retries: Maximum number of retry attempts for failed requests. + min_delay_between_retries: Minimum delay between retries (increases exponentially with each attempt). + timeout: Timeout for HTTP requests sent to the Apify API. headers: Additional HTTP headers to include in all API requests. """ # We need to do this because of mocking in tests and default mutable arguments. @@ -463,7 +479,7 @@ def token(self) -> str | None: return self._token def actor(self, actor_id: str) -> ActorClientAsync: - """Retrieve the sub-client for manipulating a single Actor. + """Get the sub-client for a specific Actor. Args: actor_id: ID of the Actor to be manipulated. @@ -471,11 +487,11 @@ def actor(self, actor_id: str) -> ActorClientAsync: return ActorClientAsync(resource_id=actor_id, **self._base_kwargs) def actors(self) -> ActorCollectionClientAsync: - """Retrieve the sub-client for manipulating Actors.""" + """Get the sub-client for the Actor collection, allowing to list and create Actors.""" return ActorCollectionClientAsync(**self._base_kwargs) def build(self, build_id: str) -> BuildClientAsync: - """Retrieve the sub-client for manipulating a single Actor build. + """Get the sub-client for a specific Actor build. Args: build_id: ID of the Actor build to be manipulated. @@ -483,11 +499,11 @@ def build(self, build_id: str) -> BuildClientAsync: return BuildClientAsync(resource_id=build_id, **self._base_kwargs) def builds(self) -> BuildCollectionClientAsync: - """Retrieve the sub-client for querying multiple builds of a user.""" + """Get the sub-client for the build collection, allowing to list builds.""" return BuildCollectionClientAsync(**self._base_kwargs) def run(self, run_id: str) -> RunClientAsync: - """Retrieve the sub-client for manipulating a single Actor run. + """Get the sub-client for a specific Actor run. Args: run_id: ID of the Actor run to be manipulated. @@ -495,11 +511,11 @@ def run(self, run_id: str) -> RunClientAsync: return RunClientAsync(resource_id=run_id, **self._base_kwargs) def runs(self) -> RunCollectionClientAsync: - """Retrieve the sub-client for querying multiple Actor runs of a user.""" + """Get the sub-client for the run collection, allowing to list Actor runs.""" return RunCollectionClientAsync(**self._base_kwargs) def dataset(self, dataset_id: str) -> DatasetClientAsync: - """Retrieve the sub-client for manipulating a single dataset. + """Get the sub-client for a specific dataset. Args: dataset_id: ID of the dataset to be manipulated. @@ -507,11 +523,11 @@ def dataset(self, dataset_id: str) -> DatasetClientAsync: return DatasetClientAsync(resource_id=dataset_id, **self._base_kwargs) def datasets(self) -> DatasetCollectionClientAsync: - """Retrieve the sub-client for manipulating datasets.""" + """Get the sub-client for the dataset collection, allowing to list and create datasets.""" return DatasetCollectionClientAsync(**self._base_kwargs) def key_value_store(self, key_value_store_id: str) -> KeyValueStoreClientAsync: - """Retrieve the sub-client for manipulating a single key-value store. + """Get the sub-client for a specific key-value store. Args: key_value_store_id: ID of the key-value store to be manipulated. @@ -519,11 +535,11 @@ def key_value_store(self, key_value_store_id: str) -> KeyValueStoreClientAsync: return KeyValueStoreClientAsync(resource_id=key_value_store_id, **self._base_kwargs) def key_value_stores(self) -> KeyValueStoreCollectionClientAsync: - """Retrieve the sub-client for manipulating key-value stores.""" + """Get the sub-client for the key-value store collection, allowing to list and create key-value stores.""" return KeyValueStoreCollectionClientAsync(**self._base_kwargs) def request_queue(self, request_queue_id: str, *, client_key: str | None = None) -> RequestQueueClientAsync: - """Retrieve the sub-client for manipulating a single request queue. + """Get the sub-client for a specific request queue. Args: request_queue_id: ID of the request queue to be manipulated. @@ -532,11 +548,11 @@ def request_queue(self, request_queue_id: str, *, client_key: str | None = None) return RequestQueueClientAsync(resource_id=request_queue_id, client_key=client_key, **self._base_kwargs) def request_queues(self) -> RequestQueueCollectionClientAsync: - """Retrieve the sub-client for manipulating request queues.""" + """Get the sub-client for the request queue collection, allowing to list and create request queues.""" return RequestQueueCollectionClientAsync(**self._base_kwargs) def webhook(self, webhook_id: str) -> WebhookClientAsync: - """Retrieve the sub-client for manipulating a single webhook. + """Get the sub-client for a specific webhook. Args: webhook_id: ID of the webhook to be manipulated. @@ -544,11 +560,11 @@ def webhook(self, webhook_id: str) -> WebhookClientAsync: return WebhookClientAsync(resource_id=webhook_id, **self._base_kwargs) def webhooks(self) -> WebhookCollectionClientAsync: - """Retrieve the sub-client for querying multiple webhooks of a user.""" + """Get the sub-client for the webhook collection, allowing to list and create webhooks.""" return WebhookCollectionClientAsync(**self._base_kwargs) def webhook_dispatch(self, webhook_dispatch_id: str) -> WebhookDispatchClientAsync: - """Retrieve the sub-client for accessing a single webhook dispatch. + """Get the sub-client for a specific webhook dispatch. Args: webhook_dispatch_id: ID of the webhook dispatch to access. @@ -556,11 +572,11 @@ def webhook_dispatch(self, webhook_dispatch_id: str) -> WebhookDispatchClientAsy return WebhookDispatchClientAsync(resource_id=webhook_dispatch_id, **self._base_kwargs) def webhook_dispatches(self) -> WebhookDispatchCollectionClientAsync: - """Retrieve the sub-client for querying multiple webhook dispatches of a user.""" + """Get the sub-client for the webhook dispatch collection, allowing to list webhook dispatches.""" return WebhookDispatchCollectionClientAsync(**self._base_kwargs) def schedule(self, schedule_id: str) -> ScheduleClientAsync: - """Retrieve the sub-client for manipulating a single schedule. + """Get the sub-client for a specific schedule. Args: schedule_id: ID of the schedule to be manipulated. @@ -568,11 +584,11 @@ def schedule(self, schedule_id: str) -> ScheduleClientAsync: return ScheduleClientAsync(resource_id=schedule_id, **self._base_kwargs) def schedules(self) -> ScheduleCollectionClientAsync: - """Retrieve the sub-client for manipulating schedules.""" + """Get the sub-client for the schedule collection, allowing to list and create schedules.""" return ScheduleCollectionClientAsync(**self._base_kwargs) def log(self, build_or_run_id: str) -> LogClientAsync: - """Retrieve the sub-client for retrieving logs. + """Get the sub-client for retrieving logs of an Actor build or run. Args: build_or_run_id: ID of the Actor build or run for which to access the log. @@ -580,7 +596,7 @@ def log(self, build_or_run_id: str) -> LogClientAsync: return LogClientAsync(resource_id=build_or_run_id, **self._base_kwargs) def task(self, task_id: str) -> TaskClientAsync: - """Retrieve the sub-client for manipulating a single task. + """Get the sub-client for a specific Actor task. Args: task_id: ID of the task to be manipulated. @@ -588,11 +604,11 @@ def task(self, task_id: str) -> TaskClientAsync: return TaskClientAsync(resource_id=task_id, **self._base_kwargs) def tasks(self) -> TaskCollectionClientAsync: - """Retrieve the sub-client for manipulating tasks.""" + """Get the sub-client for the task collection, allowing to list and create Actor tasks.""" return TaskCollectionClientAsync(**self._base_kwargs) def user(self, user_id: str | None = None) -> UserClientAsync: - """Retrieve the sub-client for querying users. + """Get the sub-client for querying user data. Args: user_id: ID of user to be queried. If None, queries the user belonging to the token supplied to the client. @@ -600,5 +616,5 @@ def user(self, user_id: str | None = None) -> UserClientAsync: return UserClientAsync(resource_id=user_id, **self._base_kwargs) def store(self) -> StoreCollectionClientAsync: - """Retrieve the sub-client for Apify store.""" + """Get the sub-client for the Apify Store, allowing to list Actors published in the store.""" return StoreCollectionClientAsync(**self._base_kwargs) diff --git a/src/apify_client/_http_clients/_http_client.py b/src/apify_client/_http_clients/_http_client.py index fd406a86..7fc10cc2 100644 --- a/src/apify_client/_http_clients/_http_client.py +++ b/src/apify_client/_http_clients/_http_client.py @@ -30,7 +30,12 @@ @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, @@ -46,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. """ @@ -251,7 +256,12 @@ def stop_retrying() -> None: @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, @@ -267,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. """ diff --git a/src/apify_client/_resource_clients/actor.py b/src/apify_client/_resource_clients/actor.py index 2ff920a7..d51de5c2 100644 --- a/src/apify_client/_resource_clients/actor.py +++ b/src/apify_client/_resource_clients/actor.py @@ -50,7 +50,11 @@ @docs_group('Resource clients') class ActorClient(ResourceClient): - """Sub-client for manipulating a single Actor.""" + """Sub-client for managing a specific Actor. + + Provides methods to get, update, delete, build, and start runs of an Actor. + Obtain an instance via `ApifyClient.actor`. + """ def __init__( self, @@ -510,7 +514,11 @@ def validate_input( @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 get, update, delete, build, and start runs of an Actor. + Obtain an instance via `ApifyClientAsync.actor`. + """ def __init__( self, diff --git a/src/apify_client/_resource_clients/actor_collection.py b/src/apify_client/_resource_clients/actor_collection.py index 62dec62d..86c74b38 100644 --- a/src/apify_client/_resource_clients/actor_collection.py +++ b/src/apify_client/_resource_clients/actor_collection.py @@ -14,7 +14,10 @@ @docs_group('Resource clients') class ActorCollectionClient(ResourceClient): - """Sub-client for manipulating Actors.""" + """Sub-client for the Actor collection. + + Provides methods to list and create Actors. Obtain an instance via `ApifyClient.actors`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'acts') @@ -142,7 +145,10 @@ def create( @docs_group('Resource clients') class ActorCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating Actors.""" + """Sub-client for the Actor collection. + + Provides methods to list and create Actors. Obtain an instance via `ApifyClientAsync.actors`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'acts') diff --git a/src/apify_client/_resource_clients/actor_env_var.py b/src/apify_client/_resource_clients/actor_env_var.py index 19c7bcd7..d9d0f7fc 100644 --- a/src/apify_client/_resource_clients/actor_env_var.py +++ b/src/apify_client/_resource_clients/actor_env_var.py @@ -24,7 +24,11 @@ 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 get, update, and delete an environment variable. + Obtain an instance via `ActorVersionClient.env_var`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'env-vars') @@ -81,7 +85,11 @@ def delete(self) -> None: @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 get, update, and delete an environment variable. + Obtain an instance via `ActorVersionClientAsync.env_var`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'env-vars') diff --git a/src/apify_client/_resource_clients/actor_env_var_collection.py b/src/apify_client/_resource_clients/actor_env_var_collection.py index 6e5f9144..b51a2731 100644 --- a/src/apify_client/_resource_clients/actor_env_var_collection.py +++ b/src/apify_client/_resource_clients/actor_env_var_collection.py @@ -11,7 +11,11 @@ @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 list and create environment variables. + Obtain an instance via `ActorVersionClient.env_vars`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'env-vars') @@ -59,7 +63,11 @@ def create( @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 list and create environment variables. + Obtain an instance via `ActorVersionClientAsync.env_vars`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'env-vars') diff --git a/src/apify_client/_resource_clients/actor_version.py b/src/apify_client/_resource_clients/actor_version.py index c54b0a30..96e1d2cb 100644 --- a/src/apify_client/_resource_clients/actor_version.py +++ b/src/apify_client/_resource_clients/actor_version.py @@ -19,7 +19,11 @@ @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 get, update, and delete an Actor version. + Obtain an instance via `ActorClient.version`. + """ def __init__( self, @@ -125,7 +129,11 @@ 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 get, update, and delete an Actor version. + Obtain an instance via `ActorClientAsync.version`. + """ def __init__( self, diff --git a/src/apify_client/_resource_clients/actor_version_collection.py b/src/apify_client/_resource_clients/actor_version_collection.py index 2cb18761..aad3e964 100644 --- a/src/apify_client/_resource_clients/actor_version_collection.py +++ b/src/apify_client/_resource_clients/actor_version_collection.py @@ -17,7 +17,11 @@ @docs_group('Resource clients') class ActorVersionCollectionClient(ResourceClient): - """Sub-client for manipulating Actor versions.""" + """Sub-client for the Actor version collection. + + Provides methods to list and create Actor versions. + Obtain an instance via `ActorClient.versions`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'versions') @@ -89,7 +93,11 @@ def create( @docs_group('Resource clients') class ActorVersionCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating Actor versions.""" + """Sub-client for the Actor version collection. + + Provides methods to list and create Actor versions. + Obtain an instance via `ActorClientAsync.versions`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'versions') diff --git a/src/apify_client/_resource_clients/build.py b/src/apify_client/_resource_clients/build.py index d87c5cd3..5578587f 100644 --- a/src/apify_client/_resource_clients/build.py +++ b/src/apify_client/_resource_clients/build.py @@ -15,7 +15,11 @@ @docs_group('Resource clients') class BuildClient(ResourceClient): - """Sub-client for manipulating a single Actor build.""" + """Sub-client for managing a specific Actor build. + + Provides methods to get, delete, abort, and wait for finish of an Actor build. + Obtain an instance via `ApifyClient.build`. + """ def __init__( self, @@ -113,7 +117,11 @@ def log(self) -> LogClient: @docs_group('Resource clients') class BuildClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single Actor build.""" + """Sub-client for managing a specific Actor build. + + Provides methods to get, delete, abort, and wait for finish of an Actor build. + Obtain an instance via `ApifyClientAsync.build`. + """ def __init__( self, diff --git a/src/apify_client/_resource_clients/build_collection.py b/src/apify_client/_resource_clients/build_collection.py index ed5c9c66..2ac5d8ea 100644 --- a/src/apify_client/_resource_clients/build_collection.py +++ b/src/apify_client/_resource_clients/build_collection.py @@ -9,7 +9,10 @@ @docs_group('Resource clients') class BuildCollectionClient(ResourceClient): - """Sub-client for listing Actor builds.""" + """Sub-client for the Actor build collection. + + Provides methods to list Actor builds. Obtain an instance via `ApifyClient.builds`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-builds') @@ -44,7 +47,10 @@ def list( @docs_group('Resource clients') class BuildCollectionClientAsync(ResourceClientAsync): - """Async sub-client for listing Actor builds.""" + """Sub-client for the Actor build collection. + + Provides methods to list Actor builds. Obtain an instance via `ApifyClientAsync.builds`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-builds') diff --git a/src/apify_client/_resource_clients/dataset.py b/src/apify_client/_resource_clients/dataset.py index 4f413ec3..92e49cd0 100644 --- a/src/apify_client/_resource_clients/dataset.py +++ b/src/apify_client/_resource_clients/dataset.py @@ -60,7 +60,11 @@ class DatasetItemsPage: @docs_group('Resource clients') class DatasetClient(ResourceClient): - """Sub-client for manipulating a single dataset.""" + """Sub-client for managing a specific dataset. + + Provides methods to get, update, delete, push items, list items, iterate items, and stream items of a dataset. + Obtain an instance via `ApifyClient.dataset`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'datasets') @@ -677,7 +681,11 @@ def create_items_public_url( @docs_group('Resource clients') class DatasetClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single dataset.""" + """Sub-client for managing a specific dataset. + + Provides methods to get, update, delete, push items, list items, iterate items, and stream items of a dataset. + Obtain an instance via `ApifyClientAsync.dataset`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'datasets') diff --git a/src/apify_client/_resource_clients/dataset_collection.py b/src/apify_client/_resource_clients/dataset_collection.py index 4a6cc160..b7f847bb 100644 --- a/src/apify_client/_resource_clients/dataset_collection.py +++ b/src/apify_client/_resource_clients/dataset_collection.py @@ -10,7 +10,10 @@ @docs_group('Resource clients') class DatasetCollectionClient(ResourceClient): - """Sub-client for manipulating datasets.""" + """Sub-client for the dataset collection. + + Provides methods to list and get or create datasets. Obtain an instance via `ApifyClient.datasets`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'datasets') @@ -58,7 +61,10 @@ def get_or_create(self, *, name: str | None = None, schema: dict | None = None) @docs_group('Resource clients') class DatasetCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating datasets.""" + """Sub-client for the dataset collection. + + Provides methods to list and get or create datasets. Obtain an instance via `ApifyClientAsync.datasets`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'datasets') diff --git a/src/apify_client/_resource_clients/key_value_store.py b/src/apify_client/_resource_clients/key_value_store.py index b998a9eb..66a9c70d 100644 --- a/src/apify_client/_resource_clients/key_value_store.py +++ b/src/apify_client/_resource_clients/key_value_store.py @@ -71,7 +71,11 @@ def _parse_get_record_response(response: Response) -> Any: @docs_group('Resource clients') class KeyValueStoreClient(ResourceClient): - """Sub-client for manipulating a single key-value store.""" + """Sub-client for managing a specific key-value store. + + Provides methods to get, update, delete, and get/set/delete records of a key-value store. + Obtain an instance via `ApifyClient.key_value_store`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'key-value-stores') @@ -451,7 +455,11 @@ def create_keys_public_url( @docs_group('Resource clients') class KeyValueStoreClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single key-value store.""" + """Sub-client for managing a specific key-value store. + + Provides methods to get, update, delete, and get/set/delete records of a key-value store. + Obtain an instance via `ApifyClientAsync.key_value_store`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'key-value-stores') diff --git a/src/apify_client/_resource_clients/key_value_store_collection.py b/src/apify_client/_resource_clients/key_value_store_collection.py index 012c2b25..90f73313 100644 --- a/src/apify_client/_resource_clients/key_value_store_collection.py +++ b/src/apify_client/_resource_clients/key_value_store_collection.py @@ -15,7 +15,11 @@ @docs_group('Resource clients') class KeyValueStoreCollectionClient(ResourceClient): - """Sub-client for manipulating key-value stores.""" + """Sub-client for the key-value store collection. + + Provides methods to list and get or create key-value stores. + Obtain an instance via `ApifyClient.key_value_stores`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'key-value-stores') @@ -68,7 +72,11 @@ def get_or_create( @docs_group('Resource clients') class KeyValueStoreCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating key-value stores.""" + """Sub-client for the key-value store collection. + + Provides methods to list and get or create key-value stores. + Obtain an instance via `ApifyClientAsync.key_value_stores`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'key-value-stores') diff --git a/src/apify_client/_resource_clients/log.py b/src/apify_client/_resource_clients/log.py index af186630..dbd7a80a 100644 --- a/src/apify_client/_resource_clients/log.py +++ b/src/apify_client/_resource_clients/log.py @@ -16,7 +16,10 @@ @docs_group('Resource clients') class LogClient(ResourceClient): - """Sub-client for manipulating logs.""" + """Sub-client for managing a specific log. + + Provides methods to get and stream logs. Obtain an instance via `ApifyClient.log`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'logs') @@ -104,7 +107,10 @@ def stream(self, *, raw: bool = False) -> Iterator[impit.Response | None]: @docs_group('Resource clients') class LogClientAsync(ResourceClientAsync): - """Async sub-client for manipulating logs.""" + """Sub-client for managing a specific log. + + Provides methods to get and stream logs. Obtain an instance via `ApifyClientAsync.log`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'logs') diff --git a/src/apify_client/_resource_clients/request_queue.py b/src/apify_client/_resource_clients/request_queue.py index d2b1e13e..174dfb1e 100644 --- a/src/apify_client/_resource_clients/request_queue.py +++ b/src/apify_client/_resource_clients/request_queue.py @@ -54,7 +54,11 @@ @docs_group('Resource clients') class RequestQueueClient(ResourceClient): - """Sub-client for manipulating a single request queue.""" + """Sub-client for managing a specific request queue. + + Provides methods to get, update, delete, and add/get/list/lock/delete requests of a request queue. + Obtain an instance via `ApifyClient.request_queue`. + """ def __init__( # noqa: D417 self, @@ -460,7 +464,11 @@ def unlock_requests(self: RequestQueueClient) -> UnlockRequestsResult: @docs_group('Resource clients') class RequestQueueClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single request queue.""" + """Sub-client for managing a specific request queue. + + Provides methods to get, update, delete, and add/get/list/lock/delete requests of a request queue. + Obtain an instance via `ApifyClientAsync.request_queue`. + """ def __init__( # noqa: D417 self, diff --git a/src/apify_client/_resource_clients/request_queue_collection.py b/src/apify_client/_resource_clients/request_queue_collection.py index ce179ea8..acf19b14 100644 --- a/src/apify_client/_resource_clients/request_queue_collection.py +++ b/src/apify_client/_resource_clients/request_queue_collection.py @@ -14,7 +14,11 @@ @docs_group('Resource clients') class RequestQueueCollectionClient(ResourceClient): - """Sub-client for manipulating request queues.""" + """Sub-client for the request queue collection. + + Provides methods to list and get or create request queues. + Obtain an instance via `ApifyClient.request_queues`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'request-queues') @@ -61,7 +65,11 @@ def get_or_create(self, *, name: str | None = None) -> RequestQueue: @docs_group('Resource clients') class RequestQueueCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating request queues.""" + """Sub-client for the request queue collection. + + Provides methods to list and get or create request queues. + Obtain an instance via `ApifyClientAsync.request_queues`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'request-queues') diff --git a/src/apify_client/_resource_clients/run.py b/src/apify_client/_resource_clients/run.py index 8e38fb24..c01ec6a2 100644 --- a/src/apify_client/_resource_clients/run.py +++ b/src/apify_client/_resource_clients/run.py @@ -42,7 +42,11 @@ @docs_group('Resource clients') class RunClient(ResourceClient): - """Sub-client for manipulating a single Actor run.""" + """Sub-client for managing a specific Actor run. + + Provides methods to get, update, abort, wait for finish, metamorph, resurrect, reboot, and charge an Actor run. + Obtain an instance via `ApifyClient.run`. + """ def __init__( self, @@ -427,7 +431,11 @@ def get_status_message_watcher( @docs_group('Resource clients') class RunClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single Actor run.""" + """Sub-client for managing a specific Actor run. + + Provides methods to get, update, abort, wait for finish, metamorph, resurrect, reboot, and charge an Actor run. + Obtain an instance via `ApifyClientAsync.run`. + """ def __init__( self, diff --git a/src/apify_client/_resource_clients/run_collection.py b/src/apify_client/_resource_clients/run_collection.py index be75ec59..cb76a4a0 100644 --- a/src/apify_client/_resource_clients/run_collection.py +++ b/src/apify_client/_resource_clients/run_collection.py @@ -15,7 +15,10 @@ @docs_group('Resource clients') class RunCollectionClient(ResourceClient): - """Sub-client for listing Actor runs.""" + """Sub-client for the Actor run collection. + + Provides methods to list Actor runs. Obtain an instance via `ApifyClient.runs`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-runs') @@ -65,7 +68,10 @@ def list( @docs_group('Resource clients') class RunCollectionClientAsync(ResourceClientAsync): - """Async sub-client for listing Actor runs.""" + """Sub-client for the Actor run collection. + + Provides methods to list Actor runs. Obtain an instance via `ApifyClientAsync.runs`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-runs') diff --git a/src/apify_client/_resource_clients/schedule.py b/src/apify_client/_resource_clients/schedule.py index 3cb85942..5fd65f69 100644 --- a/src/apify_client/_resource_clients/schedule.py +++ b/src/apify_client/_resource_clients/schedule.py @@ -12,7 +12,11 @@ @docs_group('Resource clients') class ScheduleClient(ResourceClient): - """Sub-client for manipulating a single schedule.""" + """Sub-client for managing a specific schedule. + + Provides methods to get, update, delete, and get log of a schedule. + Obtain an instance via `ApifyClient.schedule`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'schedules') @@ -108,7 +112,11 @@ def get_log(self) -> list[ScheduleInvoked] | None: @docs_group('Resource clients') class ScheduleClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single schedule.""" + """Sub-client for managing a specific schedule. + + Provides methods to get, update, delete, and get log of a schedule. + Obtain an instance via `ApifyClientAsync.schedule`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'schedules') diff --git a/src/apify_client/_resource_clients/schedule_collection.py b/src/apify_client/_resource_clients/schedule_collection.py index 7565d7f8..dd27cf93 100644 --- a/src/apify_client/_resource_clients/schedule_collection.py +++ b/src/apify_client/_resource_clients/schedule_collection.py @@ -11,7 +11,10 @@ @docs_group('Resource clients') class ScheduleCollectionClient(ResourceClient): - """Sub-client for manipulating schedules.""" + """Sub-client for the schedule collection. + + Provides methods to list and create schedules. Obtain an instance via `ApifyClient.schedules`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'schedules') @@ -90,7 +93,10 @@ def create( @docs_group('Resource clients') class ScheduleCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating schedules.""" + """Sub-client for the schedule collection. + + Provides methods to list and create schedules. Obtain an instance via `ApifyClientAsync.schedules`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'schedules') diff --git a/src/apify_client/_resource_clients/status_message_watcher.py b/src/apify_client/_resource_clients/status_message_watcher.py index c27fe756..6bdabdf7 100644 --- a/src/apify_client/_resource_clients/status_message_watcher.py +++ b/src/apify_client/_resource_clients/status_message_watcher.py @@ -21,9 +21,9 @@ @docs_group('Resource clients') class StatusMessageWatcher: - """Utility class for logging status messages from another Actor run. + """Utility class for logging status messages from an Actor run. - Status message is logged at fixed time intervals, and there is no guarantee that all messages will be logged, + The status message is polled at fixed time intervals, and there is no guarantee that all messages will be logged, especially in cases of frequent status message changes. """ @@ -70,7 +70,7 @@ def _log_run_data(self, run_data: Run | None) -> bool: @docs_group('Resource clients') class StatusMessageWatcherAsync(StatusMessageWatcher): - """Async variant of `StatusMessageWatcher` that is logging in task.""" + """Async variant of `StatusMessageWatcher` that polls and logs status messages in an asyncio task.""" def __init__( self, *, run_client: RunClientAsync, to_logger: logging.Logger, check_period: timedelta = timedelta(seconds=1) @@ -128,7 +128,7 @@ async def _log_changed_status_message(self) -> None: @docs_group('Resource clients') class StatusMessageWatcherSync(StatusMessageWatcher): - """Sync variant of `StatusMessageWatcher` that is logging in thread.""" + """Sync variant of `StatusMessageWatcher` that polls and logs status messages in a background thread.""" def __init__( self, *, run_client: RunClient, to_logger: logging.Logger, check_period: timedelta = timedelta(seconds=1) diff --git a/src/apify_client/_resource_clients/store_collection.py b/src/apify_client/_resource_clients/store_collection.py index 2140ee61..7095a0f8 100644 --- a/src/apify_client/_resource_clients/store_collection.py +++ b/src/apify_client/_resource_clients/store_collection.py @@ -9,7 +9,10 @@ @docs_group('Resource clients') class StoreCollectionClient(ResourceClient): - """Sub-client for Apify store.""" + """Sub-client for the Apify store collection. + + Provides methods to list Actors in the Apify store. Obtain an instance via `ApifyClient.store`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'store') @@ -57,7 +60,10 @@ def list( @docs_group('Resource clients') class StoreCollectionClientAsync(ResourceClientAsync): - """Async sub-client for Apify store.""" + """Sub-client for the Apify store collection. + + Provides methods to list Actors in the Apify store. Obtain an instance via `ApifyClientAsync.store`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'store') diff --git a/src/apify_client/_resource_clients/streamed_log.py b/src/apify_client/_resource_clients/streamed_log.py index 95e7851e..ec27ee67 100644 --- a/src/apify_client/_resource_clients/streamed_log.py +++ b/src/apify_client/_resource_clients/streamed_log.py @@ -19,14 +19,14 @@ @docs_group('Resource clients') class StreamedLog: - """Utility class for streaming logs from another Actor. + """Utility class for streaming logs from an Actor run. - It uses buffer to deal with possibly chunked logs. Chunked logs are stored in buffer. Chunks are expected to contain - specific markers that indicate the start of the log message. Each time a new chunk with complete split marker - arrives, the buffer is processed, logged and emptied. + It uses a buffer to deal with possibly chunked logs. Chunked logs are stored in the buffer. Chunks are expected + to contain specific markers that indicate the start of a log message. Each time a new chunk with a complete split + marker arrives, the buffer is processed, logged, and emptied. - This works only if the logs have datetime marker in ISO format. For example, `2025-05-12T15:35:59.429Z` This is the - default log standard for the Actors. + This works only if the logs have a datetime marker in ISO format. For example, `2025-05-12T15:35:59.429Z`. + This is the default log standard for Actors. """ # Test related flag to enable propagation of logs to the `caplog` fixture during tests. @@ -99,7 +99,7 @@ def _guess_log_level_from_message(message: str) -> int: @docs_group('Resource clients') class StreamedLogSync(StreamedLog): - """Sync variant of `StreamedLog` that is logging in threads.""" + """Sync variant of `StreamedLog` that streams and logs in a background thread.""" def __init__(self, log_client: LogClient, *, to_logger: logging.Logger, from_start: bool = True) -> None: super().__init__(to_logger=to_logger, from_start=from_start) @@ -152,7 +152,7 @@ def _stream_log(self) -> None: @docs_group('Resource clients') class StreamedLogAsync(StreamedLog): - """Async variant of `StreamedLog` that is logging in tasks.""" + """Async variant of `StreamedLog` that streams and logs in an asyncio task.""" def __init__(self, log_client: LogClientAsync, *, to_logger: logging.Logger, from_start: bool = True) -> None: super().__init__(to_logger=to_logger, from_start=from_start) diff --git a/src/apify_client/_resource_clients/task.py b/src/apify_client/_resource_clients/task.py index 3d209e92..5088e471 100644 --- a/src/apify_client/_resource_clients/task.py +++ b/src/apify_client/_resource_clients/task.py @@ -32,7 +32,11 @@ @docs_group('Resource clients') class TaskClient(ResourceClient): - """Sub-client for manipulating a single task.""" + """Sub-client for managing a specific task. + + Provides methods to get, update, delete, and start runs of a task. + Obtain an instance via `ApifyClient.task`. + """ def __init__( self, @@ -321,7 +325,11 @@ def webhooks(self) -> WebhookCollectionClient: @docs_group('Resource clients') class TaskClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single task.""" + """Sub-client for managing a specific task. + + Provides methods to get, update, delete, and start runs of a task. + Obtain an instance via `ApifyClientAsync.task`. + """ def __init__( self, diff --git a/src/apify_client/_resource_clients/task_collection.py b/src/apify_client/_resource_clients/task_collection.py index a09cec5e..eacf33fc 100644 --- a/src/apify_client/_resource_clients/task_collection.py +++ b/src/apify_client/_resource_clients/task_collection.py @@ -14,7 +14,10 @@ @docs_group('Resource clients') class TaskCollectionClient(ResourceClient): - """Sub-client for manipulating tasks.""" + """Sub-client for the task collection. + + Provides methods to list and create tasks. Obtain an instance via `ApifyClient.tasks`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-tasks') @@ -114,7 +117,10 @@ def create( @docs_group('Resource clients') class TaskCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating tasks.""" + """Sub-client for the task collection. + + Provides methods to list and create tasks. Obtain an instance via `ApifyClientAsync.tasks`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'actor-tasks') diff --git a/src/apify_client/_resource_clients/user.py b/src/apify_client/_resource_clients/user.py index 2b9cd188..dd40ad21 100644 --- a/src/apify_client/_resource_clients/user.py +++ b/src/apify_client/_resource_clients/user.py @@ -22,7 +22,11 @@ @docs_group('Resource clients') class UserClient(ResourceClient): - """Sub-client for querying user data.""" + """Sub-client for managing user account information. + + Provides methods to get user data, monthly usage, and account limits. + Obtain an instance via `ApifyClient.user`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_id = kwargs.pop('resource_id', None) @@ -122,7 +126,11 @@ def update_limits( @docs_group('Resource clients') class UserClientAsync(ResourceClientAsync): - """Async sub-client for querying user data.""" + """Sub-client for managing user account information. + + Provides methods to get user data, monthly usage, and account limits. + Obtain an instance via `ApifyClientAsync.user`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_id = kwargs.pop('resource_id', None) diff --git a/src/apify_client/_resource_clients/webhook.py b/src/apify_client/_resource_clients/webhook.py index cfaec8d1..4a838d34 100644 --- a/src/apify_client/_resource_clients/webhook.py +++ b/src/apify_client/_resource_clients/webhook.py @@ -21,7 +21,11 @@ @docs_group('Resource clients') class WebhookClient(ResourceClient): - """Sub-client for manipulating a single webhook.""" + """Sub-client for managing a specific webhook. + + Provides methods to get, update, delete, and test a webhook. + Obtain an instance via `ApifyClient.webhook`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhooks') @@ -139,7 +143,11 @@ def dispatches(self) -> WebhookDispatchCollectionClient: @docs_group('Resource clients') class WebhookClientAsync(ResourceClientAsync): - """Async sub-client for manipulating a single webhook.""" + """Sub-client for managing a specific webhook. + + Provides methods to get, update, delete, and test a webhook. + Obtain an instance via `ApifyClientAsync.webhook`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhooks') diff --git a/src/apify_client/_resource_clients/webhook_collection.py b/src/apify_client/_resource_clients/webhook_collection.py index 7b508e15..92a7af75 100644 --- a/src/apify_client/_resource_clients/webhook_collection.py +++ b/src/apify_client/_resource_clients/webhook_collection.py @@ -14,7 +14,10 @@ @docs_group('Resource clients') class WebhookCollectionClient(ResourceClient): - """Sub-client for manipulating webhooks.""" + """Sub-client for the webhook collection. + + Provides methods to list and create webhooks. Obtain an instance via `ApifyClient.webhooks`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhooks') @@ -101,7 +104,10 @@ def create( @docs_group('Resource clients') class WebhookCollectionClientAsync(ResourceClientAsync): - """Async sub-client for manipulating webhooks.""" + """Sub-client for the webhook collection. + + Provides methods to list and create webhooks. Obtain an instance via `ApifyClientAsync.webhooks`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhooks') diff --git a/src/apify_client/_resource_clients/webhook_dispatch.py b/src/apify_client/_resource_clients/webhook_dispatch.py index 61abda9d..945119d2 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch.py +++ b/src/apify_client/_resource_clients/webhook_dispatch.py @@ -9,7 +9,10 @@ @docs_group('Resource clients') class WebhookDispatchClient(ResourceClient): - """Sub-client for querying information about a webhook dispatch.""" + """Sub-client for managing a specific webhook dispatch. + + Provides methods to get a webhook dispatch. Obtain an instance via `ApifyClient.webhook_dispatch`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhook-dispatches') @@ -31,7 +34,10 @@ def get(self) -> WebhookDispatch | None: @docs_group('Resource clients') class WebhookDispatchClientAsync(ResourceClientAsync): - """Async sub-client for querying information about a webhook dispatch.""" + """Sub-client for managing a specific webhook dispatch. + + Provides methods to get a webhook dispatch. Obtain an instance via `ApifyClientAsync.webhook_dispatch`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhook-dispatches') diff --git a/src/apify_client/_resource_clients/webhook_dispatch_collection.py b/src/apify_client/_resource_clients/webhook_dispatch_collection.py index cee09cd4..ba4ba9b2 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch_collection.py +++ b/src/apify_client/_resource_clients/webhook_dispatch_collection.py @@ -9,7 +9,10 @@ @docs_group('Resource clients') class WebhookDispatchCollectionClient(ResourceClient): - """Sub-client for listing webhook dispatches.""" + """Sub-client for the webhook dispatch collection. + + Provides methods to list webhook dispatches. Obtain an instance via `ApifyClient.webhook_dispatches`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhook-dispatches') @@ -40,7 +43,10 @@ def list( @docs_group('Resource clients') class WebhookDispatchCollectionClientAsync(ResourceClientAsync): - """Async sub-client for listing webhook dispatches.""" + """Sub-client for the webhook dispatch collection. + + Provides methods to list webhook dispatches. Obtain an instance via `ApifyClientAsync.webhook_dispatches`. + """ def __init__(self, *args: Any, **kwargs: Any) -> None: resource_path = kwargs.pop('resource_path', 'webhook-dispatches') diff --git a/src/apify_client/errors.py b/src/apify_client/errors.py index db019c39..9037b661 100644 --- a/src/apify_client/errors.py +++ b/src/apify_client/errors.py @@ -10,24 +10,38 @@ @docs_group('Errors') class ApifyClientError(Exception): - """Base class for errors specific to the Apify API Client.""" + """Base class for all Apify API client errors. + + All exceptions raised by the Apify client inherit from this class, making it convenient + to catch any client-related error with a single except clause. + """ @docs_group('Errors') class ApifyApiError(ApifyClientError): - """Error from Apify API responses (rate limits, validation errors, internal errors). - - Thrown when HTTP request succeeds but API returns an error response. Rate limit and internal errors are - retried automatically, while validation errors are thrown immediately for user correction. + """Error raised when the Apify API returns an error response. + + This error is raised when an HTTP request to the Apify API succeeds at the transport level + but the server returns an error status code. Rate limit (HTTP 429) and server errors (HTTP 5xx) + are retried automatically before this error is raised, while client errors (HTTP 4xx) are raised + immediately. + + Attributes: + message: The error message from the API response. + type: The error type identifier from the API response (e.g. ``record-not-found``). + status_code: The HTTP status code of the error response. + attempt: The attempt number when the error was raised. + http_method: The HTTP method of the failed request. + data: Additional error data from the API response. """ def __init__(self, response: impit.Response, attempt: int, method: str = 'GET') -> None: - """Initialize an API error from a failed response. + """Initialize the API error from a failed response. Args: - response: The failed API response. - attempt: The attempt number when the request failed. - method: The HTTP method used. + response: The failed HTTP response from the Apify API. + attempt: The attempt number when the request failed (1-indexed). + method: The HTTP method of the failed request. """ self.message: str | None = None self.type: str | None = None @@ -61,16 +75,18 @@ def __init__(self, response: impit.Response, attempt: int, method: str = 'GET') @docs_group('Errors') class InvalidResponseBodyError(ApifyClientError): - """Error when response body cannot be parsed (e.g., partial JSON). + """Error raised when a response body cannot be parsed. - Commonly occurs when only partial JSON is received. Usually resolved by retrying the request. + This typically occurs when the API returns a partial or malformed JSON response, for example + due to a network interruption. The client retries such requests automatically, so this error + is only raised after all retry attempts have been exhausted. """ def __init__(self, response: impit.Response) -> None: - """Initialize a new instance. + """Initialize the error from an unparseable response. Args: - response: The response that failed to parse. + response: The HTTP response whose body could not be parsed. """ super().__init__('Response body could not be parsed') From ea0ce76ce50497c17a719a067462b82c4f6b7d99 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 10:54:24 +0100 Subject: [PATCH 3/7] docs: Fix typo 'unparseable' -> 'unparsable' in docstring Co-Authored-By: Claude Opus 4.6 --- src/apify_client/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apify_client/errors.py b/src/apify_client/errors.py index 9037b661..2396e58f 100644 --- a/src/apify_client/errors.py +++ b/src/apify_client/errors.py @@ -83,7 +83,7 @@ class InvalidResponseBodyError(ApifyClientError): """ def __init__(self, response: impit.Response) -> None: - """Initialize the error from an unparseable response. + """Initialize the error from an unparsable response. Args: response: The HTTP response whose body could not be parsed. From 9f7f38b2b808243b28ff1370b203a27d557a3503 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 11:02:43 +0100 Subject: [PATCH 4/7] docs: Add usage examples to ApifyClient and ApifyClientAsync docstrings Co-Authored-By: Claude Opus 4.6 --- src/apify_client/_apify_client.py | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/apify_client/_apify_client.py b/src/apify_client/_apify_client.py index 1200c701..d59f859e 100644 --- a/src/apify_client/_apify_client.py +++ b/src/apify_client/_apify_client.py @@ -89,6 +89,24 @@ class ApifyClient: schedules, webhooks, and more. The client automatically handles retries with exponential backoff for failed or rate-limited requests. + + ### Usage + + ```python + from apify_client import ApifyClient + + client = ApifyClient(token='MY-APIFY-TOKEN') + + # Start an Actor and wait for it to finish. + actor_client = client.actor('username/my-actor') + run = actor_client.call(run_input={'query': 'web scraping'}) + + # Fetch results from the run's default dataset. + dataset_client = client.dataset(run['defaultDatasetId']) + items = dataset_client.list_items().items + for item in items: + print(item) + ``` """ _OVERRIDABLE_DEFAULT_HEADERS: ClassVar[set[str]] = {'Accept', 'Authorization', 'Accept-Encoding', 'User-Agent'} @@ -359,6 +377,29 @@ class ApifyClientAsync: request queues, schedules, webhooks, and more. The client automatically handles retries with exponential backoff for failed or rate-limited requests. + + ### Usage + + ```python + import asyncio + + from apify_client import ApifyClientAsync + + async def main() -> None: + client = ApifyClientAsync(token='MY-APIFY-TOKEN') + + # Start an Actor and wait for it to finish. + actor_client = client.actor('username/my-actor') + run = await actor_client.call(run_input={'query': 'web scraping'}) + + # Fetch results from the run's default dataset. + dataset_client = client.dataset(run['defaultDatasetId']) + items = (await dataset_client.list_items()).items + for item in items: + print(item) + + asyncio.run(main()) + ``` """ _OVERRIDABLE_DEFAULT_HEADERS: ClassVar[set[str]] = {'Accept', 'Authorization', 'Accept-Encoding', 'User-Agent'} From caf52e8938f9469cff80f74b8c52f4a57812d33b Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 11:07:07 +0100 Subject: [PATCH 5/7] docs: Fix usage examples to use typed model attributes Use run.default_dataset_id instead of run['defaultDatasetId'] and add None check since call() returns Run | None. Co-Authored-By: Claude Opus 4.6 --- src/apify_client/_apify_client.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/apify_client/_apify_client.py b/src/apify_client/_apify_client.py index d59f859e..c726887b 100644 --- a/src/apify_client/_apify_client.py +++ b/src/apify_client/_apify_client.py @@ -102,10 +102,11 @@ class ApifyClient: run = actor_client.call(run_input={'query': 'web scraping'}) # Fetch results from the run's default dataset. - dataset_client = client.dataset(run['defaultDatasetId']) - items = dataset_client.list_items().items - for item in items: - print(item) + if run is not None: + dataset_client = client.dataset(run.default_dataset_id) + items = dataset_client.list_items().items + for item in items: + print(item) ``` """ @@ -393,10 +394,11 @@ async def main() -> None: run = await actor_client.call(run_input={'query': 'web scraping'}) # Fetch results from the run's default dataset. - dataset_client = client.dataset(run['defaultDatasetId']) - items = (await dataset_client.list_items()).items - for item in items: - print(item) + if run is not None: + dataset_client = client.dataset(run.default_dataset_id) + items = (await dataset_client.list_items()).items + for item in items: + print(item) asyncio.run(main()) ``` From 6764f59f4f35cfa399d59cd68ce6a444b642d4e1 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Tue, 24 Feb 2026 11:14:28 +0100 Subject: [PATCH 6/7] docs: Revert changes to generated _models.py file Co-Authored-By: Claude Opus 4.6 --- src/apify_client/_models.py | 194 ------------------------------------ 1 file changed, 194 deletions(-) diff --git a/src/apify_client/_models.py b/src/apify_client/_models.py index 9f6edad8..26231768 100644 --- a/src/apify_client/_models.py +++ b/src/apify_client/_models.py @@ -9,10 +9,7 @@ from pydantic import AnyUrl, AwareDatetime, BaseModel, ConfigDict, EmailStr, Field -from apify_client._docs import docs_group - -@docs_group('Models') class PaginationResponse(BaseModel): """Common pagination fields for list responses.""" @@ -41,7 +38,6 @@ class PaginationResponse(BaseModel): """ -@docs_group('Models') class ActorStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -58,7 +54,6 @@ class ActorStats(BaseModel): ] = None -@docs_group('Models') class ActorShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -72,7 +67,6 @@ class ActorShort(BaseModel): stats: ActorStats | None = None -@docs_group('Models') class ListOfActors(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -80,7 +74,6 @@ class ListOfActors(PaginationResponse): items: list[ActorShort] -@docs_group('Models') class ListOfActorsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -88,7 +81,6 @@ class ListOfActorsResponse(BaseModel): data: ListOfActors -@docs_group('Models') class Error(BaseModel): model_config = ConfigDict( extra='allow', @@ -97,7 +89,6 @@ class Error(BaseModel): message: Annotated[str, Field(examples=['Actor run did not succeed (run ID: 55uatRrZib4xbZs, status: FAILED)'])] -@docs_group('Models') class ErrorResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -105,7 +96,6 @@ class ErrorResponse(BaseModel): error: Error -@docs_group('Models') class VersionSourceType(StrEnum): SOURCE_FILES = 'SOURCE_FILES' GIT_REPO = 'GIT_REPO' @@ -113,7 +103,6 @@ class VersionSourceType(StrEnum): GITHUB_GIST = 'GITHUB_GIST' -@docs_group('Models') class EnvVar(BaseModel): model_config = ConfigDict( extra='allow', @@ -123,13 +112,11 @@ class EnvVar(BaseModel): is_secret: Annotated[bool | None, Field(alias='isSecret', examples=[False])] = None -@docs_group('Models') class SourceCodeFileFormat(StrEnum): BASE64 = 'BASE64' TEXT = 'TEXT' -@docs_group('Models') class SourceCodeFile(BaseModel): model_config = ConfigDict( extra='allow', @@ -139,7 +126,6 @@ class SourceCodeFile(BaseModel): name: Annotated[str, Field(examples=['src/main.js'])] -@docs_group('Models') class SourceCodeFolder(BaseModel): """Represents a folder in the Actor's source code structure. Distinguished from SourceCodeFile by the presence of the `folder` property set to `true`. @@ -159,7 +145,6 @@ class SourceCodeFolder(BaseModel): """ -@docs_group('Models') class Version(BaseModel): model_config = ConfigDict( extra='allow', @@ -186,7 +171,6 @@ class Version(BaseModel): """ -@docs_group('Models') class CommonActorPricingInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -208,7 +192,6 @@ class CommonActorPricingInfo(BaseModel): reason_for_change: Annotated[str | None, Field(alias='reasonForChange')] = None -@docs_group('Models') class PricingModel(StrEnum): PAY_PER_EVENT = 'PAY_PER_EVENT' PRICE_PER_DATASET_ITEM = 'PRICE_PER_DATASET_ITEM' @@ -216,7 +199,6 @@ class PricingModel(StrEnum): FREE = 'FREE' -@docs_group('Models') class ActorChargeEvent(BaseModel): model_config = ConfigDict( extra='allow', @@ -226,7 +208,6 @@ class ActorChargeEvent(BaseModel): event_description: Annotated[str, Field(alias='eventDescription')] -@docs_group('Models') class PricingPerEvent(BaseModel): model_config = ConfigDict( extra='allow', @@ -234,7 +215,6 @@ class PricingPerEvent(BaseModel): actor_charge_events: Annotated[dict[str, ActorChargeEvent] | None, Field(alias='actorChargeEvents')] = None -@docs_group('Models') class PayPerEventActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -244,7 +224,6 @@ class PayPerEventActorPricingInfo(CommonActorPricingInfo): minimal_max_total_charge_usd: Annotated[float | None, Field(alias='minimalMaxTotalChargeUsd')] = None -@docs_group('Models') class PricePerDatasetItemActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -257,7 +236,6 @@ class PricePerDatasetItemActorPricingInfo(CommonActorPricingInfo): price_per_unit_usd: Annotated[float, Field(alias='pricePerUnitUsd')] -@docs_group('Models') class FlatPricePerMonthActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -273,7 +251,6 @@ class FlatPricePerMonthActorPricingInfo(CommonActorPricingInfo): """ -@docs_group('Models') class FreeActorPricingInfo(CommonActorPricingInfo): model_config = ConfigDict( extra='allow', @@ -281,7 +258,6 @@ class FreeActorPricingInfo(CommonActorPricingInfo): pricing_model: Annotated[Literal['FREE'], Field(alias='pricingModel')] -@docs_group('Models') class DefaultRunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -292,7 +268,6 @@ class DefaultRunOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None -@docs_group('Models') class CreateActorRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -319,7 +294,6 @@ class CreateActorRequest(BaseModel): default_run_options: Annotated[DefaultRunOptions | None, Field(alias='defaultRunOptions')] = None -@docs_group('Models') class ActorPermissionLevel(StrEnum): """Determines permissions that the Actor requires to run. For more information, see the [Actor permissions documentation](https://docs.apify.com/platform/actors/development/permissions).""" @@ -327,7 +301,6 @@ class ActorPermissionLevel(StrEnum): FULL_PERMISSIONS = 'FULL_PERMISSIONS' -@docs_group('Models') class ExampleRunInput(BaseModel): model_config = ConfigDict( extra='allow', @@ -336,7 +309,6 @@ class ExampleRunInput(BaseModel): content_type: Annotated[str, Field(alias='contentType', examples=['application/json; charset=utf-8'])] -@docs_group('Models') class TaggedBuildInfo(BaseModel): """Information about a tagged build.""" @@ -359,7 +331,6 @@ class TaggedBuildInfo(BaseModel): """ -@docs_group('Models') class Actor(BaseModel): model_config = ConfigDict( extra='allow', @@ -398,7 +369,6 @@ class Actor(BaseModel): """ -@docs_group('Models') class ActorResponse(BaseModel): """Response containing Actor data.""" @@ -408,7 +378,6 @@ class ActorResponse(BaseModel): data: Actor -@docs_group('Models') class CreateOrUpdateVersionRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -435,7 +404,6 @@ class CreateOrUpdateVersionRequest(BaseModel): """ -@docs_group('Models') class BuildTag(BaseModel): model_config = ConfigDict( extra='allow', @@ -443,7 +411,6 @@ class BuildTag(BaseModel): build_id: Annotated[str, Field(alias='buildId')] -@docs_group('Models') class UpdateActorRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -516,7 +483,6 @@ class UpdateActorRequest(BaseModel): """ -@docs_group('Models') class ListOfVersions(BaseModel): model_config = ConfigDict( extra='allow', @@ -525,7 +491,6 @@ class ListOfVersions(BaseModel): items: list[Version] -@docs_group('Models') class ListOfVersionsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -533,7 +498,6 @@ class ListOfVersionsResponse(BaseModel): data: ListOfVersions -@docs_group('Models') class VersionResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -541,7 +505,6 @@ class VersionResponse(BaseModel): data: Version -@docs_group('Models') class ListOfEnvVars(BaseModel): model_config = ConfigDict( extra='allow', @@ -550,7 +513,6 @@ class ListOfEnvVars(BaseModel): items: list[EnvVar] -@docs_group('Models') class ListOfEnvVarsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -558,7 +520,6 @@ class ListOfEnvVarsResponse(BaseModel): data: ListOfEnvVars -@docs_group('Models') class EnvVarResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -566,7 +527,6 @@ class EnvVarResponse(BaseModel): data: EnvVar -@docs_group('Models') class WebhookEventType(StrEnum): """Type of event that triggers the webhook.""" @@ -584,7 +544,6 @@ class WebhookEventType(StrEnum): TEST = 'TEST' -@docs_group('Models') class WebhookCondition(BaseModel): model_config = ConfigDict( extra='allow', @@ -594,7 +553,6 @@ class WebhookCondition(BaseModel): actor_run_id: Annotated[str | None, Field(alias='actorRunId', examples=['hgdKZtadYvn4mBpoi'])] = None -@docs_group('Models') class WebhookDispatchStatus(StrEnum): """Status of the webhook dispatch indicating whether the HTTP request was successful.""" @@ -603,7 +561,6 @@ class WebhookDispatchStatus(StrEnum): FAILED = 'FAILED' -@docs_group('Models') class ExampleWebhookDispatch(BaseModel): model_config = ConfigDict( extra='allow', @@ -614,7 +571,6 @@ class ExampleWebhookDispatch(BaseModel): ) -@docs_group('Models') class WebhookStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -622,7 +578,6 @@ class WebhookStats(BaseModel): total_dispatches: Annotated[int, Field(alias='totalDispatches', examples=[1])] -@docs_group('Models') class WebhookShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -642,7 +597,6 @@ class WebhookShort(BaseModel): stats: WebhookStats | None = None -@docs_group('Models') class ListOfWebhooks(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -650,7 +604,6 @@ class ListOfWebhooks(PaginationResponse): items: list[WebhookShort] -@docs_group('Models') class ListOfWebhooksResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -658,7 +611,6 @@ class ListOfWebhooksResponse(BaseModel): data: ListOfWebhooks -@docs_group('Models') class ActorJobStatus(StrEnum): """Status of an Actor job (run or build).""" @@ -672,7 +624,6 @@ class ActorJobStatus(StrEnum): ABORTED = 'ABORTED' -@docs_group('Models') class RunOrigin(StrEnum): DEVELOPMENT = 'DEVELOPMENT' WEB = 'WEB' @@ -685,7 +636,6 @@ class RunOrigin(StrEnum): STANDBY = 'STANDBY' -@docs_group('Models') class BuildsMeta(BaseModel): model_config = ConfigDict( extra='allow', @@ -701,7 +651,6 @@ class BuildsMeta(BaseModel): """ -@docs_group('Models') class BuildShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -717,7 +666,6 @@ class BuildShort(BaseModel): meta: BuildsMeta | None = None -@docs_group('Models') class ListOfBuilds(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -725,7 +673,6 @@ class ListOfBuilds(PaginationResponse): items: list[BuildShort] -@docs_group('Models') class ListOfBuildsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -733,7 +680,6 @@ class ListOfBuildsResponse(BaseModel): data: ListOfBuilds -@docs_group('Models') class BuildStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -743,7 +689,6 @@ class BuildStats(BaseModel): compute_units: Annotated[float, Field(alias='computeUnits', examples=[0.0126994444444444])] -@docs_group('Models') class BuildOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -754,7 +699,6 @@ class BuildOptions(BaseModel): disk_mbytes: Annotated[int | None, Field(alias='diskMbytes', examples=[2048])] = None -@docs_group('Models') class BuildUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -762,7 +706,6 @@ class BuildUsage(BaseModel): actor_compute_units: Annotated[float | None, Field(alias='ACTOR_COMPUTE_UNITS', examples=[0.08])] = None -@docs_group('Models') class Storages(BaseModel): model_config = ConfigDict( extra='allow', @@ -773,7 +716,6 @@ class Storages(BaseModel): """ -@docs_group('Models') class ActorDefinition(BaseModel): """The definition of the Actor, the full specification of this field can be found in [Apify docs](https://docs.apify.com/platform/actors/development/actor-definition/actor-json)""" @@ -839,7 +781,6 @@ class ActorDefinition(BaseModel): """ -@docs_group('Models') class Build(BaseModel): model_config = ConfigDict( extra='allow', @@ -866,7 +807,6 @@ class Build(BaseModel): actor_definition: Annotated[ActorDefinition | None, Field(alias='actorDefinition')] = None -@docs_group('Models') class BuildResponse(BaseModel): """Response containing Actor build data.""" @@ -876,7 +816,6 @@ class BuildResponse(BaseModel): data: Build -@docs_group('Models') class RunMeta(BaseModel): model_config = ConfigDict( extra='allow', @@ -900,7 +839,6 @@ class RunMeta(BaseModel): """ -@docs_group('Models') class RunShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -922,7 +860,6 @@ class RunShort(BaseModel): default_request_queue_id: Annotated[str, Field(alias='defaultRequestQueueId', examples=['so93g2shcDzK3pA85'])] -@docs_group('Models') class ListOfRuns(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -930,7 +867,6 @@ class ListOfRuns(PaginationResponse): items: list[RunShort] -@docs_group('Models') class ListOfRunsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -938,7 +874,6 @@ class ListOfRunsResponse(BaseModel): data: ListOfRuns -@docs_group('Models') class RunStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -962,7 +897,6 @@ class RunStats(BaseModel): compute_units: Annotated[float, Field(alias='computeUnits', examples=[0.13804], ge=0.0)] -@docs_group('Models') class RunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -975,7 +909,6 @@ class RunOptions(BaseModel): max_total_charge_usd: Annotated[float | None, Field(alias='maxTotalChargeUsd', examples=[5], ge=0.0)] = None -@docs_group('Models') class GeneralAccess(StrEnum): """Defines the general access level for the resource.""" @@ -985,7 +918,6 @@ class GeneralAccess(StrEnum): RESTRICTED = 'RESTRICTED' -@docs_group('Models') class RunUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -1010,7 +942,6 @@ class RunUsage(BaseModel): proxy_serps: Annotated[int | None, Field(alias='PROXY_SERPS', examples=[3])] = None -@docs_group('Models') class RunUsageUsd(BaseModel): """Resource usage costs in USD. All values are monetary amounts in US dollars.""" @@ -1037,7 +968,6 @@ class RunUsageUsd(BaseModel): proxy_serps: Annotated[float | None, Field(alias='PROXY_SERPS', examples=[0.003])] = None -@docs_group('Models') class Metamorph(BaseModel): """Information about a metamorph event that occurred during the run.""" @@ -1062,7 +992,6 @@ class Metamorph(BaseModel): """ -@docs_group('Models') class Run(BaseModel): """Represents an Actor run and its associated data.""" @@ -1197,7 +1126,6 @@ class Run(BaseModel): """ -@docs_group('Models') class RunResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1205,7 +1133,6 @@ class RunResponse(BaseModel): data: Run -@docs_group('Models') class TaskStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1213,7 +1140,6 @@ class TaskStats(BaseModel): total_runs: Annotated[int | None, Field(alias='totalRuns', examples=[15])] = None -@docs_group('Models') class TaskShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -1230,7 +1156,6 @@ class TaskShort(BaseModel): stats: TaskStats | None = None -@docs_group('Models') class ListOfTasks(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1238,7 +1163,6 @@ class ListOfTasks(PaginationResponse): items: list[TaskShort] -@docs_group('Models') class ListOfTasksResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1246,7 +1170,6 @@ class ListOfTasksResponse(BaseModel): data: ListOfTasks -@docs_group('Models') class TaskOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -1257,7 +1180,6 @@ class TaskOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None -@docs_group('Models') class TaskInput(BaseModel): """The input configuration for the Actor task. This is a user-defined JSON object that will be passed to the Actor when the task is run. @@ -1269,7 +1191,6 @@ class TaskInput(BaseModel): ) -@docs_group('Models') class CreateTaskRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1280,7 +1201,6 @@ class CreateTaskRequest(BaseModel): input: TaskInput | None = None -@docs_group('Models') class Task(BaseModel): model_config = ConfigDict( extra='allow', @@ -1299,7 +1219,6 @@ class Task(BaseModel): standby_url: Annotated[AnyUrl | None, Field(alias='standbyUrl')] = None -@docs_group('Models') class TaskResponse(BaseModel): """Response containing Actor task data.""" @@ -1309,7 +1228,6 @@ class TaskResponse(BaseModel): data: Task -@docs_group('Models') class UpdateTaskRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1327,7 +1245,6 @@ class UpdateTaskRequest(BaseModel): input: TaskInput | None = None -@docs_group('Models') class Webhook(BaseModel): model_config = ConfigDict( extra='allow', @@ -1354,7 +1271,6 @@ class Webhook(BaseModel): stats: WebhookStats | None = None -@docs_group('Models') class UpdateRunRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1365,7 +1281,6 @@ class UpdateRunRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None -@docs_group('Models') class ChargeRunRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1374,13 +1289,11 @@ class ChargeRunRequest(BaseModel): count: Annotated[int, Field(examples=[1])] -@docs_group('Models') class StorageOwnership(StrEnum): OWNED_BY_ME = 'ownedByMe' SHARED_WITH_ME = 'sharedWithMe' -@docs_group('Models') class KeyValueStoreStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1392,7 +1305,6 @@ class KeyValueStoreStats(BaseModel): s3_storage_bytes: Annotated[int | None, Field(alias='s3StorageBytes', examples=[18])] = None -@docs_group('Models') class KeyValueStore(BaseModel): model_config = ConfigDict( extra='allow', @@ -1428,7 +1340,6 @@ class KeyValueStore(BaseModel): stats: KeyValueStoreStats | None = None -@docs_group('Models') class ListOfKeyValueStores(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1436,7 +1347,6 @@ class ListOfKeyValueStores(PaginationResponse): items: list[KeyValueStore] -@docs_group('Models') class ListOfKeyValueStoresResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1444,7 +1354,6 @@ class ListOfKeyValueStoresResponse(BaseModel): data: ListOfKeyValueStores -@docs_group('Models') class KeyValueStoreResponse(BaseModel): """Response containing key-value store data.""" @@ -1454,7 +1363,6 @@ class KeyValueStoreResponse(BaseModel): data: KeyValueStore -@docs_group('Models') class UpdateStoreRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1463,7 +1371,6 @@ class UpdateStoreRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None -@docs_group('Models') class KeyValueStoreKey(BaseModel): model_config = ConfigDict( extra='allow', @@ -1482,7 +1389,6 @@ class KeyValueStoreKey(BaseModel): """ -@docs_group('Models') class ListOfKeys(BaseModel): model_config = ConfigDict( extra='allow', @@ -1495,7 +1401,6 @@ class ListOfKeys(BaseModel): next_exclusive_start_key: Annotated[str | None, Field(alias='nextExclusiveStartKey', examples=['third-key'])] = None -@docs_group('Models') class ListOfKeysResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1503,7 +1408,6 @@ class ListOfKeysResponse(BaseModel): data: ListOfKeys -@docs_group('Models') class RecordResponse(BaseModel): """The response body contains the value of the record. The content type of the response is determined by the Content-Type header stored with the record. @@ -1515,7 +1419,6 @@ class RecordResponse(BaseModel): ) -@docs_group('Models') class PutRecordRequest(BaseModel): """The request body contains the value to store in the record. The content type should be specified in the Content-Type header. @@ -1527,7 +1430,6 @@ class PutRecordRequest(BaseModel): ) -@docs_group('Models') class DatasetListItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -1544,7 +1446,6 @@ class DatasetListItem(BaseModel): act_run_id: Annotated[str | None, Field(alias='actRunId')] = None -@docs_group('Models') class ListOfDatasets(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -1552,7 +1453,6 @@ class ListOfDatasets(PaginationResponse): items: list[DatasetListItem] -@docs_group('Models') class ListOfDatasetsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1560,7 +1460,6 @@ class ListOfDatasetsResponse(BaseModel): data: ListOfDatasets -@docs_group('Models') class DatasetStats(BaseModel): model_config = ConfigDict( extra='allow', @@ -1570,7 +1469,6 @@ class DatasetStats(BaseModel): storage_bytes: Annotated[int, Field(alias='storageBytes', examples=[783])] -@docs_group('Models') class Dataset(BaseModel): model_config = ConfigDict( extra='allow', @@ -1632,7 +1530,6 @@ class Dataset(BaseModel): stats: DatasetStats | None = None -@docs_group('Models') class DatasetResponse(BaseModel): """Response containing dataset metadata.""" @@ -1642,7 +1539,6 @@ class DatasetResponse(BaseModel): data: Dataset -@docs_group('Models') class UpdateDatasetRequest(BaseModel): model_config = ConfigDict( extra='allow', @@ -1651,7 +1547,6 @@ class UpdateDatasetRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None -@docs_group('Models') class PutItemsRequest(BaseModel): """The request body containing the item(s) to add to the dataset. Can be a single object or an array of objects. Each object represents one dataset item. @@ -1663,7 +1558,6 @@ class PutItemsRequest(BaseModel): ) -@docs_group('Models') class ValidationError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1690,7 +1584,6 @@ class ValidationError(BaseModel): """ -@docs_group('Models') class InvalidItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -1705,7 +1598,6 @@ class InvalidItem(BaseModel): """ -@docs_group('Models') class SchemaValidationErrorData(BaseModel): model_config = ConfigDict( extra='allow', @@ -1716,7 +1608,6 @@ class SchemaValidationErrorData(BaseModel): """ -@docs_group('Models') class DatasetSchemaValidationError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1732,7 +1623,6 @@ class DatasetSchemaValidationError(BaseModel): data: SchemaValidationErrorData | None = None -@docs_group('Models') class PutItemResponseError(BaseModel): model_config = ConfigDict( extra='allow', @@ -1740,7 +1630,6 @@ class PutItemResponseError(BaseModel): error: DatasetSchemaValidationError -@docs_group('Models') class DatasetFieldStatistics(BaseModel): model_config = ConfigDict( extra='allow', @@ -1763,7 +1652,6 @@ class DatasetFieldStatistics(BaseModel): """ -@docs_group('Models') class DatasetStatistics(BaseModel): model_config = ConfigDict( extra='allow', @@ -1774,7 +1662,6 @@ class DatasetStatistics(BaseModel): """ -@docs_group('Models') class DatasetStatisticsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -1782,7 +1669,6 @@ class DatasetStatisticsResponse(BaseModel): data: DatasetStatistics -@docs_group('Models') class RequestQueueShort(BaseModel): """A shortened request queue object for list responses.""" @@ -1847,7 +1733,6 @@ class RequestQueueShort(BaseModel): """ -@docs_group('Models') class ListOfRequestQueues(PaginationResponse): """A paginated list of request queues.""" @@ -1860,7 +1745,6 @@ class ListOfRequestQueues(PaginationResponse): """ -@docs_group('Models') class ListOfRequestQueuesResponse(BaseModel): """Response containing a list of request queues.""" @@ -1870,7 +1754,6 @@ class ListOfRequestQueuesResponse(BaseModel): data: ListOfRequestQueues -@docs_group('Models') class RequestQueueStats(BaseModel): """Statistics about request queue operations and storage.""" @@ -1899,7 +1782,6 @@ class RequestQueueStats(BaseModel): """ -@docs_group('Models') class RequestQueue(BaseModel): """A request queue object containing metadata and statistics.""" @@ -1956,7 +1838,6 @@ class RequestQueue(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None -@docs_group('Models') class RequestQueueResponse(BaseModel): """Response containing request queue data.""" @@ -1966,7 +1847,6 @@ class RequestQueueResponse(BaseModel): data: RequestQueue -@docs_group('Models') class UpdateRequestQueueRequest(BaseModel): """Request object for updating a request queue.""" @@ -1980,7 +1860,6 @@ class UpdateRequestQueueRequest(BaseModel): general_access: Annotated[GeneralAccess | None, Field(alias='generalAccess')] = None -@docs_group('Models') class RequestDraft(BaseModel): """A request that failed to be processed during a request queue operation and can be retried.""" @@ -2005,7 +1884,6 @@ class RequestDraft(BaseModel): """ -@docs_group('Models') class AddedRequest(BaseModel): """Information about a request that was successfully added to a request queue.""" @@ -2030,7 +1908,6 @@ class AddedRequest(BaseModel): """ -@docs_group('Models') class BatchAddResult(BaseModel): """Result of a batch add operation containing successfully processed and failed requests.""" @@ -2047,7 +1924,6 @@ class BatchAddResult(BaseModel): """ -@docs_group('Models') class BatchAddResponse(BaseModel): """Response containing the result of a batch add operation.""" @@ -2057,7 +1933,6 @@ class BatchAddResponse(BaseModel): data: BatchAddResult -@docs_group('Models') class DeletedRequest(BaseModel): """Confirmation of a request that was successfully deleted from a request queue.""" @@ -2074,7 +1949,6 @@ class DeletedRequest(BaseModel): """ -@docs_group('Models') class BatchDeleteResult(BaseModel): """Result of a batch delete operation containing successfully deleted and failed requests.""" @@ -2091,7 +1965,6 @@ class BatchDeleteResult(BaseModel): """ -@docs_group('Models') class BatchDeleteResponse(BaseModel): """Response containing the result of a batch delete operation.""" @@ -2101,7 +1974,6 @@ class BatchDeleteResponse(BaseModel): data: BatchDeleteResult -@docs_group('Models') class UnlockRequestsResult(BaseModel): """Result of unlocking requests in the request queue.""" @@ -2114,7 +1986,6 @@ class UnlockRequestsResult(BaseModel): """ -@docs_group('Models') class UnlockRequestsResponse(BaseModel): """Response containing the result of unlocking requests.""" @@ -2124,7 +1995,6 @@ class UnlockRequestsResponse(BaseModel): data: UnlockRequestsResult -@docs_group('Models') class RequestUserData(BaseModel): """Custom user data attached to the request. Can contain arbitrary fields.""" @@ -2141,7 +2011,6 @@ class RequestUserData(BaseModel): """ -@docs_group('Models') class Request(BaseModel): """A request stored in the request queue, including its metadata and processing state.""" @@ -2195,7 +2064,6 @@ class Request(BaseModel): """ -@docs_group('Models') class ListOfRequests(BaseModel): """A paginated list of requests from the request queue.""" @@ -2220,7 +2088,6 @@ class ListOfRequests(BaseModel): """ -@docs_group('Models') class ListOfRequestsResponse(BaseModel): """Response containing a list of requests from the request queue.""" @@ -2230,7 +2097,6 @@ class ListOfRequestsResponse(BaseModel): data: ListOfRequests -@docs_group('Models') class RequestRegistration(BaseModel): """Result of registering a request in the request queue, either by adding a new request or updating an existing one.""" @@ -2251,7 +2117,6 @@ class RequestRegistration(BaseModel): """ -@docs_group('Models') class AddRequestResponse(BaseModel): """Response containing the result of adding a request to the request queue.""" @@ -2261,7 +2126,6 @@ class AddRequestResponse(BaseModel): data: RequestRegistration -@docs_group('Models') class RequestResponse(BaseModel): """Response containing a single request from the request queue.""" @@ -2271,7 +2135,6 @@ class RequestResponse(BaseModel): data: Request -@docs_group('Models') class UpdateRequestResponse(BaseModel): """Response containing the result of updating a request in the request queue.""" @@ -2281,7 +2144,6 @@ class UpdateRequestResponse(BaseModel): data: RequestRegistration -@docs_group('Models') class HeadRequest(BaseModel): """A request from the request queue head without lock information.""" @@ -2310,7 +2172,6 @@ class HeadRequest(BaseModel): """ -@docs_group('Models') class RequestQueueHead(BaseModel): """A batch of requests from the request queue head without locking.""" @@ -2335,7 +2196,6 @@ class RequestQueueHead(BaseModel): """ -@docs_group('Models') class HeadResponse(BaseModel): """Response containing requests from the request queue head without locking.""" @@ -2345,7 +2205,6 @@ class HeadResponse(BaseModel): data: RequestQueueHead -@docs_group('Models') class LockedHeadRequest(BaseModel): """A request from the request queue head that has been locked for processing.""" @@ -2378,7 +2237,6 @@ class LockedHeadRequest(BaseModel): """ -@docs_group('Models') class LockedRequestQueueHead(BaseModel): """A batch of locked requests from the request queue head.""" @@ -2415,7 +2273,6 @@ class LockedRequestQueueHead(BaseModel): """ -@docs_group('Models') class HeadAndLockResponse(BaseModel): """Response containing locked requests from the request queue head.""" @@ -2425,7 +2282,6 @@ class HeadAndLockResponse(BaseModel): data: LockedRequestQueueHead -@docs_group('Models') class RequestLockInfo(BaseModel): """Information about a request lock.""" @@ -2438,7 +2294,6 @@ class RequestLockInfo(BaseModel): """ -@docs_group('Models') class ProlongRequestLockResponse(BaseModel): """Response containing updated lock information after prolonging a request lock.""" @@ -2448,7 +2303,6 @@ class ProlongRequestLockResponse(BaseModel): data: RequestLockInfo -@docs_group('Models') class WebhookCreate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2470,7 +2324,6 @@ class WebhookCreate(BaseModel): should_interpolate_strings: Annotated[bool | None, Field(alias='shouldInterpolateStrings', examples=[False])] = None -@docs_group('Models') class WebhookResponse(BaseModel): """Response containing webhook data.""" @@ -2480,7 +2333,6 @@ class WebhookResponse(BaseModel): data: Webhook -@docs_group('Models') class WebhookUpdate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2503,7 +2355,6 @@ class WebhookUpdate(BaseModel): should_interpolate_strings: Annotated[bool | None, Field(alias='shouldInterpolateStrings', examples=[False])] = None -@docs_group('Models') class EventData(BaseModel): model_config = ConfigDict( extra='allow', @@ -2512,7 +2363,6 @@ class EventData(BaseModel): actor_run_id: Annotated[str, Field(alias='actorRunId', examples=['JgwXN9BdwxGcu9MMF'])] -@docs_group('Models') class Call(BaseModel): model_config = ConfigDict( extra='allow', @@ -2526,7 +2376,6 @@ class Call(BaseModel): response_body: Annotated[str | None, Field(alias='responseBody', examples=['{"foo": "bar"}'])] = None -@docs_group('Models') class WebhookDispatch(BaseModel): model_config = ConfigDict( extra='allow', @@ -2541,7 +2390,6 @@ class WebhookDispatch(BaseModel): calls: Annotated[list[Call] | None, Field(title='calls')] = None -@docs_group('Models') class TestWebhookResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2549,7 +2397,6 @@ class TestWebhookResponse(BaseModel): data: WebhookDispatch -@docs_group('Models') class ListOfWebhookDispatches(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2557,7 +2404,6 @@ class ListOfWebhookDispatches(PaginationResponse): items: list[WebhookDispatch] -@docs_group('Models') class WebhookDispatchList(BaseModel): model_config = ConfigDict( extra='allow', @@ -2565,7 +2411,6 @@ class WebhookDispatchList(BaseModel): data: ListOfWebhookDispatches | None = None -@docs_group('Models') class WebhookDispatchResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2573,7 +2418,6 @@ class WebhookDispatchResponse(BaseModel): data: WebhookDispatch -@docs_group('Models') class ScheduleActionType(StrEnum): """Type of action to perform when the schedule triggers.""" @@ -2581,7 +2425,6 @@ class ScheduleActionType(StrEnum): RUN_ACTOR_TASK = 'RUN_ACTOR_TASK' -@docs_group('Models') class ScheduleAction(BaseModel): model_config = ConfigDict( extra='allow', @@ -2591,7 +2434,6 @@ class ScheduleAction(BaseModel): actor_id: Annotated[str, Field(alias='actorId', examples=['HKhKmiCMrDgu9eXeE'])] -@docs_group('Models') class ScheduleShort(BaseModel): model_config = ConfigDict( extra='allow', @@ -2610,7 +2452,6 @@ class ScheduleShort(BaseModel): actions: list[ScheduleAction] -@docs_group('Models') class ListOfSchedules(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2618,7 +2459,6 @@ class ListOfSchedules(PaginationResponse): items: list[ScheduleShort] -@docs_group('Models') class ListOfSchedulesResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2626,7 +2466,6 @@ class ListOfSchedulesResponse(BaseModel): data: ListOfSchedules -@docs_group('Models') class ScheduleActionsRunInput(BaseModel): model_config = ConfigDict( extra='allow', @@ -2635,7 +2474,6 @@ class ScheduleActionsRunInput(BaseModel): content_type: Annotated[str | None, Field(alias='contentType', examples=['application/json; charset=utf-8'])] = None -@docs_group('Models') class ScheduleActionsRunOptions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2646,7 +2484,6 @@ class ScheduleActionsRunOptions(BaseModel): restart_on_error: Annotated[bool | None, Field(alias='restartOnError', examples=[False])] = None -@docs_group('Models') class ScheduleCreateActions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2657,7 +2494,6 @@ class ScheduleCreateActions(BaseModel): run_options: Annotated[ScheduleActionsRunOptions | None, Field(alias='runOptions')] = None -@docs_group('Models') class ScheduleCreate(BaseModel): model_config = ConfigDict( extra='allow', @@ -2671,7 +2507,6 @@ class ScheduleCreate(BaseModel): actions: list[ScheduleCreateActions] | None = None -@docs_group('Models') class ScheduleActions(BaseModel): model_config = ConfigDict( extra='allow', @@ -2683,7 +2518,6 @@ class ScheduleActions(BaseModel): run_options: Annotated[ScheduleActionsRunOptions | None, Field(alias='runOptions')] = None -@docs_group('Models') class Schedule(BaseModel): model_config = ConfigDict( extra='allow', @@ -2703,7 +2537,6 @@ class Schedule(BaseModel): actions: list[ScheduleActions] -@docs_group('Models') class ScheduleResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2711,7 +2544,6 @@ class ScheduleResponse(BaseModel): data: Schedule -@docs_group('Models') class ScheduleInvoked(BaseModel): model_config = ConfigDict( extra='allow', @@ -2721,7 +2553,6 @@ class ScheduleInvoked(BaseModel): created_at: Annotated[AwareDatetime, Field(alias='createdAt', examples=['2019-03-26T12:28:00.370Z'])] -@docs_group('Models') class ScheduleLogResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2729,7 +2560,6 @@ class ScheduleLogResponse(BaseModel): data: list[ScheduleInvoked] -@docs_group('Models') class CurrentPricingInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2737,7 +2567,6 @@ class CurrentPricingInfo(BaseModel): pricing_model: Annotated[str, Field(alias='pricingModel', examples=['FREE'])] -@docs_group('Models') class StoreListActor(BaseModel): model_config = ConfigDict( extra='allow', @@ -2765,7 +2594,6 @@ class StoreListActor(BaseModel): """ -@docs_group('Models') class ListOfStoreActors(PaginationResponse): model_config = ConfigDict( extra='allow', @@ -2773,7 +2601,6 @@ class ListOfStoreActors(PaginationResponse): items: list[StoreListActor] -@docs_group('Models') class ListOfActorsInStoreResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2781,7 +2608,6 @@ class ListOfActorsInStoreResponse(BaseModel): data: ListOfStoreActors -@docs_group('Models') class Profile(BaseModel): model_config = ConfigDict( extra='allow', @@ -2796,7 +2622,6 @@ class Profile(BaseModel): twitter_username: Annotated[str | None, Field(alias='twitterUsername', examples=['@BillGates'])] = None -@docs_group('Models') class UserPublicInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2805,7 +2630,6 @@ class UserPublicInfo(BaseModel): profile: Profile -@docs_group('Models') class PublicUserDataResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2813,7 +2637,6 @@ class PublicUserDataResponse(BaseModel): data: UserPublicInfo -@docs_group('Models') class ProxyGroup(BaseModel): model_config = ConfigDict( extra='allow', @@ -2823,7 +2646,6 @@ class ProxyGroup(BaseModel): available_count: Annotated[int, Field(alias='availableCount', examples=[10])] -@docs_group('Models') class Proxy(BaseModel): model_config = ConfigDict( extra='allow', @@ -2832,7 +2654,6 @@ class Proxy(BaseModel): groups: list[ProxyGroup] -@docs_group('Models') class Plan(BaseModel): model_config = ConfigDict( extra='allow', @@ -2872,7 +2693,6 @@ class Plan(BaseModel): available_add_ons: Annotated[list[str], Field(alias='availableAddOns', examples=[[]])] -@docs_group('Models') class EffectivePlatformFeature(BaseModel): model_config = ConfigDict( extra='allow', @@ -2894,7 +2714,6 @@ class EffectivePlatformFeature(BaseModel): ] = None -@docs_group('Models') class EffectivePlatformFeatures(BaseModel): model_config = ConfigDict( extra='allow', @@ -2911,7 +2730,6 @@ class EffectivePlatformFeatures(BaseModel): actors_public_developer: Annotated[EffectivePlatformFeature, Field(alias='ACTORS_PUBLIC_DEVELOPER')] -@docs_group('Models') class UserPrivateInfo(BaseModel): model_config = ConfigDict( extra='allow', @@ -2927,7 +2745,6 @@ class UserPrivateInfo(BaseModel): is_paying: Annotated[bool, Field(alias='isPaying', examples=[True])] -@docs_group('Models') class PrivateUserDataResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -2935,7 +2752,6 @@ class PrivateUserDataResponse(BaseModel): data: UserPrivateInfo -@docs_group('Models') class UsageCycle(BaseModel): model_config = ConfigDict( extra='allow', @@ -2944,7 +2760,6 @@ class UsageCycle(BaseModel): end_at: Annotated[AwareDatetime, Field(alias='endAt', examples=['2022-11-01T23:59:59.999Z'])] -@docs_group('Models') class PriceTiers(BaseModel): model_config = ConfigDict( extra='allow', @@ -2956,7 +2771,6 @@ class PriceTiers(BaseModel): price_usd: Annotated[float, Field(alias='priceUsd', examples=[0])] -@docs_group('Models') class UsageItem(BaseModel): model_config = ConfigDict( extra='allow', @@ -2970,7 +2784,6 @@ class UsageItem(BaseModel): price_tiers: Annotated[list[PriceTiers] | None, Field(alias='priceTiers')] = None -@docs_group('Models') class DailyServiceUsages(BaseModel): model_config = ConfigDict( extra='allow', @@ -2980,7 +2793,6 @@ class DailyServiceUsages(BaseModel): total_usage_credits_usd: Annotated[float, Field(alias='totalUsageCreditsUsd', examples=[0.0474385791970591])] -@docs_group('Models') class MonthlyUsage(BaseModel): model_config = ConfigDict( extra='allow', @@ -2996,7 +2808,6 @@ class MonthlyUsage(BaseModel): ] -@docs_group('Models') class MonthlyUsageResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -3004,7 +2815,6 @@ class MonthlyUsageResponse(BaseModel): data: MonthlyUsage -@docs_group('Models') class Limits(BaseModel): model_config = ConfigDict( extra='allow', @@ -3026,7 +2836,6 @@ class Limits(BaseModel): data_retention_days: Annotated[int, Field(alias='dataRetentionDays', examples=[90])] -@docs_group('Models') class Current(BaseModel): model_config = ConfigDict( extra='allow', @@ -3045,7 +2854,6 @@ class Current(BaseModel): team_account_seat_count: Annotated[int, Field(alias='teamAccountSeatCount', examples=[5])] -@docs_group('Models') class AccountLimits(BaseModel): model_config = ConfigDict( extra='allow', @@ -3055,7 +2863,6 @@ class AccountLimits(BaseModel): current: Current -@docs_group('Models') class LimitsResponse(BaseModel): model_config = ConfigDict( extra='allow', @@ -3063,7 +2870,6 @@ class LimitsResponse(BaseModel): data: AccountLimits -@docs_group('Models') class UpdateLimitsRequest(BaseModel): model_config = ConfigDict( extra='allow', From 81b7b42ec7dc9a2b552640ec6354ff0da12234a4 Mon Sep 17 00:00:00 2001 From: Vlada Dusek Date: Wed, 25 Feb 2026 10:56:04 +0100 Subject: [PATCH 7/7] Address comments --- src/apify_client/_apify_client.py | 10 +-- src/apify_client/_client_registry.py | 8 -- src/apify_client/_docs.py | 8 +- .../_resource_clients/__init__.py | 8 -- .../_resource_clients/_resource_client.py | 3 + src/apify_client/_resource_clients/actor.py | 8 +- .../_resource_clients/actor_collection.py | 6 +- .../_resource_clients/actor_env_var.py | 8 +- .../actor_env_var_collection.py | 8 +- .../_resource_clients/actor_version.py | 8 +- .../actor_version_collection.py | 8 +- src/apify_client/_resource_clients/build.py | 8 +- .../_resource_clients/build_collection.py | 6 +- src/apify_client/_resource_clients/dataset.py | 10 +-- .../_resource_clients/dataset_collection.py | 6 +- .../_resource_clients/key_value_store.py | 8 +- .../key_value_store_collection.py | 8 +- src/apify_client/_resource_clients/log.py | 6 +- .../_resource_clients/request_queue.py | 8 +- .../request_queue_collection.py | 8 +- src/apify_client/_resource_clients/run.py | 44 ++++++----- .../_resource_clients/run_collection.py | 6 +- .../_resource_clients/schedule.py | 8 +- .../_resource_clients/schedule_collection.py | 6 +- .../_resource_clients/store_collection.py | 6 +- src/apify_client/_resource_clients/task.py | 8 +- .../_resource_clients/task_collection.py | 6 +- src/apify_client/_resource_clients/user.py | 8 +- src/apify_client/_resource_clients/webhook.py | 8 +- .../_resource_clients/webhook_collection.py | 6 +- .../_resource_clients/webhook_dispatch.py | 6 +- .../webhook_dispatch_collection.py | 6 +- ..._watcher.py => _status_message_watcher.py} | 73 ++++++++++-------- .../streamed_log.py => _streamed_log.py} | 76 ++++++++++++------- src/apify_client/errors.py | 4 +- tests/integration/test_webhook.py | 51 ++++++++----- tests/unit/test_logging.py | 15 ++-- website/transformDocs.js | 21 ++--- 38 files changed, 280 insertions(+), 229 deletions(-) rename src/apify_client/{_resource_clients/status_message_watcher.py => _status_message_watcher.py} (69%) rename src/apify_client/{_resource_clients/streamed_log.py => _streamed_log.py} (75%) diff --git a/src/apify_client/_apify_client.py b/src/apify_client/_apify_client.py index c726887b..17651f15 100644 --- a/src/apify_client/_apify_client.py +++ b/src/apify_client/_apify_client.py @@ -53,12 +53,8 @@ ScheduleClientAsync, ScheduleCollectionClient, ScheduleCollectionClientAsync, - StatusMessageWatcherAsync, - StatusMessageWatcherSync, StoreCollectionClient, StoreCollectionClientAsync, - StreamedLogAsync, - StreamedLogSync, TaskClient, TaskClientAsync, TaskCollectionClient, @@ -181,8 +177,6 @@ def __init__( key_value_store_client=KeyValueStoreClient, key_value_store_collection_client=KeyValueStoreCollectionClient, log_client=LogClient, - status_message_watcher=StatusMessageWatcherSync, - streamed_log=StreamedLogSync, request_queue_client=RequestQueueClient, request_queue_collection_client=RequestQueueCollectionClient, run_client=RunClient, @@ -386,6 +380,7 @@ class ApifyClientAsync: from apify_client import ApifyClientAsync + async def main() -> None: client = ApifyClientAsync(token='MY-APIFY-TOKEN') @@ -400,6 +395,7 @@ async def main() -> None: for item in items: print(item) + asyncio.run(main()) ``` """ @@ -475,8 +471,6 @@ def __init__( key_value_store_client=KeyValueStoreClientAsync, key_value_store_collection_client=KeyValueStoreCollectionClientAsync, log_client=LogClientAsync, - status_message_watcher=StatusMessageWatcherAsync, - streamed_log=StreamedLogAsync, request_queue_client=RequestQueueClientAsync, request_queue_collection_client=RequestQueueCollectionClientAsync, run_client=RunClientAsync, diff --git a/src/apify_client/_client_registry.py b/src/apify_client/_client_registry.py index 3564a458..5f3c7994 100644 --- a/src/apify_client/_client_registry.py +++ b/src/apify_client/_client_registry.py @@ -43,12 +43,8 @@ ScheduleClientAsync, ScheduleCollectionClient, ScheduleCollectionClientAsync, - StatusMessageWatcherAsync, - StatusMessageWatcherSync, StoreCollectionClient, StoreCollectionClientAsync, - StreamedLogAsync, - StreamedLogSync, TaskClient, TaskClientAsync, TaskCollectionClient, @@ -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] @@ -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] diff --git a/src/apify_client/_docs.py b/src/apify_client/_docs.py index da26df6a..fa5983fa 100644 --- a/src/apify_client/_docs.py +++ b/src/apify_client/_docs.py @@ -3,13 +3,15 @@ from collections.abc import Callable from typing import Any, Literal, TypeVar -# The order of the rendered API groups is defined in the website/docusaurus.config.js file. +# 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', - 'Resource clients', 'HTTP clients', - 'Models', + 'Resource clients', 'Errors', + 'Models', + 'Other', ] T = TypeVar('T', bound=Callable[..., Any]) diff --git a/src/apify_client/_resource_clients/__init__.py b/src/apify_client/_resource_clients/__init__.py index d95ec9f9..e818ce34 100644 --- a/src/apify_client/_resource_clients/__init__.py +++ b/src/apify_client/_resource_clients/__init__.py @@ -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 @@ -67,14 +65,8 @@ 'ScheduleClientAsync', 'ScheduleCollectionClient', 'ScheduleCollectionClientAsync', - 'StatusMessageWatcher', - 'StatusMessageWatcherAsync', - 'StatusMessageWatcherSync', 'StoreCollectionClient', 'StoreCollectionClientAsync', - 'StreamedLog', - 'StreamedLogAsync', - 'StreamedLogSync', 'TaskClient', 'TaskClientAsync', 'TaskCollectionClient', diff --git a/src/apify_client/_resource_clients/_resource_client.py b/src/apify_client/_resource_clients/_resource_client.py index 7b2020ff..5f271ee8 100644 --- a/src/apify_client/_resource_clients/_resource_client.py +++ b/src/apify_client/_resource_clients/_resource_client.py @@ -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 @@ -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.""" @@ -286,6 +288,7 @@ def _wait_for_finish( return actor_job +@docs_group('Resource clients') class ResourceClientAsync(ResourceClientBase): """Base class for asynchronous resource clients.""" diff --git a/src/apify_client/_resource_clients/actor.py b/src/apify_client/_resource_clients/actor.py index d51de5c2..c7000e66 100644 --- a/src/apify_client/_resource_clients/actor.py +++ b/src/apify_client/_resource_clients/actor.py @@ -52,8 +52,8 @@ class ActorClient(ResourceClient): """Sub-client for managing a specific Actor. - Provides methods to get, update, delete, build, and start runs of an Actor. - Obtain an instance via `ApifyClient.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__( @@ -516,8 +516,8 @@ def validate_input( class ActorClientAsync(ResourceClientAsync): """Sub-client for managing a specific Actor. - Provides methods to get, update, delete, build, and start runs of an Actor. - Obtain an instance via `ApifyClientAsync.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__( diff --git a/src/apify_client/_resource_clients/actor_collection.py b/src/apify_client/_resource_clients/actor_collection.py index 86c74b38..255d9f9c 100644 --- a/src/apify_client/_resource_clients/actor_collection.py +++ b/src/apify_client/_resource_clients/actor_collection.py @@ -16,7 +16,8 @@ class ActorCollectionClient(ResourceClient): """Sub-client for the Actor collection. - Provides methods to list and create Actors. Obtain an instance via `ApifyClient.actors`. + 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: @@ -147,7 +148,8 @@ def create( class ActorCollectionClientAsync(ResourceClientAsync): """Sub-client for the Actor collection. - Provides methods to list and create Actors. Obtain an instance via `ApifyClientAsync.actors`. + 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: diff --git a/src/apify_client/_resource_clients/actor_env_var.py b/src/apify_client/_resource_clients/actor_env_var.py index d9d0f7fc..ea5acce9 100644 --- a/src/apify_client/_resource_clients/actor_env_var.py +++ b/src/apify_client/_resource_clients/actor_env_var.py @@ -26,8 +26,8 @@ def get_actor_env_var_representation( class ActorEnvVarClient(ResourceClient): """Sub-client for managing a specific Actor environment variable. - Provides methods to get, update, and delete an environment variable. - Obtain an instance via `ActorVersionClient.env_var`. + 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: @@ -87,8 +87,8 @@ def delete(self) -> None: class ActorEnvVarClientAsync(ResourceClientAsync): """Sub-client for managing a specific Actor environment variable. - Provides methods to get, update, and delete an environment variable. - Obtain an instance via `ActorVersionClientAsync.env_var`. + 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: diff --git a/src/apify_client/_resource_clients/actor_env_var_collection.py b/src/apify_client/_resource_clients/actor_env_var_collection.py index b51a2731..4a82fb6a 100644 --- a/src/apify_client/_resource_clients/actor_env_var_collection.py +++ b/src/apify_client/_resource_clients/actor_env_var_collection.py @@ -13,8 +13,8 @@ class ActorEnvVarCollectionClient(ResourceClient): """Sub-client for the Actor environment variable collection. - Provides methods to list and create environment variables. - Obtain an instance via `ActorVersionClient.env_vars`. + 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: @@ -65,8 +65,8 @@ def create( class ActorEnvVarCollectionClientAsync(ResourceClientAsync): """Sub-client for the Actor environment variable collection. - Provides methods to list and create environment variables. - Obtain an instance via `ActorVersionClientAsync.env_vars`. + 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: diff --git a/src/apify_client/_resource_clients/actor_version.py b/src/apify_client/_resource_clients/actor_version.py index 96e1d2cb..ce53e521 100644 --- a/src/apify_client/_resource_clients/actor_version.py +++ b/src/apify_client/_resource_clients/actor_version.py @@ -21,8 +21,8 @@ class ActorVersionClient(ResourceClient): """Sub-client for managing a specific Actor version. - Provides methods to get, update, and delete an Actor version. - Obtain an instance via `ActorClient.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__( @@ -131,8 +131,8 @@ def env_var(self, env_var_name: str) -> ActorEnvVarClient: class ActorVersionClientAsync(ResourceClientAsync): """Sub-client for managing a specific Actor version. - Provides methods to get, update, and delete an Actor version. - Obtain an instance via `ActorClientAsync.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__( diff --git a/src/apify_client/_resource_clients/actor_version_collection.py b/src/apify_client/_resource_clients/actor_version_collection.py index aad3e964..bde7517b 100644 --- a/src/apify_client/_resource_clients/actor_version_collection.py +++ b/src/apify_client/_resource_clients/actor_version_collection.py @@ -19,8 +19,8 @@ class ActorVersionCollectionClient(ResourceClient): """Sub-client for the Actor version collection. - Provides methods to list and create Actor versions. - Obtain an instance via `ActorClient.versions`. + Provides methods to manage Actor versions, e.g. list or create them. Obtain an instance via an appropriate method + on the `ActorClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -95,8 +95,8 @@ def create( class ActorVersionCollectionClientAsync(ResourceClientAsync): """Sub-client for the Actor version collection. - Provides methods to list and create Actor versions. - Obtain an instance via `ActorClientAsync.versions`. + Provides methods to manage Actor versions, e.g. list or create them. Obtain an instance via an appropriate method + on the `ActorClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/build.py b/src/apify_client/_resource_clients/build.py index 5578587f..7416b614 100644 --- a/src/apify_client/_resource_clients/build.py +++ b/src/apify_client/_resource_clients/build.py @@ -17,8 +17,8 @@ class BuildClient(ResourceClient): """Sub-client for managing a specific Actor build. - Provides methods to get, delete, abort, and wait for finish of an Actor build. - Obtain an instance via `ApifyClient.build`. + Provides methods to manage a specific Actor build, e.g. get it, abort it, or wait for it to finish. Obtain an + instance via an appropriate method on the `ApifyClient` class. """ def __init__( @@ -119,8 +119,8 @@ def log(self) -> LogClient: class BuildClientAsync(ResourceClientAsync): """Sub-client for managing a specific Actor build. - Provides methods to get, delete, abort, and wait for finish of an Actor build. - Obtain an instance via `ApifyClientAsync.build`. + Provides methods to manage a specific Actor build, e.g. get it, abort it, or wait for it to finish. Obtain an + instance via an appropriate method on the `ApifyClientAsync` class. """ def __init__( diff --git a/src/apify_client/_resource_clients/build_collection.py b/src/apify_client/_resource_clients/build_collection.py index 2ac5d8ea..1a395a7f 100644 --- a/src/apify_client/_resource_clients/build_collection.py +++ b/src/apify_client/_resource_clients/build_collection.py @@ -11,7 +11,8 @@ class BuildCollectionClient(ResourceClient): """Sub-client for the Actor build collection. - Provides methods to list Actor builds. Obtain an instance via `ApifyClient.builds`. + Provides methods to manage Actor builds, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -49,7 +50,8 @@ def list( class BuildCollectionClientAsync(ResourceClientAsync): """Sub-client for the Actor build collection. - Provides methods to list Actor builds. Obtain an instance via `ApifyClientAsync.builds`. + Provides methods to manage Actor builds, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/dataset.py b/src/apify_client/_resource_clients/dataset.py index 92e49cd0..2720a6cc 100644 --- a/src/apify_client/_resource_clients/dataset.py +++ b/src/apify_client/_resource_clients/dataset.py @@ -29,7 +29,7 @@ from apify_client._models import GeneralAccess -@docs_group('Models') +@docs_group('Other') @dataclass class DatasetItemsPage: """A page of dataset items returned by the `list_items` method. @@ -62,8 +62,8 @@ class DatasetItemsPage: class DatasetClient(ResourceClient): """Sub-client for managing a specific dataset. - Provides methods to get, update, delete, push items, list items, iterate items, and stream items of a dataset. - Obtain an instance via `ApifyClient.dataset`. + Provides methods to manage a specific dataset, e.g. get it, update it, or download its items. Obtain an instance + via an appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -683,8 +683,8 @@ def create_items_public_url( class DatasetClientAsync(ResourceClientAsync): """Sub-client for managing a specific dataset. - Provides methods to get, update, delete, push items, list items, iterate items, and stream items of a dataset. - Obtain an instance via `ApifyClientAsync.dataset`. + Provides methods to manage a specific dataset, e.g. get it, update it, or download its items. Obtain an instance + via an appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/dataset_collection.py b/src/apify_client/_resource_clients/dataset_collection.py index b7f847bb..2322fd67 100644 --- a/src/apify_client/_resource_clients/dataset_collection.py +++ b/src/apify_client/_resource_clients/dataset_collection.py @@ -12,7 +12,8 @@ class DatasetCollectionClient(ResourceClient): """Sub-client for the dataset collection. - Provides methods to list and get or create datasets. Obtain an instance via `ApifyClient.datasets`. + Provides methods to manage the dataset collection, e.g. list or create datasets. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -63,7 +64,8 @@ def get_or_create(self, *, name: str | None = None, schema: dict | None = None) class DatasetCollectionClientAsync(ResourceClientAsync): """Sub-client for the dataset collection. - Provides methods to list and get or create datasets. Obtain an instance via `ApifyClientAsync.datasets`. + Provides methods to manage the dataset collection, e.g. list or create datasets. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/key_value_store.py b/src/apify_client/_resource_clients/key_value_store.py index 66a9c70d..03119c5f 100644 --- a/src/apify_client/_resource_clients/key_value_store.py +++ b/src/apify_client/_resource_clients/key_value_store.py @@ -73,8 +73,8 @@ def _parse_get_record_response(response: Response) -> Any: class KeyValueStoreClient(ResourceClient): """Sub-client for managing a specific key-value store. - Provides methods to get, update, delete, and get/set/delete records of a key-value store. - Obtain an instance via `ApifyClient.key_value_store`. + Provides methods to manage a specific key-value store, e.g. get it, update it, or manage its records. Obtain an + instance via an appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -457,8 +457,8 @@ def create_keys_public_url( class KeyValueStoreClientAsync(ResourceClientAsync): """Sub-client for managing a specific key-value store. - Provides methods to get, update, delete, and get/set/delete records of a key-value store. - Obtain an instance via `ApifyClientAsync.key_value_store`. + Provides methods to manage a specific key-value store, e.g. get it, update it, or manage its records. Obtain an + instance via an appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/key_value_store_collection.py b/src/apify_client/_resource_clients/key_value_store_collection.py index 90f73313..f693952d 100644 --- a/src/apify_client/_resource_clients/key_value_store_collection.py +++ b/src/apify_client/_resource_clients/key_value_store_collection.py @@ -17,8 +17,8 @@ class KeyValueStoreCollectionClient(ResourceClient): """Sub-client for the key-value store collection. - Provides methods to list and get or create key-value stores. - Obtain an instance via `ApifyClient.key_value_stores`. + Provides methods to manage the key-value store collection, e.g. list or create key-value stores. Obtain an instance + via an appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -74,8 +74,8 @@ def get_or_create( class KeyValueStoreCollectionClientAsync(ResourceClientAsync): """Sub-client for the key-value store collection. - Provides methods to list and get or create key-value stores. - Obtain an instance via `ApifyClientAsync.key_value_stores`. + Provides methods to manage the key-value store collection, e.g. list or create key-value stores. Obtain an instance + via an appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/log.py b/src/apify_client/_resource_clients/log.py index dbd7a80a..07493ab9 100644 --- a/src/apify_client/_resource_clients/log.py +++ b/src/apify_client/_resource_clients/log.py @@ -18,7 +18,8 @@ class LogClient(ResourceClient): """Sub-client for managing a specific log. - Provides methods to get and stream logs. Obtain an instance via `ApifyClient.log`. + Provides methods to manage logs, e.g. get or stream them. Obtain an instance via an appropriate method on the + `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -109,7 +110,8 @@ def stream(self, *, raw: bool = False) -> Iterator[impit.Response | None]: class LogClientAsync(ResourceClientAsync): """Sub-client for managing a specific log. - Provides methods to get and stream logs. Obtain an instance via `ApifyClientAsync.log`. + Provides methods to manage logs, e.g. get or stream them. Obtain an instance via an appropriate method on the + `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/request_queue.py b/src/apify_client/_resource_clients/request_queue.py index 174dfb1e..408a3d73 100644 --- a/src/apify_client/_resource_clients/request_queue.py +++ b/src/apify_client/_resource_clients/request_queue.py @@ -56,8 +56,8 @@ class RequestQueueClient(ResourceClient): """Sub-client for managing a specific request queue. - Provides methods to get, update, delete, and add/get/list/lock/delete requests of a request queue. - Obtain an instance via `ApifyClient.request_queue`. + Provides methods to manage a specific request queue, e.g. update it, delete it, or manage its requests. Obtain an + instance via an appropriate method on the `ApifyClient` class. """ def __init__( # noqa: D417 @@ -466,8 +466,8 @@ def unlock_requests(self: RequestQueueClient) -> UnlockRequestsResult: class RequestQueueClientAsync(ResourceClientAsync): """Sub-client for managing a specific request queue. - Provides methods to get, update, delete, and add/get/list/lock/delete requests of a request queue. - Obtain an instance via `ApifyClientAsync.request_queue`. + Provides methods to manage a specific request queue, e.g. update it, delete it, or manage its requests. Obtain an + instance via an appropriate method on the `ApifyClientAsync` class. """ def __init__( # noqa: D417 diff --git a/src/apify_client/_resource_clients/request_queue_collection.py b/src/apify_client/_resource_clients/request_queue_collection.py index acf19b14..04ae9afd 100644 --- a/src/apify_client/_resource_clients/request_queue_collection.py +++ b/src/apify_client/_resource_clients/request_queue_collection.py @@ -16,8 +16,8 @@ class RequestQueueCollectionClient(ResourceClient): """Sub-client for the request queue collection. - Provides methods to list and get or create request queues. - Obtain an instance via `ApifyClient.request_queues`. + Provides methods to manage the request queue collection, e.g. list or create request queues. Obtain an instance + via an appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -67,8 +67,8 @@ def get_or_create(self, *, name: str | None = None) -> RequestQueue: class RequestQueueCollectionClientAsync(ResourceClientAsync): """Sub-client for the request queue collection. - Provides methods to list and get or create request queues. - Obtain an instance via `ApifyClientAsync.request_queues`. + Provides methods to manage the request queue collection, e.g. list or create request queues. Obtain an instance + via an appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/run.py b/src/apify_client/_resource_clients/run.py index c01ec6a2..1f7da905 100644 --- a/src/apify_client/_resource_clients/run.py +++ b/src/apify_client/_resource_clients/run.py @@ -11,6 +11,8 @@ from apify_client._logging import create_redirect_logger from apify_client._models import Run, RunResponse from apify_client._resource_clients._resource_client import ResourceClient, ResourceClientAsync +from apify_client._status_message_watcher import StatusMessageWatcher, StatusMessageWatcherAsync +from apify_client._streamed_log import StreamedLog, StreamedLogAsync from apify_client._utils import ( encode_key_value_store_record_value, filter_none_values, @@ -33,10 +35,6 @@ LogClientAsync, RequestQueueClient, RequestQueueClientAsync, - StatusMessageWatcherAsync, - StatusMessageWatcherSync, - StreamedLogAsync, - StreamedLogSync, ) @@ -44,8 +42,8 @@ class RunClient(ResourceClient): """Sub-client for managing a specific Actor run. - Provides methods to get, update, abort, wait for finish, metamorph, resurrect, reboot, and charge an Actor run. - Obtain an instance via `ApifyClient.run`. + Provides methods to manage a specific Actor run, e.g. get it, update it, abort it, or wait for it to finish. + Obtain an instance via an appropriate method on the `ApifyClient` class. """ def __init__( @@ -311,7 +309,12 @@ def log(self) -> LogClient: **self._base_client_kwargs, ) - def get_streamed_log(self, to_logger: logging.Logger | None = None, *, from_start: bool = True) -> StreamedLogSync: + def get_streamed_log( + self, + to_logger: logging.Logger | None = None, + *, + from_start: bool = True, + ) -> StreamedLog: """Get `StreamedLog` instance that can be used to redirect logs. `StreamedLog` can be explicitly started and stopped or used as a context manager. @@ -345,7 +348,7 @@ def get_streamed_log(self, to_logger: logging.Logger | None = None, *, from_star name = ' '.join(part for part in (actor_name, run_id) if part) to_logger = create_redirect_logger(f'apify.{name}') - return self._client_registry.streamed_log(log_client=self.log(), to_logger=to_logger, from_start=from_start) + return StreamedLog(log_client=self.log(), to_logger=to_logger, from_start=from_start) def charge( self, @@ -390,8 +393,10 @@ def charge( ) def get_status_message_watcher( - self, to_logger: logging.Logger | None = None, check_period: timedelta = timedelta(seconds=1) - ) -> StatusMessageWatcherSync: + self, + to_logger: logging.Logger | None = None, + check_period: timedelta = timedelta(seconds=1), + ) -> StatusMessageWatcher: """Get `StatusMessageWatcher` instance that can be used to redirect status and status messages to logs. `StatusMessageWatcher` can be explicitly started and stopped or used as a context manager. @@ -424,17 +429,15 @@ def get_status_message_watcher( name = ' '.join(part for part in (actor_name, run_id) if part) to_logger = create_redirect_logger(f'apify.{name}') - return self._client_registry.status_message_watcher( - run_client=self, to_logger=to_logger, check_period=check_period - ) + return StatusMessageWatcher(run_client=self, to_logger=to_logger, check_period=check_period) @docs_group('Resource clients') class RunClientAsync(ResourceClientAsync): """Sub-client for managing a specific Actor run. - Provides methods to get, update, abort, wait for finish, metamorph, resurrect, reboot, and charge an Actor run. - Obtain an instance via `ApifyClientAsync.run`. + Provides methods to manage a specific Actor run, e.g. get it, update it, abort it, or wait for it to finish. + Obtain an instance via an appropriate method on the `ApifyClientAsync` class. """ def __init__( @@ -700,7 +703,10 @@ def log(self) -> LogClientAsync: ) async def get_streamed_log( - self, to_logger: logging.Logger | None = None, *, from_start: bool = True + self, + to_logger: logging.Logger | None = None, + *, + from_start: bool = True, ) -> StreamedLogAsync: """Get `StreamedLog` instance that can be used to redirect logs. @@ -735,7 +741,7 @@ async def get_streamed_log( name = ' '.join(part for part in (actor_name, run_id) if part) to_logger = create_redirect_logger(f'apify.{name}') - return self._client_registry.streamed_log(log_client=self.log(), to_logger=to_logger, from_start=from_start) + return StreamedLogAsync(log_client=self.log(), to_logger=to_logger, from_start=from_start) async def charge( self, @@ -817,6 +823,4 @@ async def get_status_message_watcher( name = ' '.join(part for part in (actor_name, run_id) if part) to_logger = create_redirect_logger(f'apify.{name}') - return self._client_registry.status_message_watcher( - run_client=self, to_logger=to_logger, check_period=check_period - ) + return StatusMessageWatcherAsync(run_client=self, to_logger=to_logger, check_period=check_period) diff --git a/src/apify_client/_resource_clients/run_collection.py b/src/apify_client/_resource_clients/run_collection.py index cb76a4a0..2cf32801 100644 --- a/src/apify_client/_resource_clients/run_collection.py +++ b/src/apify_client/_resource_clients/run_collection.py @@ -17,7 +17,8 @@ class RunCollectionClient(ResourceClient): """Sub-client for the Actor run collection. - Provides methods to list Actor runs. Obtain an instance via `ApifyClient.runs`. + Provides methods to manage Actor runs, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -70,7 +71,8 @@ def list( class RunCollectionClientAsync(ResourceClientAsync): """Sub-client for the Actor run collection. - Provides methods to list Actor runs. Obtain an instance via `ApifyClientAsync.runs`. + Provides methods to manage Actor runs, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/schedule.py b/src/apify_client/_resource_clients/schedule.py index 5fd65f69..63bd4ebd 100644 --- a/src/apify_client/_resource_clients/schedule.py +++ b/src/apify_client/_resource_clients/schedule.py @@ -14,8 +14,8 @@ class ScheduleClient(ResourceClient): """Sub-client for managing a specific schedule. - Provides methods to get, update, delete, and get log of a schedule. - Obtain an instance via `ApifyClient.schedule`. + Provides methods to manage a specific schedule, e.g. get, update, or delete it. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -114,8 +114,8 @@ def get_log(self) -> list[ScheduleInvoked] | None: class ScheduleClientAsync(ResourceClientAsync): """Sub-client for managing a specific schedule. - Provides methods to get, update, delete, and get log of a schedule. - Obtain an instance via `ApifyClientAsync.schedule`. + Provides methods to manage a specific schedule, e.g. get, update, or delete it. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/schedule_collection.py b/src/apify_client/_resource_clients/schedule_collection.py index dd27cf93..a335b213 100644 --- a/src/apify_client/_resource_clients/schedule_collection.py +++ b/src/apify_client/_resource_clients/schedule_collection.py @@ -13,7 +13,8 @@ class ScheduleCollectionClient(ResourceClient): """Sub-client for the schedule collection. - Provides methods to list and create schedules. Obtain an instance via `ApifyClient.schedules`. + Provides methods to manage the schedule collection, e.g. list or create schedules. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -95,7 +96,8 @@ def create( class ScheduleCollectionClientAsync(ResourceClientAsync): """Sub-client for the schedule collection. - Provides methods to list and create schedules. Obtain an instance via `ApifyClientAsync.schedules`. + Provides methods to manage the schedule collection, e.g. list or create schedules. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/store_collection.py b/src/apify_client/_resource_clients/store_collection.py index 7095a0f8..002dacf3 100644 --- a/src/apify_client/_resource_clients/store_collection.py +++ b/src/apify_client/_resource_clients/store_collection.py @@ -11,7 +11,8 @@ class StoreCollectionClient(ResourceClient): """Sub-client for the Apify store collection. - Provides methods to list Actors in the Apify store. Obtain an instance via `ApifyClient.store`. + Provides methods to browse the Apify store, e.g. list available Actors. Obtain an instance via an appropriate + method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -62,7 +63,8 @@ def list( class StoreCollectionClientAsync(ResourceClientAsync): """Sub-client for the Apify store collection. - Provides methods to list Actors in the Apify store. Obtain an instance via `ApifyClientAsync.store`. + Provides methods to browse the Apify store, e.g. list available Actors. Obtain an instance via an appropriate + method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/task.py b/src/apify_client/_resource_clients/task.py index 5088e471..04d76883 100644 --- a/src/apify_client/_resource_clients/task.py +++ b/src/apify_client/_resource_clients/task.py @@ -34,8 +34,8 @@ class TaskClient(ResourceClient): """Sub-client for managing a specific task. - Provides methods to get, update, delete, and start runs of a task. - Obtain an instance via `ApifyClient.task`. + Provides methods to manage a specific task, e.g. update it, delete it, or start runs. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__( @@ -327,8 +327,8 @@ def webhooks(self) -> WebhookCollectionClient: class TaskClientAsync(ResourceClientAsync): """Sub-client for managing a specific task. - Provides methods to get, update, delete, and start runs of a task. - Obtain an instance via `ApifyClientAsync.task`. + Provides methods to manage a specific task, e.g. update it, delete it, or start runs. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__( diff --git a/src/apify_client/_resource_clients/task_collection.py b/src/apify_client/_resource_clients/task_collection.py index eacf33fc..b70bcae0 100644 --- a/src/apify_client/_resource_clients/task_collection.py +++ b/src/apify_client/_resource_clients/task_collection.py @@ -16,7 +16,8 @@ class TaskCollectionClient(ResourceClient): """Sub-client for the task collection. - Provides methods to list and create tasks. Obtain an instance via `ApifyClient.tasks`. + Provides methods to manage the task collection, e.g. list or create tasks. Obtain an instance via an appropriate + method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -119,7 +120,8 @@ def create( class TaskCollectionClientAsync(ResourceClientAsync): """Sub-client for the task collection. - Provides methods to list and create tasks. Obtain an instance via `ApifyClientAsync.tasks`. + Provides methods to manage the task collection, e.g. list or create tasks. Obtain an instance via an appropriate + method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/user.py b/src/apify_client/_resource_clients/user.py index dd40ad21..165242f8 100644 --- a/src/apify_client/_resource_clients/user.py +++ b/src/apify_client/_resource_clients/user.py @@ -24,8 +24,8 @@ class UserClient(ResourceClient): """Sub-client for managing user account information. - Provides methods to get user data, monthly usage, and account limits. - Obtain an instance via `ApifyClient.user`. + Provides methods to manage user account information, e.g. get user data or monthly usage. Obtain an instance via + an appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -128,8 +128,8 @@ def update_limits( class UserClientAsync(ResourceClientAsync): """Sub-client for managing user account information. - Provides methods to get user data, monthly usage, and account limits. - Obtain an instance via `ApifyClientAsync.user`. + Provides methods to manage user account information, e.g. get user data or monthly usage. Obtain an instance via + an appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/webhook.py b/src/apify_client/_resource_clients/webhook.py index 4a838d34..bb70e23f 100644 --- a/src/apify_client/_resource_clients/webhook.py +++ b/src/apify_client/_resource_clients/webhook.py @@ -23,8 +23,8 @@ class WebhookClient(ResourceClient): """Sub-client for managing a specific webhook. - Provides methods to get, update, delete, and test a webhook. - Obtain an instance via `ApifyClient.webhook`. + Provides methods to manage a specific webhook, e.g. get, update, or delete it. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -145,8 +145,8 @@ def dispatches(self) -> WebhookDispatchCollectionClient: class WebhookClientAsync(ResourceClientAsync): """Sub-client for managing a specific webhook. - Provides methods to get, update, delete, and test a webhook. - Obtain an instance via `ApifyClientAsync.webhook`. + Provides methods to manage a specific webhook, e.g. get, update, or delete it. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/webhook_collection.py b/src/apify_client/_resource_clients/webhook_collection.py index 92a7af75..db4de310 100644 --- a/src/apify_client/_resource_clients/webhook_collection.py +++ b/src/apify_client/_resource_clients/webhook_collection.py @@ -16,7 +16,8 @@ class WebhookCollectionClient(ResourceClient): """Sub-client for the webhook collection. - Provides methods to list and create webhooks. Obtain an instance via `ApifyClient.webhooks`. + Provides methods to manage the webhook collection, e.g. list or create webhooks. Obtain an instance via an + appropriate method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -106,7 +107,8 @@ def create( class WebhookCollectionClientAsync(ResourceClientAsync): """Sub-client for the webhook collection. - Provides methods to list and create webhooks. Obtain an instance via `ApifyClientAsync.webhooks`. + Provides methods to manage the webhook collection, e.g. list or create webhooks. Obtain an instance via an + appropriate method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/webhook_dispatch.py b/src/apify_client/_resource_clients/webhook_dispatch.py index 945119d2..be9a8a6e 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch.py +++ b/src/apify_client/_resource_clients/webhook_dispatch.py @@ -11,7 +11,8 @@ class WebhookDispatchClient(ResourceClient): """Sub-client for managing a specific webhook dispatch. - Provides methods to get a webhook dispatch. Obtain an instance via `ApifyClient.webhook_dispatch`. + Provides methods to manage a specific webhook dispatch, e.g. get its details. Obtain an instance via an appropriate + method on the `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -36,7 +37,8 @@ def get(self) -> WebhookDispatch | None: class WebhookDispatchClientAsync(ResourceClientAsync): """Sub-client for managing a specific webhook dispatch. - Provides methods to get a webhook dispatch. Obtain an instance via `ApifyClientAsync.webhook_dispatch`. + Provides methods to manage a specific webhook dispatch, e.g. get its details. Obtain an instance via an appropriate + method on the `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/webhook_dispatch_collection.py b/src/apify_client/_resource_clients/webhook_dispatch_collection.py index ba4ba9b2..7a70b4ad 100644 --- a/src/apify_client/_resource_clients/webhook_dispatch_collection.py +++ b/src/apify_client/_resource_clients/webhook_dispatch_collection.py @@ -11,7 +11,8 @@ class WebhookDispatchCollectionClient(ResourceClient): """Sub-client for the webhook dispatch collection. - Provides methods to list webhook dispatches. Obtain an instance via `ApifyClient.webhook_dispatches`. + Provides methods to manage webhook dispatches, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClient` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -45,7 +46,8 @@ def list( class WebhookDispatchCollectionClientAsync(ResourceClientAsync): """Sub-client for the webhook dispatch collection. - Provides methods to list webhook dispatches. Obtain an instance via `ApifyClientAsync.webhook_dispatches`. + Provides methods to manage webhook dispatches, e.g. list them. Obtain an instance via an appropriate method on the + `ApifyClientAsync` class. """ def __init__(self, *args: Any, **kwargs: Any) -> None: diff --git a/src/apify_client/_resource_clients/status_message_watcher.py b/src/apify_client/_status_message_watcher.py similarity index 69% rename from src/apify_client/_resource_clients/status_message_watcher.py rename to src/apify_client/_status_message_watcher.py index 6bdabdf7..138c2207 100644 --- a/src/apify_client/_resource_clients/status_message_watcher.py +++ b/src/apify_client/_status_message_watcher.py @@ -19,13 +19,8 @@ from apify_client._resource_clients import RunClient, RunClientAsync -@docs_group('Resource clients') -class StatusMessageWatcher: - """Utility class for logging status messages from an Actor run. - - The status message is polled at fixed time intervals, and there is no guarantee that all messages will be logged, - especially in cases of frequent status message changes. - """ +class StatusMessageWatcherBase: + """Base class for polling and logging Actor run status messages.""" _force_propagate = False # This is final sleep time to try to get the last status and status message of finished Actor run. @@ -34,12 +29,6 @@ class StatusMessageWatcher: _final_sleep_time_s = 6 def __init__(self, *, to_logger: logging.Logger, check_period: timedelta = timedelta(seconds=5)) -> None: - """Initialize `StatusMessageWatcher`. - - Args: - to_logger: The logger to which the status message will be redirected. - check_period: The period with which the status message will be polled. - """ if self._force_propagate: to_logger.propagate = True self._to_logger = to_logger @@ -68,9 +57,17 @@ def _log_run_data(self, run_data: Run | None) -> bool: return True -@docs_group('Resource clients') -class StatusMessageWatcherAsync(StatusMessageWatcher): - """Async variant of `StatusMessageWatcher` that polls and logs status messages in an asyncio task.""" +@docs_group('Other') +class StatusMessageWatcherAsync(StatusMessageWatcherBase): + """Polls and logs Actor run status messages in an asyncio task. + + The status message and status of the Actor run are polled at a fixed interval and forwarded to the provided logger + whenever they change. There is no guarantee that every intermediate status message will be captured, especially + when messages change rapidly. + + Can be used as an async context manager, which automatically starts and cancels the polling task. Alternatively, + call `start` and `stop` manually. Obtain an instance via `RunClientAsync.get_status_message_watcher`. + """ def __init__( self, *, run_client: RunClientAsync, to_logger: logging.Logger, check_period: timedelta = timedelta(seconds=1) @@ -78,16 +75,19 @@ def __init__( """Initialize `StatusMessageWatcherAsync`. Args: - run_client: The client for run that will be used to get a status and message. - to_logger: The logger to which the status message will be redirected. - check_period: The period with which the status message will be polled. + run_client: The run client used to poll the Actor run status and status message. + to_logger: The logger to which the status messages will be forwarded. + check_period: How often to poll the status message. """ super().__init__(to_logger=to_logger, check_period=check_period) self._run_client = run_client self._logging_task: Task | None = None def start(self) -> Task: - """Start the logging task. The caller has to handle any cleanup by manually calling the `stop` method.""" + """Start the polling task. + + The caller is responsible for cleanup by calling the `stop` method when done. + """ if self._logging_task and not self._logging_task.done(): raise RuntimeError('Logging task already active') self._logging_task = asyncio.create_task(self._log_changed_status_message()) @@ -126,19 +126,27 @@ async def _log_changed_status_message(self) -> None: await asyncio.sleep(self._check_period) -@docs_group('Resource clients') -class StatusMessageWatcherSync(StatusMessageWatcher): - """Sync variant of `StatusMessageWatcher` that polls and logs status messages in a background thread.""" +@docs_group('Other') +class StatusMessageWatcher(StatusMessageWatcherBase): + """Polls and logs Actor run status messages in a background thread. + + The status message and status of the Actor run are polled at a fixed interval and forwarded to the provided logger + whenever they change. There is no guarantee that every intermediate status message will be captured, especially + when messages change rapidly. + + Can be used as a context manager, which automatically starts and stops the polling thread. Alternatively, + call `start` and `stop` manually. Obtain an instance via `RunClient.get_status_message_watcher`. + """ def __init__( self, *, run_client: RunClient, to_logger: logging.Logger, check_period: timedelta = timedelta(seconds=1) ) -> None: - """Initialize `StatusMessageWatcherSync`. + """Initialize `StatusMessageWatcher`. Args: - run_client: The client for run that will be used to get a status and message. - to_logger: The logger to which the status message will be redirected. - check_period: The period with which the status message will be polled. + run_client: The run client used to poll the Actor run status and status message. + to_logger: The logger to which the status messages will be forwarded. + check_period: How often to poll the status message. """ super().__init__(to_logger=to_logger, check_period=check_period) self._run_client = run_client @@ -146,7 +154,10 @@ def __init__( self._stop_logging = False def start(self) -> Thread: - """Start the logging thread. The caller has to handle any cleanup by manually calling the `stop` method.""" + """Start the polling thread. + + The caller is responsible for cleanup by calling the `stop` method when done. + """ if self._logging_thread: raise RuntimeError('Logging thread already active') self._stop_logging = False @@ -155,7 +166,7 @@ def start(self) -> Thread: return self._logging_thread def stop(self) -> None: - """Signal the _logging_thread thread to stop logging and wait for it to finish.""" + """Signal the logging thread to stop logging and wait for it to finish.""" if not self._logging_thread: raise RuntimeError('Logging thread is not active') time.sleep(self._final_sleep_time_s) @@ -165,14 +176,14 @@ def stop(self) -> None: self._stop_logging = False def __enter__(self) -> Self: - """Start the logging task within the context. Exiting the context will cancel the logging task.""" + """Start the logging thread within the context. Exiting the context will stop the logging thread.""" self.start() return self def __exit__( self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None ) -> None: - """Cancel the logging task.""" + """Stop the logging thread.""" self.stop() def _log_changed_status_message(self) -> None: diff --git a/src/apify_client/_resource_clients/streamed_log.py b/src/apify_client/_streamed_log.py similarity index 75% rename from src/apify_client/_resource_clients/streamed_log.py rename to src/apify_client/_streamed_log.py index ec27ee67..f57ba074 100644 --- a/src/apify_client/_resource_clients/streamed_log.py +++ b/src/apify_client/_streamed_log.py @@ -17,31 +17,13 @@ from apify_client._resource_clients import LogClient, LogClientAsync -@docs_group('Resource clients') -class StreamedLog: - """Utility class for streaming logs from an Actor run. - - It uses a buffer to deal with possibly chunked logs. Chunked logs are stored in the buffer. Chunks are expected - to contain specific markers that indicate the start of a log message. Each time a new chunk with a complete split - marker arrives, the buffer is processed, logged, and emptied. - - This works only if the logs have a datetime marker in ISO format. For example, `2025-05-12T15:35:59.429Z`. - This is the default log standard for Actors. - """ +class StreamedLogBase: + """Base class for streaming and buffering chunked Actor run logs.""" # Test related flag to enable propagation of logs to the `caplog` fixture during tests. _force_propagate = False def __init__(self, to_logger: logging.Logger, *, from_start: bool = True) -> None: - """Initialize `StreamedLog`. - - Args: - to_logger: The logger to which the logs will be redirected. - from_start: If `True`, all logs from the start of the Actor run will be redirected. If `False`, only newly - arrived logs will be redirected. This can be useful for redirecting only a small portion of relevant - logs for long-running Actors in stand-by. - - """ if self._force_propagate: to_logger.propagate = True self._to_logger = to_logger @@ -97,18 +79,37 @@ def _guess_log_level_from_message(message: str) -> int: return logging.INFO -@docs_group('Resource clients') -class StreamedLogSync(StreamedLog): - """Sync variant of `StreamedLog` that streams and logs in a background thread.""" +@docs_group('Other') +class StreamedLog(StreamedLogBase): + """Streams Actor run log output to a Python logger in a background thread. + + The log stream is consumed in a background thread and each log message is forwarded to the provided logger with + an appropriate log level inferred from the message content. + + Can be used as a context manager, which automatically starts and stops the streaming thread. Alternatively, + call `start` and `stop` manually. Obtain an instance via `RunClient.get_streamed_log`. + """ def __init__(self, log_client: LogClient, *, to_logger: logging.Logger, from_start: bool = True) -> None: + """Initialize `StreamedLog`. + + Args: + log_client: The log client used to stream raw log data from the Actor run. + to_logger: The logger to which the log messages will be forwarded. + from_start: If `True`, all logs from the start of the Actor run will be streamed. If `False`, only newly + arrived logs will be streamed. This can be useful for long-running Actors in stand-by mode where only + recent logs are relevant. + """ super().__init__(to_logger=to_logger, from_start=from_start) self._log_client = log_client self._streaming_thread: Thread | None = None self._stop_logging = False def start(self) -> Thread: - """Start the streaming thread. The caller has to handle any cleanup by manually calling the `stop` method.""" + """Start the streaming thread. + + The caller is responsible for cleanup by calling the `stop` method when done. + """ if self._streaming_thread: raise RuntimeError('Streaming thread already active') self._stop_logging = False @@ -150,17 +151,36 @@ def _stream_log(self) -> None: return -@docs_group('Resource clients') -class StreamedLogAsync(StreamedLog): - """Async variant of `StreamedLog` that streams and logs in an asyncio task.""" +@docs_group('Other') +class StreamedLogAsync(StreamedLogBase): + """Streams Actor run log output to a Python logger in an asyncio task. + + The log stream is consumed in a background asyncio task and each log message is forwarded to the provided logger + with an appropriate log level inferred from the message content. + + Can be used as an async context manager, which automatically starts and cancels the streaming task. Alternatively, + call `start` and `stop` manually. Obtain an instance via `RunClientAsync.get_streamed_log`. + """ def __init__(self, log_client: LogClientAsync, *, to_logger: logging.Logger, from_start: bool = True) -> None: + """Initialize `StreamedLogAsync`. + + Args: + log_client: The async log client used to stream raw log data from the Actor run. + to_logger: The logger to which the log messages will be forwarded. + from_start: If `True`, all logs from the start of the Actor run will be streamed. If `False`, only newly + arrived logs will be streamed. This can be useful for long-running Actors in stand-by mode where only + recent logs are relevant. + """ super().__init__(to_logger=to_logger, from_start=from_start) self._log_client = log_client self._streaming_task: Task | None = None def start(self) -> Task: - """Start the streaming task. The caller has to handle any cleanup by manually calling the `stop` method.""" + """Start the streaming task. + + The caller is responsible for cleanup by calling the `stop` method when done. + """ if self._streaming_task and not self._streaming_task.done(): raise RuntimeError('Streaming task already active') self._streaming_task = asyncio.create_task(self._stream_log()) diff --git a/src/apify_client/errors.py b/src/apify_client/errors.py index 2396e58f..ba167d33 100644 --- a/src/apify_client/errors.py +++ b/src/apify_client/errors.py @@ -12,7 +12,7 @@ class ApifyClientError(Exception): """Base class for all Apify API client errors. - All exceptions raised by the Apify client inherit from this class, making it convenient + All custom exceptions defined by this package inherit from this class, making it convenient to catch any client-related error with a single except clause. """ @@ -28,7 +28,7 @@ class ApifyApiError(ApifyClientError): Attributes: message: The error message from the API response. - type: The error type identifier from the API response (e.g. ``record-not-found``). + type: The error type identifier from the API response (e.g. `record-not-found`). status_code: The HTTP status code of the error response. attempt: The attempt number when the error was raised. http_method: The HTTP method of the failed request. diff --git a/tests/integration/test_webhook.py b/tests/integration/test_webhook.py index abd15451..7d26fd4f 100644 --- a/tests/integration/test_webhook.py +++ b/tests/integration/test_webhook.py @@ -1,9 +1,4 @@ -"""Unified tests for webhook (sync + async). - -Webhook CRUD tests bind to a specific already-completed run (actor_run_id) instead of to an actor (actor_id). -This prevents webhooks from firing when other integration tests run the same actor, which would cause -"Webhook was removed" error emails. -""" +"""Unified tests for webhook (sync + async).""" from __future__ import annotations @@ -14,7 +9,15 @@ from ._utils import maybe_await -from apify_client._models import ActorJobStatus, WebhookEventType +from apify_client._models import ( + ActorJobStatus, + ListOfRuns, + ListOfWebhookDispatches, + ListOfWebhooks, + Webhook, + WebhookDispatch, + WebhookEventType, +) HELLO_WORLD_ACTOR = 'apify/hello-world' @@ -27,14 +30,17 @@ async def _get_finished_run_id(client: ApifyClient | ApifyClientAsync) -> str: waits for it to finish. """ runs_page = await maybe_await(client.actor(HELLO_WORLD_ACTOR).runs().list(limit=1, status=ActorJobStatus.SUCCEEDED)) - assert runs_page is not None + + assert isinstance(runs_page, ListOfRuns) if len(runs_page.items) > 0: return runs_page.items[0].id # No completed runs found - start one and wait for it to finish run = await maybe_await(client.actor(HELLO_WORLD_ACTOR).call()) - assert run is not None + + assert isinstance(run, ListOfRuns) + return run.id @@ -42,9 +48,7 @@ async def test_list_webhooks(client: ApifyClient | ApifyClientAsync) -> None: """Test listing webhooks.""" webhooks_page = await maybe_await(client.webhooks().list(limit=10)) - assert webhooks_page is not None - assert webhooks_page.items is not None - # User may have 0 webhooks + assert isinstance(webhooks_page, ListOfWebhooks) assert isinstance(webhooks_page.items, list) @@ -52,8 +56,7 @@ async def test_list_webhooks_pagination(client: ApifyClient | ApifyClientAsync) """Test listing webhooks with pagination.""" webhooks_page = await maybe_await(client.webhooks().list(limit=5, offset=0)) - assert webhooks_page is not None - assert webhooks_page.items is not None + assert isinstance(webhooks_page, ListOfWebhooks) assert isinstance(webhooks_page.items, list) @@ -70,15 +73,15 @@ async def test_webhook_create_and_get(client: ApifyClient | ApifyClientAsync) -> is_ad_hoc=True, ) ) - webhook_client = client.webhook(created_webhook.id) try: - assert created_webhook is not None - assert created_webhook.id is not None + assert isinstance(created_webhook, Webhook) # Get the same webhook + webhook_client = client.webhook(created_webhook.id) retrieved_webhook = await maybe_await(webhook_client.get()) - assert retrieved_webhook is not None + + assert isinstance(retrieved_webhook, Webhook) assert retrieved_webhook.id == created_webhook.id finally: await maybe_await(webhook_client.delete()) @@ -97,6 +100,7 @@ async def test_webhook_update(client: ApifyClient | ApifyClientAsync) -> None: is_ad_hoc=True, ) ) + assert isinstance(created_webhook, Webhook) webhook_client = client.webhook(created_webhook.id) try: @@ -107,6 +111,7 @@ async def test_webhook_update(client: ApifyClient | ApifyClientAsync) -> None: actor_run_id=run_id, ) ) + assert isinstance(updated_webhook, Webhook) assert str(updated_webhook.request_url) == 'https://httpbin.org/anything' finally: await maybe_await(webhook_client.delete()) @@ -125,12 +130,13 @@ async def test_webhook_test(client: ApifyClient | ApifyClientAsync) -> None: is_ad_hoc=True, ) ) + assert isinstance(created_webhook, Webhook) webhook_client = client.webhook(created_webhook.id) try: # Test webhook (creates a dispatch with dummy payload) dispatch = await maybe_await(webhook_client.test()) - assert dispatch is not None + assert isinstance(dispatch, WebhookDispatch) assert dispatch.id is not None finally: await maybe_await(webhook_client.delete()) @@ -149,6 +155,8 @@ async def test_webhook_dispatches(client: ApifyClient | ApifyClientAsync) -> Non is_ad_hoc=True, ) ) + + assert isinstance(created_webhook, Webhook) webhook_client = client.webhook(created_webhook.id) try: @@ -157,9 +165,9 @@ async def test_webhook_dispatches(client: ApifyClient | ApifyClientAsync) -> Non # List dispatches for this webhook dispatches = await maybe_await(webhook_client.dispatches().list()) - assert dispatches is not None - assert dispatches.items is not None + assert isinstance(dispatches, ListOfWebhookDispatches) assert len(dispatches.items) > 0 + finally: await maybe_await(webhook_client.delete()) @@ -177,6 +185,7 @@ async def test_webhook_delete(client: ApifyClient | ApifyClientAsync) -> None: is_ad_hoc=True, ) ) + assert isinstance(created_webhook, Webhook) webhook_client = client.webhook(created_webhook.id) # Delete webhook diff --git a/tests/unit/test_logging.py b/tests/unit/test_logging.py index de9eb318..83635b06 100644 --- a/tests/unit/test_logging.py +++ b/tests/unit/test_logging.py @@ -14,7 +14,8 @@ from apify_client import ApifyClient, ApifyClientAsync from apify_client._logging import RedirectLogFormatter from apify_client._models import ActorJobStatus -from apify_client._resource_clients import StatusMessageWatcher, StreamedLog +from apify_client._status_message_watcher import StatusMessageWatcherBase +from apify_client._streamed_log import StreamedLogBase if TYPE_CHECKING: from collections.abc import Iterator @@ -212,18 +213,18 @@ def mock_api(httpserver: HTTPServer) -> None: @pytest.fixture def propagate_stream_logs() -> None: """Enable propagation of logs to the caplog fixture.""" - StreamedLog._force_propagate = True - StatusMessageWatcher._force_propagate = True + StreamedLogBase._force_propagate = True + StatusMessageWatcherBase._force_propagate = True logging.getLogger(f'apify.{_MOCKED_ACTOR_NAME}-{_MOCKED_RUN_ID}').setLevel(logging.DEBUG) @pytest.fixture def reduce_final_timeout_for_status_message_redirector() -> None: - """Reduce timeout used by the `StatusMessageWatcher`. + """Reduce timeout used by the status message watcher. This timeout makes sense on the platform, but in tests it is better to reduce it to speed up the tests. """ - StatusMessageWatcher._final_sleep_time_s = 2 + StatusMessageWatcherBase._final_sleep_time_s = 2 @pytest.mark.parametrize( @@ -247,7 +248,7 @@ async def test_redirected_logs_async( run_client = ApifyClientAsync(token='mocked_token', api_url=api_url).run(run_id=_MOCKED_RUN_ID) - with patch('apify_client._resource_clients.streamed_log.datetime') as mocked_datetime: + with patch('apify_client._streamed_log.datetime') as mocked_datetime: # Mock `now()` so that it has timestamp bigger than the first 3 logs mocked_datetime.now.return_value = datetime.fromisoformat('2025-05-13T07:24:14.132+00:00') streamed_log = await run_client.get_streamed_log(from_start=log_from_start) @@ -287,7 +288,7 @@ def test_redirected_logs_sync( run_client = ApifyClient(token='mocked_token', api_url=api_url).run(run_id=_MOCKED_RUN_ID) - with patch('apify_client._resource_clients.streamed_log.datetime') as mocked_datetime: + with patch('apify_client._streamed_log.datetime') as mocked_datetime: # Mock `now()` so that it has timestamp bigger than the first 3 logs mocked_datetime.now.return_value = datetime.fromisoformat('2025-05-13T07:24:14.132+00:00') streamed_log = run_client.get_streamed_log(from_start=log_from_start) diff --git a/website/transformDocs.js b/website/transformDocs.js index ebcddb62..12994d9f 100644 --- a/website/transformDocs.js +++ b/website/transformDocs.js @@ -56,21 +56,22 @@ const TYPEDOC_KINDS = { const GROUP_ORDER = [ 'Apify API clients', - 'Resource clients', 'HTTP clients', - 'Models', + 'Resource clients', 'Errors', - 'Constructors', - 'Methods', - 'Properties', - 'Constants', - 'Enumeration Members' + 'Models', + 'Other', ]; const groupSort = (g1, g2) => { - if(GROUP_ORDER.includes(g1) && GROUP_ORDER.includes(g2)){ - return GROUP_ORDER.indexOf(g1) - GROUP_ORDER.indexOf(g2) - } + const i1 = GROUP_ORDER.indexOf(g1); + const i2 = GROUP_ORDER.indexOf(g2); + // Both known – sort by defined order + if (i1 !== -1 && i2 !== -1) return i1 - i2; + // Unknown groups go after known ones + if (i1 !== -1) return -1; + if (i2 !== -1) return 1; + // Both unknown – alphabetical return g1.localeCompare(g2); };