[PATCH] Simplify MappedIMAPFolder, fixing bugs

Sebastian Spaeth Sebastian at SSpaeth.de
Fri Jun 24 10:28:30 BST 2011

Previously, we instanciated an MappedImapFolder, and would cleverly (too
cleverly?) invoke methods on it casting it to an IMAPFolder by calling
methods such as: self._mb.cachemessages(self) where self._MB is the class
IMAPFolder and self and instance of MappedImapFolder. If
e.g. cachemessages() invokes a method uidexists() which exists for
MappedImapFolder, but not directly in IMAPFolder, I am not sure if
Python would at some point attempt to use the method of the wrong class.
Also, this leads to some twisted thinking as our class would in same
cases act as an IMAPFolder and in some cases as an MappedImapFOlder and
it is not always clear if we mean REMOTE UID or LOCAL UID.

This commit simplifies the class, by a)doing away with the complex Mixin
construct and directly inheriting from IMAPFOlder (so we get all the
IMAPFOlder methods that we can inherit). We instantiate self._mb as a
new instance of IMAPFolder which represents the local IMAP using local
UIDs, separating the MappedIMAPFolder construct logically from the
IMAPFolder somewhat.

In the long run, I would like to remove self._mb completely and simply
override any method that needs overriding, but let us take small and
understandable baby steps here.

Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
 offlineimap/folder/UIDMaps.py |   46 ++++++++++++++++++++--------------------
 1 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/offlineimap/folder/UIDMaps.py b/offlineimap/folder/UIDMaps.py
index 5f770ce..9233662 100644
--- a/offlineimap/folder/UIDMaps.py
+++ b/offlineimap/folder/UIDMaps.py
@@ -20,8 +20,11 @@ from threading import *
 from IMAP import IMAPFolder
 import os.path
-class MappingFolderMixIn:
-    """Helper class to map between Folder() instances where both side assign a uid
+class MappedIMAPFolder(IMAPFolder):
+    """IMAP class to map between Folder() instances where both side assign a uid
+    This Folder is used on the local side, while the remote side should
+    be an IMAPFolder.
     Instance variables (self.):
       r2l: dict mapping message uids: self.r2l[remoteuid]=localuid
@@ -29,10 +32,13 @@ class MappingFolderMixIn:
       #TODO: what is the difference, how are they used?
       diskr2l: dict mapping message uids: self.r2l[remoteuid]=localuid
       diskl2r: dict mapping message uids: self.r2l[localuid]=remoteuid"""
-    def _initmapping(self):
+    def __init__(self, *args, **kwargs):
+	IMAPFolder.__init__(self, *args, **kwargs)
         self.maplock = Lock()
         (self.diskr2l, self.diskl2r) = self._loadmaps()
-        self._mb = self.__class__.__bases__[1]
+        self._mb = IMAPFolder(*args, **kwargs)
+        """Representing the local IMAP Folder using local UIDs"""
     def _getmapfilename(self):
         return os.path.join(self.repository.getmapdir(),
@@ -81,8 +87,8 @@ class MappingFolderMixIn:
         return [mapping[x] for x in items]
     def cachemessagelist(self):
-        self._mb.cachemessagelist(self)
-        reallist = self._mb.getmessagelist(self)
+        self._mb.cachemessagelist()
+        reallist = self._mb.getmessagelist()
@@ -137,7 +143,7 @@ class MappingFolderMixIn:
         cachemessagelist() before calling this function!"""
         retval = {}
-        localhash = self._mb.getmessagelist(self)
+        localhash = self._mb.getmessagelist()
             for key, value in localhash.items():
@@ -158,7 +164,7 @@ class MappingFolderMixIn:
     def getmessage(self, uid):
         """Returns the content of the specified message."""
-        return self._mb.getmessage(self, self.r2l[uid])
+        return self._mb.getmessage(self.r2l[uid])
     def savemessage(self, uid, content, flags, rtime):
         """Writes a new message, with the specified uid.
@@ -185,7 +191,7 @@ class MappingFolderMixIn:
             self.savemessageflags(uid, flags)
             return uid
-        newluid = self._mb.savemessage(self, -1, content, flags, rtime)
+        newluid = self._mb.savemessage(-1, content, flags, rtime)
         if newluid < 1:
             raise ValueError("Backend could not find uid for message")
@@ -200,19 +206,19 @@ class MappingFolderMixIn:
         return uid
     def getmessageflags(self, uid):
-        return self._mb.getmessageflags(self, self.r2l[uid])
+        return self._mb.getmessageflags(self.r2l[uid])
     def getmessagetime(self, uid):
         return None
     def savemessageflags(self, uid, flags):
-        self._mb.savemessageflags(self, self.r2l[uid], flags)
+        self._mb.savemessageflags(self.r2l[uid], flags)
     def addmessageflags(self, uid, flags):
-        self._mb.addmessageflags(self, self.r2l[uid], flags)
+        self._mb.addmessageflags(self.r2l[uid], flags)
     def addmessagesflags(self, uidlist, flags):
-        self._mb.addmessagesflags(self, self._uidlist(self.r2l, uidlist),
+        self._mb.addmessagesflags(self._uidlist(self.r2l, uidlist),
     def _mapped_delete(self, uidlist):
@@ -233,22 +239,16 @@ class MappingFolderMixIn:
     def deletemessageflags(self, uid, flags):
-        self._mb.deletemessageflags(self, self.r2l[uid], flags)
+        self._mb.deletemessageflags(self.r2l[uid], flags)
     def deletemessagesflags(self, uidlist, flags):
-        self._mb.deletemessagesflags(self, self._uidlist(self.r2l, uidlist),
+        self._mb.deletemessagesflags(self._uidlist(self.r2l, uidlist),
     def deletemessage(self, uid):
-        self._mb.deletemessage(self, self.r2l[uid])
+        self._mb.deletemessage(self.r2l[uid])
     def deletemessages(self, uidlist):
-        self._mb.deletemessages(self, self._uidlist(self.r2l, uidlist))
+        self._mb.deletemessages(self._uidlist(self.r2l, uidlist))
-# Define a class for local part of IMAP.
-class MappedIMAPFolder(MappingFolderMixIn, IMAPFolder):
-    def __init__(self, *args, **kwargs):
-	IMAPFolder.__init__(self, *args, **kwargs)
-        self._initmapping()

More information about the OfflineIMAP-project mailing list