fix attribute name _utime_from_header
Code style. Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
parent
59f5da5e9e
commit
80dcf76414
@ -21,39 +21,43 @@ import six
|
|||||||
from sys import exc_info
|
from sys import exc_info
|
||||||
|
|
||||||
from .Maildir import MaildirFolder
|
from .Maildir import MaildirFolder
|
||||||
from offlineimap import OfflineImapError
|
|
||||||
import offlineimap.accounts
|
import offlineimap.accounts
|
||||||
|
from offlineimap import OfflineImapError
|
||||||
from offlineimap import imaputil
|
from offlineimap import imaputil
|
||||||
|
|
||||||
class GmailMaildirFolder(MaildirFolder):
|
class GmailMaildirFolder(MaildirFolder):
|
||||||
"""Folder implementation to support adding labels to messages in a Maildir.
|
"""Folder implementation to support adding labels to messages in a Maildir."""
|
||||||
"""
|
|
||||||
def __init__(self, root, name, sep, repository):
|
def __init__(self, root, name, sep, repository):
|
||||||
super(GmailMaildirFolder, self).__init__(root, name, sep, repository)
|
super(GmailMaildirFolder, self).__init__(root, name, sep, repository)
|
||||||
|
|
||||||
# The header under which labels are stored
|
# The header under which labels are stored.
|
||||||
self.labelsheader = self.repository.account.getconf('labelsheader', 'X-Keywords')
|
self.labelsheader = self.repository.account.getconf('labelsheader',
|
||||||
|
'X-Keywords')
|
||||||
|
|
||||||
# enables / disables label sync
|
# Enables / disables label sync.
|
||||||
self.synclabels = self.repository.account.getconfboolean('synclabels', 0)
|
self.synclabels = self.repository.account.getconfboolean('synclabels', 0)
|
||||||
|
|
||||||
# if synclabels is enabled, add a 4th pass to sync labels
|
# If synclabels is enabled, add a 4th pass to sync labels.
|
||||||
if self.synclabels:
|
if self.synclabels:
|
||||||
self.syncmessagesto_passes.append(('syncing labels', self.syncmessagesto_labels))
|
self.syncmessagesto_passes.append(('syncing labels',
|
||||||
|
self.syncmessagesto_labels))
|
||||||
|
|
||||||
def quickchanged(self, statusfolder):
|
def quickchanged(self, statusfolder):
|
||||||
"""Returns True if the Maildir has changed. Checks uids, flags and mtimes"""
|
"""Returns True if the Maildir has changed.
|
||||||
|
|
||||||
|
Checks uids, flags and mtimes"""
|
||||||
|
|
||||||
if self._utime_from_header is True:
|
if self._utime_from_header is True:
|
||||||
raise Exception("GmailMaildir does not support quick mode"
|
raise Exception("GmailMaildir does not support quick mode"
|
||||||
" when 'utime_from_header' is enabled.")
|
" when 'utime_from_header' is enabled.")
|
||||||
|
|
||||||
self.cachemessagelist()
|
self.cachemessagelist()
|
||||||
# Folder has different uids than statusfolder => TRUE
|
# Folder has different uids than statusfolder => TRUE.
|
||||||
if sorted(self.getmessageuidlist()) != \
|
if sorted(self.getmessageuidlist()) != \
|
||||||
sorted(statusfolder.getmessageuidlist()):
|
sorted(statusfolder.getmessageuidlist()):
|
||||||
return True
|
return True
|
||||||
# check for flag changes, it's quick on a Maildir
|
# Check for flag changes, it's quick on a Maildir.
|
||||||
for (uid, message) in self.getmessagelist().items():
|
for (uid, message) in self.getmessagelist().items():
|
||||||
if message['flags'] != statusfolder.getmessageflags(uid):
|
if message['flags'] != statusfolder.getmessageflags(uid):
|
||||||
return True
|
return True
|
||||||
@ -72,7 +76,8 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
|
|
||||||
def cachemessagelist(self, min_date=None, min_uid=None):
|
def cachemessagelist(self, min_date=None, min_uid=None):
|
||||||
if self.ismessagelistempty():
|
if self.ismessagelistempty():
|
||||||
self.messagelist = self._scanfolder(min_date=min_date, min_uid=min_uid)
|
self.messagelist = self._scanfolder(min_date=min_date,
|
||||||
|
min_uid=min_uid)
|
||||||
|
|
||||||
# Get mtimes
|
# Get mtimes
|
||||||
if self.synclabels:
|
if self.synclabels:
|
||||||
@ -117,15 +122,17 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
savemessage is never called in a dryrun mode."""
|
savemessage is never called in a dryrun mode."""
|
||||||
|
|
||||||
if not self.synclabels:
|
if not self.synclabels:
|
||||||
return super(GmailMaildirFolder, self).savemessage(uid, content, flags, rtime)
|
return super(GmailMaildirFolder, self).savemessage(uid, content,
|
||||||
|
flags, rtime)
|
||||||
|
|
||||||
labels = set()
|
labels = set()
|
||||||
for hstr in self.getmessageheaderlist(content, self.labelsheader):
|
for hstr in self.getmessageheaderlist(content, self.labelsheader):
|
||||||
labels.update(imaputil.labels_from_header(self.labelsheader, hstr))
|
labels.update(imaputil.labels_from_header(self.labelsheader, hstr))
|
||||||
|
|
||||||
ret = super(GmailMaildirFolder, self).savemessage(uid, content, flags, rtime)
|
ret = super(GmailMaildirFolder, self).savemessage(uid, content, flags,
|
||||||
|
rtime)
|
||||||
|
|
||||||
# Update the mtime and labels
|
# Update the mtime and labels.
|
||||||
filename = self.messagelist[uid]['filename']
|
filename = self.messagelist[uid]['filename']
|
||||||
filepath = os.path.join(self.getfullname(), filename)
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
self.messagelist[uid]['mtime'] = int(os.stat(filepath).st_mtime)
|
self.messagelist[uid]['mtime'] = int(os.stat(filepath).st_mtime)
|
||||||
@ -147,32 +154,34 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
|
|
||||||
oldlabels = set()
|
oldlabels = set()
|
||||||
for hstr in self.getmessageheaderlist(content, self.labelsheader):
|
for hstr in self.getmessageheaderlist(content, self.labelsheader):
|
||||||
oldlabels.update(imaputil.labels_from_header(self.labelsheader, hstr))
|
oldlabels.update(imaputil.labels_from_header(self.labelsheader,
|
||||||
|
hstr))
|
||||||
|
|
||||||
labels = labels - ignorelabels
|
labels = labels - ignorelabels
|
||||||
ignoredlabels = oldlabels & ignorelabels
|
ignoredlabels = oldlabels & ignorelabels
|
||||||
oldlabels = oldlabels - ignorelabels
|
oldlabels = oldlabels - ignorelabels
|
||||||
|
|
||||||
# Nothing to change
|
# Nothing to change.
|
||||||
if labels == oldlabels:
|
if labels == oldlabels:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Change labels into content
|
# Change labels into content.
|
||||||
labels_str = imaputil.format_labels_string(self.labelsheader,
|
labels_str = imaputil.format_labels_string(self.labelsheader,
|
||||||
sorted(labels | ignoredlabels))
|
sorted(labels | ignoredlabels))
|
||||||
|
|
||||||
# First remove old labels header, and then add the new one
|
# First remove old labels header, and then add the new one.
|
||||||
content = self.deletemessageheaders(content, self.labelsheader)
|
content = self.deletemessageheaders(content, self.labelsheader)
|
||||||
content = self.addmessageheader(content, '\n', self.labelsheader, labels_str)
|
content = self.addmessageheader(content, '\n', self.labelsheader,
|
||||||
|
labels_str)
|
||||||
|
|
||||||
mtime = int(os.stat(filepath).st_mtime)
|
mtime = int(os.stat(filepath).st_mtime)
|
||||||
|
|
||||||
# write file with new labels to a unique file in tmp
|
# Write file with new labels to a unique file in tmp.
|
||||||
messagename = self.new_message_filename(uid, set())
|
messagename = self.new_message_filename(uid, set())
|
||||||
tmpname = self.save_to_tmp_file(messagename, content)
|
tmpname = self.save_to_tmp_file(messagename, content)
|
||||||
tmppath = os.path.join(self.getfullname(), tmpname)
|
tmppath = os.path.join(self.getfullname(), tmpname)
|
||||||
|
|
||||||
# move to actual location
|
# Move to actual location.
|
||||||
try:
|
try:
|
||||||
os.rename(tmppath, filepath)
|
os.rename(tmppath, filepath)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
@ -182,15 +191,15 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
OfflineImapError.ERROR.FOLDER),
|
OfflineImapError.ERROR.FOLDER),
|
||||||
exc_info()[2])
|
exc_info()[2])
|
||||||
|
|
||||||
# if utime_from_header=true, we don't want to change the mtime.
|
# If utime_from_header=true, we don't want to change the mtime.
|
||||||
if self.utime_from_header and mtime:
|
if self._utime_from_header and mtime:
|
||||||
os.utime(filepath, (mtime, mtime))
|
os.utime(filepath, (mtime, mtime))
|
||||||
|
|
||||||
# save the new mtime and labels
|
# save the new mtime and labels
|
||||||
self.messagelist[uid]['mtime'] = int(os.stat(filepath).st_mtime)
|
self.messagelist[uid]['mtime'] = int(os.stat(filepath).st_mtime)
|
||||||
self.messagelist[uid]['labels'] = labels
|
self.messagelist[uid]['labels'] = labels
|
||||||
|
|
||||||
def copymessageto(self, uid, dstfolder, statusfolder, register = 1):
|
def copymessageto(self, uid, dstfolder, statusfolder, register=1):
|
||||||
"""Copies a message from self to dst if needed, updating the status
|
"""Copies a message from self to dst if needed, updating the status
|
||||||
|
|
||||||
Note that this function does not check against dryrun settings,
|
Note that this function does not check against dryrun settings,
|
||||||
@ -203,20 +212,22 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
:param register: whether we should register a new thread."
|
:param register: whether we should register a new thread."
|
||||||
:returns: Nothing on success, or raises an Exception."""
|
:returns: Nothing on success, or raises an Exception."""
|
||||||
|
|
||||||
# Check if we are really copying
|
# Check if we are really copying.
|
||||||
realcopy = uid > 0 and not dstfolder.uidexists(uid)
|
realcopy = uid > 0 and not dstfolder.uidexists(uid)
|
||||||
|
|
||||||
# first copy the message
|
# First copy the message.
|
||||||
super(GmailMaildirFolder, self).copymessageto(uid, dstfolder, statusfolder, register)
|
super(GmailMaildirFolder, self).copymessageto(uid, dstfolder,
|
||||||
|
statusfolder, register)
|
||||||
|
|
||||||
# sync labels and mtime now when the message is new (the embedded labels are up to date,
|
# Sync labels and mtime now when the message is new (the embedded labels
|
||||||
# and have already propagated to the remote server.
|
# are up to date, and have already propagated to the remote server. For
|
||||||
# for message which already existed on the remote, this is useless, as later the labels may
|
# message which already existed on the remote, this is useless, as later
|
||||||
# get updated.
|
# the labels may get updated.
|
||||||
if realcopy and self.synclabels:
|
if realcopy and self.synclabels:
|
||||||
try:
|
try:
|
||||||
labels = dstfolder.getmessagelabels(uid)
|
labels = dstfolder.getmessagelabels(uid)
|
||||||
statusfolder.savemessagelabels(uid, labels, mtime=self.getmessagemtime(uid))
|
statusfolder.savemessagelabels(uid, labels,
|
||||||
|
mtime=self.getmessagemtime(uid))
|
||||||
|
|
||||||
# dstfolder is not GmailMaildir.
|
# dstfolder is not GmailMaildir.
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
@ -243,14 +254,14 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
uidlist = []
|
uidlist = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# filter uids (fast)
|
# Filter uids (fast).
|
||||||
for uid in self.getmessageuidlist():
|
for uid in self.getmessageuidlist():
|
||||||
# bail out on CTRL-C or SIGTERM
|
# Bail out on CTRL-C or SIGTERM.
|
||||||
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
||||||
break
|
break
|
||||||
|
|
||||||
# Ignore messages with negative UIDs missed by pass 1 and
|
# Ignore messages with negative UIDs missed by pass 1 and
|
||||||
# don't do anything if the message has been deleted remotely
|
# don't do anything if the message has been deleted remotely.
|
||||||
if uid < 0 or not dstfolder.uidexists(uid):
|
if uid < 0 or not dstfolder.uidexists(uid):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -266,9 +277,9 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
|
|
||||||
|
|
||||||
self.ui.collectingdata(uidlist, self)
|
self.ui.collectingdata(uidlist, self)
|
||||||
# This can be slow if there is a lot of modified files
|
# This can be slow if there is a lot of modified files.
|
||||||
for uid in uidlist:
|
for uid in uidlist:
|
||||||
# bail out on CTRL-C or SIGTERM
|
# Bail out on CTRL-C or SIGTERM.
|
||||||
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -293,44 +304,46 @@ class GmailMaildirFolder(MaildirFolder):
|
|||||||
dellabellist[lb].append(uid)
|
dellabellist[lb].append(uid)
|
||||||
|
|
||||||
for lb, uids in addlabellist.items():
|
for lb, uids in addlabellist.items():
|
||||||
# bail out on CTRL-C or SIGTERM
|
# Bail out on CTRL-C or SIGTERM.
|
||||||
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
||||||
break
|
break
|
||||||
|
|
||||||
self.ui.addinglabels(uids, lb, dstfolder)
|
self.ui.addinglabels(uids, lb, dstfolder)
|
||||||
if self.repository.account.dryrun:
|
if self.repository.account.dryrun:
|
||||||
continue #don't actually add in a dryrun
|
continue # Don't actually add in a dryrun.
|
||||||
dstfolder.addmessageslabels(uids, set([lb]))
|
dstfolder.addmessageslabels(uids, set([lb]))
|
||||||
statusfolder.addmessageslabels(uids, set([lb]))
|
statusfolder.addmessageslabels(uids, set([lb]))
|
||||||
|
|
||||||
for lb, uids in dellabellist.items():
|
for lb, uids in dellabellist.items():
|
||||||
# bail out on CTRL-C or SIGTERM
|
# Bail out on CTRL-C or SIGTERM.
|
||||||
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
||||||
break
|
break
|
||||||
|
|
||||||
self.ui.deletinglabels(uids, lb, dstfolder)
|
self.ui.deletinglabels(uids, lb, dstfolder)
|
||||||
if self.repository.account.dryrun:
|
if self.repository.account.dryrun:
|
||||||
continue #don't actually remove in a dryrun
|
continue # Don't actually remove in a dryrun.
|
||||||
dstfolder.deletemessageslabels(uids, set([lb]))
|
dstfolder.deletemessageslabels(uids, set([lb]))
|
||||||
statusfolder.deletemessageslabels(uids, set([lb]))
|
statusfolder.deletemessageslabels(uids, set([lb]))
|
||||||
|
|
||||||
# Update mtimes on StatusFolder. It is done last to be safe. If something els fails
|
# Update mtimes on StatusFolder. It is done last to be safe. If
|
||||||
# and the mtime is not updated, the labels will still be synced next time.
|
# something els fails and the mtime is not updated, the labels will
|
||||||
|
# still be synced next time.
|
||||||
mtimes = {}
|
mtimes = {}
|
||||||
for uid in uidlist:
|
for uid in uidlist:
|
||||||
# bail out on CTRL-C or SIGTERM
|
# Bail out on CTRL-C or SIGTERM.
|
||||||
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
if offlineimap.accounts.Account.abort_NOW_signal.is_set():
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.repository.account.dryrun:
|
if self.repository.account.dryrun:
|
||||||
continue #don't actually update statusfolder
|
continue # Don't actually update statusfolder.
|
||||||
|
|
||||||
filename = self.messagelist[uid]['filename']
|
filename = self.messagelist[uid]['filename']
|
||||||
filepath = os.path.join(self.getfullname(), filename)
|
filepath = os.path.join(self.getfullname(), filename)
|
||||||
mtimes[uid] = int(os.stat(filepath).st_mtime)
|
mtimes[uid] = int(os.stat(filepath).st_mtime)
|
||||||
|
|
||||||
# finally update statusfolder in a single DB transaction
|
# Finally, update statusfolder in a single DB transaction.
|
||||||
statusfolder.savemessagesmtimebulk(mtimes)
|
statusfolder.savemessagesmtimebulk(mtimes)
|
||||||
|
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
self.ui.warn("Can't sync labels. You need to configure a remote repository of type Gmail.")
|
self.ui.warn("Can't sync labels. You need to configure a remote "
|
||||||
|
"repository of type Gmail.")
|
||||||
|
Loading…
Reference in New Issue
Block a user