diff --git a/src/apify_client/_http_client.py b/src/apify_client/_http_client.py index d6e2f1f6..d847144d 100644 --- a/src/apify_client/_http_client.py +++ b/src/apify_client/_http_client.py @@ -13,10 +13,10 @@ import impit from apify_shared.utils import ignore_docs, is_content_type_json, is_content_type_text, is_content_type_xml -from apify_client._errors import ApifyApiError, InvalidResponseBodyError, is_retryable_error from apify_client._logging import log_context, logger_name from apify_client._statistics import Statistics -from apify_client._utils import retry_with_exp_backoff, retry_with_exp_backoff_async +from apify_client._utils import is_retryable_error, retry_with_exp_backoff, retry_with_exp_backoff_async +from apify_client.errors import ApifyApiError, InvalidResponseBodyError if TYPE_CHECKING: from collections.abc import Callable diff --git a/src/apify_client/_utils.py b/src/apify_client/_utils.py index 512d492b..9c422815 100644 --- a/src/apify_client/_utils.py +++ b/src/apify_client/_utils.py @@ -9,12 +9,15 @@ from http import HTTPStatus from typing import TYPE_CHECKING, Any, TypeVar, cast +import impit from apify_shared.utils import is_file_or_bytes, maybe_extract_enum_member_value +from apify_client.errors import InvalidResponseBodyError + if TYPE_CHECKING: from collections.abc import Awaitable - from apify_client._errors import ApifyApiError + from apify_client.errors import ApifyApiError PARSE_DATE_FIELDS_MAX_DEPTH = 3 PARSE_DATE_FIELDS_KEY_SUFFIX = 'At' @@ -149,3 +152,16 @@ def encode_key_value_store_record_value(value: Any, content_type: str | None = N value = json.dumps(value, ensure_ascii=False, indent=2, allow_nan=False, default=str).encode('utf-8') return (value, content_type) + + +def is_retryable_error(exc: Exception) -> bool: + """Check if the given error is retryable.""" + return isinstance( + exc, + ( + InvalidResponseBodyError, + impit.NetworkError, + impit.TimeoutException, + impit.RemoteProtocolError, + ), + ) diff --git a/src/apify_client/clients/base/actor_job_base_client.py b/src/apify_client/clients/base/actor_job_base_client.py index 13c23c40..678994ea 100644 --- a/src/apify_client/clients/base/actor_job_base_client.py +++ b/src/apify_client/clients/base/actor_job_base_client.py @@ -9,9 +9,9 @@ from apify_shared.consts import ActorJobStatus from apify_shared.utils import ignore_docs, parse_date_fields -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base.resource_client import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError DEFAULT_WAIT_FOR_FINISH_SEC = 999999 diff --git a/src/apify_client/clients/base/resource_client.py b/src/apify_client/clients/base/resource_client.py index 8a8ef279..f5e7a2bc 100644 --- a/src/apify_client/clients/base/resource_client.py +++ b/src/apify_client/clients/base/resource_client.py @@ -4,9 +4,9 @@ from apify_shared.utils import ignore_docs, parse_date_fields -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base.base_client import BaseClient, BaseClientAsync +from apify_client.errors import ApifyApiError @ignore_docs diff --git a/src/apify_client/clients/resource_clients/dataset.py b/src/apify_client/clients/resource_clients/dataset.py index a36e850e..c109aa0d 100644 --- a/src/apify_client/clients/resource_clients/dataset.py +++ b/src/apify_client/clients/resource_clients/dataset.py @@ -8,9 +8,9 @@ from apify_shared.models import ListPage from apify_shared.utils import filter_out_none_values_recursively, ignore_docs -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from collections.abc import AsyncIterator, Iterator diff --git a/src/apify_client/clients/resource_clients/key_value_store.py b/src/apify_client/clients/resource_clients/key_value_store.py index ccc254f8..761a5fb4 100644 --- a/src/apify_client/clients/resource_clients/key_value_store.py +++ b/src/apify_client/clients/resource_clients/key_value_store.py @@ -8,9 +8,9 @@ from apify_shared.utils import filter_out_none_values_recursively, ignore_docs, parse_date_fields -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, encode_key_value_store_record_value, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from collections.abc import AsyncIterator, Iterator diff --git a/src/apify_client/clients/resource_clients/log.py b/src/apify_client/clients/resource_clients/log.py index e007f667..58e8ab39 100644 --- a/src/apify_client/clients/resource_clients/log.py +++ b/src/apify_client/clients/resource_clients/log.py @@ -13,9 +13,9 @@ from apify_shared.utils import ignore_docs -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from collections.abc import AsyncIterator, Iterator diff --git a/src/apify_client/clients/resource_clients/request_queue.py b/src/apify_client/clients/resource_clients/request_queue.py index d6716b33..8dd238ea 100644 --- a/src/apify_client/clients/resource_clients/request_queue.py +++ b/src/apify_client/clients/resource_clients/request_queue.py @@ -11,9 +11,9 @@ from apify_shared.utils import filter_out_none_values_recursively, ignore_docs, parse_date_fields from more_itertools import constrained_batches -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from datetime import timedelta diff --git a/src/apify_client/clients/resource_clients/schedule.py b/src/apify_client/clients/resource_clients/schedule.py index 360e819e..2af40792 100644 --- a/src/apify_client/clients/resource_clients/schedule.py +++ b/src/apify_client/clients/resource_clients/schedule.py @@ -5,9 +5,9 @@ from apify_shared.utils import filter_out_none_values_recursively, ignore_docs -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data_as_list from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError def _get_schedule_representation( diff --git a/src/apify_client/clients/resource_clients/task.py b/src/apify_client/clients/resource_clients/task.py index 7276650e..d05ac363 100644 --- a/src/apify_client/clients/resource_clients/task.py +++ b/src/apify_client/clients/resource_clients/task.py @@ -10,7 +10,6 @@ parse_date_fields, ) -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, encode_webhook_list_to_base64, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync from apify_client.clients.resource_clients.run import RunClient, RunClientAsync @@ -19,6 +18,7 @@ WebhookCollectionClient, WebhookCollectionClientAsync, ) +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from apify_shared.consts import ActorJobStatus, MetaOrigin diff --git a/src/apify_client/clients/resource_clients/user.py b/src/apify_client/clients/resource_clients/user.py index 87d7aeb2..049028f0 100644 --- a/src/apify_client/clients/resource_clients/user.py +++ b/src/apify_client/clients/resource_clients/user.py @@ -5,9 +5,9 @@ from apify_shared.utils import filter_out_none_values_recursively, ignore_docs, parse_date_fields -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync +from apify_client.errors import ApifyApiError class UserClient(ResourceClient): diff --git a/src/apify_client/clients/resource_clients/webhook.py b/src/apify_client/clients/resource_clients/webhook.py index a74d0216..dbc5f241 100644 --- a/src/apify_client/clients/resource_clients/webhook.py +++ b/src/apify_client/clients/resource_clients/webhook.py @@ -10,13 +10,13 @@ parse_date_fields, ) -from apify_client._errors import ApifyApiError from apify_client._utils import catch_not_found_or_throw, pluck_data from apify_client.clients.base import ResourceClient, ResourceClientAsync from apify_client.clients.resource_clients.webhook_dispatch_collection import ( WebhookDispatchCollectionClient, WebhookDispatchCollectionClientAsync, ) +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from apify_shared.consts import WebhookEventType diff --git a/src/apify_client/_errors.py b/src/apify_client/errors.py similarity index 89% rename from src/apify_client/_errors.py rename to src/apify_client/errors.py index 6b3d8db2..118c4456 100644 --- a/src/apify_client/_errors.py +++ b/src/apify_client/errors.py @@ -1,10 +1,13 @@ from __future__ import annotations import json as jsonlib +from typing import TYPE_CHECKING -import impit from apify_shared.utils import ignore_docs +if TYPE_CHECKING: + import impit + class ApifyClientError(Exception): """Base class for errors specific to the Apify API Client.""" @@ -75,16 +78,3 @@ def __init__(self, response: impit.Response) -> None: self.name = 'InvalidResponseBodyError' self.code = 'invalid-response-body' self.response = response - - -def is_retryable_error(exc: Exception) -> bool: - """Check if the given error is retryable.""" - return isinstance( - exc, - ( - InvalidResponseBodyError, - impit.NetworkError, - impit.TimeoutException, - impit.RemoteProtocolError, - ), - ) diff --git a/tests/unit/test_client_errors.py b/tests/unit/test_client_errors.py index ca410ce4..8b4a152e 100644 --- a/tests/unit/test_client_errors.py +++ b/tests/unit/test_client_errors.py @@ -7,8 +7,8 @@ import pytest from werkzeug import Response -from apify_client._errors import ApifyApiError from apify_client._http_client import HTTPClient, HTTPClientAsync +from apify_client.errors import ApifyApiError if TYPE_CHECKING: from collections.abc import Iterator diff --git a/tests/unit/test_client_request_queue.py b/tests/unit/test_client_request_queue.py index ec6bf606..bc082c90 100644 --- a/tests/unit/test_client_request_queue.py +++ b/tests/unit/test_client_request_queue.py @@ -43,7 +43,7 @@ async def test_batch_not_processed_raises_exception_async(httpserver: HTTPServer ] rq_client = client.request_queue(request_queue_id='whatever') - with pytest.raises(apify_client._errors.ApifyApiError): + with pytest.raises(apify_client.errors.ApifyApiError): await rq_client.batch_add_requests(requests=requests) @@ -77,7 +77,7 @@ def test_batch_not_processed_raises_exception_sync(httpserver: HTTPServer) -> No ] rq_client = client.request_queue(request_queue_id='whatever') - with pytest.raises(apify_client._errors.ApifyApiError): + with pytest.raises(apify_client.errors.ApifyApiError): rq_client.batch_add_requests(requests=requests)