Skip to content

Commit 11f1b70

Browse files
gh-153417: Fix BytesWarning in imaplib error messages for bytes arguments (GH-153423)
IMAP4.select() and IMAP4.uid() formatted the mailbox and command argument with %s in their error messages, which raised BytesWarning under -bb when the argument was bytes and masked the real error. Use %r instead, which is safe for bytes and also quotes the value. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent cd9994e commit 11f1b70

3 files changed

Lines changed: 31 additions & 2 deletions

File tree

Lib/imaplib.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ def select(self, mailbox='INBOX', readonly=False):
960960
if __debug__:
961961
if self.debug >= 1:
962962
self._dump_ur(self.untagged_responses)
963-
raise self.readonly('%s is not writable' % mailbox)
963+
raise self.readonly('%r is not writable' % (mailbox,))
964964
return typ, self.untagged_responses.get('EXISTS', [None])
965965

966966

@@ -1085,7 +1085,7 @@ def uid(self, command, *args):
10851085
"""
10861086
command = command.upper()
10871087
if not command in Commands:
1088-
raise self.error("Unknown IMAP4 UID command: %s" % command)
1088+
raise self.error("Unknown IMAP4 UID command: %r" % (command,))
10891089
if self.state not in Commands[command]:
10901090
raise self.error("command %s illegal in state %s, "
10911091
"only allowed in states %s" %

Lib/test/test_imaplib.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,32 @@ def cmd_CAPABILITY(self, tag, args):
995995
client.login('user', 'pass')
996996
self.assertIn('ENABLE', client.capabilities)
997997

998+
def test_readonly_error_reports_mailbox(self):
999+
# The read-only error reports the mailbox via repr(), which also
1000+
# avoids BytesWarning for a bytes mailbox under -bb.
1001+
class ReadOnlyHandler(SimpleIMAPHandler):
1002+
def cmd_SELECT(self, tag, args):
1003+
self._send_line(b'* 2 EXISTS')
1004+
self._send_tagged(tag, 'OK', '[READ-ONLY] SELECT completed.')
1005+
client, _ = self._setup(ReadOnlyHandler)
1006+
client.login('user', 'pass')
1007+
for mailbox, expected in [('INBOX', "'INBOX'"), (b'INBOX', r"b'INBOX'")]:
1008+
with self.subTest(mailbox=mailbox):
1009+
with self.assertRaisesRegex(imaplib.IMAP4.readonly,
1010+
r"%s is not writable" % expected):
1011+
client.select(mailbox)
1012+
1013+
def test_uid_unknown_command_reports_command(self):
1014+
# The unknown-UID-command error reports the command via repr(), which
1015+
# also avoids BytesWarning for a bytes command under -bb.
1016+
client, _ = self._setup(SimpleIMAPHandler)
1017+
for command, expected in [('BOGUS', "'BOGUS'"), (b'BOGUS', r"b'BOGUS'")]:
1018+
with self.subTest(command=command):
1019+
with self.assertRaisesRegex(
1020+
imaplib.IMAP4.error,
1021+
r"Unknown IMAP4 UID command: %s" % expected):
1022+
client.uid(command, '1')
1023+
9981024
def test_logout(self):
9991025
client, _ = self._setup(SimpleIMAPHandler)
10001026
typ, data = client.login('user', 'pass')
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Error messages from :meth:`imaplib.IMAP4.select` and :meth:`imaplib.IMAP4.uid`
2+
no longer raise :exc:`BytesWarning` under :option:`!-bb`
3+
when the mailbox or command argument is :class:`bytes`.

0 commit comments

Comments
 (0)