bpo-40375: Implement imaplib.IMAP4.unselect (GH-19712)

This commit is contained in:
Dong-hee Na 2020-04-27 23:52:55 +09:00 committed by GitHub
parent 91a5ae1835
commit c5c42815ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 0 deletions

View File

@ -582,6 +582,15 @@ An :class:`IMAP4` instance has the following methods:
Unsubscribe from old mailbox. Unsubscribe from old mailbox.
.. method:: IMAP4.unselect()
:meth:`imaplib.IMAP4.unselect` frees server's resources associated with the
selected mailbox and returns the server to the authenticated
state. This command performs the same actions as :meth:`imaplib.IMAP4.close`, except
that no messages are permanently removed from the currently
selected mailbox.
.. versionadded:: 3.9
.. method:: IMAP4.xatom(name[, ...]) .. method:: IMAP4.xatom(name[, ...])

View File

@ -320,6 +320,13 @@ with this change. The overridden methods of :class:`~imaplib.IMAP4_SSL` and
:class:`~imaplib.IMAP4_stream` were applied to this change. :class:`~imaplib.IMAP4_stream` were applied to this change.
(Contributed by Dong-hee Na in :issue:`38615`.) (Contributed by Dong-hee Na in :issue:`38615`.)
:meth:`imaplib.IMAP4.unselect` is added.
:meth:`imaplib.IMAP4.unselect` frees server's resources associated with the
selected mailbox and returns the server to the authenticated
state. This command performs the same actions as :meth:`imaplib.IMAP4.close`, except
that no messages are permanently removed from the currently
selected mailbox. (Contributed by Dong-hee Na in :issue:`40375`.)
importlib importlib
--------- ---------

View File

@ -98,6 +98,7 @@ Commands = {
'THREAD': ('SELECTED',), 'THREAD': ('SELECTED',),
'UID': ('SELECTED',), 'UID': ('SELECTED',),
'UNSUBSCRIBE': ('AUTH', 'SELECTED'), 'UNSUBSCRIBE': ('AUTH', 'SELECTED'),
'UNSELECT': ('SELECTED',),
} }
# Patterns to match server responses # Patterns to match server responses
@ -902,6 +903,22 @@ class IMAP4:
return self._simple_command('UNSUBSCRIBE', mailbox) return self._simple_command('UNSUBSCRIBE', mailbox)
def unselect(self):
"""Free server's resources associated with the selected mailbox
and returns the server to the authenticated state.
This command performs the same actions as CLOSE, except
that no messages are permanently removed from the currently
selected mailbox.
(typ, [data]) = <instance>.unselect()
"""
try:
typ, data = self._simple_command('UNSELECT')
finally:
self.state = 'AUTH'
return typ, data
def xatom(self, name, *args): def xatom(self, name, *args):
"""Allow simple extension commands """Allow simple extension commands
notified by server in CAPABILITY response. notified by server in CAPABILITY response.

View File

@ -116,6 +116,7 @@ class SimpleIMAPHandler(socketserver.StreamRequestHandler):
def setup(self): def setup(self):
super().setup() super().setup()
self.server.is_selected = False
self.server.logged = None self.server.logged = None
def _send(self, message): def _send(self, message):
@ -190,6 +191,18 @@ class SimpleIMAPHandler(socketserver.StreamRequestHandler):
self.server.logged = args[0] self.server.logged = args[0]
self._send_tagged(tag, 'OK', 'LOGIN completed') self._send_tagged(tag, 'OK', 'LOGIN completed')
def cmd_SELECT(self, tag, args):
self.server.is_selected = True
self._send_line(b'* 2 EXISTS')
self._send_tagged(tag, 'OK', '[READ-WRITE] SELECT completed.')
def cmd_UNSELECT(self, tag, args):
if self.server.is_selected:
self.server.is_selected = False
self._send_tagged(tag, 'OK', 'Returned to authenticated state. (Success)')
else:
self._send_tagged(tag, 'BAD', 'No mailbox selected')
class NewIMAPTestsMixin(): class NewIMAPTestsMixin():
client = None client = None
@ -511,6 +524,18 @@ class NewIMAPTestsMixin():
self.assertEqual(typ, 'OK') self.assertEqual(typ, 'OK')
self.assertEqual(data[0], b'() "." directoryA') self.assertEqual(data[0], b'() "." directoryA')
def test_unselect(self):
client, _ = self._setup(SimpleIMAPHandler)
client.login('user', 'pass')
typ, data = client.select()
self.assertEqual(typ, 'OK')
self.assertEqual(data[0], b'2')
typ, data = client.unselect()
self.assertEqual(typ, 'OK')
self.assertEqual(data[0], b'Returned to authenticated state. (Success)')
self.assertEqual(client.state, 'AUTH')
class NewIMAPTests(NewIMAPTestsMixin, unittest.TestCase): class NewIMAPTests(NewIMAPTestsMixin, unittest.TestCase):
imap_class = imaplib.IMAP4 imap_class = imaplib.IMAP4

View File

@ -0,0 +1 @@
:meth:`imaplib.IMAP4.unselect` is added. Patch by Dong-hee Na.