2 from ctypes import c_int, c_char_p, c_void_p
3 from cnotmuch.globals import nmlib, STATUS, NotmuchError
6 class Database(object):
7 """ Wrapper around a notmuch_database_t
9 Do note that as soon as we tear down this object, all derived queries,
10 threads, and messages will be freed as well.
17 """Class attribute of users default database"""
19 """notmuch_database_get_path (notmuch_database_t *database)"""
20 _get_path = nmlib.notmuch_database_get_path
21 _get_path.restype = c_char_p
23 """notmuch_database_open (const char *path, notmuch_database_mode_t mode)"""
24 _open = nmlib.notmuch_database_open
25 _open.restype = c_void_p
27 """ notmuch_database_find_message """
28 _find_message = nmlib.notmuch_database_find_message
29 _find_message.restype = c_void_p
31 """notmuch_database_get_all_tags (notmuch_database_t *database)"""
32 _get_all_tags = nmlib.notmuch_database_get_all_tags
33 _get_all_tags.restype = c_void_p
35 """ notmuch_database_create(const char *path):"""
36 _create = nmlib.notmuch_database_create
37 _create.restype = c_void_p
39 def __init__(self, path=None, create=False, status= MODE_READ_ONLY):
40 """ Open or create a notmuch database
42 If path is None, we will try to read a users notmuch configuration and
43 use his default database.
44 Throws a NotmuchError in case of failure.
48 # no path specified. use a user's default database
49 if Database._std_db_path is None:
50 #the following line throws a NotmuchError if it fails
51 Database._std_db_path = self._get_user_default_db()
52 path = Database._std_db_path
55 self.open(path, status)
57 self.create(path, status)
59 def create(self, path, status=MODE_READ_ONLY):
60 """ notmuch_database_create(const char *path)
62 :returns: Raises :exc:`notmuch.NotmuchError` in case
63 of any failure (after printing an error message on stderr).
65 res = Database._create(path, status)
69 message="Could not create the specified database")
72 def open(self, path, status= MODE_READ_ONLY):
73 """calls notmuch_database_open
75 :returns: Raises :exc:`notmuch.NotmuchError` in case
76 of any failure (after printing an error message on stderr).
78 res = Database._open(path, status)
82 message="Could not open the specified database")
86 """notmuch_database_get_path (notmuch_database_t *database); """
87 return Database._get_path(self._db)
89 def find_message(self, msgid):
90 """notmuch_database_find_message
91 :param msgid: The message id
94 :returns: Message() or None if no message is found or if an
95 out-of-memory situation occurs.
98 raise NotmuchError(STATUS.NOT_INITIALIZED)
99 msg_p = Database._find_message(self._db, msgid)
102 return Message(msg_p, self)
104 def get_all_tags(self):
105 """Return a Tags() object (list of all tags found in the database)
107 :returns: Tags() object or raises :exc:`NotmuchError` with
108 STATUS.NULL_POINTER on error
111 raise NotmuchError(STATUS.NOT_INITIALIZED)
113 tags_p = Database._get_all_tags (self._db)
115 raise NotmuchError(STATUS.NULL_POINTER)
116 return Tags(tags_p, self)
119 return "'Notmuch DB " + self.get_path() + "'"
122 """Close and free the notmuch database if needed"""
123 if self._db is not None:
124 print("Freeing the database now")
125 nmlib.notmuch_database_close(self._db)
127 def _get_user_default_db(self):
128 """ Reads a user's notmuch config and returns his db location
130 Throws a NotmuchError if it cannot find it"""
131 from ConfigParser import SafeConfigParser
133 config = SafeConfigParser()
134 config.read(os.path.expanduser('~/.notmuch-config'))
135 if not config.has_option('database','path'):
136 raise NotmuchError(message=
137 "No DB path specified and no user default found")
138 return config.get('database','path')
142 """Returns a pointer to the current notmuch_database_t or None"""
145 #------------------------------------------------------------------------------
147 """ Wrapper around a notmuch_query_t
149 Do note that as soon as we tear down this object, all derived
150 threads, and messages will be freed as well.
152 def __init__(self, db, querystr):
155 #------------------------------------------------------------------------------
157 """Wrapper around notmuch_tags_t"""
160 _get = nmlib.notmuch_tags_get
161 _get.restype = c_char_p
163 def __init__(self, tags_p, db=None):
165 msg_p is a pointer to an notmuch_message_t Structure. If it is None,
166 we will raise an NotmuchError(STATUS.NULL_POINTER).
168 Is passed the db these tags are derived from, and saves a
169 reference to it, so we can automatically delete the db object
170 once all derived objects are dead.
172 Tags() provides an iterator over all contained tags. However, you will
173 only be able to iterate over the Tags once, because the underlying C
174 function only allows iterating once.
175 #TODO: make the iterator work more than once and cache the tags in
179 NotmuchError(STATUS.NULL_POINTER)
183 print "Inited Tags derived from %s" %(str(db))
186 """ Make Tags an iterator """
190 if self._tags is None:
192 nmlib.notmuch_tags_move_to_next(self._tags)
193 if not nmlib.notmuch_tags_valid(self._tags):
194 print("Freeing the Tags now")
195 nmlib.notmuch_tags_destroy (self._tags)
197 return Tags._get (self._tags)
200 """Close and free the notmuch tags"""
201 if self._tags is not None:
202 print("Freeing the Tags now")
203 nmlib.notmuch_tags_destroy (self._tags)
205 #------------------------------------------------------------------------------
206 class Message(object):
207 """Wrapper around notmuch_message_t"""
209 """notmuch_message_get_filename (notmuch_message_t *message)"""
210 _get_filename = nmlib.notmuch_message_get_filename
211 _get_filename.restype = c_char_p
212 """notmuch_message_get_message_id (notmuch_message_t *message)"""
213 _get_message_id = nmlib.notmuch_message_get_message_id
214 _get_message_id.restype = c_char_p
216 """notmuch_message_get_tags (notmuch_message_t *message)"""
217 _get_tags = nmlib.notmuch_message_get_tags
218 _get_tags.restype = c_void_p
220 def __init__(self, msg_p, parent=None):
222 msg_p is a pointer to an notmuch_message_t Structure. If it is None,
223 we will raise an NotmuchError(STATUS.NULL_POINTER).
225 Is a 'parent' object is passed which this message is derived from,
226 we save a reference to it, so we can automatically delete the parent
227 object once all derived objects are dead.
230 NotmuchError(STATUS.NULL_POINTER)
232 self._parent = parent
233 print "Inited Message derived from %s" %(str(parent))
236 def get_message_id(self):
237 """ return the msg id
239 Raises NotmuchError(STATUS.NOT_INITIALIZED) if not inited
241 if self._msg is None:
242 raise NotmuchError(STATUS.NOT_INITIALIZED)
243 return Message._get_message_id(self._msg)
246 def get_filename(self):
247 """ return the msg filename
249 Raises NotmuchError(STATUS.NOT_INITIALIZED) if not inited
251 if self._msg is None:
252 raise NotmuchError(STATUS.NOT_INITIALIZED)
253 return Message._get_filename(self._msg)
256 """ return the msg tags
258 Raises NotmuchError(STATUS.NOT_INITIALIZED) if not inited
259 Raises NotmuchError(STATUS.NULL_POINTER) on error.
261 if self._msg is None:
262 raise NotmuchError(STATUS.NOT_INITIALIZED)
264 tags_p = Message._get_tags(self._msg)
266 raise NotmuchError(STATUS.NULL_POINTER)
267 return Tags(tags_p, self)
270 """Close and free the notmuch Message"""
271 if self._msg is not None:
272 print("Freeing the Message now")
273 nmlib.notmuch_message_destroy (self._msg)