Bump imaplib2 from 2.43 to 2.48

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2015-09-14 14:56:17 +02:00
parent 55ca922dd1
commit 71dd03e88c

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.43" __version__ = "2.48"
__release__ = "2" __release__ = "2"
__revision__ = "43" __revision__ = "48"
__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.
@ -46,18 +46,23 @@ Fix for offlineimap "indexerror: string index out of range" bug provided by Eyge
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. Conversion to Python3 provided by F. Malina <fmalina@gmail.com> February 2015.
Fix for READ-ONLY error from multiple EXAMINE/SELECT calls by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015. Fix for READ-ONLY error from multiple EXAMINE/SELECT calls by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.
Fix for null strings appended to untagged responses by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.""" Fix for null strings appended to untagged responses by Pierre-Louis Bonicoli <pierre-louis.bonicoli@gmx.fr> March 2015.
Fix for correct byte encoding for _CRAM_MD5_AUTH taken from python3.5 imaplib.py June 2015.
Fix for correct Python 3 exception handling by Tobias Brink <tobias.brink@gmail.com> August 2015.
Fix to allow interruptible IDLE command by Tim Peoples <dromedary512@users.sf.net> September 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, random, re, select, socket, sys, time, threading, zlib import binascii, errno, os, random, re, select, socket, sys, time, threading, zlib
try: if bytes != str:
import queue # py3 # Python 3, but NB assumes strings in all I/O
# for backwards compatibility with python 2 usage.
import queue
string_types = str string_types = str
except ImportError: else:
import Queue as queue # py2 import Queue as queue
string_types = basestring string_types = basestring
@ -179,7 +184,7 @@ class Request(object):
def get_response(self, exc_fmt=None): def get_response(self, exc_fmt=None):
self.callback = None self.callback = None
if __debug__: self.parent._log(3, '%s:%s.ready.wait' % (self.name, self.tag)) if __debug__: self.parent._log(3, '%s:%s.ready.wait' % (self.name, self.tag))
self.ready.wait() self.ready.wait(sys.float_info.max)
if self.aborted is not None: if self.aborted is not None:
typ, val = self.aborted typ, val = self.aborted
@ -441,19 +446,22 @@ 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 as msg: except socket.error as m:
msg = m
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 as msg: except socket.error as m:
msg = m
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 as msg: except socket.error as m:
msg = m
s.close() s.close()
continue continue
break break
@ -534,8 +542,8 @@ class IMAP4(object):
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
if bytes != str: if bytes != str:
self.sock.sendall(bytes(data, 'utf8')) data = bytes(data, 'utf8')
else:
self.sock.sendall(data) self.sock.sendall(data)
@ -881,7 +889,9 @@ class IMAP4(object):
def _CRAM_MD5_AUTH(self, challenge): def _CRAM_MD5_AUTH(self, challenge):
"""Authobject to use with CRAM-MD5 authentication.""" """Authobject to use with CRAM-MD5 authentication."""
import hmac import hmac
return self.user + " " + hmac.HMAC(self.password, challenge).hexdigest() pwd = (self.password.encode('utf-8') if isinstance(self.password, str)
else self.password)
return self.user + " " + hmac.HMAC(pwd, challenge, 'md5').hexdigest()
def logout(self, **kw): def logout(self, **kw):
@ -1229,7 +1239,7 @@ class IMAP4(object):
self.commands_lock.release() self.commands_lock.release()
if __debug__: self._log(5, 'untagged_responses[%s] %s += ["%s"]' % (typ, len(urd)-1, dat)) if __debug__: self._log(5, 'untagged_responses[%s] %s += ["%.80s"]' % (typ, len(urd)-1, dat))
def _check_bye(self): def _check_bye(self):
@ -1297,7 +1307,7 @@ class IMAP4(object):
self.commands_lock.release() self.commands_lock.release()
if need_event: if need_event:
if __debug__: self._log(3, 'sync command %s waiting for empty commands Q' % name) if __debug__: self._log(3, 'sync command %s waiting for empty commands Q' % name)
self.state_change_free.wait() self.state_change_free.wait(sys.float_info.max)
if __debug__: self._log(3, 'sync command %s proceeding' % name) if __debug__: self._log(3, 'sync command %s proceeding' % name)
if self.state not in Commands[name][CMD_VAL_STATES]: if self.state not in Commands[name][CMD_VAL_STATES]:
@ -1316,7 +1326,7 @@ class IMAP4(object):
while self._get_untagged_response(typ): while self._get_untagged_response(typ):
continue continue
if self._get_untagged_response('READ-ONLY', leave=True) and not self.is_readonly: if not self.is_readonly and self._get_untagged_response('READ-ONLY', leave=True):
self.literal = None self.literal = None
raise self.readonly('mailbox status changed to READ-ONLY') raise self.readonly('mailbox status changed to READ-ONLY')
@ -1402,7 +1412,7 @@ class IMAP4(object):
def _command_completer(self, cb_arg_list): def _command_completer(self, cb_arg_list):
# Called for callback commands # Called for callback commands
(response, cb_arg, error) = cb_arg_list 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')
@ -1420,6 +1430,7 @@ class IMAP4(object):
if __debug__: self._print_log() if __debug__: self._print_log()
rqb.abort(self.error, '%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data)) rqb.abort(self.error, '%s command error: %s %s. Data: %.100s' % (rqb.name, typ, dat, rqb.data))
return return
if __debug__: self._log(4, '_command_completer(%s, %s, None) = %s' % (response, cb_arg, rqb.tag))
if 'untagged_response' in kw: if 'untagged_response' in kw:
response = self._untagged_response(typ, dat, kw['untagged_response']) response = self._untagged_response(typ, dat, kw['untagged_response'])
rqb.deliver(response) rqb.deliver(response)
@ -1463,7 +1474,7 @@ class IMAP4(object):
if not leave: if not leave:
del self.untagged_responses[i] del self.untagged_responses[i]
self.commands_lock.release() self.commands_lock.release()
if __debug__: self._log(5, '_get_untagged_response(%s) => %s' % (name, dat)) if __debug__: self._log(5, '_get_untagged_response(%s) => %.80s' % (name, dat))
return dat return dat
self.commands_lock.release() self.commands_lock.release()
@ -1605,11 +1616,17 @@ class IMAP4(object):
self.commands_lock.acquire() self.commands_lock.acquire()
rqb = self.tagged_commands.pop(name) rqb = self.tagged_commands.pop(name)
if not self.tagged_commands: if not self.tagged_commands:
need_event = True
else:
need_event = False
self.commands_lock.release()
if __debug__: self._log(4, '_request_pop(%s, %s) [%d] = %s' % (name, data, len(self.tagged_commands), rqb.tag))
rqb.deliver(data)
if need_event:
if __debug__: self._log(3, 'state_change_free.set') if __debug__: self._log(3, 'state_change_free.set')
self.state_change_free.set() self.state_change_free.set()
self.commands_lock.release()
if __debug__: self._log(4, '_request_pop(%s, %s) = %s' % (name, data, rqb.tag))
rqb.deliver(data)
def _request_push(self, tag=None, name=None, **kw): def _request_push(self, tag=None, name=None, **kw):
@ -1645,7 +1662,7 @@ class IMAP4(object):
if not dat: if not dat:
break break
data += dat data += dat
if __debug__: self._log(4, '_untagged_response(%s, ?, %s) => %s' % (typ, name, data)) if __debug__: self._log(4, '_untagged_response(%s, ?, %s) => %.80s' % (typ, name, data))
return typ, data return typ, data
@ -1762,6 +1779,9 @@ class IMAP4(object):
} }
return ' '.join([PollErrors[s] for s in PollErrors.keys() if (s & state)]) return ' '.join([PollErrors[s] for s in PollErrors.keys() if (s & state)])
if bytes != str:
line_part = b''
else:
line_part = '' line_part = ''
poll = select.poll() poll = select.poll()
@ -1774,7 +1794,7 @@ class IMAP4(object):
while not (terminate or self.Terminate): while not (terminate or self.Terminate):
if self.state == LOGOUT: if self.state == LOGOUT:
timeout = 1 timeout = 10
else: else:
timeout = read_poll_timeout timeout = read_poll_timeout
try: try:
@ -1802,11 +1822,11 @@ class IMAP4(object):
if bytes != str: if bytes != str:
stop = data.find(b'\n', start) stop = data.find(b'\n', start)
if stop < 0: if stop < 0:
line_part += data[start:].decode() line_part += data[start:]
break break
stop += 1 stop += 1
line_part, start, line = \ line_part, start, line = \
'', stop, line_part + data[start:stop].decode() b'', stop, (line_part + data[start:stop]).decode(errors='ignore')
else: else:
stop = data.find('\n', start) stop = data.find('\n', start)
if stop < 0: if stop < 0:
@ -1846,6 +1866,9 @@ class IMAP4(object):
if __debug__: self._log(1, 'starting using select') if __debug__: self._log(1, 'starting using select')
if bytes != str:
line_part = b''
else:
line_part = '' line_part = ''
rxzero = 0 rxzero = 0
@ -1878,11 +1901,11 @@ class IMAP4(object):
if bytes != str: if bytes != str:
stop = data.find(b'\n', start) stop = data.find(b'\n', start)
if stop < 0: if stop < 0:
line_part += data[start:].decode() line_part += data[start:]
break break
stop += 1 stop += 1
line_part, start, line = \ line_part, start, line = \
'', stop, line_part + data[start:stop].decode() b'', stop, (line_part + data[start:stop]).decode(errors='ignore')
else: else:
stop = data.find('\n', start) stop = data.find('\n', start)
if stop < 0: if stop < 0:
@ -2100,17 +2123,8 @@ class IMAP4_SSL(IMAP4):
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
if bytes != str: if bytes != str:
if hasattr(self.sock, "sendall"): data = bytes(data, 'utf8')
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:
if hasattr(self.sock, "sendall"): if hasattr(self.sock, "sendall"):
self.sock.sendall(data) self.sock.sendall(data)
else: else:
@ -2195,8 +2209,8 @@ class IMAP4_stream(IMAP4):
data += self.compressor.flush(zlib.Z_SYNC_FLUSH) data += self.compressor.flush(zlib.Z_SYNC_FLUSH)
if bytes != str: if bytes != str:
self.writefile.write(bytes(data, 'utf8')) data = bytes(data, 'utf8')
else:
self.writefile.write(data) self.writefile.write(data)
self.writefile.flush() self.writefile.flush()
@ -2372,8 +2386,14 @@ if __name__ == '__main__':
# To test: invoke either as 'python imaplib2.py [IMAP4_server_hostname]', # To test: invoke either as 'python imaplib2.py [IMAP4_server_hostname]',
# or as 'python imaplib2.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"' # or as 'python imaplib2.py -s "rsh IMAP4_server_hostname exec /etc/rimapd"'
# or as 'python imaplib2.py -l "keyfile[:certfile]" [IMAP4_SSL_server_hostname]' # or as 'python imaplib2.py -l keyfile[:certfile]|: [IMAP4_SSL_server_hostname]'
#
# Option "-d <level>" turns on debugging (use "-d 5" for everything)
# Option "-i" tests that IDLE is interruptible # Option "-i" tests that IDLE is interruptible
# Option "-p <port>" allows alternate ports
if not __debug__:
raise ValueError('Please run without -O')
import getopt, getpass import getopt, getpass
@ -2446,10 +2466,10 @@ if __name__ == '__main__':
) )
AsyncError = None AsyncError, M = None, None
def responder(cb_arg_list): def responder(cb_arg_list):
(response, cb_arg, error) = 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:
@ -2569,7 +2589,7 @@ if __name__ == '__main__':
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 M is None or not 'IDLE' in M.capabilities:
print('Tests failed.') print('Tests failed.')
if not debug: if not debug: