idempotency (#282)
This commit is contained in:
@@ -3,6 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from .types import (
|
||||
APIError,
|
||||
@@ -18,6 +19,17 @@ from .types import (
|
||||
)
|
||||
|
||||
|
||||
class EmailOptions(TypedDict, total=False):
|
||||
"""Options for email operations."""
|
||||
idempotency_key: Optional[str]
|
||||
|
||||
|
||||
def _idem_headers(idempotency_key: Optional[str]) -> Optional[Dict[str, str]]:
|
||||
if idempotency_key:
|
||||
return {"Idempotency-Key": idempotency_key}
|
||||
return None
|
||||
|
||||
|
||||
class Emails:
|
||||
"""Client for `/emails` endpoints."""
|
||||
|
||||
@@ -25,11 +37,19 @@ class Emails:
|
||||
self.usesend = usesend
|
||||
|
||||
# Basic operations -------------------------------------------------
|
||||
def send(self, payload: EmailCreate) -> Tuple[Optional[EmailCreateResponse], Optional[APIError]]:
|
||||
def send(
|
||||
self,
|
||||
payload: EmailCreate,
|
||||
options: Optional[EmailOptions] = None,
|
||||
) -> Tuple[Optional[EmailCreateResponse], Optional[APIError]]:
|
||||
"""Alias for :meth:`create`."""
|
||||
return self.create(payload)
|
||||
return self.create(payload, options)
|
||||
|
||||
def create(self, payload: Union[EmailCreate, Dict[str, Any]]) -> Tuple[Optional[EmailCreateResponse], Optional[APIError]]:
|
||||
def create(
|
||||
self,
|
||||
payload: Union[EmailCreate, Dict[str, Any]],
|
||||
options: Optional[EmailOptions] = None,
|
||||
) -> Tuple[Optional[EmailCreateResponse], Optional[APIError]]:
|
||||
if isinstance(payload, dict):
|
||||
payload = dict(payload)
|
||||
|
||||
@@ -42,10 +62,17 @@ class Emails:
|
||||
if isinstance(body.get("scheduledAt"), datetime):
|
||||
body["scheduledAt"] = body["scheduledAt"].isoformat()
|
||||
|
||||
data, err = self.usesend.post("/emails", body)
|
||||
idempotency_key = options.get("idempotency_key") if options else None
|
||||
data, err = self.usesend.post(
|
||||
"/emails", body, headers=_idem_headers(idempotency_key)
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def batch(self, payload: Sequence[Union[EmailBatchItem, Dict[str, Any]]]) -> Tuple[Optional[EmailBatchResponse], Optional[APIError]]:
|
||||
def batch(
|
||||
self,
|
||||
payload: Sequence[Union[EmailBatchItem, Dict[str, Any]]],
|
||||
options: Optional[EmailOptions] = None,
|
||||
) -> Tuple[Optional[EmailBatchResponse], Optional[APIError]]:
|
||||
items: List[Dict[str, Any]] = []
|
||||
for item in payload:
|
||||
d = dict(item)
|
||||
@@ -54,7 +81,10 @@ class Emails:
|
||||
if isinstance(d.get("scheduledAt"), datetime):
|
||||
d["scheduledAt"] = d["scheduledAt"].isoformat()
|
||||
items.append(d)
|
||||
data, err = self.usesend.post("/emails/batch", items)
|
||||
idempotency_key = options.get("idempotency_key") if options else None
|
||||
data, err = self.usesend.post(
|
||||
"/emails/batch", items, headers=_idem_headers(idempotency_key)
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def get(self, email_id: str) -> Tuple[Optional[Email], Optional[APIError]]:
|
||||
|
||||
Reference in New Issue
Block a user