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
16 changes: 9 additions & 7 deletions src/apify/_actor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
import warnings
from contextlib import suppress
from dataclasses import asdict
from datetime import UTC, datetime, timedelta
from functools import cached_property
from typing import TYPE_CHECKING, Any, Literal, TypeVar, cast, overload
Expand Down Expand Up @@ -1283,15 +1284,16 @@ async def add_webhook(self, webhook: Webhook, *, idempotency_key: str | None = N
if not self.configuration.actor_run_id:
raise RuntimeError('actor_run_id cannot be None when running on the Apify platform.')

# `Webhook`'s field names match `webhooks().create()`'s parameters, so we forward them by name rather
# than listing each one.
webhook_fields = asdict(webhook)

if idempotency_key is not None:
webhook_fields['idempotency_key'] = idempotency_key

await self.apify_client.webhooks().create(
**webhook_fields,
actor_run_id=self.configuration.actor_run_id,
event_types=webhook.event_types,
request_url=webhook.request_url,
payload_template=webhook.payload_template,
headers_template=webhook.headers_template,
ignore_ssl_errors=webhook.ignore_ssl_errors,
do_not_retry=webhook.do_not_retry,
idempotency_key=idempotency_key if idempotency_key is not None else webhook.idempotency_key,
is_ad_hoc=True,
)

Expand Down
18 changes: 8 additions & 10 deletions src/apify/_webhook.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,13 @@ def __post_init__(self) -> None:


def to_client_representations(webhooks: list[Webhook] | None) -> list[WebhookRepresentation] | None:
"""Project SDK webhooks to the minimal ad-hoc representation accepted by the client's `start()` / `call()`."""
"""Convert SDK webhooks to the ad-hoc representation accepted by the client's `start()` / `call()`.

`Webhook`'s field names match `WebhookRepresentation`'s, so we let pydantic read them straight off the
instance rather than listing each one. This forwards any field the representation declares without changes
here, and never emits an undeclared field as a malformed snake_case extra.
"""
if not webhooks:
return None
return [
WebhookRepresentation(
event_types=w.event_types,
request_url=w.request_url,
payload_template=w.payload_template,
headers_template=w.headers_template,
)
for w in webhooks
]

return [WebhookRepresentation.model_validate(webhook, from_attributes=True) for webhook in webhooks]