mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-28 13:44:12 +01:00
Implement Message.tags_to_maildir_flags
and also maildir_flags_to_tags. The methods will be invoked by db.add_message() and also (if not overridden via function parameter) by add|remove_tag and remove_all_tags. Documentation on the usage has been updated. Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
parent
b4049316cc
commit
d8c0e0c72d
2 changed files with 122 additions and 22 deletions
|
@ -273,6 +273,9 @@ class Database(object):
|
||||||
notmuch database will reference the filename, and will not copy the
|
notmuch database will reference the filename, and will not copy the
|
||||||
entire contents of the file.
|
entire contents of the file.
|
||||||
|
|
||||||
|
If the message contains Maildir flags, we will -depending on the
|
||||||
|
notmuch configuration- sync those tags to initial notmuch tags.
|
||||||
|
|
||||||
:returns: On success, we return
|
:returns: On success, we return
|
||||||
|
|
||||||
1) a :class:`Message` object that can be used for things
|
1) a :class:`Message` object that can be used for things
|
||||||
|
@ -310,11 +313,12 @@ class Database(object):
|
||||||
filename,
|
filename,
|
||||||
byref(msg_p))
|
byref(msg_p))
|
||||||
|
|
||||||
if not status in [STATUS.SUCCESS,STATUS.DUPLICATE_MESSAGE_ID]:
|
if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]:
|
||||||
raise NotmuchError(status)
|
raise NotmuchError(status)
|
||||||
|
|
||||||
#construct Message() and return
|
#construct Message(), sync initial tags from Maildir flags and return
|
||||||
msg = Message(msg_p, self)
|
msg = Message(msg_p, self)
|
||||||
|
msg.maildir_flags_to_tags()
|
||||||
return (msg, status)
|
return (msg, status)
|
||||||
|
|
||||||
def remove_message(self, filename):
|
def remove_message(self, filename):
|
||||||
|
|
|
@ -19,7 +19,7 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
from ctypes import c_char_p, c_void_p, c_long, c_uint
|
from ctypes import c_char_p, c_void_p, c_long, c_uint, c_int
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from notmuch.globals import nmlib, STATUS, NotmuchError, Enum
|
from notmuch.globals import nmlib, STATUS, NotmuchError, Enum
|
||||||
from notmuch.tag import Tags
|
from notmuch.tag import Tags
|
||||||
|
@ -268,6 +268,14 @@ class Message(object):
|
||||||
_get_header = nmlib.notmuch_message_get_header
|
_get_header = nmlib.notmuch_message_get_header
|
||||||
_get_header.restype = c_char_p
|
_get_header.restype = c_char_p
|
||||||
|
|
||||||
|
"""notmuch_status_t ..._maildir_flags_to_tags (notmuch_message_t *)"""
|
||||||
|
_tags_to_maildir_flags = nmlib.notmuch_message_tags_to_maildir_flags
|
||||||
|
_tags_to_maildir_flags.restype = c_int
|
||||||
|
|
||||||
|
"""notmuch_status_t ..._tags_to_maildir_flags (notmuch_message_t *)"""
|
||||||
|
_maildir_flags_to_tags = nmlib.notmuch_message_maildir_flags_to_tags
|
||||||
|
_maildir_flags_to_tags.restype = c_int
|
||||||
|
|
||||||
#Constants: Flags that can be set/get with set_flag
|
#Constants: Flags that can be set/get with set_flag
|
||||||
FLAG = Enum(['MATCH'])
|
FLAG = Enum(['MATCH'])
|
||||||
|
|
||||||
|
@ -461,13 +469,22 @@ class Message(object):
|
||||||
raise NotmuchError(STATUS.NULL_POINTER)
|
raise NotmuchError(STATUS.NULL_POINTER)
|
||||||
return Tags(tags_p, self)
|
return Tags(tags_p, self)
|
||||||
|
|
||||||
def add_tag(self, tag):
|
def add_tag(self, tag, sync_maildir_flags=True):
|
||||||
"""Adds a tag to the given message
|
"""Adds a tag to the given message
|
||||||
|
|
||||||
Adds a tag to the current message. The maximal tag length is defined in
|
Adds a tag to the current message. The maximal tag length is defined in
|
||||||
the notmuch library and is currently 200 bytes.
|
the notmuch library and is currently 200 bytes.
|
||||||
|
|
||||||
:param tag: String with a 'tag' to be added.
|
:param tag: String with a 'tag' to be added.
|
||||||
|
|
||||||
|
:param sync_maildir_flags: If notmuch configuration is set to do
|
||||||
|
this, add maildir flags corresponding to notmuch tags. See
|
||||||
|
:meth:`tags_to_maildir_flags`. Use False if you want to
|
||||||
|
add/remove many tags on a message without having to
|
||||||
|
physically rename the file every time. Do note, that this
|
||||||
|
will do nothing when a message is frozen, as tag changes
|
||||||
|
will not be committed to the database yet.
|
||||||
|
|
||||||
:returns: STATUS.SUCCESS if the tag was successfully added.
|
:returns: STATUS.SUCCESS if the tag was successfully added.
|
||||||
Raises an exception otherwise.
|
Raises an exception otherwise.
|
||||||
:exception: :exc:`NotmuchError`. They have the following meaning:
|
:exception: :exc:`NotmuchError`. They have the following meaning:
|
||||||
|
@ -488,19 +505,29 @@ class Message(object):
|
||||||
|
|
||||||
status = nmlib.notmuch_message_add_tag (self._msg, tag)
|
status = nmlib.notmuch_message_add_tag (self._msg, tag)
|
||||||
|
|
||||||
if STATUS.SUCCESS == status:
|
# bail out on failure
|
||||||
# return on success
|
if status != STATUS.SUCCESS:
|
||||||
return status
|
raise NotmuchError(status)
|
||||||
|
|
||||||
raise NotmuchError(status)
|
if sync_maildir_flags:
|
||||||
|
self.tags_to_maildir_flags()
|
||||||
|
return STATUS.SUCCESS
|
||||||
|
|
||||||
def remove_tag(self, tag):
|
def remove_tag(self, tag, sync_maildir_flags=True):
|
||||||
"""Removes a tag from the given message
|
"""Removes a tag from the given message
|
||||||
|
|
||||||
If the message has no such tag, this is a non-operation and
|
If the message has no such tag, this is a non-operation and
|
||||||
will report success anyway.
|
will report success anyway.
|
||||||
|
|
||||||
:param tag: String with a 'tag' to be removed.
|
:param tag: String with a 'tag' to be removed.
|
||||||
|
:param sync_maildir_flags: If notmuch configuration is set to do
|
||||||
|
this, add maildir flags corresponding to notmuch tags. See
|
||||||
|
:meth:`tags_to_maildir_flags`. Use False if you want to
|
||||||
|
add/remove many tags on a message without having to
|
||||||
|
physically rename the file every time. Do note, that this
|
||||||
|
will do nothing when a message is frozen, as tag changes
|
||||||
|
will not be committed to the database yet.
|
||||||
|
|
||||||
:returns: STATUS.SUCCESS if the tag was successfully removed or if
|
:returns: STATUS.SUCCESS if the tag was successfully removed or if
|
||||||
the message had no such tag.
|
the message had no such tag.
|
||||||
Raises an exception otherwise.
|
Raises an exception otherwise.
|
||||||
|
@ -521,19 +548,30 @@ class Message(object):
|
||||||
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
|
||||||
status = nmlib.notmuch_message_remove_tag(self._msg, tag)
|
status = nmlib.notmuch_message_remove_tag(self._msg, tag)
|
||||||
|
# bail out on error
|
||||||
|
if status != STATUS.SUCCESS:
|
||||||
|
raise NotmuchError(status)
|
||||||
|
|
||||||
if STATUS.SUCCESS == status:
|
if sync_maildir_flags:
|
||||||
# return on success
|
self.tags_to_maildir_flags()
|
||||||
return status
|
return STATUS.SUCCESS
|
||||||
|
|
||||||
raise NotmuchError(status)
|
|
||||||
|
|
||||||
def remove_all_tags(self):
|
|
||||||
|
def remove_all_tags(self, sync_maildir_flags=True):
|
||||||
"""Removes all tags from the given message.
|
"""Removes all tags from the given message.
|
||||||
|
|
||||||
See :meth:`freeze` for an example showing how to safely
|
See :meth:`freeze` for an example showing how to safely
|
||||||
replace tag values.
|
replace tag values.
|
||||||
|
|
||||||
|
:param sync_maildir_flags: If notmuch configuration is set to do
|
||||||
|
this, add maildir flags corresponding to notmuch tags. See
|
||||||
|
:meth:`tags_to_maildir_flags`. Use False if you want to
|
||||||
|
add/remove many tags on a message without having to
|
||||||
|
physically rename the file every time. Do note, that this
|
||||||
|
will do nothing when a message is frozen, as tag changes
|
||||||
|
will not be committed to the database yet.
|
||||||
|
|
||||||
:returns: STATUS.SUCCESS if the tags were successfully removed.
|
:returns: STATUS.SUCCESS if the tags were successfully removed.
|
||||||
Raises an exception otherwise.
|
Raises an exception otherwise.
|
||||||
:exception: :exc:`NotmuchError`. They have the following meaning:
|
:exception: :exc:`NotmuchError`. They have the following meaning:
|
||||||
|
@ -549,11 +587,13 @@ class Message(object):
|
||||||
|
|
||||||
status = nmlib.notmuch_message_remove_all_tags(self._msg)
|
status = nmlib.notmuch_message_remove_all_tags(self._msg)
|
||||||
|
|
||||||
if STATUS.SUCCESS == status:
|
# bail out on error
|
||||||
# return on success
|
if status != STATUS.SUCCESS:
|
||||||
return status
|
raise NotmuchError(status)
|
||||||
|
|
||||||
raise NotmuchError(status)
|
if sync_maildir_flags:
|
||||||
|
self.tags_to_maildir_flags()
|
||||||
|
return STATUS.SUCCESS
|
||||||
|
|
||||||
def freeze(self):
|
def freeze(self):
|
||||||
"""Freezes the current state of 'message' within the database
|
"""Freezes the current state of 'message' within the database
|
||||||
|
@ -571,10 +611,11 @@ class Message(object):
|
||||||
have a given set of tags might look like this::
|
have a given set of tags might look like this::
|
||||||
|
|
||||||
msg.freeze()
|
msg.freeze()
|
||||||
msg.remove_all_tags()
|
msg.remove_all_tags(False)
|
||||||
for tag in new_tags:
|
for tag in new_tags:
|
||||||
msg.add_tag(tag)
|
msg.add_tag(tag, False)
|
||||||
msg.thaw()
|
msg.thaw()
|
||||||
|
msg.tags_to_maildir_flags()
|
||||||
|
|
||||||
With freeze/thaw used like this, the message in the database is
|
With freeze/thaw used like this, the message in the database is
|
||||||
guaranteed to have either the full set of original tag values, or
|
guaranteed to have either the full set of original tag values, or
|
||||||
|
@ -646,6 +687,61 @@ class Message(object):
|
||||||
"""(Not implemented)"""
|
"""(Not implemented)"""
|
||||||
return self.get_flag(Message.FLAG.MATCH)
|
return self.get_flag(Message.FLAG.MATCH)
|
||||||
|
|
||||||
|
def tags_to_maildir_flags(self):
|
||||||
|
"""Synchronize notmuch tags to file Maildir flags
|
||||||
|
|
||||||
|
'D' if the message has the "draft" tag
|
||||||
|
'F' if the message has the "flagged" tag
|
||||||
|
'P' if the message has the "passed" tag
|
||||||
|
'R' if the message has the "replied" tag
|
||||||
|
'S' if the message does not have the "unread" tag
|
||||||
|
|
||||||
|
Any existing flags unmentioned in the list above will be
|
||||||
|
preserved in the renaming.
|
||||||
|
|
||||||
|
Also, if this filename is in a directory named "new", rename it
|
||||||
|
to be within the neighboring directory named "cur".
|
||||||
|
|
||||||
|
Usually, you do not need to call this manually as
|
||||||
|
tag changing methods should be implicitly calling it.
|
||||||
|
|
||||||
|
:returns: a :class:`STATUS`. In short, you want to see
|
||||||
|
notmuch.STATUS.SUCCESS here. See there for details."""
|
||||||
|
if self._msg is None:
|
||||||
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
status = Message._tags_to_maildir_flags(self._msg)
|
||||||
|
|
||||||
|
def maildir_flags_to_tags(self):
|
||||||
|
"""Synchronize file Maildir flags to notmuch tags
|
||||||
|
|
||||||
|
Flag Action if present
|
||||||
|
---- -----------------
|
||||||
|
'D' Adds the "draft" tag to the message
|
||||||
|
'F' Adds the "flagged" tag to the message
|
||||||
|
'P' Adds the "passed" tag to the message
|
||||||
|
'R' Adds the "replied" tag to the message
|
||||||
|
'S' Removes the "unread" tag from the message
|
||||||
|
|
||||||
|
For each flag that is not present, the opposite action
|
||||||
|
(add/remove) is performed for the corresponding tags. If there
|
||||||
|
are multiple filenames associated with this message, the flag is
|
||||||
|
considered present if it appears in one or more filenames. (That
|
||||||
|
is, the flags from the multiple filenames are combined with the
|
||||||
|
logical OR operator.)
|
||||||
|
|
||||||
|
Usually, you do not need to call this manually as
|
||||||
|
:meth:`Database.add_message` implicitly calls it.
|
||||||
|
|
||||||
|
:returns: a :class:`STATUS`. In short, you want to see
|
||||||
|
notmuch.STATUS.SUCCESS here. See there for details."""
|
||||||
|
if self._msg is None:
|
||||||
|
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||||
|
status = Message._tags_to_maildir_flags(self._msg)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
"""Represent a Message() object by str()"""
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""A message() is represented by a 1-line summary"""
|
"""A message() is represented by a 1-line summary"""
|
||||||
msg = {}
|
msg = {}
|
||||||
|
@ -653,8 +749,8 @@ class Message(object):
|
||||||
msg['tags'] = str(self.get_tags())
|
msg['tags'] = str(self.get_tags())
|
||||||
msg['date'] = date.fromtimestamp(self.get_date())
|
msg['date'] = date.fromtimestamp(self.get_date())
|
||||||
replies = self.get_replies()
|
replies = self.get_replies()
|
||||||
msg['replies'] = len(replies) if replies is not None else -1
|
msg['replies'] = len(replies) if replies is not None else 0
|
||||||
return "%(from)s (%(date)s) (%(tags)s) (%(replies)d) replies" % (msg)
|
return "%(from)s (%(date)s) (%(tags)s) %(replies)d replies" % (msg)
|
||||||
|
|
||||||
|
|
||||||
def get_message_parts(self):
|
def get_message_parts(self):
|
||||||
|
|
Loading…
Reference in a new issue