]> git.notmuchmail.org Git - notmuch/blobdiff - cnotmuch/database.py
Implement an Enum class and make the STATUS object one
[notmuch] / cnotmuch / database.py
index 8313813ce85e67903b3ccc12809713e4718986e2..b4411ab1ee71ff87c265b471ec8e1b0ffa3a6fd3 100644 (file)
@@ -1,7 +1,8 @@
 import ctypes
 import ctypes
-from ctypes import c_int, c_char_p, c_void_p
-from cnotmuch.globals import nmlib, STATUS, NotmuchError
+from ctypes import c_int, c_char_p, c_void_p, c_uint64
+from cnotmuch.globals import nmlib, STATUS, NotmuchError, Enum
 import logging
 import logging
+from datetime import date
 
 class Database(object):
     """ Wrapper around a notmuch_database_t
 
 class Database(object):
     """ Wrapper around a notmuch_database_t
@@ -9,9 +10,8 @@ class Database(object):
     Do note that as soon as we tear down this object, all derived queries,
     threads, and messages will be freed as well.
     """
     Do note that as soon as we tear down this object, all derived queries,
     threads, and messages will be freed as well.
     """
-    #constants
-    MODE_READ_ONLY = 0
-    MODE_READ_WRITE = 1
+    MODE = Enum(['READ_ONLY','READ_WRITE'])
+    """Constants: Mode in which to open the database"""
 
     _std_db_path = None
     """Class attribute of users default database"""
 
     _std_db_path = None
     """Class attribute of users default database"""
@@ -185,6 +185,16 @@ class Query(object):
             NotmuchError(STATUS.NULL_POINTER)
         self._query = query_p
 
             NotmuchError(STATUS.NULL_POINTER)
         self._query = query_p
 
+    def set_sort(self, sort):
+        """notmuch_query_set_sort
+
+        :param sort: one of Query.SORT_OLDEST_FIRST|SORT_NEWEST_FIRST|SORT_MESSAGE_ID
+        :returns: Nothing, but raises NotmuchError if query is not inited
+        """
+        if self._query is None:
+            raise NotmuchError(STATUS.NOT_INITIALIZED)
+
+        nmlib.notmuch_query_set_sort(self._query, sort)
 
     def search_messages(self):
         """notmuch_query_search_messages
 
     def search_messages(self):
         """notmuch_query_search_messages
@@ -215,12 +225,12 @@ class Tags(object):
     _get = nmlib.notmuch_tags_get
     _get.restype = c_char_p
 
     _get = nmlib.notmuch_tags_get
     _get.restype = c_char_p
 
-    def __init__(self, tags_p, db=None):
+    def __init__(self, tags_p, parent=None):
         """
         msg_p is a pointer to an notmuch_message_t Structure. If it is None,
         we will raise an NotmuchError(STATUS.NULL_POINTER).
 
         """
         msg_p is a pointer to an notmuch_message_t Structure. If it is None,
         we will raise an NotmuchError(STATUS.NULL_POINTER).
 
-        Is passed the db these tags are derived from, and saves a
+        Is passed the parent these tags are derived from, and saves a
         reference to it, so we can automatically delete the db object
         once all derived objects are dead.
 
         reference to it, so we can automatically delete the db object
         once all derived objects are dead.
 
@@ -234,8 +244,9 @@ class Tags(object):
             NotmuchError(STATUS.NULL_POINTER)
 
         self._tags = tags_p
             NotmuchError(STATUS.NULL_POINTER)
 
         self._tags = tags_p
-        self._db = db
-        logging.debug("Inited Tags derived from %s" %(str(db)))
+        #save reference to parent object so we keep it alive
+        self._parent = parent
+        logging.debug("Inited Tags derived from %s" %(repr(parent)))
     
     def __iter__(self):
         """ Make Tags an iterator """
     
     def __iter__(self):
         """ Make Tags an iterator """
@@ -253,6 +264,13 @@ class Tags(object):
         nmlib.notmuch_tags_move_to_next(self._tags)
         return tag
 
         nmlib.notmuch_tags_move_to_next(self._tags)
         return tag
 
