Skip to content

Commit e3e8d4f

Browse files
serhiy-storchakaclaude
authored andcommitted
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. (cherry picked from commit 11f1b70) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 246d9ad commit e3e8d4f

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
@@ -893,7 +893,7 @@ def select(self, mailbox='INBOX', readonly=False):
893893
if __debug__:
894894
if self.debug >= 1:
895895
self._dump_ur(self.untagged_responses)
896-
raise self.readonly('%s is not writable' % mailbox)
896+
raise self.readonly('%r is not writable' % (mailbox,))
897897
return typ, self.untagged_responses.get('EXISTS', [None])
898898

899899

@@ -1017,7 +1017,7 @@ def uid(self, command, *args):
10171017
"""
10181018
command = command.upper()
10191019
if not command in Commands:
1020-
raise self.error("Unknown IMAP4 UID command: %s" % command)
1020+
raise self.error("Unknown IMAP4 UID command: %r" % (command,))
10211021
if self.state not in Commands[command]:
10221022
raise self.error("command %s illegal in state %s, "
10231023
"only allowed in states %s" %

Lib/test/test_imaplib.py

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

951+
def test_readonly_error_reports_mailbox(self):
952+
# The read-only error reports the mailbox via repr(), which also
953+
# avoids BytesWarning for a bytes mailbox under -bb.
954+
class ReadOnlyHandler(SimpleIMAPHandler):
955+
def cmd_SELECT(self, tag, args):
956+
self._send_line(b'* 2 EXISTS')
957+
self._send_tagged(tag, 'OK', '[READ-ONLY] SELECT completed.')
958+
client, _ = self._setup(ReadOnlyHandler)
959+
client.login('user', 'pass')
960+
for mailbox, expected in [('INBOX', "'INBOX'"), (b'INBOX', r"b'INBOX'")]:
961+
with self.subTest(mailbox=mailbox):
962+
with self.assertRaisesRegex(imaplib.IMAP4.readonly,
963+
r"%s is not writable" % expected):
964+
client.select(mailbox)
965+
966+
def test_uid_unknown_command_reports_command(self):
967+
# The unknown-UID-command error reports the command via repr(), which
968+
# also avoids BytesWarning for a bytes command under -bb.
969+
client, _ = self._setup(SimpleIMAPHandler)
970+
for command, expected in [('BOGUS', "'BOGUS'"), (b'BOGUS', r"b'BOGUS'")]:
971+
with self.subTest(command=command):
972+
with self.assertRaisesRegex(
973+
imaplib.IMAP4.error,
974+
r"Unknown IMAP4 UID command: %s" % expected):
975+
client.uid(command, '1')
976+
951977
def test_logout(self):
952978
client, _ = self._setup(SimpleIMAPHandler)
953979
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)