From dc3ad723c9b60eb766bf6c9af93f5818d72be9f2 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Wed, 16 Mar 2011 16:24:07 +0100 Subject: [PATCH 1/2] Give some love to UIDMaps - Some documentation improvements, this is a severely underdocumented class. This still needs some further improvements though. - Don't use apply(Baseclass) (which is going away in Python 3), use IMAPFolder.__init__(self, *args, **kwargs). - Don't call ValueError, string. It is ValueError(string) Signed-off-by: Sebastian Spaeth Signed-off-by: Nicolas Sebrecht --- offlineimap/folder/Base.py | 19 ++++++++++--------- offlineimap/folder/UIDMaps.py | 34 ++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/offlineimap/folder/Base.py b/offlineimap/folder/Base.py index 4bc5aab..a545783 100644 --- a/offlineimap/folder/Base.py +++ b/offlineimap/folder/Base.py @@ -158,20 +158,21 @@ class BaseFolder: def savemessage(self, uid, content, flags, rtime): """Writes a new message, with the specified uid. - If the uid is < 0, the backend should assign a new uid and return it. - If the backend cannot assign a new uid, it returns the uid passed in - WITHOUT saving the message. + If the uid is < 0: The backend should assign a new uid and + return it. In case it cannot assign a new uid, it returns + the negative uid passed in WITHOUT saving the message. - If the backend CAN assign a new uid, but cannot find out what this UID - is (as is the case with many IMAP servers), it returns 0 but DOES save - the message. + If the backend CAN assign a new uid, but cannot find out what + this UID is (as is the case with some IMAP servers), it + returns 0 but DOES save the message. - IMAP backend should be the only one that can assign a new uid. + IMAP backend should be the only one that can assign a new + uid. If the uid is > 0, the backend should set the uid to this, if it can. - If it cannot set the uid to that, it will save it anyway. - It will return the uid assigned in any case. + If it cannot set the uid to that, it will save it anyway. + It will return the uid assigned in any case. """ raise NotImplementedException diff --git a/offlineimap/folder/UIDMaps.py b/offlineimap/folder/UIDMaps.py index e7394b5..78e4357 100644 --- a/offlineimap/folder/UIDMaps.py +++ b/offlineimap/folder/UIDMaps.py @@ -23,6 +23,14 @@ from IMAP import IMAPFolder import os.path, re class MappingFolderMixIn: + """Helper class to map between Folder() instances where both side assign a uid + + Instance variables (self.): + r2l: dict mapping message uids: self.r2l[remoteuid]=localuid + l2r: dict mapping message uids: self.r2l[localuid]=remoteuid + #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): self.maplock = Lock() (self.diskr2l, self.diskl2r) = self._loadmaps() @@ -131,30 +139,32 @@ class MappingFolderMixIn: def savemessage(self, uid, content, flags, rtime): """Writes a new message, with the specified uid. - If the uid is < 0, the backend should assign a new uid and return it. - If the backend cannot assign a new uid, it returns the uid passed in - WITHOUT saving the message. - - If the backend CAN assign a new uid, but cannot find out what this UID - is (as is the case with many IMAP servers), it returns 0 but DOES save - the message. - - IMAP backend should be the only one that can assign a new uid. + The UIDMaps class will not return a newly assigned uid, as it + internally maps different uids between IMAP servers. So a + successful savemessage() invocation will return the same uid it + has been invoked with. As it maps between 2 IMAP servers which + means the source message must already have an uid, it requires a + positive uid to be passed in. Passing in a message with a + negative uid will do nothing and return the negative uid. If the uid is > 0, the backend should set the uid to this, if it can. If it cannot set the uid to that, it will save it anyway. It will return the uid assigned in any case. """ + # Mapped UID instances require the source to already have a + # positive UID, so simply return here. if uid < 0: - # We cannot assign a new uid. return uid + + #if msg uid already exists, just modify the flags if uid in self.r2l: self.savemessageflags(uid, flags) return uid + newluid = self._mb.savemessage(self, -1, content, flags, rtime) if newluid < 1: - raise ValueError, "Backend could not find uid for message" + raise ValueError("Backend could not find uid for message") self.maplock.acquire() try: self.diskl2r[newluid] = uid @@ -221,5 +231,5 @@ class MappingFolderMixIn: # Define a class for local part of IMAP. class MappedIMAPFolder(MappingFolderMixIn, IMAPFolder): def __init__(self, *args, **kwargs): - apply(IMAPFolder.__init__, (self,) + args, kwargs) + IMAPFolder.__init__(self, *args, **kwargs) self._initmapping() From fd28c5a2d345327fc3784a820c59f408f376adc6 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Wed, 16 Mar 2011 16:03:35 +0100 Subject: [PATCH 2/2] folder/IMAP: savemessage() should just save flags if uid already exists As the LocalStatus and UIDMap backend already did: If the uid already exists for savemessage(), only modify the flags and don't append a new message. We don't invoke savemessage() on messages that already exist in our sync logic, so this has no change on our current behavior. But it makes backends befave more consistent with each other. Signed-off-by: Sebastian Spaeth Signed-off-by: Nicolas Sebrecht --- offlineimap/folder/IMAP.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/offlineimap/folder/IMAP.py b/offlineimap/folder/IMAP.py index 89848b2..74a9b87 100644 --- a/offlineimap/folder/IMAP.py +++ b/offlineimap/folder/IMAP.py @@ -394,6 +394,11 @@ class IMAPFolder(BaseFolder): server. If the folder is read-only it will return 0.""" self.ui.debug('imap', 'savemessage: called') + # already have it, just save modified flags + if uid > 0 and uid in self.messagelist: + self.savemessageflags(uid, flags) + return uid + try: imapobj = self.imapserver.acquireconnection()