imaplib2: bump to v2.41
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
cf2a2c769c
commit
43dbe1578c
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user