imaplib2: bump to v2.41

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2015-03-18 21:54:36 +01:00
parent cf2a2c769c
commit 43dbe1578c

View File

@ -17,9 +17,9 @@ Public functions: Internaldate2Time
__all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream", __all__ = ("IMAP4", "IMAP4_SSL", "IMAP4_stream",
"Internaldate2Time", "ParseFlags", "Time2Internaldate") "Internaldate2Time", "ParseFlags", "Time2Internaldate")
__version__ = "2.37" __version__ = "2.41"
__release__ = "2" __release__ = "2"
__revision__ = "37" __revision__ = "41"
__credits__ = """ __credits__ = """
Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998. Authentication code contributed by Donn Cave <donn@u.washington.edu> June 1998.
String method conversion by ESR, February 2001. String method conversion by ESR, February 2001.
@ -43,12 +43,22 @@ Single quoting introduced with the help of Vladimir Marek <vladimir.marek@oracle
Support for specifying SSL version by Ryan Kavanagh <rak@debian.org> July 2013. Support for specifying SSL version by Ryan Kavanagh <rak@debian.org> July 2013.
Fix for gmail "read 0" error provided by Jim Greenleaf <james.a.greenleaf@gmail.com> August 2013. Fix for gmail "read 0" error provided by Jim Greenleaf <james.a.greenleaf@gmail.com> August 2013.
Fix for offlineimap "indexerror: string index out of range" bug provided by Eygene Ryabinkin <rea@codelabs.ru> August 2013. Fix for offlineimap "indexerror: string index out of range" bug provided by Eygene Ryabinkin <rea@codelabs.ru> August 2013.
Fix for missing idle_lock in _handler() provided by Franklin Brook <franklin@brook.se> August 2014""" Fix for missing idle_lock in _handler() provided by Franklin Brook <franklin@brook.se> August 2014.
Conversion to Python3 provided by F. Malina <fmalina@gmail.com> February 2015.
Fix for READ-ONLY error from multiple EXAMINE/SELECT calls for same mailbox by <piloub@users.sf.net> March 2015."""
__author__ = "Piers Lauder <piers@janeelix.com>" __author__ = "Piers Lauder <piers@janeelix.com>"
__URL__ = "http://imaplib2.sourceforge.net" __URL__ = "http://imaplib2.sourceforge.net"
__license__ = "Python License" __license__ = "Python License"
import binascii, errno, os, Queue, random, re, select, socket, sys, time, threading, traceback, zlib import binascii, errno, os, random, re, select, socket, sys, time, threading, zlib
try:
import queue # py3
string_types = str
except ImportError:
import Queue as queue # py2
string_types = basestring
select_module = select select_module = select
@ -160,13 +170,9 @@ class Request(object):
self.data = None self.data = None
def abort_tb(self, typ, val, tb):
self.aborted = (typ, val, tb)
self.deliver(None)
def abort(self, typ, val): def abort(self, typ, val):
self.abort_tb(typ, val, traceback.extract_stack()) self.aborted = (typ, val)
self.deliver(None)
def get_response(self, exc_fmt=None): def get_response(self, exc_fmt=None):
@ -175,10 +181,10 @@ class Request(object):
self.ready.wait() self.ready.wait()
if self.aborted is not None: if self.aborted is not None:
typ, val, tb = self.aborted typ, val = self.aborted
if exc_fmt is None: if exc_fmt is None:
exc_fmt = '%s - %%s' % typ exc_fmt = '%s - %%s' % typ
raise typ, typ(exc_fmt % str(val)), tb raise typ(exc_fmt % str(val))
return self.response return self.response
@ -256,7 +262,7 @@ class IMAP4(object):
containing the wildcard character '*', then enclose the argument containing the wildcard character '*', then enclose the argument
in single quotes: the quotes will be removed and the resulting in single quotes: the quotes will be removed and the resulting
string passed unquoted. Note also that you can pass in an argument string passed unquoted. Note also that you can pass in an argument
with a type that doesn't evaluate to 'basestring' (eg: 'bytearray') with a type that doesn't evaluate to 'string_types' (eg: 'bytearray')
and it will be converted to a string without quoting. and it will be converted to a string without quoting.
There is one instance variable, 'state', that is useful for tracking There is one instance variable, 'state', that is useful for tracking
@ -301,7 +307,6 @@ class IMAP4(object):
self.tagged_commands = {} # Tagged commands awaiting response self.tagged_commands = {} # Tagged commands awaiting response
self.untagged_responses = [] # [[typ: [data, ...]], ...] self.untagged_responses = [] # [[typ: [data, ...]], ...]
self.mailbox = None # Current mailbox selected self.mailbox = None # Current mailbox selected
self.mailboxes = {} # Untagged responses state per mailbox
self.is_readonly = False # READ-ONLY desired state self.is_readonly = False # READ-ONLY desired state
self.idle_rqb = None # Server IDLE Request - see _IdleCont self.idle_rqb = None # Server IDLE Request - see _IdleCont
self.idle_timeout = None # Must prod server occasionally self.idle_timeout = None # Must prod server occasionally
@ -357,8 +362,8 @@ class IMAP4(object):
self.commands_lock = threading.Lock() self.commands_lock = threading.Lock()
self.idle_lock = threading.Lock() self.idle_lock = threading.Lock()
self.ouq = Queue.Queue(10) self.ouq = queue.Queue(10)
self.inq = Queue.Queue() self.inq = queue.Queue()
self.wrth = threading.Thread(target=self._writer) self.wrth = threading.Thread(target=self._writer)
self.wrth.setDaemon(True) self.wrth.setDaemon(True)
@ -435,19 +440,19 @@ class IMAP4(object):
af, socktype, proto, canonname, sa = res af, socktype, proto, canonname, sa = res
try: try:
s = socket.socket(af, socktype, proto) s = socket.socket(af, socktype, proto)
except socket.error, msg: except socket.error as msg:
continue continue
try: try:
for i in (0, 1): for i in (0, 1):
try: try:
s.connect(sa) s.connect(sa)
break break
except socket.error, msg: except socket.error as msg:
if len(msg.args) < 2 or msg.args[0] != errno.EINTR: if len(msg.args) < 2 or msg.args[0] != errno.EINTR:
raise raise
else: else:
raise socket.error(msg) raise socket.error(msg)
except socket.error, msg: except socket.error as msg:
s.close() s.close()
continue continue
break break
@ -527,7 +532,10 @@ class IMAP4(object):
data = self.compressor.compress(data) data = self.compressor.compress(data)
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
self.sock.sendall(data) if bytes != str:
self.sock.sendall(bytes(data, 'utf8'))
else:
self.sock.sendall(data)
def shutdown(self): def shutdown(self):
@ -813,7 +821,8 @@ class IMAP4(object):
data = kv_pairs[0] # Assume invoker passing correctly formatted string (back-compat) data = kv_pairs[0] # Assume invoker passing correctly formatted string (back-compat)
else: else:
data = '(%s)' % ' '.join([(arg and self._quote(arg) or 'NIL') for arg in kv_pairs]) data = '(%s)' % ' '.join([(arg and self._quote(arg) or 'NIL') for arg in kv_pairs])
return self._simple_command(name, (data,), **kw)
return self._simple_command(name, data, **kw)
def idle(self, timeout=None, **kw): def idle(self, timeout=None, **kw):
@ -981,20 +990,14 @@ class IMAP4(object):
def select(self, mailbox='INBOX', readonly=False, **kw): def select(self, mailbox='INBOX', readonly=False, **kw):
"""(typ, [data]) = select(mailbox='INBOX', readonly=False) """(typ, [data]) = select(mailbox='INBOX', readonly=False)
Select a mailbox. (Restores any previous untagged responses.) Select a mailbox. (Flushes all untagged responses.)
'data' is count of messages in mailbox ('EXISTS' response). 'data' is count of messages in mailbox ('EXISTS' response).
Mandated responses are ('FLAGS', 'EXISTS', 'RECENT', 'UIDVALIDITY'), so Mandated responses are ('FLAGS', 'EXISTS', 'RECENT', 'UIDVALIDITY'), so
other responses should be obtained via "response('FLAGS')" etc.""" other responses should be obtained via "response('FLAGS')" etc."""
self.commands_lock.acquire()
# Save state of old mailbox, restore state for new...
self.mailboxes[self.mailbox] = self.untagged_responses
self.untagged_responses = self.mailboxes.setdefault(mailbox, [])
self.commands_lock.release()
self.mailbox = mailbox self.mailbox = mailbox
self.is_readonly = readonly and True or False self.is_readonly = bool(readonly)
if readonly: if readonly:
name = 'EXAMINE' name = 'EXAMINE'
else: else:
@ -1240,7 +1243,7 @@ class IMAP4(object):
# Must quote command args if "atom-specials" present, # Must quote command args if "atom-specials" present,
# and not already quoted. NB: single quotes are removed. # and not already quoted. NB: single quotes are removed.
if not isinstance(arg, basestring): if not isinstance(arg, string_types):
return arg return arg
if len(arg) >= 2 and (arg[0],arg[-1]) in (('(',')'),('"','"')): if len(arg) >= 2 and (arg[0],arg[-1]) in (('(',')'),('"','"')):
return arg return arg
@ -1252,8 +1255,8 @@ class IMAP4(object):
def _choose_nonull_or_dflt(self, dflt, *args): def _choose_nonull_or_dflt(self, dflt, *args):
if isinstance(dflt, basestring): if isinstance(dflt, string_types):
dflttyp = basestring # Allow any string type dflttyp = string_types # Allow any string type
else: else:
dflttyp = type(dflt) dflttyp = type(dflt)
for arg in args: for arg in args:
@ -1303,12 +1306,16 @@ class IMAP4(object):
self._check_bye() self._check_bye()
for typ in ('OK', 'NO', 'BAD'): if name in ('EXAMINE', 'SELECT'):
self._get_untagged_response(typ) self.untagged_responses = [] # Flush all untagged responses
else:
for typ in ('OK', 'NO', 'BAD'):
while self._get_untagged_response(typ):
continue
if self._get_untagged_response('READ-ONLY', leave=True) and not self.is_readonly: if self._get_untagged_response('READ-ONLY', leave=True) and not self.is_readonly:
self.literal = None self.literal = None
raise self.readonly('mailbox status changed to READ-ONLY') raise self.readonly('mailbox status changed to READ-ONLY')
if self.Terminate: if self.Terminate:
raise self.abort('connection closed') raise self.abort('connection closed')
@ -1323,7 +1330,7 @@ class IMAP4(object):
literal = self.literal literal = self.literal
if literal is not None: if literal is not None:
self.literal = None self.literal = None
if isinstance(literal, basestring): if isinstance(literal, string_types):
literator = None literator = None
data = '%s {%s}' % (data, len(literal)) data = '%s {%s}' % (data, len(literal))
else: else:
@ -1389,9 +1396,10 @@ class IMAP4(object):
return typ, dat return typ, dat
def _command_completer(self, (response, cb_arg, error)): def _command_completer(self, cb_arg_list):
# Called for callback commands # Called for callback commands
(response, cb_arg, error) = cb_arg_list
rqb, kw = cb_arg rqb, kw = cb_arg
rqb.callback = kw['callback'] rqb.callback = kw['callback']
rqb.callback_arg = kw.get('cb_arg') rqb.callback_arg = kw.get('cb_arg')
@ -1665,7 +1673,7 @@ class IMAP4(object):
if __debug__: self._log(1, 'starting') if __debug__: self._log(1, 'starting')
typ, val, tb = self.abort, 'connection terminated', None typ, val = self.abort, 'connection terminated'
while not self.Terminate: while not self.Terminate:
@ -1683,12 +1691,11 @@ class IMAP4(object):
try: try:
line = self.inq.get(True, timeout) line = self.inq.get(True, timeout)
except Queue.Empty: except queue.Empty:
if self.idle_rqb is None: if self.idle_rqb is None:
if resp_timeout is not None and self.tagged_commands: if resp_timeout is not None and self.tagged_commands:
if __debug__: self._log(1, 'response timeout') if __debug__: self._log(1, 'response timeout')
typ, val = self.abort, 'no response after %s secs' % resp_timeout typ, val = self.abort, 'no response after %s secs' % resp_timeout
tb = traceback.extract_stack()
break break
continue continue
if self.idle_timeout > time.time(): if self.idle_timeout > time.time():
@ -1700,41 +1707,33 @@ class IMAP4(object):
if __debug__: self._log(1, 'inq None - terminating') if __debug__: self._log(1, 'inq None - terminating')
break break
# self.inq can contain tuple, it means we got an exception. if not isinstance(line, string_types):
# For example of code that produces tuple see IMAP4._reader() typ, val = line
# and IMAP4._writer().
#
# XXX: may be it will be more explicit to create own exception
# XXX: class and pass it instead of tuple.
if not isinstance(line, basestring):
typ, val, tb = line
break break
try: try:
self._put_response(line) self._put_response(line)
except: except:
typ, val = self.error, 'program error: %s - %s' % sys.exc_info()[:2] typ, val = self.error, 'program error: %s - %s' % sys.exc_info()[:2]
tb = sys.exc_info()[2]
break break
self.Terminate = True self.Terminate = True
if not tb:
tb = traceback.extract_stack()
if __debug__: self._log(1, 'terminating: %s' % repr(val)) if __debug__: self._log(1, 'terminating: %s' % repr(val))
while not self.ouq.empty(): while not self.ouq.empty():
try: try:
self.ouq.get_nowait().abort_tb(typ, val, tb) qel = self.ouq.get_nowait()
except Queue.Empty: if qel is not None:
qel.abort(typ, val)
except queue.Empty:
break break
self.ouq.put(None) self.ouq.put(None)
self.commands_lock.acquire() self.commands_lock.acquire()
for name in self.tagged_commands.keys(): for name in list(self.tagged_commands.keys()):
rqb = self.tagged_commands.pop(name) rqb = self.tagged_commands.pop(name)
rqb.abort_tb(typ, val, tb) rqb.abort(typ, val)
self.state_change_free.set() self.state_change_free.set()
self.commands_lock.release() self.commands_lock.release()
if __debug__: self._log(3, 'state_change_free.set') if __debug__: self._log(3, 'state_change_free.set')
@ -1795,13 +1794,22 @@ class IMAP4(object):
rxzero = 0 rxzero = 0
while True: while True:
stop = data.find('\n', start) if bytes != str:
if stop < 0: stop = data.find(b'\n', start)
line_part += data[start:] if stop < 0:
break line_part += data[start:].decode()
stop += 1 break
line_part, start, line = \ stop += 1
'', stop, line_part + data[start:stop] line_part, start, line = \
'', stop, line_part + data[start:stop].decode()
else:
stop = data.find('\n', start)
if stop < 0:
line_part += data[start:]
break
stop += 1
line_part, start, line = \
'', stop, line_part + data[start:stop]
if __debug__: self._log(4, '< %s' % line) if __debug__: self._log(4, '< %s' % line)
self.inq.put(line) self.inq.put(line)
if self.TerminateReader: if self.TerminateReader:
@ -1816,7 +1824,7 @@ class IMAP4(object):
self._print_log() self._print_log()
if self.debug: self.debug += 4 # Output all if self.debug: self.debug += 4 # Output all
self._log(1, reason) self._log(1, reason)
self.inq.put((self.abort, reason, sys.exc_info()[2])) self.inq.put((self.abort, reason))
break break
poll.unregister(self.read_fd) poll.unregister(self.read_fd)
@ -1862,13 +1870,22 @@ class IMAP4(object):
rxzero = 0 rxzero = 0
while True: while True:
stop = data.find('\n', start) if bytes != str:
if stop < 0: stop = data.find(b'\n', start)
line_part += data[start:] if stop < 0:
break line_part += data[start:].decode()
stop += 1 break
line_part, start, line = \ stop += 1
'', stop, line_part + data[start:stop] line_part, start, line = \
'', stop, line_part + data[start:stop].decode()
else:
stop = data.find('\n', start)
if stop < 0:
line_part += data[start:]
break
stop += 1
line_part, start, line = \
'', stop, line_part + data[start:stop]
if __debug__: self._log(4, '< %s' % line) if __debug__: self._log(4, '< %s' % line)
self.inq.put(line) self.inq.put(line)
if self.TerminateReader: if self.TerminateReader:
@ -1880,7 +1897,7 @@ class IMAP4(object):
self._print_log() self._print_log()
if self.debug: self.debug += 4 # Output all if self.debug: self.debug += 4 # Output all
self._log(1, reason) self._log(1, reason)
self.inq.put((self.abort, reason, sys.exc_info()[2])) self.inq.put((self.abort, reason))
break break
if __debug__: self._log(1, 'finished') if __debug__: self._log(1, 'finished')
@ -1893,7 +1910,6 @@ class IMAP4(object):
if __debug__: self._log(1, 'starting') if __debug__: self._log(1, 'starting')
reason = 'Terminated' reason = 'Terminated'
tb = None
while not self.Terminate: while not self.Terminate:
rqb = self.ouq.get() rqb = self.ouq.get()
@ -1905,19 +1921,15 @@ class IMAP4(object):
if __debug__: self._log(4, '> %s' % rqb.data) if __debug__: self._log(4, '> %s' % rqb.data)
except: except:
reason = 'socket error: %s - %s' % sys.exc_info()[:2] reason = 'socket error: %s - %s' % sys.exc_info()[:2]
tb = sys.exc_info()[2]
if __debug__: if __debug__:
if not self.Terminate: if not self.Terminate:
self._print_log() self._print_log()
if self.debug: self.debug += 4 # Output all if self.debug: self.debug += 4 # Output all
self._log(1, reason) self._log(1, reason)
rqb.abort_tb(self.abort, reason, tb) rqb.abort(self.abort, reason)
break break
if not tb: self.inq.put((self.abort, reason))
tb = traceback.extract_stack()
self.inq.put((self.abort, reason, tb))
if __debug__: self._log(1, 'finished') if __debug__: self._log(1, 'finished')
@ -1952,7 +1964,7 @@ class IMAP4(object):
return return
t = '\n\t\t' t = '\n\t\t'
l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l) l = ['%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or '') for x in l]
self.debug_lock.acquire() self.debug_lock.acquire()
self._mesg('untagged responses dump:%s%s' % (t, t.join(l))) self._mesg('untagged responses dump:%s%s' % (t, t.join(l)))
self.debug_lock.release() self.debug_lock.release()
@ -2082,16 +2094,28 @@ class IMAP4_SSL(IMAP4):
data = self.compressor.compress(data) data = self.compressor.compress(data)
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
if hasattr(self.sock, "sendall"): if bytes != str:
self.sock.sendall(data) if hasattr(self.sock, "sendall"):
self.sock.sendall(bytes(data, 'utf8'))
else:
dlen = len(data)
while dlen > 0:
sent = self.sock.write(bytes(data, 'utf8'))
if sent == dlen:
break # avoid copy
data = data[sent:]
dlen = dlen - sent
else: else:
bytes = len(data) if hasattr(self.sock, "sendall"):
while bytes > 0: self.sock.sendall(data)
sent = self.sock.write(data) else:
if sent == bytes: dlen = len(data)
break # avoid copy while dlen > 0:
data = data[sent:] sent = self.sock.write(data)
bytes = bytes - sent if sent == dlen:
break # avoid copy
data = data[sent:]
dlen = dlen - sent
def ssl(self): def ssl(self):
@ -2165,7 +2189,10 @@ class IMAP4_stream(IMAP4):
data = self.compressor.compress(data) data = self.compressor.compress(data)
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
self.writefile.write(data) if bytes != str:
self.writefile.write(bytes(data, 'utf8'))
else:
self.writefile.write(data)
self.writefile.flush() self.writefile.flush()
@ -2243,7 +2270,7 @@ class _IdleCont(object):
MonthNames = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', MonthNames = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
Mon2num = dict(zip((x.encode() for x in MonthNames[1:]), range(1, 13))) Mon2num = dict(list(zip((x.encode() for x in MonthNames[1:]), list(range(1, 13)))))
InternalDate = re.compile(r'.*INTERNALDATE "' InternalDate = re.compile(r'.*INTERNALDATE "'
r'(?P<day>[ 0123][0-9])-(?P<mon>[A-Z][a-z][a-z])-(?P<year>[0-9][0-9][0-9][0-9])' r'(?P<day>[ 0123][0-9])-(?P<mon>[A-Z][a-z][a-z])-(?P<year>[0-9][0-9][0-9][0-9])'
@ -2347,7 +2374,7 @@ if __name__ == '__main__':
try: try:
optlist, args = getopt.getopt(sys.argv[1:], 'd:il:s:p:') optlist, args = getopt.getopt(sys.argv[1:], 'd:il:s:p:')
except getopt.error, val: except getopt.error as val:
optlist, args = (), () optlist, args = (), ()
debug, debug_buf_lvl, port, stream_command, keyfile, certfile, idle_intr = (None,)*7 debug, debug_buf_lvl, port, stream_command, keyfile, certfile, idle_intr = (None,)*7
@ -2380,13 +2407,14 @@ if __name__ == '__main__':
% {'user':USER, 'lf':'\n', 'data':data} % {'user':USER, 'lf':'\n', 'data':data}
test_seq1 = [ test_seq1 = [
('list', ('""', '""')),
('list', ('""', '%')), ('list', ('""', '%')),
('create', ('/tmp/imaplib2_test.0',)), ('create', ('imaplib2_test0',)),
('rename', ('/tmp/imaplib2_test.0', '/tmp/imaplib2_test.1')), ('rename', ('imaplib2_test0', 'imaplib2_test1')),
('CREATE', ('/tmp/imaplib2_test.2',)), ('CREATE', ('imaplib2_test2',)),
('append', ('/tmp/imaplib2_test.2', None, None, test_mesg)), ('append', ('imaplib2_test2', None, None, test_mesg)),
('list', ('/tmp', 'imaplib2_test*')), ('list', ('', 'imaplib2_test%')),
('select', ('/tmp/imaplib2_test.2',)), ('select', ('imaplib2_test2',)),
('search', (None, 'SUBJECT', 'IMAP4 test')), ('search', (None, 'SUBJECT', 'IMAP4 test')),
('fetch', ("'1:*'", '(FLAGS INTERNALDATE RFC822)')), ('fetch', ("'1:*'", '(FLAGS INTERNALDATE RFC822)')),
('store', ('1', 'FLAGS', '(\Deleted)')), ('store', ('1', 'FLAGS', '(\Deleted)')),
@ -2405,12 +2433,17 @@ if __name__ == '__main__':
('uid', ('SEARCH', 'ALL')), ('uid', ('SEARCH', 'ALL')),
('uid', ('THREAD', 'references', 'UTF-8', '(SEEN)')), ('uid', ('THREAD', 'references', 'UTF-8', '(SEEN)')),
('recent', ()), ('recent', ()),
('examine', ()),
('select', ()),
('examine', ()),
('select', ()),
) )
AsyncError = None AsyncError = None
def responder((response, cb_arg, error)): def responder(cb_arg_list):
(response, cb_arg, error) = cb_arg_list
global AsyncError global AsyncError
cmd, args = cb_arg cmd, args = cb_arg
if error is not None: if error is not None:
@ -2467,7 +2500,7 @@ if __name__ == '__main__':
for cmd,args in test_seq1: for cmd,args in test_seq1:
run(cmd, args) run(cmd, args)
for ml in run('list', ('/tmp/', 'imaplib2_test%'), cb=False): for ml in run('list', ('', 'imaplib2_test%'), cb=False):
mo = re.match(r'.*"([^"]+)"$', ml) mo = re.match(r'.*"([^"]+)"$', ml)
if mo: path = mo.group(1) if mo: path = mo.group(1)
else: path = ml.split()[-1] else: path = ml.split()[-1]
@ -2475,7 +2508,7 @@ if __name__ == '__main__':
if 'ID' in M.capabilities: if 'ID' in M.capabilities:
run('id', ()) run('id', ())
run('id', ('("name", "imaplib2")',)) run('id', ("(name imaplib2)",))
run('id', ("version", __version__, "os", os.uname()[0])) run('id', ("version", __version__, "os", os.uname()[0]))
for cmd,args in test_seq2: for cmd,args in test_seq2:
@ -2527,16 +2560,16 @@ if __name__ == '__main__':
M._mesg('unused untagged responses in order, most recent last:') M._mesg('unused untagged responses in order, most recent last:')
for typ,dat in M.pop_untagged_responses(): M._mesg('\t%s %s' % (typ, dat)) for typ,dat in M.pop_untagged_responses(): M._mesg('\t%s %s' % (typ, dat))
print 'All tests OK.' print('All tests OK.')
except: except:
if not idle_intr or not 'IDLE' in M.capabilities: if not idle_intr or not 'IDLE' in M.capabilities:
print 'Tests failed.' print('Tests failed.')
if not debug: if not debug:
print ''' print('''
If you would like to see debugging output, If you would like to see debugging output,
try: %s -d5 try: %s -d5
''' % sys.argv[0] ''' % sys.argv[0])
raise raise