From 7a287cef57a25a475f34d68b86f49f10140c4900 Mon Sep 17 00:00:00 2001 From: John Goerzen Date: Thu, 5 Jul 2007 14:49:54 +0100 Subject: [PATCH] Checkpointing --- offlineimap/ui/Machine.py | 24 +++++--- offlineimap/ui/UIBase.py | 51 ++++------------- offlineimap/ui/transmitter.py | 100 ++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 46 deletions(-) create mode 100644 offlineimap/ui/transmitter.py diff --git a/offlineimap/ui/Machine.py b/offlineimap/ui/Machine.py index d02bbbc..29823ad 100644 --- a/offlineimap/ui/Machine.py +++ b/offlineimap/ui/Machine.py @@ -59,17 +59,20 @@ class MachineUI(UIBase): def warn(s, msg, minor): s._printData('warn', '%s\n%d' % (msg, int(minor))) - def registerthread(s, account): - UIBase.registerthread(s, account) - s._printData('registerthread', account) + def registerthread(s, threadname, accountname): + UIBase.registerthread(s, threadname, accountname) + s._printData('registerthread', accountname) - def unregisterthread(s, thread): - UIBase.unregisterthread(s, thread) - s._printData('unregisterthread', thread.getName()) + def unregisterthread(s, threadname): + UIBase.unregisterthread(s, threadname) + s._printData('unregisterthread', threadname) def debugging(s, debugtype): s._printData('debugging', debugtype) + def print_debug(s, debugtype, msg): + s._printData('print_debug', "%s\n%s" % (debugtype, msg)) + def acct(s, accountname): s._printData('acct', accountname) @@ -161,7 +164,7 @@ class MachineUI(UIBase): return 0 - def getpass(s, accountname, config, errmsg = None): + def getpass(s, accountname, errmsg = None): s.outputlock.acquire() try: if errmsg: @@ -175,3 +178,10 @@ class MachineUI(UIBase): def init_banner(s): s._printData('initbanner', offlineimap.version.banner) + def msgtoreadonly(s, destfoldernice, destfoldername, uid): + s._printData('msgtoreadonly', "%s\n%s\n%d" % (destfoldernice, destfoldername, uid)) + + def flagstoreadonly(s, destfoldernice, destfoldername, uidlist): + s._printData('flagstoreadonly', "%s\n%s\n%s" % (destfoldernice, destfoldername, "\f".join( + + diff --git a/offlineimap/ui/UIBase.py b/offlineimap/ui/UIBase.py index fc1610c..d40fdb3 100644 --- a/offlineimap/ui/UIBase.py +++ b/offlineimap/ui/UIBase.py @@ -24,21 +24,11 @@ debugtypes = {'imap': 'IMAP protocol debugging', 'maildir': 'Maildir repository debugging', 'thread': 'Threading debugging'} -globalui = None -def setglobalui(newui): - global globalui - globalui = newui -def getglobalui(): - global globalui - return globalui - class UIBase: def __init__(s, config, verbose = 0): s.verbose = verbose s.config = config s.debuglist = [] - s.debugmessages = {} - s.debugmsglen = 50 s.threadaccounts = {} s.logfile = None @@ -76,19 +66,19 @@ class UIBase: else: s._msg("WARNING: " + msg) - def registerthread(s, account): + def registerthread(s, threadname, accountname): #FIX IN CODE """Provides a hint to UIs about which account this particular thread is processing.""" - if s.threadaccounts.has_key(threading.currentThread()): + if s.threadaccounts.has_key(threadname): raise ValueError, "Thread %s already registered (old %s, new %s)" %\ - (threading.currentThread().getName(), + (threadname s.getthreadaccount(s), account) - s.threadaccounts[threading.currentThread()] = account + s.threadaccounts[threadname] = account - def unregisterthread(s, thr): + def unregisterthread(s, threadname): #FIX IN CODE """Recognizes a thread has exited.""" - if s.threadaccounts.has_key(thr): - del s.threadaccounts[thr] + if s.threadaccounts.has_key(threadname): + del s.threadaccounts[threadname] def getthreadaccount(s, thr = None): if not thr: @@ -97,16 +87,7 @@ class UIBase: return s.threadaccounts[thr] return '*Control' - def debug(s, debugtype, msg): - thisthread = threading.currentThread() - if s.debugmessages.has_key(thisthread): - s.debugmessages[thisthread].append("%s: %s" % (debugtype, msg)) - else: - s.debugmessages[thisthread] = ["%s: %s" % (debugtype, msg)] - - while len(s.debugmessages[thisthread]) > s.debugmsglen: - s.debugmessages[thisthread] = s.debugmessages[thisthread][1:] - + def print_debug(s, debugtype, msg): if debugtype in s.debuglist: if not s._log("DEBUG[%s]: %s" % (debugtype, msg)): s._display("DEBUG[%s]: %s" % (debugtype, msg)) @@ -124,17 +105,9 @@ class UIBase: global debugtypes s._msg("Now debugging for %s: %s" % (debugtype, debugtypes[debugtype])) - def invaliddebug(s, debugtype): - s.warn("Invalid debug type: %s" % debugtype) - def locked(s): raise Exception, "Another OfflineIMAP is running with the same metadatadir; exiting." - def getnicename(s, object): - prelimname = str(object.__class__).split('.')[-1] - # Strip off extra stuff. - return re.sub('(Folder|Repository)', '', prelimname) - def isusable(s): """Returns true if this UI object is usable in the current environment. For instance, an X GUI would return true if it's @@ -143,19 +116,19 @@ class UIBase: ################################################## INPUT - def getpass(s, accountname, config, errmsg = None): + def getpass(s, accountname, errmsg = None): # FIX IN CODE raise NotImplementedError def folderlist(s, list): return ', '.join(["%s[%s]" % (s.getnicename(x), x.getname()) for x in list]) ################################################## WARNINGS - def msgtoreadonly(s, destfolder, uid, content, flags): + def msgtoreadonly(s, destfoldernicename, destfoldername, uid): #FIX IN CODE # FIX IN CODE if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")): s.warn("Attempted to synchronize message %d to folder %s[%s], but that folder is read-only. The message will not be copied to that folder." % \ - (uid, s.getnicename(destfolder), destfolder.getname())) + (uid, destfoldernicename, destfoldername)) - def flagstoreadonly(s, destfolder, uidlist, flags): + def flagstoreadonly(s, destfolder, uidlist): #FIX IN CODE if not (config.has_option('general', 'ignore-readonly') and config.getboolean("general", "ignore-readonly")): s.warn("Attempted to modify flags for messages %s in folder %s[%s], but that folder is read-only. No flags have been modified for that message." % \ (str(uidlist), s.getnicename(destfolder), destfolder.getname())) diff --git a/offlineimap/ui/transmitter.py b/offlineimap/ui/transmitter.py new file mode 100644 index 0000000..8de9cb7 --- /dev/null +++ b/offlineimap/ui/transmitter.py @@ -0,0 +1,100 @@ +# User interface transmitter +# +# Used by per-account OfflineIMAP threads +# +# Transmits messages using Machine +# +# Copyright (C) 2002-2007 John Goerzen +# +# +# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +import offlineimap.version +import re, time, sys, traceback, threading, thread +from StringIO import StringIO + +debugtypes = {'imap': 'IMAP protocol debugging', + 'maildir': 'Maildir repository debugging', + 'thread': 'Threading debugging'} + +globalui = None +def setglobalui(newui): + global globalui + globalui = newui +def getglobalui(): + global globalui + return globalui + +class UITransmitter: + """This class is designed to transmit UI messages to the OfflineIMAP + ui process. It receives raw data and formats it nicely.""" + def __init__(s, config, verbose = 0): + s.verbose = verbose + s.config = config + s.debuglist = [] + s.debugmessages = {} + s.debugmsglen = 50 + s.threadaccounts = {} + s.logfile = None + s.m = Machine.MachineUI(config, verbose) + + def warn(s, msg, minor = 0): + s.m.warn(msg, minor) + + def registerthread(s, accountname): + s.m.registerthread(threading.currentThread().getName(), accountname) + + def unregisterthread(s, threadobj): + s.m.unregisterthread(threadobj.getName()) + + def debugging(s, debugtype): + s.m.debugging(s, debugtype) + + def debug(s, debugtype, msg): + thisthread = threading.currentThread() + if s.debugmessages.has_key(thisthread): + s.debugmessages[thisthread].append("%s: %s" % (debugtype, msg)) + else: + s.debugmessages[thisthread] = ["%s: %s" % (debugtype, msg)] + + while len(s.debugmessages[thisthread]) > s.debugmsglen: + s.debugmessages[thisthread] = s.debugmessages[thisthread][1:] + + s.print_debug(debugtype, msg) + + def print_debug(s, debugtype, msg): + s.m.print_debug(s, debugtype, msg) + + def debugging(s, debugtype): + s.m.debugging(s, debugtype) + + def invaliddebug(s, debugtype): + s.warn("Invalid debug type: %s" % debugtype) + + def getnicename(s, object): + prelimname = str(object.__class__).split('.')[-1] + # Strip off extra stuff. + return re.sub('(Folder|Repository)', '', prelimname) + + ################################################## INPUT + def getpass(s, accountname, errmsg = None): + s.m.getpass(accountname, errmsg) + + ################################################## WARNINGS + def msgtoreadonly(s, destfolder, uid): + s.m.msgtoreadonly(s, s.getnicename(destfolder), + destfolder.getname(), uid) + -- 2.39.2