Skip to content

Commit 13a0871

Browse files
Run pyupgrade
Co-authored-by: Terence D. Honles <terence@honles.com>
1 parent 7bf7a1a commit 13a0871

22 files changed

Lines changed: 82 additions & 106 deletions

anymail/backends/amazon_ses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ def finalize_payload(self):
435435
def parse_recipient_status(self, response):
436436
try:
437437
results = response["BulkEmailEntryResults"]
438-
ses_status_set = set(result["Status"] for result in results)
438+
ses_status_set = {result["Status"] for result in results}
439439
anymail_statuses = [
440440
AnymailRecipientStatus(
441441
message_id=result.get("MessageId", None),

anymail/backends/base.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ def is_batch(self):
391391
def unsupported_feature(self, feature):
392392
if not self.backend.ignore_unsupported_features:
393393
raise AnymailUnsupportedFeature(
394-
"%s does not support %s" % (self.esp_name, feature),
394+
f"{self.esp_name} does not support {feature}",
395395
email_message=self.message,
396396
payload=self,
397397
backend=self.backend,
@@ -462,9 +462,7 @@ def validate_not_bare_string(self, attr, value):
462462
# TypeError: can only concatenate list (not "str") to list
463463
# TypeError: Can't convert 'list' object to str implicitly
464464
if isinstance(value, str) or is_lazy(value):
465-
raise TypeError(
466-
'"{attr}" attribute must be a list or other iterable'.format(attr=attr)
467-
)
465+
raise TypeError(f'"{attr}" attribute must be a list or other iterable')
468466

469467
#
470468
# Attribute converters

anymail/backends/base_requests.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ def _dump_api_request(response, **kwargs):
150150
method=request.method,
151151
url=request.url,
152152
headers="".join(
153-
"{header}: {value}\n".format(header=header, value=value)
153+
f"{header}: {value}\n"
154154
for (header, value) in request.headers.items()
155155
),
156156
)
@@ -168,7 +168,7 @@ def _dump_api_request(response, **kwargs):
168168
status=response.status_code,
169169
reason=response.reason,
170170
headers="".join(
171-
"{header}: {value}\n".format(header=header, value=value)
171+
f"{header}: {value}\n"
172172
for (header, value) in response.headers.items()
173173
),
174174
body=response.text, # Let Requests decode body content for us

anymail/backends/mailgun.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,15 @@ def populate_recipient_variables(self):
217217
if self.merge_metadata:
218218

219219
def vkey(key): # 'v:key'
220-
return "v:{}".format(key)
220+
return f"v:{key}"
221221

222222
# all keys used in any recipient's merge_metadata:
223223
merge_metadata_keys = flatset(
224224
recipient_data.keys() for recipient_data in self.merge_metadata.values()
225225
)
226226
# custom_data['key'] = '%recipient.v:key%' indirection:
227227
custom_data.update(
228-
{key: "%recipient.{}%".format(vkey(key)) for key in merge_metadata_keys}
228+
{key: f"%recipient.{vkey(key)}%" for key in merge_metadata_keys}
229229
)
230230
# defaults for each recipient must cover all keys:
231231
base_recipient_data = {
@@ -268,14 +268,14 @@ def vkey(key): # 'v:key'
268268
)
269269
# custom_data['key'] = '%recipient.key%' indirection:
270270
custom_data.update(
271-
{key: "%recipient.{}%".format(key) for key in merge_data_keys}
271+
{key: f"%recipient.{key}%" for key in merge_data_keys}
272272
)
273273

274274
# (6) merge_headers --> Mailgun recipient_variables via 'h:'-prefixed keys
275275
if self.merge_headers:
276276

277277
def hkey(field_name): # 'h:Field-Name'
278-
return "h:{}".format(field_name.title())
278+
return f"h:{field_name.title()}"
279279

280280
merge_header_fields = flatset(
281281
recipient_headers.keys()
@@ -461,4 +461,4 @@ def flatset(iterables):
461461
>>> flatset([1, 2], [2, 3])
462462
set(1, 2, 3)
463463
"""
464-
return set(item for iterable in iterables for item in iterable)
464+
return {item for iterable in iterables for item in iterable}

anymail/backends/mailtrap.py

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
from urllib.parse import quote
33

44
if sys.version_info < (3, 11):
5-
from typing_extensions import Any, Dict, List, Literal, NotRequired, TypedDict
5+
from typing import Any, Literal
6+
7+
from typing_extensions import NotRequired, TypedDict
68
else:
7-
from typing import Any, Dict, List, Literal, NotRequired, TypedDict
9+
from typing import Any, Literal, NotRequired, TypedDict
810

911
from ..exceptions import AnymailRequestsAPIError
1012
from ..message import AnymailMessage, AnymailRecipientStatus
@@ -31,29 +33,26 @@ class MailtrapAttachment(TypedDict):
3133
# Although "from" and "subject" are technically required,
3234
# allow Mailtrap's API to enforce that.
3335
"from": NotRequired[MailtrapAddress],
34-
"to": NotRequired[List[MailtrapAddress]],
35-
"cc": NotRequired[List[MailtrapAddress]],
36-
"bcc": NotRequired[List[MailtrapAddress]],
36+
"to": NotRequired[list[MailtrapAddress]],
37+
"cc": NotRequired[list[MailtrapAddress]],
38+
"bcc": NotRequired[list[MailtrapAddress]],
3739
"reply_to": NotRequired[MailtrapAddress],
38-
"attachments": NotRequired[List[MailtrapAttachment]],
39-
"headers": NotRequired[Dict[str, str]],
40-
"custom_variables": NotRequired[Dict[str, str]],
40+
"attachments": NotRequired[list[MailtrapAttachment]],
41+
"headers": NotRequired[dict[str, str]],
42+
"custom_variables": NotRequired[dict[str, str]],
4143
"subject": NotRequired[str],
4244
"text": NotRequired[str],
4345
"html": NotRequired[str],
4446
"category": NotRequired[str],
4547
"template_uuid": NotRequired[str],
46-
"template_variables": NotRequired[Dict[str, Any]],
48+
"template_variables": NotRequired[dict[str, Any]],
4749
},
4850
)
4951

50-
MailtrapBatchData = TypedDict(
51-
"MailtrapBatchData",
52-
{
53-
"base": MailtrapData,
54-
"requests": List[MailtrapData],
55-
},
56-
)
52+
53+
class MailtrapBatchData(TypedDict):
54+
base: MailtrapData
55+
requests: list[MailtrapData]
5756

5857

5958
class MailtrapPayload(RequestsPayload):
@@ -74,14 +73,14 @@ def __init__(
7473
self.backend = backend
7574

7675
# Late bound batch send data
77-
self.merge_data: Dict[str, Any] = {}
78-
self.merge_metadata: Dict[str, Dict[str, str]] = {}
79-
self.merge_headers: Dict[str, Dict[str, str]] = {}
76+
self.merge_data = dict[str, Any]()
77+
self.merge_metadata = dict[str, dict[str, str]]()
78+
self.merge_headers = dict[str, dict[str, str]]()
8079

8180
# needed for backend.parse_recipient_status
82-
self.recipients_to: List[str] = []
83-
self.recipients_cc: List[str] = []
84-
self.recipients_bcc: List[str] = []
81+
self.recipients_to = list[str]()
82+
self.recipients_cc = list[str]()
83+
self.recipients_bcc = list[str]()
8584

8685
super().__init__(
8786
message, defaults, backend, *args, headers=http_headers, **kwargs
@@ -141,7 +140,7 @@ def set_from_email(self, email: EmailAddress):
141140
self.data["from"] = email.as_dict(idna_encode=self.backend.idna_encode)
142141

143142
def set_recipients(
144-
self, recipient_type: Literal["to", "cc", "bcc"], emails: List[EmailAddress]
143+
self, recipient_type: Literal["to", "cc", "bcc"], emails: list[EmailAddress]
145144
):
146145
assert recipient_type in ["to", "cc", "bcc"]
147146
if emails:
@@ -161,7 +160,7 @@ def set_subject(self, subject):
161160
# (must ignore default empty subject for use with template_uuid)
162161
self.data["subject"] = subject
163162

164-
def set_reply_to(self, emails: List[EmailAddress]):
163+
def set_reply_to(self, emails: list[EmailAddress]):
165164
if len(emails) == 1:
166165
# Let Mailtrap handle the header generation (and EAI if needed)
167166
self.data["reply_to"] = emails[0].as_dict(
@@ -210,7 +209,7 @@ def add_attachment(self, attachment: Attachment):
210209
att["content_id"] = attachment.cid
211210
self.data.setdefault("attachments", []).append(att)
212211

213-
def set_tags(self, tags: List[str]):
212+
def set_tags(self, tags: list[str]):
214213
if len(tags) > 1:
215214
self.unsupported_feature("multiple tags")
216215
if len(tags) > 0:
@@ -232,7 +231,7 @@ def set_merge_headers(self, merge_headers):
232231
# Late-bound in burst_for_batch
233232
self.merge_headers = merge_headers
234233

235-
def set_merge_global_data(self, merge_global_data: Dict[str, Any]):
234+
def set_merge_global_data(self, merge_global_data: dict[str, Any]):
236235
self.data.setdefault("template_variables", {}).update(merge_global_data)
237236

238237
def set_merge_metadata(self, merge_metadata):
@@ -315,7 +314,7 @@ def parse_recipient_status(
315314

316315
# Merge recipient statuses for each item in the batch.
317316
# Each API response includes message_ids in the order 'to', 'cc, 'bcc'.
318-
recipient_status: Dict[str, AnymailRecipientStatus] = {}
317+
recipient_status: dict[str, AnymailRecipientStatus] = {}
319318
for to, one_response in zip(payload.recipients_to, responses):
320319
recipients = [to, *payload.recipients_cc, *payload.recipients_bcc]
321320
one_status = self.parse_one_response(
@@ -339,11 +338,11 @@ def parse_recipient_status(
339338
def parse_one_response(
340339
self,
341340
one_response,
342-
recipients: List[str],
341+
recipients: list[str],
343342
raw_response,
344343
payload: MailtrapPayload,
345344
message: AnymailMessage,
346-
) -> Dict[str, AnymailRecipientStatus]:
345+
) -> dict[str, AnymailRecipientStatus]:
347346
"""
348347
Return parsed status for recipients in one_response, which is either
349348
a top-level send response or an individual 'responses' item for batch send.

anymail/message.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def __init__(self, message_id, status):
117117
try:
118118
# message_id must be something that can be put in a set
119119
# (see AnymailStatus.set_recipient_status)
120-
set([message_id])
120+
{message_id}
121121
except TypeError:
122122
raise TypeError("Invalid message_id %r is not scalar type" % message_id)
123123
if status is not None and status not in ANYMAIL_STATUSES:
@@ -152,11 +152,9 @@ def _repr(o):
152152
else:
153153
return repr(o)
154154

155-
details = ["status={status}".format(status=_repr(self.status))]
155+
details = [f"status={_repr(self.status)}"]
156156
if self.message_id:
157-
details.append(
158-
"message_id={message_id}".format(message_id=_repr(self.message_id))
159-
)
157+
details.append(f"message_id={_repr(self.message_id)}")
160158
if self.recipients:
161159
details.append(
162160
"{num_recipients} recipients".format(
@@ -168,9 +166,7 @@ def _repr(o):
168166
def set_recipient_status(self, recipients):
169167
self.recipients.update(recipients)
170168
recipient_statuses = self.recipients.values()
171-
self.message_id = set(
172-
[recipient.message_id for recipient in recipient_statuses]
173-
)
169+
self.message_id = {recipient.message_id for recipient in recipient_statuses}
174170
if len(self.message_id) == 1:
175171
self.message_id = self.message_id.pop() # de-set-ify if single message_id
176-
self.status = set([recipient.status for recipient in recipient_statuses])
172+
self.status = {recipient.status for recipient in recipient_statuses}

anymail/utils.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -552,17 +552,12 @@ def __init__(self, attachment):
552552
self.cid = unquote(content_id) # without the <>
553553

554554
def __repr__(self):
555-
details = [
556-
self.mimetype,
557-
"len={length}".format(length=len(self.content)),
558-
]
555+
details = [self.mimetype, f"len={len(self.content)}"]
559556
if self.name:
560-
details.append("name={name!r}".format(name=self.name))
557+
details.append(f"name={self.name!r}")
561558
if self.inline:
562559
details.insert(0, "inline")
563-
details.append(
564-
"content_id={content_id!r}".format(content_id=self.content_id)
565-
)
560+
details.append(f"content_id={self.content_id!r}")
566561
return "Attachment<{details}>".format(details=", ".join(details))
567562

568563
@property
@@ -644,12 +639,12 @@ def get_anymail_setting(
644639
except AttributeError:
645640
pass
646641
if default is UNSET:
647-
message = "You must set %s or ANYMAIL = {'%s': ...}" % (
648-
anymail_setting,
649-
setting,
642+
message = (
643+
f"You must set {anymail_setting} or ANYMAIL = {{'{setting}': ...}}"
650644
)
645+
651646
if allow_bare:
652-
message += " or %s" % setting
647+
message += f" or {setting}"
653648
message += " in your Django settings"
654649
raise AnymailConfigurationError(message) from None
655650
else:

anymail/webhooks/amazon_ses.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,7 @@ def auto_confirm_sns_subscription(self, sns_message):
208208
_resource,
209209
) = topic_arn.split(":", maxsplit=6)
210210
except (TypeError, ValueError):
211-
raise ValueError(
212-
"Invalid ARN format '{topic_arn!s}'".format(topic_arn=topic_arn)
213-
)
211+
raise ValueError(f"Invalid ARN format '{topic_arn!s}'")
214212

215213
sns_client = self.get_boto_client("sns", region_name=region)
216214
try:

anymail/webhooks/mailgun.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def validate_request(self, request):
9191

9292
expected_signature = hmac.new(
9393
key=self.webhook_signing_key,
94-
msg="{}{}".format(timestamp, token).encode("ascii"),
94+
msg=f"{timestamp}{token}".encode("ascii"),
9595
digestmod=hashlib.sha256,
9696
).hexdigest()
9797
if not constant_time_compare(signature, expected_signature):
@@ -165,7 +165,7 @@ def esp_to_anymail_event(self, esp_event):
165165
except KeyError:
166166
message_id = None
167167
if message_id and not message_id.startswith("<"):
168-
message_id = "<{}>".format(message_id)
168+
message_id = f"<{message_id}>"
169169

170170
metadata = event_data.get("user-variables", {})
171171
tags = event_data.get("tags", [])
@@ -270,7 +270,7 @@ def mailgun_legacy_to_anymail_event(self, esp_event):
270270
"message-id", None
271271
)
272272
if message_id and not message_id.startswith("<"):
273-
message_id = "<{}>".format(message_id)
273+
message_id = f"<{message_id}>"
274274

275275
description = esp_event.getfirst("description", None)
276276
mta_response = esp_event.getfirst("error", None) or esp_event.getfirst(

anymail/webhooks/mailtrap.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
from datetime import datetime, timezone
44

55
if sys.version_info < (3, 11):
6-
from typing_extensions import Dict, Literal, NotRequired, TypedDict, Union
6+
from typing import Literal
7+
8+
from typing_extensions import NotRequired, TypedDict
79
else:
8-
from typing import Dict, Literal, NotRequired, TypedDict, Union
10+
from typing import Literal, NotRequired, TypedDict
911

1012
from ..signals import AnymailTrackingEvent, EventType, RejectReason, tracking
1113
from .base import AnymailBaseWebhookView
@@ -30,7 +32,7 @@ class MailtrapEvent(TypedDict):
3032
timestamp: int
3133
event_id: str
3234
category: NotRequired[str]
33-
custom_variables: NotRequired[Dict[str, Union[str, int, float, bool]]]
35+
custom_variables: NotRequired[dict[str, str | int | float | bool]]
3436
reason: NotRequired[str]
3537
response: NotRequired[str]
3638
response_code: NotRequired[int]

0 commit comments

Comments
 (0)