+    def __str__(self):
+        """str() of Tags() is a space separated list of tags
+
+        This iterates over the list of Tags and will therefore 'exhaust' Tags()
+        """
+        return " ".join(self)
+
     def __del__(self):
         """Close and free the notmuch tags"""
         if self._tags is not None:
     def __del__(self):
         """Close and free the notmuch tags"""
         if self._tags is not None:
@@ -329,6 +347,24 @@ class Messages(object):
         nmlib.notmuch_messages_move_to_next(self._msgs)
         return msg
 
         nmlib.notmuch_messages_move_to_next(self._msgs)
         return msg
 
+    def __len__(self):
+        """ Returns the number of contained messages
+
+        :note: As this iterates over the messages, we will not be able to 
+               iterate over them again (as in retrieve them)!
+        """
+        if self._msgs is None:
+            raise NotmuchError(STATUS.NOT_INITIALIZED)
+
+        i=0
+        while nmlib.notmuch_messages_valid(self._msgs):
+            nmlib.notmuch_messages_move_to_next(self._msgs)
+            i += 1
+        self._msgs = None
+        return i
+
+
+
     def __del__(self):
         """Close and free the notmuch Messages"""
         if self._msgs is not None:
     def __del__(self):
         """Close and free the notmuch Messages"""
         if self._msgs is not None:
@@ -351,6 +387,12 @@ class Message(object):
     _get_tags = nmlib.notmuch_message_get_tags
     _get_tags.restype = c_void_p
 
     _get_tags = nmlib.notmuch_message_get_tags
     _get_tags.restype = c_void_p
 
+    _get_date = nmlib.notmuch_message_get_date
+    _get_date.restype = c_uint64
+
+    _get_header = nmlib.notmuch_message_get_header
+    _get_header.restype = c_char_p
+
     def __init__(self, msg_p, parent=None):
         """
         msg_p is a pointer to an notmuch_message_t Structure. If it is None,
     def __init__(self, msg_p, parent=None):
         """
         msg_p is a pointer to an notmuch_message_t Structure. If it is None,
@@ -377,6 +419,28 @@ class Message(object):
             raise NotmuchError(STATUS.NOT_INITIALIZED)
         return Message._get_message_id(self._msg)
 
             raise NotmuchError(STATUS.NOT_INITIALIZED)
         return Message._get_message_id(self._msg)
 
+    def get_date(self):
+        """returns time_t of the message date
+
+        For the original textual representation of the Date header from the
+        message call notmuch_message_get_header() with a header value of
+        "date".
+        Raises NotmuchError(STATUS.NOT_INITIALIZED) if not inited
+        """
+        if self._msg is None:
+            raise NotmuchError(STATUS.NOT_INITIALIZED)
+        return Message._get_date(self._msg)
+
+    def get_header(self, header):
+        """ TODO document me"""
+        if self._msg is None:
+            raise NotmuchError(STATUS.NOT_INITIALIZED)
+
+        #Returns NULL if any error occurs.
+        header = Message._get_header (self._msg, header)
+        if header == None:
+            raise NotmuchError(STATUS.NULL_POINTER)
+        return header
 
     def get_filename(self):
         """ return the msg filename
 
     def get_filename(self):
         """ return the msg filename
@@ -401,6 +465,18 @@ class Message(object):
             raise NotmuchError(STATUS.NULL_POINTER)
         return Tags(tags_p, self)
 
             raise NotmuchError(STATUS.NULL_POINTER)
         return Tags(tags_p, self)
 
+    def __str__(self):
+        """A message() is represented by a 1-line summary"""
+        msg = {}
+        msg['from'] = self.get_header('from')
+        msg['tags'] = str(self.get_tags())
+        msg['date'] = date.fromtimestamp(self.get_date())
+        return "%(from)s (%(date)s) (%(tags)s)" % (msg)
+
+    def format_as_text(self):
+        """ Output like notmuch show """
+        return str(self)
+
     def __del__(self):
         """Close and free the notmuch Message"""
         if self._msg is not None:
     def __del__(self):
         """Close and free the notmuch Message"""
         if self._msg is not None: