Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ dev = [
"pytest-timeout<3.0.0",
"pytest-xdist<4.0.0",
"pytest<10.0.0",
"ruff~=0.15.0",
"ruff~=0.16.0",
"setuptools", # setuptools are used by pytest but not explicitly required
"ty~=0.0.0",
"types-cachetools<7.0.1",
Expand Down Expand Up @@ -119,6 +119,7 @@ ignore = [
"BLE001", # Do not catch blind exception
"C901", # `{name}` is too complex
"COM812", # This rule may cause conflicts when used with the formatter
"CPY001", # Missing copyright notice at top of file
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
"D107", # Missing docstring in `__init__`
Expand Down
11 changes: 6 additions & 5 deletions src/apify/_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ async def __aexit__(
self.exit_code = code if isinstance(code, int) else 0 if code is None else 1
elif isinstance(exc_value, Exception) and not is_running_in_ipython():
# In IPython we don't call `sys.exit()`, so the traceback prints on its own.
self.log.exception('Actor failed with an exception', exc_info=exc_value)
# `error(exc_info=...)` not `exception()`: there is no ambient exception outside an `except` block.
self.log.error('Actor failed with an exception', exc_info=exc_value)
# Fall back to the error code only if the caller hasn't chosen one (e.g. via `fail(exit_code=...)`).
if self.exit_code == 0:
self.exit_code = EXIT_CODE_ERROR_USER_FUNCTION_THREW
Expand Down Expand Up @@ -909,7 +910,7 @@ async def start(
max_total_charge_usd: Decimal | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
timeout: timedelta | None | Literal['inherit'] = None,
timeout: timedelta | Literal['inherit'] | None = None,
force_permission_level: ActorPermissionLevel | None = None,
webhooks: list[Webhook] | None = None,
) -> Run:
Expand Down Expand Up @@ -1015,11 +1016,11 @@ async def call(
max_total_charge_usd: Decimal | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
timeout: timedelta | None | Literal['inherit'] = None,
timeout: timedelta | Literal['inherit'] | None = None,
force_permission_level: ActorPermissionLevel | None = None,
webhooks: list[Webhook] | None = None,
wait: timedelta | None = None,
logger: logging.Logger | None | Literal['default'] = 'default',
logger: logging.Logger | Literal['default'] | None = 'default',
) -> Run:
"""Start an Actor on the Apify Platform and wait for it to finish before returning.

Expand Down Expand Up @@ -1093,7 +1094,7 @@ async def call_task(
build: str | None = None,
restart_on_error: bool | None = None,
memory_mbytes: int | None = None,
timeout: timedelta | None | Literal['inherit'] = None,
timeout: timedelta | Literal['inherit'] | None = None,
webhooks: list[Webhook] | None = None,
wait: timedelta | None = None,
token: str | None = None,
Expand Down
2 changes: 1 addition & 1 deletion src/apify/_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ActorStorages(TypedDict):
request_queues: dict[str, str]


def _load_storage_keys(data: None | str | ActorStorages) -> ActorStorages | None:
def _load_storage_keys(data: str | ActorStorages | None) -> ActorStorages | None:
"""Parse the `ACTOR_STORAGES_JSON` value into a normalized `ActorStorages` dict.

The platform provides this as a JSON string with camelCase keys (`keyValueStores`, `requestQueues`, `datasets`).
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/actor/test_actor_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ async def listener(_data: object) -> None:

@pytest.mark.parametrize(('client_resource', 'client_method', 'actor_method_name', 'entity_id'), _ACTOR_REMOTE_METHODS)
async def test_remote_method_with_webhooks(
*,
apify_client_async_patcher: ApifyClientAsyncPatcher,
fake_actor_run: Run,
client_resource: str,
Expand All @@ -254,6 +255,7 @@ async def test_remote_method_with_webhooks(

@pytest.mark.parametrize(('client_resource', 'client_method', 'actor_method_name', 'entity_id'), _ACTOR_REMOTE_METHODS)
async def test_remote_method_with_timedelta_timeout(
*,
apify_client_async_patcher: ApifyClientAsyncPatcher,
fake_actor_run: Run,
client_resource: str,
Expand All @@ -276,6 +278,7 @@ async def test_remote_method_with_timedelta_timeout(

@pytest.mark.parametrize(('client_resource', 'client_method', 'actor_method_name', 'entity_id'), _ACTOR_REMOTE_METHODS)
async def test_remote_method_with_invalid_timeout(
*,
apify_client_async_patcher: ApifyClientAsyncPatcher,
fake_actor_run: Run,
client_resource: str,
Expand Down
1 change: 1 addition & 0 deletions tests/unit/scrapy/middlewares/test_apify_proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ async def mock_new_url() -> str:
ids=['valid_example_proxy', 'valid_apify_proxy', 'invalid_proxy_missing_credentials'],
)
async def test_process_request_with_proxy(
*,
monkeypatch: pytest.MonkeyPatch,
middleware: ApifyHttpProxyMiddleware,
dummy_request: Request,
Expand Down
44 changes: 22 additions & 22 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading