aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Sebastian Spaeth <Sebastian@SSpaeth.de>2011-06-16 14:41:02 +0200
committerGravatar Sebastian Spaeth <Sebastian@SSpaeth.de>2011-06-16 14:41:02 +0200
commitd8c0e0c72dd19b50d51f07c70b880f21d69c2590 (patch)
tree57f997907bddeaf4a2100f43d5f03dc42df20996
parentb4049316cc3bc933453268ed8d3e89b1ee0098a1 (diff)
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>
-rw-r--r--bindings/python/notmuch/database.py8
-rw-r--r--bindings/python/notmuch/message.py136
2 files changed, 122 insertions, 22 deletions
diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py
index 7f0091de..9016f0ae 100644
--- a/bindings/python/notmuch/database.py
+++ b/bindings/python/notmuch/database.py
@@ -273,6 +273,9 @@ class Database(object):
notmuch database will reference the filename, and will not copy the
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
1) a :class:`Message` object that can be used for things
@@ -310,11 +313,12 @@ class Database(object):
filename,
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)
- #construct Message() and return
+ #construct Message(), sync initial tags from Maildir flags and return
msg = Message(msg_p, self)
+ msg.maildir_flags_to_tags()
return (msg, status)
def remove_message(self, filename):
diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py
index 950d632a..8944af42 100644
--- a/bindings/python/notmuch/message.py
+++ b/bindings/python/notmuch/message.py
@@ -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 notmuch.globals import nmlib, STATUS, NotmuchError, Enum
from notmuch.tag import Tags
@@ -268,6 +268,14 @@ class Message(object):
_get_header = nmlib.notmuch_message_get_header
_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
FLAG = Enum(['MATCH'])
@@ -461,13 +469,22 @@ class Message(object):
raise NotmuchError(STATUS.NULL_POINTER)
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 current message. The maximal tag length is defined in
the notmuch library and is currently 200 bytes.
: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.
Raises an exception otherwise.
:exception: :exc:`NotmuchError`. They have the following meaning:
@@ -488,19 +505,29 @@ class Message(object):
status = nmlib.notmuch_message_add_tag (self._msg, tag)
- if STATUS.SUCCESS == status:
- # return on success
- return status
+ # bail out on failure
+ if status != STATUS.SUCCESS:
+ 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
If the message has no such tag, this is a non-operation and
will report success anyway.
: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
the message had no such tag.
Raises an exception otherwise.
@@ -521,19 +548,30 @@ class Message(object):
raise NotmuchError(STATUS.NOT_INITIALIZED)
status = nmlib.notmuch_message_remove_tag(self._msg, tag)
+ # bail out on error
+ if status != STATUS.SUCCESS:
+ raise NotmuchError(status)
- if STATUS.SUCCESS == status:
- # return on success
- return status
+ if sync_maildir_flags:
+ self.tags_to_maildir_flags()
+ 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.
See :meth:`freeze` for an example showing how to safely
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.
Raises an exception otherwise.
:exception: :exc:`NotmuchError`. They have the following meaning:
@@ -549,11 +587,13 @@ class Message(object):
status = nmlib.notmuch_message_remove_all_tags(self._msg)
- if STATUS.SUCCESS == status:
- # return on success
- return status
+ # bail out on error
+ if status != STATUS.SUCCESS:
+ raise NotmuchError(status)
- raise NotmuchError(status)
+ if sync_maildir_flags:
+ self.tags_to_maildir_flags()
+ return STATUS.SUCCESS
def freeze(self):
"""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::
msg.freeze()
- msg.remove_all_tags()
+ msg.remove_all_tags(False)
for tag in new_tags:
- msg.add_tag(tag)
+ msg.add_tag(tag, False)
msg.thaw()
+ msg.tags_to_maildir_flags()
With freeze/thaw used like this, the message in the database is
guaranteed to have either the full set of original tag values, or
@@ -646,6 +687,61 @@ class Message(object):
"""(Not implemented)"""
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):
"""A message() is represented by a 1-line summary"""
msg = {}
@@ -653,8 +749,8 @@ class Message(object):
msg['tags'] = str(self.get_tags())
msg['date'] = date.fromtimestamp(self.get_date())
replies = self.get_replies()
- msg['replies'] = len(replies) if replies is not None else -1
- return "%(from)s (%(date)s) (%(tags)s) (%(replies)d) replies" % (msg)
+ msg['replies'] = len(replies) if replies is not None else 0
+ return "%(from)s (%(date)s) (%(tags)s) %(replies)d replies" % (msg)
def get_message_parts(self):