mirror of https://github.com/python/cpython
moved command logging routines into IMAP4 class: thread safe/faster
This commit is contained in:
parent
d2d58e0496
commit
f2d7d15805
121
Lib/imaplib.py
121
Lib/imaplib.py
|
@ -16,7 +16,7 @@ Public functions: Internaldate2tuple
|
||||||
# String method conversion by ESR, February 2001.
|
# String method conversion by ESR, February 2001.
|
||||||
# GET/SETACL contributed by Anthony Baxter <anthony@interlink.com.au> April 2001.
|
# GET/SETACL contributed by Anthony Baxter <anthony@interlink.com.au> April 2001.
|
||||||
|
|
||||||
__version__ = "2.49"
|
__version__ = "2.50"
|
||||||
|
|
||||||
import binascii, re, socket, time, random, sys
|
import binascii, re, socket, time, random, sys
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ Commands = {
|
||||||
'LSUB': ('AUTH', 'SELECTED'),
|
'LSUB': ('AUTH', 'SELECTED'),
|
||||||
'NAMESPACE': ('AUTH', 'SELECTED'),
|
'NAMESPACE': ('AUTH', 'SELECTED'),
|
||||||
'NOOP': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'),
|
'NOOP': ('NONAUTH', 'AUTH', 'SELECTED', 'LOGOUT'),
|
||||||
'PARTIAL': ('SELECTED',),
|
'PARTIAL': ('SELECTED',), # NB: obsolete
|
||||||
'RENAME': ('AUTH', 'SELECTED'),
|
'RENAME': ('AUTH', 'SELECTED'),
|
||||||
'SEARCH': ('SELECTED',),
|
'SEARCH': ('SELECTED',),
|
||||||
'SELECT': ('AUTH', 'SELECTED'),
|
'SELECT': ('AUTH', 'SELECTED'),
|
||||||
|
@ -158,9 +158,12 @@ class IMAP4:
|
||||||
# request and store CAPABILITY response.
|
# request and store CAPABILITY response.
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
self._cmd_log_len = 10
|
||||||
|
self._cmd_log_idx = 0
|
||||||
|
self._cmd_log = {} # Last `_cmd_log_len' interactions
|
||||||
if self.debug >= 1:
|
if self.debug >= 1:
|
||||||
_mesg('imaplib version %s' % __version__)
|
self._mesg('imaplib version %s' % __version__)
|
||||||
_mesg('new IMAP4 connection, tag=%s' % self.tagpre)
|
self._mesg('new IMAP4 connection, tag=%s' % self.tagpre)
|
||||||
|
|
||||||
self.welcome = self._get_response()
|
self.welcome = self._get_response()
|
||||||
if self.untagged_responses.has_key('PREAUTH'):
|
if self.untagged_responses.has_key('PREAUTH'):
|
||||||
|
@ -178,7 +181,7 @@ class IMAP4:
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 3:
|
if self.debug >= 3:
|
||||||
_mesg('CAPABILITIES: %s' % `self.capabilities`)
|
self._mesg('CAPABILITIES: %s' % `self.capabilities`)
|
||||||
|
|
||||||
for version in AllowedVersions:
|
for version in AllowedVersions:
|
||||||
if not version in self.capabilities:
|
if not version in self.capabilities:
|
||||||
|
@ -224,6 +227,7 @@ class IMAP4:
|
||||||
"""Send data to remote."""
|
"""Send data to remote."""
|
||||||
self.sock.sendall(data)
|
self.sock.sendall(data)
|
||||||
|
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
"""Close I/O established in "open"."""
|
"""Close I/O established in "open"."""
|
||||||
self.file.close()
|
self.file.close()
|
||||||
|
@ -482,7 +486,7 @@ class IMAP4:
|
||||||
"""
|
"""
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 3:
|
if self.debug >= 3:
|
||||||
_dump_ur(self.untagged_responses)
|
self._dump_ur(self.untagged_responses)
|
||||||
return self._simple_command('NOOP')
|
return self._simple_command('NOOP')
|
||||||
|
|
||||||
|
|
||||||
|
@ -546,7 +550,7 @@ class IMAP4:
|
||||||
and not readonly:
|
and not readonly:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 1:
|
if self.debug >= 1:
|
||||||
_dump_ur(self.untagged_responses)
|
self._dump_ur(self.untagged_responses)
|
||||||
raise self.readonly('%s is not writable' % mailbox)
|
raise self.readonly('%s is not writable' % mailbox)
|
||||||
return typ, self.untagged_responses.get('EXISTS', [None])
|
return typ, self.untagged_responses.get('EXISTS', [None])
|
||||||
|
|
||||||
|
@ -663,7 +667,7 @@ class IMAP4:
|
||||||
ur = self.untagged_responses
|
ur = self.untagged_responses
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 5:
|
if self.debug >= 5:
|
||||||
_mesg('untagged_responses[%s] %s += ["%s"]' %
|
self._mesg('untagged_responses[%s] %s += ["%s"]' %
|
||||||
(typ, len(ur.get(typ,'')), dat))
|
(typ, len(ur.get(typ,'')), dat))
|
||||||
if ur.has_key(typ):
|
if ur.has_key(typ):
|
||||||
ur[typ].append(dat)
|
ur[typ].append(dat)
|
||||||
|
@ -709,9 +713,9 @@ class IMAP4:
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 4:
|
if self.debug >= 4:
|
||||||
_mesg('> %s' % data)
|
self._mesg('> %s' % data)
|
||||||
else:
|
else:
|
||||||
_log('> %s' % data)
|
self._log('> %s' % data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.send('%s%s' % (data, CRLF))
|
self.send('%s%s' % (data, CRLF))
|
||||||
|
@ -735,7 +739,7 @@ class IMAP4:
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 4:
|
if self.debug >= 4:
|
||||||
_mesg('write literal size %s' % len(literal))
|
self._mesg('write literal size %s' % len(literal))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.send(literal)
|
self.send(literal)
|
||||||
|
@ -814,7 +818,7 @@ class IMAP4:
|
||||||
size = int(self.mo.group('size'))
|
size = int(self.mo.group('size'))
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 4:
|
if self.debug >= 4:
|
||||||
_mesg('read literal size %s' % size)
|
self._mesg('read literal size %s' % size)
|
||||||
data = self.read(size)
|
data = self.read(size)
|
||||||
|
|
||||||
# Store response with literal as tuple
|
# Store response with literal as tuple
|
||||||
|
@ -834,7 +838,7 @@ class IMAP4:
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 1 and typ in ('NO', 'BAD', 'BYE'):
|
if self.debug >= 1 and typ in ('NO', 'BAD', 'BYE'):
|
||||||
_mesg('%s response: %s' % (typ, dat))
|
self._mesg('%s response: %s' % (typ, dat))
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@ -857,7 +861,7 @@ class IMAP4:
|
||||||
except self.abort, val:
|
except self.abort, val:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 1:
|
if self.debug >= 1:
|
||||||
print_log()
|
self.print_log()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@ -872,9 +876,9 @@ class IMAP4:
|
||||||
line = line[:-2]
|
line = line[:-2]
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 4:
|
if self.debug >= 4:
|
||||||
_mesg('< %s' % line)
|
self._mesg('< %s' % line)
|
||||||
else:
|
else:
|
||||||
_log('< %s' % line)
|
self._log('< %s' % line)
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
@ -886,7 +890,7 @@ class IMAP4:
|
||||||
self.mo = cre.match(s)
|
self.mo = cre.match(s)
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.mo is not None and self.debug >= 5:
|
if self.mo is not None and self.debug >= 5:
|
||||||
_mesg("\tmatched r'%s' => %s" % (cre.pattern, `self.mo.groups()`))
|
self._mesg("\tmatched r'%s' => %s" % (cre.pattern, `self.mo.groups()`))
|
||||||
return self.mo is not None
|
return self.mo is not None
|
||||||
|
|
||||||
|
|
||||||
|
@ -934,11 +938,49 @@ class IMAP4:
|
||||||
data = self.untagged_responses[name]
|
data = self.untagged_responses[name]
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self.debug >= 5:
|
if self.debug >= 5:
|
||||||
_mesg('untagged_responses[%s] => %s' % (name, data))
|
self._mesg('untagged_responses[%s] => %s' % (name, data))
|
||||||
del self.untagged_responses[name]
|
del self.untagged_responses[name]
|
||||||
return typ, data
|
return typ, data
|
||||||
|
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
|
||||||
|
def _mesg(self, s, secs=None):
|
||||||
|
if secs is None:
|
||||||
|
secs = time.time()
|
||||||
|
tm = time.strftime('%M:%S', time.localtime(secs))
|
||||||
|
sys.stderr.write(' %s.%02d %s\n' % (tm, (secs*100)%100, s))
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
def _dump_ur(self, dict):
|
||||||
|
# Dump untagged responses (in `dict').
|
||||||
|
l = dict.items()
|
||||||
|
if not l: return
|
||||||
|
t = '\n\t\t'
|
||||||
|
l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l)
|
||||||
|
self._mesg('untagged responses dump:%s%s' % (t, t.join(l)))
|
||||||
|
|
||||||
|
def _log(self, line):
|
||||||
|
# Keep log of last `_cmd_log_len' interactions for debugging.
|
||||||
|
self._cmd_log[self._cmd_log_idx] = (line, time.time())
|
||||||
|
self._cmd_log_idx += 1
|
||||||
|
if self._cmd_log_idx >= self._cmd_log_len:
|
||||||
|
self._cmd_log_idx = 0
|
||||||
|
|
||||||
|
def print_log(self):
|
||||||
|
self._mesg('last %d IMAP4 interactions:' % len(self._cmd_log))
|
||||||
|
i, n = self._cmd_log_idx, self._cmd_log_len
|
||||||
|
while n:
|
||||||
|
try:
|
||||||
|
apply(self._mesg, self._cmd_log[i])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
i += 1
|
||||||
|
if i >= self._cmd_log_len:
|
||||||
|
i = 0
|
||||||
|
n -= 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class _Authenticator:
|
class _Authenticator:
|
||||||
|
|
||||||
|
@ -1082,39 +1124,6 @@ def Time2Internaldate(date_time):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __debug__:
|
|
||||||
|
|
||||||
def _mesg(s, secs=None):
|
|
||||||
if secs is None:
|
|
||||||
secs = time.time()
|
|
||||||
tm = time.strftime('%M:%S', time.localtime(secs))
|
|
||||||
sys.stderr.write(' %s.%02d %s\n' % (tm, (secs*100)%100, s))
|
|
||||||
sys.stderr.flush()
|
|
||||||
|
|
||||||
def _dump_ur(dict):
|
|
||||||
# Dump untagged responses (in `dict').
|
|
||||||
l = dict.items()
|
|
||||||
if not l: return
|
|
||||||
t = '\n\t\t'
|
|
||||||
l = map(lambda x:'%s: "%s"' % (x[0], x[1][0] and '" "'.join(x[1]) or ''), l)
|
|
||||||
_mesg('untagged responses dump:%s%s' % (t, t.join(l)))
|
|
||||||
|
|
||||||
_cmd_log = [] # Last `_cmd_log_len' interactions
|
|
||||||
_cmd_log_len = 10
|
|
||||||
|
|
||||||
def _log(line):
|
|
||||||
# Keep log of last `_cmd_log_len' interactions for debugging.
|
|
||||||
if len(_cmd_log) == _cmd_log_len:
|
|
||||||
del _cmd_log[0]
|
|
||||||
_cmd_log.append((time.time(), line))
|
|
||||||
|
|
||||||
def print_log():
|
|
||||||
_mesg('last %d IMAP4 interactions:' % len(_cmd_log))
|
|
||||||
for secs,line in _cmd_log:
|
|
||||||
_mesg(line, secs)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
import getopt, getpass
|
import getopt, getpass
|
||||||
|
@ -1145,7 +1154,7 @@ if __name__ == '__main__':
|
||||||
('list', ('/tmp', 'yy*')),
|
('list', ('/tmp', 'yy*')),
|
||||||
('select', ('/tmp/yyz 2',)),
|
('select', ('/tmp/yyz 2',)),
|
||||||
('search', (None, 'SUBJECT', 'test')),
|
('search', (None, 'SUBJECT', 'test')),
|
||||||
('partial', ('1', 'RFC822', 1, 1024)),
|
('fetch', ('1', '(FLAGS INTERNALDATE RFC822)')),
|
||||||
('store', ('1', 'FLAGS', '(\Deleted)')),
|
('store', ('1', 'FLAGS', '(\Deleted)')),
|
||||||
('namespace', ()),
|
('namespace', ()),
|
||||||
('expunge', ()),
|
('expunge', ()),
|
||||||
|
@ -1164,15 +1173,15 @@ if __name__ == '__main__':
|
||||||
)
|
)
|
||||||
|
|
||||||
def run(cmd, args):
|
def run(cmd, args):
|
||||||
_mesg('%s %s' % (cmd, args))
|
M._mesg('%s %s' % (cmd, args))
|
||||||
typ, dat = apply(getattr(M, cmd), args)
|
typ, dat = apply(getattr(M, cmd), args)
|
||||||
_mesg('%s => %s %s' % (cmd, typ, dat))
|
M._mesg('%s => %s %s' % (cmd, typ, dat))
|
||||||
return dat
|
return dat
|
||||||
|
|
||||||
try:
|
try:
|
||||||
M = IMAP4(host)
|
M = IMAP4(host)
|
||||||
_mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
M._mesg('PROTOCOL_VERSION = %s' % M.PROTOCOL_VERSION)
|
||||||
_mesg('CAPABILITIES = %s' % `M.capabilities`)
|
M._mesg('CAPABILITIES = %s' % `M.capabilities`)
|
||||||
|
|
||||||
for cmd,args in test_seq1:
|
for cmd,args in test_seq1:
|
||||||
run(cmd, args)
|
run(cmd, args)
|
||||||
|
|
Loading…
Reference in New Issue