offlineimap rev 569
"Automatic Subversion Change Mailer" <[email protected]> Fri, 15 Aug 2003 13:51:17 -0500 (CDT)
| Newsgroups | gmane.mail.imap.offlineimap.subversion |
|---|---|
| Message-ID | <[email protected]> |
You are receiving this message because
all commits get sent to this address.
Author: jgoerzen
Date: 2003-08-15 13:50:54 -0500 (Fri, 15 Aug 2003)
New Revision: 569
Modified:
offlineimap/branches/twisted/offlineimap/accounts.py
offlineimap/branches/twisted/offlineimap/folder/Base.py
offlineimap/branches/twisted/offlineimap/folder/IMAP.py
offlineimap/branches/twisted/offlineimap/folder/LocalStatus.py
offlineimap/branches/twisted/offlineimap/folder/Maildir.py
offlineimap/branches/twisted/offlineimap/imapserver.py
offlineimap/branches/twisted/offlineimap/repository/Base.py
offlineimap/branches/twisted/offlineimap/repository/IMAP.py
offlineimap/branches/twisted/offlineimap/repository/Maildir.py
offlineimap/branches/twisted/offlineimap/twistedutil.py
offlineimap/branches/twisted/offlineimap/ui/TTY.py
offlineimap/branches/twisted/offlineimap/ui/UIBase.py
offlineimap/branches/twisted/offlineimap.sgml
Log:
Helped out the implementation of password prompting. It now works better,
and expects a Deferred back from the UI module.
Moved rd() from imaputil to twistedutil() so that modules that want just
that don't have to import a whole big chunk of IMAP-related junk.
Added new debug type 'traffic' and documented it in offlineimap.sgml.
Diff:
Modified: offlineimap/branches/twisted/offlineimap/accounts.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/accounts.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/accounts.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -20,7 +20,7 @@
from offlineimap.ui import UIBase
import os
from twisted.internet import defer
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
def getaccountlist(customconfig):
Modified: offlineimap/branches/twisted/offlineimap/folder/Base.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/folder/Base.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/folder/Base.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -19,7 +19,7 @@
from threading import *
from offlineimap.ui import UIBase
import os.path, re
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
from twisted.internet import defer
class BaseFolder:
Modified: offlineimap/branches/twisted/offlineimap/folder/IMAP.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/folder/IMAP.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/folder/IMAP.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -24,7 +24,7 @@
from copy import copy
from twisted.internet import defer
from twisted.protocols.imap4 import Query
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
class IMAPFolder(BaseFolder, imaputil.AcquireMixin):
Modified: offlineimap/branches/twisted/offlineimap/folder/LocalStatus.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/folder/LocalStatus.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/folder/LocalStatus.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -18,7 +18,7 @@
from Base import BaseFolder
import os, threading
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
Modified: offlineimap/branches/twisted/offlineimap/folder/Maildir.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/folder/Maildir.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/folder/Maildir.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -21,7 +21,7 @@
from offlineimap.ui import UIBase
from threading import Lock
import os.path, os, re, time, socket, md5
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
foldermatchre = re.compile(',FMD5=([0-9a-f]{32})')
Modified: offlineimap/branches/twisted/offlineimap/imapserver.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/imapserver.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/imapserver.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -21,28 +21,34 @@
import thread, hmac, os
from twisted.internet import defer, protocol, reactor
#from twisted.protocols.imap4 import IMAP4Client
-from twistedfixes.imap4 import IMAP4Client
+from twistedfixes.imap4 import IMAP4Client, IMAP4Exception
from twisted.internet.ssl import ClientContextFactory
from imaputil import rd
import re
def getname(object):
+ "Utility function designed to return a unique name for a given IMAP object."
+
name = str(object)
return re.search(r'instance at 0x([0-9A-Za-z]+)>', name).group(1)
class MyIMAP(IMAP4Client):
+ """This class adds a few debugging and processing features to the standard
+ Twisted IMAP4Client class."""
def connectionMade(self):
- #print "Connectionmade."
+ "Call us back once we're connected."
self.factory.imapserver.connectionMade(self)
def sendLine(self, line):
+ "Hook to log outbound traffic if debugging."
ui = UIBase.getglobalui()
- ui.debug('imap', getname(self) + ' Send: ' + str(line))
+ ui.debug('traffic', getname(self) + ' Send: ' + str(line))
return IMAP4Client.sendLine(self, line)
def lineReceived(self, line):
+ "Hook to log inbound traffic if debugging."
ui = UIBase.getglobalui()
- ui.debug('imap', getname(self) + ' Recv: ' + str(line))
+ ui.debug('traffic', getname(self) + ' Recv: ' + str(line))
return IMAP4Client.lineReceived(self, line)
@@ -69,6 +75,10 @@
protocol = IMAP4Client
class IMAPServer:
+ """This class is designed to handle information necessary to keep track of
+ a connection or connections to a particular IMAP server. It maintains
+ the pool of connections from which clients can request an open one, among
+ other things."""
def __init__(self, config, reposname,
username = None, password = None, hostname = None,
port = None, ssl = 1, maxconnections = 1, tunnel = None,
@@ -98,18 +108,41 @@
#self.semaphore = BoundedSemaphore(self.maxconnections)
self.connectionlock = Lock()
self.reference = reference
+ self.deferpassword = None
def getpassword(self):
+ """Called to read in a password from the user, or use
+ a cached one if available. Returns a Deferred that gets
+ called with the password.
+
+ ALL CALLBACKS ON THIS CHAIN MUST RETURN THE PASSWORD
+ AS IT WAS PASSED IN."""
+
if self.password != None and self.passworderror == None:
- return self.password
+ # We already have a valid password. Just return it.
+ return rd(self.password)
- self.password = UIBase.getglobalui().getpass(self.reposname,
- self.config,
- self.passworderror)
- self.passworderror = None
+ if self.deferpassword != None:
+ # Another call to getpassword() is pending. Let the caller
+ # chain on to it.
+ return self.deferpassword
- return self.password
+ d = UIBase.getglobalui().getpass(self.reposname, self.config,
+ self.passworderror)
+ self.deferpassword = d
+ d.addCallback(self.cachepassword)
+ return d
+ def cachepassword(self, password):
+ """Called by the deferred from getpassword() to store the
+ user-supplied password for future uses. Returns the password
+ so that callbacks from getpassword() can still get it the normal
+ way."""
+ self.password = password
+ self.passworderror = None # Reset this before going on.
+ self.deferpassword = None # Ditto.
+ return password
+
def getdelim(self):
"""Returns this server's folder delimiter. Can only be called
after one or more calls to acquireconnection."""
@@ -140,10 +173,15 @@
return retval
def plainauth(self, imapobj):
+ d = self.getpassword()
+ d.addCallback(self.plainauth_worker, imapobj)
+ return d
+
+ def plainauth_worker(self, password, imapobj):
UIBase.getglobalui().debug('imap',
'Attempting plain authentication')
#print "imapobj is", imapobj
- d = imapobj.login(self.username, self.getpassword())
+ d = imapobj.login(self.username, password)
d.addErrback(self.plainautherror, imapobj)
#print "reference is", self.reference
d.addCallback(self.listcallback, imapobj, self.reference, '')
@@ -152,6 +190,12 @@
d.addCallback(lambda x, imap: self._handleAvailableConnection(imap),
imapobj)
+ def plainautherror(self, error, imapobj):
+ error.trap(IMAP4Exception)
+ UIBase.getglobalui().warn(error.getErrorMessage())
+ self.passworderror = str(error.getErrorMessage())
+ return self.plainauth(imapobj)
+
def _opened(self, discard = None):
#print "opened"
self.openingcount -= 1
@@ -177,10 +221,6 @@
#print "listres is", listres
self.delim, self.root = listres[0][1:]
- def plainautherror(self, error, imapobj):
- UIBase.getglobalui().warn(str(error))
- self.plainauth(imapobj)
-
def acquireconnection(self, d):
"""Fetches a connection from the pool, making sure to create a new one
if needed, to obey the maximum connection limits, etc.
Modified: offlineimap/branches/twisted/offlineimap/repository/Base.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/repository/Base.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/repository/Base.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -19,7 +19,7 @@
from offlineimap import CustomConfig
import os.path
from twisted.internet import defer
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
def LoadRepository(name, account, reqtype):
from offlineimap.repository.IMAP import IMAPRepository, MappedIMAPRepository
Modified: offlineimap/branches/twisted/offlineimap/repository/IMAP.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/repository/IMAP.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/repository/IMAP.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -20,7 +20,7 @@
from offlineimap import folder, imaputil, imapserver
from offlineimap.folder.UIDMaps import MappedIMAPFolder
import re, types, os
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
from twisted.internet import defer
class IMAPRepository(BaseRepository, imaputil.AcquireMixin):
Modified: offlineimap/branches/twisted/offlineimap/repository/Maildir.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/repository/Maildir.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/repository/Maildir.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -18,7 +18,7 @@
from Base import BaseRepository
from offlineimap import folder, imaputil
-from offlineimap.imaputil import rd
+from offlineimap.twistedutil import rd
from offlineimap.ui import UIBase
from mailbox import Maildir
import os
Added: offlineimap/branches/twisted/offlineimap/twistedutil.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/twistedutil.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/twistedutil.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -0,0 +1,26 @@
+# Twisted utility module
+# Copyright (C) 2003 John Goerzen
+# <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from twisted.internet import defer
+
+def rd(val):
+ """Utility function to retern a deferred with its value set to val."""
+ d = defer.Deferred()
+ d.callback(val)
+ return d
+
Modified: offlineimap/branches/twisted/offlineimap/ui/TTY.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/ui/TTY.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/ui/TTY.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -20,35 +20,27 @@
from getpass import getpass
import select, sys
from threading import *
+from offlineimap.twistedutil import rd
class TTYUI(UIBase):
def __init__(s, config, verbose = 0):
UIBase.__init__(s, config, verbose)
s.iswaiting = 0
- s.outputlock = Lock()
def isusable(s):
return sys.stdout.isatty() and sys.stdin.isatty()
def _display(s, msg):
- s.outputlock.acquire()
- try:
- if (currentThread().getName() == 'MainThread'):
- print msg
- else:
- print "%s:\n %s" % (currentThread().getName(), msg)
- sys.stdout.flush()
- finally:
- s.outputlock.release()
+ if (currentThread().getName() == 'MainThread'):
+ print msg
+ else:
+ print "%s:\n %s" % (currentThread().getName(), msg)
+ sys.stdout.flush()
def getpass(s, accountname, config, errmsg = None):
if errmsg:
s._msg("%s: %s" % (accountname, errmsg))
- s.outputlock.acquire()
- try:
- return getpass("%s: Enter password: " % accountname)
- finally:
- s.outputlock.release()
+ return rd(getpass("%s: Enter password: " % accountname))
def mainException(s):
if isinstance(sys.exc_info()[1], KeyboardInterrupt) and \
Modified: offlineimap/branches/twisted/offlineimap/ui/UIBase.py
===================================================================
--- offlineimap/branches/twisted/offlineimap/ui/UIBase.py 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap/ui/UIBase.py 2003-08-15 18:50:54 UTC (rev 569)
@@ -23,7 +23,8 @@
debugtypes = {'imap': 'IMAP protocol debugging',
'maildir': 'Maildir repository debugging',
- 'thread': 'Threading debugging'}
+ 'thread': 'Threading debugging',
+ 'traffic': 'Network Traffic'}
globalui = None
def setglobalui(newui):
@@ -147,6 +148,7 @@
################################################## INPUT
def getpass(s, accountname, config, errmsg = None):
+ """Returns Deferred."""
raise NotImplementedError
def folderlist(s, list):
Modified: offlineimap/branches/twisted/offlineimap.sgml
===================================================================
--- offlineimap/branches/twisted/offlineimap.sgml 2003-08-14 18:56:11 UTC (rev 568)
+++ offlineimap/branches/twisted/offlineimap.sgml 2003-08-15 18:50:54 UTC (rev 569)
@@ -363,10 +363,15 @@
<para><option>-d</option> requires one or more debugtypes,
separated by commas. These define what exactly will be
- debugged, and include three options: <property>imap</property>,
+ debugged, and include four options:
+ <property>imap</property>,
+ <property>traffic</property>,
<property>maildir</property>, and <property>thread</property>.
The <property>imap</property>
- option will enable IMAP protocol stream and parsing debugging. Note
+ option will enable IMAP activity debugging. The
+ <property>traffic</property> option will enable dumping
+ of most traffic going back and forth between IMAP
+ servers. Note
that the output may contain passwords, so take care to remove that
from the debugging output before sending it to anyone else. The
<property>maildir</property> option will enable debugging for