Make flags a set rather than a list
As this is essentially what it is, a set of values. This allows as to do set arithmetics to see, e.g. the intersection of 2 flag sets rather than clunkily having to do: for flag in newflags: if flag not in oldflags: oldflags.append(flag) Also some more code documenting. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de> Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
373e7cdbc1
commit
466ded04d9
@ -22,6 +22,10 @@ import os.path
|
||||
import re
|
||||
from sys import exc_info
|
||||
import traceback
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
class BaseFolder(object):
|
||||
def __init__(self):
|
||||
@ -189,12 +193,9 @@ class BaseFolder(object):
|
||||
|
||||
def addmessageflags(self, uid, flags):
|
||||
"""Adds the specified flags to the message's flag set. If a given
|
||||
flag is already present, it will not be duplicated."""
|
||||
newflags = self.getmessageflags(uid)
|
||||
for flag in flags:
|
||||
if not flag in newflags:
|
||||
newflags.append(flag)
|
||||
newflags.sort()
|
||||
flag is already present, it will not be duplicated.
|
||||
:param flags: A set() of flags"""
|
||||
newflags = self.getmessageflags(uid) | flags
|
||||
self.savemessageflags(uid, newflags)
|
||||
|
||||
def addmessagesflags(self, uidlist, flags):
|
||||
@ -204,11 +205,7 @@ class BaseFolder(object):
|
||||
def deletemessageflags(self, uid, flags):
|
||||
"""Removes each flag given from the message's flag set. If a given
|
||||
flag is already removed, no action will be taken for that flag."""
|
||||
newflags = self.getmessageflags(uid)
|
||||
for flag in flags:
|
||||
if flag in newflags:
|
||||
newflags.remove(flag)
|
||||
newflags.sort()
|
||||
newflags = self.getmessageflags(uid) - flags
|
||||
self.savemessageflags(uid, newflags)
|
||||
|
||||
def deletemessagesflags(self, uidlist, flags):
|
||||
@ -362,8 +359,8 @@ class BaseFolder(object):
|
||||
addflaglist = {}
|
||||
delflaglist = {}
|
||||
for uid in self.getmessageuidlist():
|
||||
# Ignore messages with negative UIDs missed by pass 1
|
||||
# also don't do anything if the message has been deleted remotely
|
||||
# Ignore messages with negative UIDs missed by pass 1 and
|
||||
# don't do anything if the message has been deleted remotely
|
||||
if uid < 0 or not dstfolder.uidexists(uid):
|
||||
continue
|
||||
|
||||
@ -371,29 +368,30 @@ class BaseFolder(object):
|
||||
statusflags = statusfolder.getmessageflags(uid)
|
||||
#if we could not get message flags from LocalStatus, assume empty.
|
||||
if statusflags is None:
|
||||
statusflags = []
|
||||
addflags = [x for x in selfflags if x not in statusflags]
|
||||
statusflags = set()
|
||||
|
||||
addflags = selfflags - statusflags
|
||||
delflags = statusflags - selfflags
|
||||
|
||||
for flag in addflags:
|
||||
if not flag in addflaglist:
|
||||
addflaglist[flag] = []
|
||||
addflaglist[flag].append(uid)
|
||||
|
||||
delflags = [x for x in statusflags if x not in selfflags]
|
||||
for flag in delflags:
|
||||
if not flag in delflaglist:
|
||||
delflaglist[flag] = []
|
||||
delflaglist[flag].append(uid)
|
||||
|
||||
for flag in addflaglist.keys():
|
||||
self.ui.addingflags(addflaglist[flag], flag, dstfolder)
|
||||
dstfolder.addmessagesflags(addflaglist[flag], [flag])
|
||||
statusfolder.addmessagesflags(addflaglist[flag], [flag])
|
||||
for flag, uids in addflaglist.items():
|
||||
self.ui.addingflags(uids, flag, dstfolder)
|
||||
dstfolder.addmessagesflags(uids, set(flag))
|
||||
statusfolder.addmessagesflags(uids, set(flag))
|
||||
|
||||
for flag in delflaglist.keys():
|
||||
self.ui.deletingflags(delflaglist[flag], flag, dstfolder)
|
||||
dstfolder.deletemessagesflags(delflaglist[flag], [flag])
|
||||
statusfolder.deletemessagesflags(delflaglist[flag], [flag])
|
||||
for flag,uids in delflaglist.items():
|
||||
self.ui.deletingflags(uids, flag, dstfolder)
|
||||
dstfolder.deletemessagesflags(uids, set(flag))
|
||||
statusfolder.deletemessagesflags(uids, set(flag))
|
||||
|
||||
def syncmessagesto(self, dstfolder, statusfolder):
|
||||
"""Syncs messages in this folder to the destination dstfolder.
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
from IMAP import IMAPFolder
|
||||
from offlineimap import imaputil
|
||||
from copy import copy
|
||||
|
||||
|
||||
class GmailFolder(IMAPFolder):
|
||||
|
@ -24,6 +24,11 @@ import time
|
||||
from copy import copy
|
||||
from Base import BaseFolder
|
||||
from offlineimap import imaputil, imaplibutil, OfflineImapError
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
|
||||
class IMAPFolder(BaseFolder):
|
||||
def __init__(self, imapserver, name, visiblename, accountname, repository):
|
||||
@ -176,7 +181,8 @@ class IMAPFolder(BaseFolder):
|
||||
finally:
|
||||
self.imapserver.releaseconnection(imapobj)
|
||||
for messagestr in response:
|
||||
# Discard the message number.
|
||||
# looks like: '1 (FLAGS (\\Seen Old) UID 4807)'
|
||||
# Discard initial message number.
|
||||
messagestr = messagestr.split(' ', 1)[1]
|
||||
options = imaputil.flags2hash(messagestr)
|
||||
if not options.has_key('UID'):
|
||||
@ -652,23 +658,18 @@ class IMAPFolder(BaseFolder):
|
||||
if not ('UID' in attributehash and 'FLAGS' in attributehash):
|
||||
# Compensate for servers that don't return a UID attribute.
|
||||
continue
|
||||
lflags = attributehash['FLAGS']
|
||||
flagstr = attributehash['FLAGS']
|
||||
uid = long(attributehash['UID'])
|
||||
self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(lflags)
|
||||
self.messagelist[uid]['flags'] = imaputil.flagsimap2maildir(flagstr)
|
||||
try:
|
||||
needupdate.remove(uid)
|
||||
except ValueError: # Let it slide if it's not in the list
|
||||
pass
|
||||
for uid in needupdate:
|
||||
if operation == '+':
|
||||
for flag in flags:
|
||||
if not flag in self.messagelist[uid]['flags']:
|
||||
self.messagelist[uid]['flags'].append(flag)
|
||||
self.messagelist[uid]['flags'].sort()
|
||||
self.messagelist[uid]['flags'] |= flags
|
||||
elif operation == '-':
|
||||
for flag in flags:
|
||||
if flag in self.messagelist[uid]['flags']:
|
||||
self.messagelist[uid]['flags'].remove(flag)
|
||||
self.messagelist[uid]['flags'] -= flags
|
||||
|
||||
def deletemessage(self, uid):
|
||||
self.deletemessages_noconvert([uid])
|
||||
@ -682,7 +683,7 @@ class IMAPFolder(BaseFolder):
|
||||
if not len(uidlist):
|
||||
return
|
||||
|
||||
self.addmessagesflags_noconvert(uidlist, ['T'])
|
||||
self.addmessagesflags_noconvert(uidlist, set('T'))
|
||||
imapobj = self.imapserver.acquireconnection()
|
||||
try:
|
||||
try:
|
||||
|
@ -1,6 +1,5 @@
|
||||
# Local status cache virtual folder
|
||||
# Copyright (C) 2002 - 2008 John Goerzen
|
||||
# <jgoerzen@complete.org>
|
||||
# Copyright (C) 2002 - 2011 John Goerzen & contributors
|
||||
#
|
||||
# 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
|
||||
@ -19,6 +18,10 @@
|
||||
from Base import BaseFolder
|
||||
import os
|
||||
import threading
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT 1"
|
||||
|
||||
@ -80,11 +83,12 @@ class LocalStatusFolder(BaseFolder):
|
||||
try:
|
||||
uid, flags = line.split(':')
|
||||
uid = long(uid)
|
||||
flags = set(flags)
|
||||
except ValueError, e:
|
||||
errstr = "Corrupt line '%s' in cache file '%s'" % (line, self.filename)
|
||||
errstr = "Corrupt line '%s' in cache file '%s'" % \
|
||||
(line, self.filename)
|
||||
self.ui.warn(errstr)
|
||||
raise ValueError(errstr)
|
||||
flags = [x for x in flags]
|
||||
self.messagelist[uid] = {'uid': uid, 'flags': flags}
|
||||
file.close()
|
||||
|
||||
@ -95,8 +99,7 @@ class LocalStatusFolder(BaseFolder):
|
||||
file.write(magicline + "\n")
|
||||
for msg in self.messagelist.values():
|
||||
flags = msg['flags']
|
||||
flags.sort()
|
||||
flags = ''.join(flags)
|
||||
flags = ''.join(sorted(flags))
|
||||
file.write("%s:%s\n" % (msg['uid'], flags))
|
||||
file.flush()
|
||||
if self.doautosave:
|
||||
|
@ -23,6 +23,11 @@ try:
|
||||
except:
|
||||
pass #fail only if needed later on, not on import
|
||||
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
class LocalStatusSQLiteFolder(LocalStatusFolder):
|
||||
"""LocalStatus backend implemented with an SQLite database
|
||||
|
||||
@ -127,7 +132,6 @@ class LocalStatusSQLiteFolder(LocalStatusFolder):
|
||||
for line in file.xreadlines():
|
||||
uid, flags = line.strip().split(':')
|
||||
uid = long(uid)
|
||||
flags = list(flags)
|
||||
flags = ''.join(sorted(flags))
|
||||
data.append((uid,flags))
|
||||
self.connection.executemany('INSERT INTO status (id,flags) VALUES (?,?)',
|
||||
@ -167,7 +171,7 @@ class LocalStatusSQLiteFolder(LocalStatusFolder):
|
||||
self.messagelist = {}
|
||||
cursor = self.connection.execute('SELECT id,flags from status')
|
||||
for row in cursor:
|
||||
flags = [x for x in row[1]]
|
||||
flags = set(row[1])
|
||||
self.messagelist[row[0]] = {'uid': row[0], 'flags': flags}
|
||||
|
||||
def save(self):
|
||||
|
@ -28,6 +28,11 @@ try:
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
from offlineimap import OfflineImapError
|
||||
|
||||
uidmatchre = re.compile(',U=(\d+)')
|
||||
@ -166,11 +171,12 @@ class MaildirFolder(BaseFolder):
|
||||
nouidcounter -= 1
|
||||
else:
|
||||
uid = long(uidmatch.group(1))
|
||||
#identify flags in the path name
|
||||
flagmatch = self.flagmatchre.search(messagename)
|
||||
flags = []
|
||||
if flagmatch:
|
||||
flags = [x for x in flagmatch.group(1)]
|
||||
flags.sort()
|
||||
flags = set(flagmatch.group(1))
|
||||
else:
|
||||
flags = set()
|
||||
retval[uid] = {'uid': uid,
|
||||
'flags': flags,
|
||||
'filename': file}
|
||||
@ -261,7 +267,7 @@ class MaildirFolder(BaseFolder):
|
||||
if rtime != None:
|
||||
os.utime(os.path.join(tmpdir, messagename), (rtime, rtime))
|
||||
|
||||
self.messagelist[uid] = {'uid': uid, 'flags': [],
|
||||
self.messagelist[uid] = {'uid': uid, 'flags': set(),
|
||||
'filename': os.path.join('tmp', messagename)}
|
||||
# savemessageflags moves msg to 'cur' or 'new' as appropriate
|
||||
self.savemessageflags(uid, flags)
|
||||
@ -288,8 +294,7 @@ class MaildirFolder(BaseFolder):
|
||||
infostr = infomatch.group(1)
|
||||
newname = newname.split(self.infosep)[0] # Strip off the info string.
|
||||
infostr = re.sub('2,[A-Z]*', '', infostr)
|
||||
flags.sort()
|
||||
infostr += '2,' + ''.join(flags)
|
||||
infostr += '2,' + ''.join(sorted(flags))
|
||||
newname += infostr
|
||||
|
||||
newfilename = os.path.join(dir_prefix, newname)
|
||||
|
@ -20,6 +20,11 @@ import re
|
||||
import string
|
||||
import types
|
||||
from offlineimap.ui import getglobalui
|
||||
try: # python 2.6 has set() built in
|
||||
set
|
||||
except NameError:
|
||||
from sets import Set as set
|
||||
|
||||
quotere = re.compile('^("(?:[^"]|\\\\")*")')
|
||||
|
||||
def debug(*args):
|
||||
@ -42,11 +47,21 @@ def dequote(string):
|
||||
return string
|
||||
|
||||
def flagsplit(string):
|
||||
"""Converts a string of IMAP flags to a list
|
||||
|
||||
:returns: E.g. '(\\Draft \\Deleted)' returns ['\\Draft','\\Deleted'].
|
||||
(FLAGS (\\Seen Old) UID 4807) returns
|
||||
['FLAGS,'(\\Seen Old)','UID', '4807']
|
||||
"""
|
||||
if string[0] != '(' or string[-1] != ')':
|
||||
raise ValueError, "Passed string '%s' is not a flag list" % string
|
||||
return imapsplit(string[1:-1])
|
||||
|
||||
def options2hash(list):
|
||||
"""convert list [1,2,3,4,5,6] to {1:2, 3:4, 5:6}"""
|
||||
# effectively this does dict(zip(l[::2],l[1::2])), however
|
||||
# measurements seemed to have indicated that the manual variant is
|
||||
# faster for mosly small lists.
|
||||
retval = {}
|
||||
counter = 0
|
||||
while (counter < len(list)):
|
||||
@ -55,8 +70,12 @@ def options2hash(list):
|
||||
debug("options2hash returning:", retval)
|
||||
return retval
|
||||
|
||||
def flags2hash(string):
|
||||
return options2hash(flagsplit(string))
|
||||
def flags2hash(flags):
|
||||
"""Converts IMAP response string from eg IMAP4.fetch() to a hash.
|
||||
|
||||
E.g. '(FLAGS (\\Seen Old) UID 4807)' leads to
|
||||
{'FLAGS': '(\\Seen Old)', 'UID': '4807'}"""
|
||||
return options2hash(flagsplit(flags))
|
||||
|
||||
def imapsplit(imapstring):
|
||||
"""Takes a string from an IMAP conversation and returns a list containing
|
||||
@ -152,15 +171,16 @@ flagmap = [('\\Seen', 'S'),
|
||||
('\\Draft', 'D')]
|
||||
|
||||
def flagsimap2maildir(flagstring):
|
||||
retval = []
|
||||
imapflaglist = [x.lower() for x in flagstring[1:-1].split()]
|
||||
"""Convert string '(\\Draft \\Deleted)' into a flags set(DR)"""
|
||||
retval = set()
|
||||
imapflaglist = flagstring[1:-1].split()
|
||||
for imapflag, maildirflag in flagmap:
|
||||
if imapflag.lower() in imapflaglist:
|
||||
retval.append(maildirflag)
|
||||
retval.sort()
|
||||
if imapflag in imapflaglist:
|
||||
retval.add(maildirflag)
|
||||
return retval
|
||||
|
||||
def flagsmaildir2imap(maildirflaglist):
|
||||
"""Convert set of flags ([DR]) into a string '(\\Draft \\Deleted)'"""
|
||||
retval = []
|
||||
for imapflag, maildirflag in flagmap:
|
||||
if maildirflag in maildirflaglist:
|
||||
@ -198,8 +218,3 @@ def listjoin(list):
|
||||
retval.append(getlist(start, end))
|
||||
|
||||
return ",".join(retval)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user