more style consistency
Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
@ -48,13 +48,11 @@ class BaseFolder(object):
|
||||
self.visiblename = ''
|
||||
|
||||
self.config = repository.getconfig()
|
||||
utime_from_message_global = \
|
||||
self.config.getdefaultboolean("general",
|
||||
"utime_from_message", False)
|
||||
utime_from_message_global = self.config.getdefaultboolean(
|
||||
"general", "utime_from_message", False)
|
||||
repo = "Repository " + repository.name
|
||||
self._utime_from_message = \
|
||||
self.config.getdefaultboolean(repo,
|
||||
"utime_from_message", utime_from_message_global)
|
||||
self._utime_from_message = self.config.getdefaultboolean(repo,
|
||||
"utime_from_message", utime_from_message_global)
|
||||
|
||||
# Determine if we're running static or dynamic folder filtering
|
||||
# and check filtering status
|
||||
@ -78,16 +76,19 @@ class BaseFolder(object):
|
||||
return self.name
|
||||
|
||||
def __str__(self):
|
||||
# FIMXE: remove calls of this. We have getname().
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def accountname(self):
|
||||
"""Account name as string"""
|
||||
|
||||
return self.repository.accountname
|
||||
|
||||
@property
|
||||
def sync_this(self):
|
||||
"""Should this folder be synced or is it e.g. filtered out?"""
|
||||
|
||||
if not self._dynamic_folderfilter:
|
||||
return self._sync_this
|
||||
else:
|
||||
@ -144,7 +145,7 @@ class BaseFolder(object):
|
||||
if self.name == self.visiblename:
|
||||
return self.name
|
||||
else:
|
||||
return "%s [remote name %s]" % (self.visiblename, self.name)
|
||||
return "%s [remote name %s]"% (self.visiblename, self.name)
|
||||
|
||||
def getrepository(self):
|
||||
"""Returns the repository object that this folder is within."""
|
||||
@ -172,9 +173,9 @@ class BaseFolder(object):
|
||||
|
||||
if not self.name:
|
||||
basename = '.'
|
||||
else: #avoid directory hierarchies and file names such as '/'
|
||||
else: # Avoid directory hierarchies and file names such as '/'.
|
||||
basename = self.name.replace('/', '.')
|
||||
# replace with literal 'dot' if final path name is '.' as '.' is
|
||||
# Replace with literal 'dot' if final path name is '.' as '.' is
|
||||
# an invalid file name.
|
||||
basename = re.sub('(^|\/)\.$','\\1dot', basename)
|
||||
return basename
|
||||
@ -196,7 +197,7 @@ class BaseFolder(object):
|
||||
return True
|
||||
|
||||
def _getuidfilename(self):
|
||||
"""provides UIDVALIDITY cache filename for class internal purposes"""
|
||||
"""provides UIDVALIDITY cache filename for class internal purposes.
|
||||
|
||||
return os.path.join(self.repository.getuiddir(),
|
||||
self.getfolderbasename())
|
||||
@ -228,7 +229,7 @@ class BaseFolder(object):
|
||||
uidfilename = self._getuidfilename()
|
||||
|
||||
with open(uidfilename + ".tmp", "wt") as file:
|
||||
file.write("%d\n" % newval)
|
||||
file.write("%d\n"% newval)
|
||||
os.rename(uidfilename + ".tmp", uidfilename)
|
||||
self._base_saved_uidvalidity = newval
|
||||
|
||||
@ -252,6 +253,7 @@ class BaseFolder(object):
|
||||
|
||||
def getmessagelist(self):
|
||||
"""Gets the current message list.
|
||||
|
||||
You must call cachemessagelist() before calling this function!"""
|
||||
|
||||
raise NotImplementedError
|
||||
@ -272,6 +274,7 @@ class BaseFolder(object):
|
||||
|
||||
def getmessageuidlist(self):
|
||||
"""Gets a list of UIDs.
|
||||
|
||||
You may have to call cachemessagelist() before calling this function!"""
|
||||
|
||||
return self.getmessagelist().keys()
|
||||
@ -377,6 +380,7 @@ class BaseFolder(object):
|
||||
|
||||
def getmessagelabels(self, uid):
|
||||
"""Returns the labels for the specified message."""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def savemessagelabels(self, uid, labels, ignorelabels=set(), mtime=0):
|
||||
@ -691,10 +695,10 @@ class BaseFolder(object):
|
||||
# load it up.
|
||||
if dstfolder.storesmessages():
|
||||
message = self.getmessage(uid)
|
||||
#Succeeded? -> IMAP actually assigned a UID. If newid
|
||||
#remained negative, no server was willing to assign us an
|
||||
#UID. If newid is 0, saving succeeded, but we could not
|
||||
#retrieve the new UID. Ignore message in this case.
|
||||
# Succeeded? -> IMAP actually assigned a UID. If newid
|
||||
# remained negative, no server was willing to assign us an
|
||||
# UID. If newid is 0, saving succeeded, but we could not
|
||||
# retrieve the new UID. Ignore message in this case.
|
||||
new_uid = dstfolder.savemessage(uid, message, flags, rtime)
|
||||
if new_uid > 0:
|
||||
if new_uid != uid:
|
||||
@ -728,7 +732,7 @@ class BaseFolder(object):
|
||||
raise #raise on unknown errors, so we can fix those
|
||||
|
||||
def __syncmessagesto_copy(self, dstfolder, statusfolder):
|
||||
"""Pass1: Copy locally existing messages not on the other side
|
||||
"""Pass1: Copy locally existing messages not on the other side.
|
||||
|
||||
This will copy messages to dstfolder that exist locally but are
|
||||
not in the statusfolder yet. The strategy is:
|
||||
@ -738,18 +742,16 @@ class BaseFolder(object):
|
||||
- If dstfolder doesn't have it yet, add them to dstfolder.
|
||||
- Update statusfolder
|
||||
|
||||
This function checks and protects us from action in ryrun mode.
|
||||
"""
|
||||
This function checks and protects us from action in dryrun mode."""
|
||||
|
||||
threads = []
|
||||
|
||||
copylist = filter(lambda uid: not \
|
||||
statusfolder.uidexists(uid),
|
||||
self.getmessageuidlist())
|
||||
copylist = filter(lambda uid: not statusfolder.uidexists(uid),
|
||||
self.getmessageuidlist())
|
||||
num_to_copy = len(copylist)
|
||||
if num_to_copy and self.repository.account.dryrun:
|
||||
self.ui.info("[DRYRUN] Copy {0} messages from {1}[{2}] to {3}".format(
|
||||
num_to_copy, self, self.repository, dstfolder.repository))
|
||||
num_to_copy, self, self.repository, dstfolder.repository))
|
||||
return
|
||||
for num, uid in enumerate(copylist):
|
||||
# bail out on CTRL-C or SIGTERM
|
||||
@ -773,7 +775,7 @@ class BaseFolder(object):
|
||||
thread.join()
|
||||
|
||||
def __syncmessagesto_delete(self, dstfolder, statusfolder):
|
||||
"""Pass 2: Remove locally deleted messages on dst
|
||||
"""Pass 2: Remove locally deleted messages on dst.
|
||||
|
||||
Get all UIDS in statusfolder but not self. These are messages
|
||||
that were deleted in 'self'. Delete those from dstfolder and
|
||||
@ -782,9 +784,8 @@ class BaseFolder(object):
|
||||
This function checks and protects us from action in ryrun mode.
|
||||
"""
|
||||
|
||||
deletelist = filter(lambda uid: uid>=0 \
|
||||
and not self.uidexists(uid),
|
||||
statusfolder.getmessageuidlist())
|
||||
deletelist = filter(lambda uid: uid >= 0 and not
|
||||
self.uidexists(uid), statusfolder.getmessageuidlist())
|
||||
if len(deletelist):
|
||||
self.ui.deletingmessages(deletelist, [dstfolder])
|
||||
if self.repository.account.dryrun:
|
||||
@ -795,7 +796,7 @@ class BaseFolder(object):
|
||||
folder.deletemessages(deletelist)
|
||||
|
||||
def __syncmessagesto_flags(self, dstfolder, statusfolder):
|
||||
"""Pass 3: Flag synchronization
|
||||
"""Pass 3: Flag synchronization.
|
||||
|
||||
Compare flag mismatches in self with those in statusfolder. If
|
||||
msg has a valid UID and exists on dstfolder (has not e.g. been
|
||||
@ -904,7 +905,7 @@ class BaseFolder(object):
|
||||
|
||||
def __eq__(self, other):
|
||||
"""Comparisons work either on string comparing folder names or
|
||||
on the same instance
|
||||
on the same instance.
|
||||
|
||||
MailDirFolder('foo') == 'foo' --> True
|
||||
a = MailDirFolder('foo'); a == b --> True
|
||||
|
@ -22,11 +22,10 @@ from sys import exc_info
|
||||
from offlineimap import imaputil, OfflineImapError
|
||||
from offlineimap import imaplibutil
|
||||
import offlineimap.accounts
|
||||
|
||||
"""Folder implementation to support features of the Gmail IMAP server.
|
||||
"""
|
||||
from .IMAP import IMAPFolder
|
||||
|
||||
"""Folder implementation to support features of the Gmail IMAP server."""
|
||||
|
||||
class GmailFolder(IMAPFolder):
|
||||
"""Folder implementation to support features of the Gmail IMAP server.
|
||||
|
||||
@ -101,11 +100,11 @@ class GmailFolder(IMAPFolder):
|
||||
body = self.addmessageheader(body, '\n', self.labelsheader, labels_str)
|
||||
|
||||
if len(body)>200:
|
||||
dbg_output = "%s...%s" % (str(body)[:150], str(body)[-50:])
|
||||
dbg_output = "%s...%s"% (str(body)[:150], str(body)[-50:])
|
||||
else:
|
||||
dbg_output = body
|
||||
|
||||
self.ui.debug('imap', "Returned object from fetching %d: '%s'" %
|
||||
self.ui.debug('imap', "Returned object from fetching %d: '%s'"%
|
||||
(uid, dbg_output))
|
||||
return body
|
||||
|
||||
@ -139,7 +138,7 @@ class GmailFolder(IMAPFolder):
|
||||
# imaplib2 from quoting the sequence.
|
||||
#
|
||||
# NB: msgsToFetch are sequential numbers, not UID's
|
||||
res_type, response = imapobj.fetch("'%s'" % msgsToFetch,
|
||||
res_type, response = imapobj.fetch("'%s'"% msgsToFetch,
|
||||
'(FLAGS X-GM-LABELS UID)')
|
||||
if res_type != 'OK':
|
||||
raise OfflineImapError("FETCHING UIDs in folder [%s]%s failed. " % \
|
||||
|
@ -164,10 +164,10 @@ class IMAPFolder(BaseFolder):
|
||||
# By default examine all messages in this folder
|
||||
msgsToFetch = '1:*'
|
||||
|
||||
maxage = self.config.getdefaultint("Account %s"% self.accountname,
|
||||
"maxage", -1)
|
||||
maxsize = self.config.getdefaultint("Account %s"% self.accountname,
|
||||
"maxsize", -1)
|
||||
maxage = self.config.getdefaultint(
|
||||
"Account %s"% self.accountname, "maxage", -1)
|
||||
maxsize = self.config.getdefaultint(
|
||||
"Account %s"% self.accountname, "maxsize", -1)
|
||||
|
||||
# Build search condition
|
||||
if (maxage != -1) | (maxsize != -1):
|
||||
@ -178,9 +178,9 @@ class IMAPFolder(BaseFolder):
|
||||
oldest_struct = time.gmtime(time.time() - (60*60*24*maxage))
|
||||
if oldest_struct[0] < 1900:
|
||||
raise OfflineImapError("maxage setting led to year %d. "
|
||||
"Abort syncing." % oldest_struct[0],
|
||||
OfflineImapError.ERROR.REPO)
|
||||
search_cond += "SINCE %02d-%s-%d" % (
|
||||
"Abort syncing."% oldest_struct[0],
|
||||
OfflineImapError.ERROR.REPO)
|
||||
search_cond += "SINCE %02d-%s-%d"% (
|
||||
oldest_struct[2],
|
||||
MonthNames[oldest_struct[1]],
|
||||
oldest_struct[0])
|
||||
@ -188,7 +188,7 @@ class IMAPFolder(BaseFolder):
|
||||
if(maxsize != -1):
|
||||
if(maxage != -1): # There are two conditions, add space
|
||||
search_cond += " "
|
||||
search_cond += "SMALLER %d" % maxsize
|
||||
search_cond += "SMALLER %d"% maxsize
|
||||
|
||||
search_cond += ")"
|
||||
|
||||
@ -225,10 +225,8 @@ class IMAPFolder(BaseFolder):
|
||||
msgsToFetch, '(FLAGS UID)')
|
||||
if res_type != 'OK':
|
||||
raise OfflineImapError("FETCHING UIDs in folder [%s]%s failed. "
|
||||
"Server responded '[%s] %s'"% (
|
||||
self.getrepository(), self,
|
||||
res_type, response),
|
||||
OfflineImapError.ERROR.FOLDER)
|
||||
"Server responded '[%s] %s'"% (self.getrepository(), self,
|
||||
res_type, response), OfflineImapError.ERROR.FOLDER)
|
||||
finally:
|
||||
self.imapserver.releaseconnection(imapobj)
|
||||
|
||||
@ -259,7 +257,7 @@ class IMAPFolder(BaseFolder):
|
||||
|
||||
# Interface from BaseFolder
|
||||
def getmessage(self, uid):
|
||||
"""Retrieve message with UID from the IMAP server (incl body)
|
||||
"""Retrieve message with UID from the IMAP server (incl body).
|
||||
|
||||
After this function all CRLFs will be transformed to '\n'.
|
||||
|
||||
@ -280,7 +278,7 @@ class IMAPFolder(BaseFolder):
|
||||
data = data[0][1].replace(CRLF, "\n")
|
||||
|
||||
if len(data)>200:
|
||||
dbg_output = "%s...%s" % (str(data)[:150], str(data)[-50:])
|
||||
dbg_output = "%s...%s"% (str(data)[:150], str(data)[-50:])
|
||||
else:
|
||||
dbg_output = data
|
||||
|
||||
@ -331,7 +329,8 @@ class IMAPFolder(BaseFolder):
|
||||
# Now find the UID it got.
|
||||
headervalue = imapobj._quote(headervalue)
|
||||
try:
|
||||
matchinguids = imapobj.uid('search', 'HEADER', headername, headervalue)[1][0]
|
||||
matchinguids = imapobj.uid('search', 'HEADER',
|
||||
headername, headervalue)[1][0]
|
||||
except imapobj.error as err:
|
||||
# IMAP server doesn't implement search or had a problem.
|
||||
self.ui.debug('imap', "__savemessage_searchforheader: got IMAP error '%s' while attempting to UID SEARCH for message with header %s"% (err, headername))
|
||||
@ -396,8 +395,8 @@ class IMAPFolder(BaseFolder):
|
||||
|
||||
result = imapobj.uid('FETCH', bytearray('%d:*'% start), 'rfc822.header')
|
||||
if result[0] != 'OK':
|
||||
raise OfflineImapError('Error fetching mail headers: ' + '. '.join(result[1]),
|
||||
OfflineImapError.ERROR.MESSAGE)
|
||||
raise OfflineImapError('Error fetching mail headers: %s'%
|
||||
'. '.join(result[1]), OfflineImapError.ERROR.MESSAGE)
|
||||
|
||||
result = result[1]
|
||||
|
||||
@ -423,7 +422,8 @@ class IMAPFolder(BaseFolder):
|
||||
def __getmessageinternaldate(self, content, rtime=None):
|
||||
"""Parses mail and returns an INTERNALDATE string
|
||||
|
||||
It will use information in the following order, falling back as an attempt fails:
|
||||
It will use information in the following order, falling back as an
|
||||
attempt fails:
|
||||
- rtime parameter
|
||||
- Date header of email
|
||||
|
||||
@ -475,21 +475,22 @@ class IMAPFolder(BaseFolder):
|
||||
"Server will use local time."% datetuple)
|
||||
return None
|
||||
|
||||
#produce a string representation of datetuple that works as
|
||||
#INTERNALDATE
|
||||
# Produce a string representation of datetuple that works as
|
||||
# INTERNALDATE.
|
||||
num2mon = {1:'Jan', 2:'Feb', 3:'Mar', 4:'Apr', 5:'May', 6:'Jun',
|
||||
7:'Jul', 8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec'}
|
||||
|
||||
#tm_isdst coming from email.parsedate is not usable, we still use it here, mhh
|
||||
# tm_isdst coming from email.parsedate is not usable, we still use it
|
||||
# here, mhh.
|
||||
if datetuple.tm_isdst == '1':
|
||||
zone = -time.altzone
|
||||
else:
|
||||
zone = -time.timezone
|
||||
offset_h, offset_m = divmod(zone//60, 60)
|
||||
|
||||
internaldate = '"%02d-%s-%04d %02d:%02d:%02d %+03d%02d"' \
|
||||
% (datetuple.tm_mday, num2mon[datetuple.tm_mon], datetuple.tm_year, \
|
||||
datetuple.tm_hour, datetuple.tm_min, datetuple.tm_sec, offset_h, offset_m)
|
||||
internaldate = '"%02d-%s-%04d %02d:%02d:%02d %+03d%02d"'% \
|
||||
(datetuple.tm_mday, num2mon[datetuple.tm_mon], datetuple.tm_year, \
|
||||
datetuple.tm_hour, datetuple.tm_min, datetuple.tm_sec, offset_h, offset_m)
|
||||
|
||||
return internaldate
|
||||
|
||||
@ -554,7 +555,7 @@ class IMAPFolder(BaseFolder):
|
||||
content = self.addmessageheader(content, CRLF, headername, headervalue)
|
||||
|
||||
if len(content)>200:
|
||||
dbg_output = "%s...%s" % (content[:150], content[-50:])
|
||||
dbg_output = "%s...%s"% (content[:150], content[-50:])
|
||||
else:
|
||||
dbg_output = content
|
||||
self.ui.debug('imap', "savemessage: date: %s, content: '%s'"%
|
||||
@ -726,6 +727,7 @@ class IMAPFolder(BaseFolder):
|
||||
Note that this function does not check against dryrun settings,
|
||||
so you need to ensure that it is never called in a
|
||||
dryrun mode."""
|
||||
|
||||
imapobj = self.imapserver.acquireconnection()
|
||||
try:
|
||||
result = self._store_to_imap(imapobj, str(uid), 'FLAGS',
|
||||
|
@ -21,8 +21,9 @@ import threading
|
||||
|
||||
from .Base import BaseFolder
|
||||
|
||||
|
||||
class LocalStatusFolder(BaseFolder):
|
||||
"""LocalStatus backend implemented as a plain text file"""
|
||||
"""LocalStatus backend implemented as a plain text file."""
|
||||
|
||||
cur_version = 2
|
||||
magicline = "OFFLINEIMAP LocalStatus CACHE DATA - DO NOT MODIFY - FORMAT %d"
|
||||
@ -53,12 +54,10 @@ class LocalStatusFolder(BaseFolder):
|
||||
if not self.isnewfolder():
|
||||
os.unlink(self.filename)
|
||||
|
||||
|
||||
# Interface from BaseFolder
|
||||
def msglist_item_initializer(self, uid):
|
||||
return {'uid': uid, 'flags': set(), 'labels': set(), 'time': 0, 'mtime': 0}
|
||||
|
||||
|
||||
def readstatus_v1(self, fp):
|
||||
"""Read status folder in format version 1.
|
||||
|
||||
@ -80,7 +79,6 @@ class LocalStatusFolder(BaseFolder):
|
||||
self.messagelist[uid] = self.msglist_item_initializer(uid)
|
||||
self.messagelist[uid]['flags'] = flags
|
||||
|
||||
|
||||
def readstatus(self, fp):
|
||||
"""Read status file in the current format.
|
||||
|
||||
@ -97,7 +95,7 @@ class LocalStatusFolder(BaseFolder):
|
||||
mtime = long(mtime)
|
||||
labels = set([lb.strip() for lb in labels.split(',') if len(lb.strip()) > 0])
|
||||
except ValueError as e:
|
||||
errstr = "Corrupt line '%s' in cache file '%s'" % \
|
||||
errstr = "Corrupt line '%s' in cache file '%s'"% \
|
||||
(line, self.filename)
|
||||
self.ui.warn(errstr)
|
||||
raise ValueError(errstr), None, exc_info()[2]
|
||||
@ -227,7 +225,6 @@ class LocalStatusFolder(BaseFolder):
|
||||
self.messagelist[uid]['flags'] = flags
|
||||
self.save()
|
||||
|
||||
|
||||
def savemessagelabels(self, uid, labels, mtime=None):
|
||||
self.messagelist[uid]['labels'] = labels
|
||||
if mtime: self.messagelist[uid]['mtime'] = mtime
|
||||
@ -263,7 +260,6 @@ class LocalStatusFolder(BaseFolder):
|
||||
def getmessagemtime(self, uid):
|
||||
return self.messagelist[uid]['mtime']
|
||||
|
||||
|
||||
# Interface from BaseFolder
|
||||
def deletemessage(self, uid):
|
||||
self.deletemessages([uid])
|
||||
|
@ -64,7 +64,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
#Try to establish connection, no need for threadsafety in __init__
|
||||
try:
|
||||
self.connection = sqlite.connect(self.filename, check_same_thread = False)
|
||||
self.connection = sqlite.connect(self.filename, check_same_thread=False)
|
||||
except NameError:
|
||||
# sqlite import had failed
|
||||
raise UserWarning('SQLite backend chosen, but no sqlite python '
|
||||
@ -93,7 +93,6 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
def getfullname(self):
|
||||
return self.filename
|
||||
|
||||
|
||||
# Interface from LocalStatusFolder
|
||||
def isnewfolder(self):
|
||||
return self._newfolder
|
||||
@ -101,7 +100,8 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
# Interface from LocalStatusFolder
|
||||
def deletemessagelist(self):
|
||||
"""delete all messages in the db"""
|
||||
"""Delete all messages in the db."""
|
||||
|
||||
self.__sql_write('DELETE FROM status')
|
||||
|
||||
|
||||
@ -114,6 +114,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
:param executemany: bool indicating whether we want to
|
||||
perform conn.executemany() or conn.execute().
|
||||
:returns: the Cursor() or raises an Exception"""
|
||||
|
||||
success = False
|
||||
while not success:
|
||||
self._dblock.acquire()
|
||||
@ -153,8 +154,8 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
# Upgrade from database version 1 to version 2
|
||||
# This change adds labels and mtime columns, to be used by Gmail IMAP and Maildir folders.
|
||||
if from_ver <= 1:
|
||||
self.ui._msg('Upgrading LocalStatus cache from version 1 to version 2 for %s:%s' %\
|
||||
(self.repository, self))
|
||||
self.ui._msg('Upgrading LocalStatus cache from version 1 to version 2 for %s:%s'%
|
||||
(self.repository, self))
|
||||
self.connection.executescript("""ALTER TABLE status ADD mtime INTEGER DEFAULT 0;
|
||||
ALTER TABLE status ADD labels VARCHAR(256) DEFAULT '';
|
||||
UPDATE metadata SET value='2' WHERE key='db_version';
|
||||
@ -167,12 +168,10 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
|
||||
def __create_db(self):
|
||||
"""
|
||||
Create a new db file.
|
||||
"""Create a new db file.
|
||||
|
||||
self.connection must point to the opened and valid SQlite
|
||||
database connection.
|
||||
"""
|
||||
database connection."""
|
||||
self.ui._msg('Creating new Local Status db for %s:%s' \
|
||||
% (self.repository, self))
|
||||
self.connection.executescript("""
|
||||
@ -212,6 +211,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
def saveall(self):
|
||||
"""Saves the entire messagelist to the database."""
|
||||
|
||||
data = []
|
||||
for uid, msg in self.messagelist.items():
|
||||
mtime = msg['mtime']
|
||||
@ -219,8 +219,9 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
labels = ', '.join(sorted(msg['labels']))
|
||||
data.append((uid, flags, mtime, labels))
|
||||
|
||||
self.__sql_write('INSERT OR REPLACE INTO status (id,flags,mtime,labels) VALUES (?,?,?,?)',
|
||||
data, executemany=True)
|
||||
self.__sql_write('INSERT OR REPLACE INTO status '
|
||||
'(id,flags,mtime,labels) VALUES (?,?,?,?)',
|
||||
data, executemany=True)
|
||||
|
||||
|
||||
# Following some pure SQLite functions, where we chose to use
|
||||
@ -267,14 +268,12 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
# Interface from BaseFolder
|
||||
def savemessage(self, uid, content, flags, rtime, mtime=0, labels=set()):
|
||||
"""
|
||||
Writes a new message, with the specified uid.
|
||||
"""Writes a new message, with the specified uid.
|
||||
|
||||
See folder/Base for detail. Note that savemessage() does not
|
||||
check against dryrun settings, so you need to ensure that
|
||||
savemessage is never called in a dryrun mode.
|
||||
|
||||
"""
|
||||
savemessage is never called in a dryrun mode."""
|
||||
|
||||
if uid < 0:
|
||||
# We cannot assign a uid.
|
||||
return uid
|
||||
@ -352,6 +351,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
|
||||
def savemessagesmtimebulk(self, mtimes):
|
||||
"""Saves mtimes from the mtimes dictionary in a single database operation."""
|
||||
|
||||
data = [(mt, uid) for uid, mt in mtimes.items()]
|
||||
self.__sql_write('UPDATE status SET mtime=? WHERE id=?', data, executemany=True)
|
||||
for uid, mt in mtimes.items():
|
||||
@ -376,6 +376,7 @@ class LocalStatusSQLiteFolder(BaseFolder):
|
||||
This function uses sqlites executemany() function which is
|
||||
much faster than iterating through deletemessage() when we have
|
||||
many messages to delete."""
|
||||
|
||||
# Weed out ones not in self.messagelist
|
||||
uidlist = [uid for uid in uidlist if uid in self.messagelist]
|
||||
if not len(uidlist):
|
||||
|
@ -69,7 +69,7 @@ class MaildirFolder(BaseFolder):
|
||||
"Account "+self.accountname, "maildir-windows-compatible", False)
|
||||
self.infosep = '!' if self.wincompatible else ':'
|
||||
"""infosep is the separator between maildir name and flag appendix"""
|
||||
self.re_flagmatch = re.compile('%s2,(\w*)' % self.infosep)
|
||||
self.re_flagmatch = re.compile('%s2,(\w*)'% self.infosep)
|
||||
#self.ui is set in BaseFolder.init()
|
||||
# Everything up to the first comma or colon (or ! if Windows):
|
||||
self.re_prefixmatch = re.compile('([^'+ self.infosep + ',]*)')
|
||||
@ -128,13 +128,14 @@ class MaildirFolder(BaseFolder):
|
||||
detected, we return an empty flags list.
|
||||
|
||||
:returns: (prefix, UID, FMD5, flags). UID is a numeric "long"
|
||||
type. flags is a set() of Maildir flags"""
|
||||
type. flags is a set() of Maildir flags.
|
||||
"""
|
||||
|
||||
prefix, uid, fmd5, flags = None, None, None, set()
|
||||
prefixmatch = self.re_prefixmatch.match(filename)
|
||||
if prefixmatch:
|
||||
prefix = prefixmatch.group(1)
|
||||
folderstr = ',FMD5=%s' % self._foldermd5
|
||||
folderstr = ',FMD5=%s'% self._foldermd5
|
||||
foldermatch = folderstr in filename
|
||||
# If there was no folder MD5 specified, or if it mismatches,
|
||||
# assume it is a foreign (new) message and ret: uid, fmd5 = None, None
|
||||
@ -154,7 +155,9 @@ class MaildirFolder(BaseFolder):
|
||||
|
||||
Maildir flags are: R (replied) S (seen) T (trashed) D (draft) F
|
||||
(flagged).
|
||||
:returns: dict that can be used as self.messagelist"""
|
||||
:returns: dict that can be used as self.messagelist.
|
||||
"""
|
||||
|
||||
maxage = self.config.getdefaultint("Account " + self.accountname,
|
||||
"maxage", None)
|
||||
maxsize = self.config.getdefaultint("Account " + self.accountname,
|
||||
@ -254,9 +257,9 @@ class MaildirFolder(BaseFolder):
|
||||
:returns: String containing unique message filename"""
|
||||
|
||||
timeval, timeseq = _gettimeseq()
|
||||
return '%d_%d.%d.%s,U=%d,FMD5=%s%s2,%s' % \
|
||||
return '%d_%d.%d.%s,U=%d,FMD5=%s%s2,%s'% \
|
||||
(timeval, timeseq, os.getpid(), socket.gethostname(),
|
||||
uid, self._foldermd5, self.infosep, ''.join(sorted(flags)))
|
||||
uid, self._foldermd5, self.infosep, ''.join(sorted(flags)))
|
||||
|
||||
|
||||
def save_to_tmp_file(self, filename, content):
|
||||
@ -393,7 +396,7 @@ class MaildirFolder(BaseFolder):
|
||||
"""
|
||||
|
||||
if not uid in self.messagelist:
|
||||
raise OfflineImapError("Cannot change unknown Maildir UID %s" % uid)
|
||||
raise OfflineImapError("Cannot change unknown Maildir UID %s"% uid)
|
||||
if uid == new_uid: return
|
||||
|
||||
oldfilename = self.messagelist[uid]['filename']
|
||||
|
@ -78,7 +78,7 @@ class MappedIMAPFolder(IMAPFolder):
|
||||
try:
|
||||
file = open(mapfilename + ".tmp", 'wt')
|
||||
for (key, value) in self.diskl2r.iteritems():
|
||||
file.write("%d:%d\n" % (key, value))
|
||||
file.write("%d:%d\n"% (key, value))
|
||||
file.close()
|
||||
os.rename(mapfilename + '.tmp', mapfilename)
|
||||
finally:
|
||||
@ -91,7 +91,7 @@ class MappedIMAPFolder(IMAPFolder):
|
||||
raise OfflineImapError("Could not find UID for msg '{0}' (f:'{1}'."
|
||||
" This is usually a bad thing and should be reported on the ma"
|
||||
"iling list.".format(e.args[0], self),
|
||||
OfflineImapError.ERROR.MESSAGE), None, exc_info()[2]
|
||||
OfflineImapError.ERROR.MESSAGE), None, exc_info()[2]
|
||||
|
||||
# Interface from BaseFolder
|
||||
def cachemessagelist(self):
|
||||
@ -215,8 +215,8 @@ class MappedIMAPFolder(IMAPFolder):
|
||||
|
||||
newluid = self._mb.savemessage(-1, content, flags, rtime)
|
||||
if newluid < 1:
|
||||
raise ValueError("Backend could not find uid for message, returned "
|
||||
"%s" % newluid)
|
||||
raise ValueError("Backend could not find uid for message, "
|
||||
"returned %s"% newluid)
|
||||
self.maplock.acquire()
|
||||
try:
|
||||
self.diskl2r[newluid] = uid
|
||||
@ -262,8 +262,8 @@ class MappedIMAPFolder(IMAPFolder):
|
||||
UID. The UIDMaps case handles this efficiently by simply
|
||||
changing the mappings file."""
|
||||
if ruid not in self.r2l:
|
||||
raise OfflineImapError("Cannot change unknown Maildir UID %s" % ruid,
|
||||
OfflineImapError.ERROR.MESSAGE)
|
||||
raise OfflineImapError("Cannot change unknown Maildir UID %s"%
|
||||
ruid, OfflineImapError.ERROR.MESSAGE)
|
||||
if ruid == new_ruid: return # sanity check shortcut
|
||||
self.maplock.acquire()
|
||||
try:
|
||||
@ -271,10 +271,10 @@ class MappedIMAPFolder(IMAPFolder):
|
||||
self.l2r[luid] = new_ruid
|
||||
del self.r2l[ruid]
|
||||
self.r2l[new_ruid] = luid
|
||||
#TODO: diskl2r|r2l are a pain to sync and should be done away with
|
||||
#diskl2r only contains positive UIDs, so wrap in ifs
|
||||
if luid>0: self.diskl2r[luid] = new_ruid
|
||||
if ruid>0: del self.diskr2l[ruid]
|
||||
# TODO: diskl2r|r2l are a pain to sync and should be done away with
|
||||
# diskl2r only contains positive UIDs, so wrap in ifs.
|
||||
if luid > 0: self.diskl2r[luid] = new_ruid
|
||||
if ruid > 0: del self.diskr2l[ruid]
|
||||
if new_ruid > 0: self.diskr2l[new_ruid] = luid
|
||||
self._savemaps(dolock = 0)
|
||||
finally:
|
||||
|
Reference in New Issue
Block a user