[PATCH 2/6] Add IdleThread class

Ethan Glasser-Camp ethan at betacantrips.com
Wed May 18 13:48:53 BST 2011


This encapsulates the logic for sending a keepalive/IDLE call,
including starting a sync if needed.

This code was originally by James Bunton <jamesbunton at fastmail.fm>.  I
modified the idle() method to put the select() call after
acquireconnection().

Signed-off-by: Ethan Glasser-Camp <ethan at betacantrips.com>
---
 offlineimap/imapserver.py |   60 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/offlineimap/imapserver.py b/offlineimap/imapserver.py
index 58e7e57..ebd867e 100644
--- a/offlineimap/imapserver.py
+++ b/offlineimap/imapserver.py
@@ -18,8 +18,9 @@
 
 from offlineimap import imaplibutil, imaputil, threadutil, OfflineImapError
 from offlineimap.ui import getglobalui
-from threading import Lock, BoundedSemaphore
+from threading import Lock, BoundedSemaphore, Thread, Event, currentThread
 from thread import get_ident	# python < 2.6 support
+import offlineimap.accounts
 import time
 import hmac
 import socket
@@ -367,6 +368,63 @@ class IMAPServer:
 
             self.ui.debug('imap', 'keepalive: bottom of loop')
 
+class IdleThread(object):
+    def __init__(self, parent, folder=None):
+        self.parent = parent
+        self.folder = folder
+        self.event = Event()
+        if folder is None:
+            self.thread = Thread(target=self.noop)
+        else:
+            self.thread = Thread(target=self.idle)
+        self.thread.setDaemon(1)
+
+    def start(self):
+        self.thread.start()
+
+    def stop(self):
+        self.event.set()
+
+    def join(self):
+        self.thread.join()
+
+    def noop(self):
+        imapobj = self.parent.acquireconnection()
+        imapobj.noop()
+        self.event.wait()
+        self.parent.releaseconnection(imapobj)
+
+    def dosync(self):
+        remoterepos = self.parent.repos
+        account = remoterepos.account
+        localrepos = account.localrepos
+        remoterepos = account.remoterepos
+        statusrepos = account.statusrepos
+        remotefolder = remoterepos.getfolder(self.folder)
+        offlineimap.accounts.syncfolder(account.name, remoterepos, remotefolder, localrepos, statusrepos, quick=False)
+        ui = getglobalui()
+        ui.unregisterthread(currentThread())
+
+    def idle(self):
+        while True:
+            if self.event.isSet():
+                return
+            self.needsync = False
+            def callback(args):
+                if not self.event.isSet():
+                    self.needsync = True
+                    self.event.set()
+            imapobj = self.parent.acquireconnection()
+            imapobj.select(self.folder)
+            imapobj.idle(callback=callback)
+            self.event.wait()
+            if self.event.isSet():
+                imapobj.noop()
+            self.parent.releaseconnection(imapobj)
+            if self.needsync:
+                self.event.clear()
+                self.dosync()
+
 class ConfigedIMAPServer(IMAPServer):
     """This class is designed for easier initialization given a ConfigParser
     object and an account name.  The passwordhash is used if
-- 
1.7.4.1





More information about the OfflineIMAP-project mailing list