Re: [PATCH v2] nmbug-status: add support for specifying sort order for each view
[notmuch-archives.git] / ab / 2ad867f139112094b0c49c9b043f13ace38ac8
1 Return-Path: <teythoon@jade-hamburg.de>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id C0C7E429E25\r
6         for <notmuch@notmuchmail.org>; Sun,  9 Oct 2011 15:13:45 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0.001\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0.001 tagged_above=-999 required=5\r
12         tests=[UNPARSEABLE_RELAY=0.001] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id KcPOLsTVLwUh for <notmuch@notmuchmail.org>;\r
16         Sun,  9 Oct 2011 15:13:43 -0700 (PDT)\r
17 Received: from mail.cryptobitch.de (cryptobitch.de [88.198.7.68])\r
18         (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))\r
19         (No client certificate requested)\r
20         by olra.theworths.org (Postfix) with ESMTPS id 344A8431FB6\r
21         for <notmuch@notmuchmail.org>; Sun,  9 Oct 2011 15:13:43 -0700 (PDT)\r
22 Received: from mail.jade-hamburg.de (unknown [85.183.11.228])\r
23         (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))\r
24         (No client certificate requested)\r
25         by mail.cryptobitch.de (Postfix) with ESMTPSA id E1747509367\r
26         for <notmuch@notmuchmail.org>; Mon, 10 Oct 2011 00:13:41 +0200 (CEST)\r
27 Received: by mail.jade-hamburg.de (Postfix, from userid 401)\r
28         id 60011DF2A1; Mon, 10 Oct 2011 00:13:41 +0200 (CEST)\r
29 Received: from thinkbox.jade-hamburg.de (unknown\r
30         [IPv6:fe80::216:d3ff:fe3e:5058%br0])\r
31         (using TLSv1 with cipher AES256-SHA (256/256 bits))\r
32         (No client certificate requested) (Authenticated sender: teythoon)\r
33         by mail.jade-hamburg.de (Postfix) with ESMTPSA id 680C2DF29F;\r
34         Mon, 10 Oct 2011 00:13:22 +0200 (CEST)\r
35 Received: from teythoon by thinkbox.jade-hamburg.de with local (Exim 4.76)\r
36         (envelope-from <teythoon@thinkbox.jade-hamburg.de>)\r
37         id 1RD1cX-0000HM-JH; Mon, 10 Oct 2011 00:13:21 +0200\r
38 From: Justus Winter <4winter@informatik.uni-hamburg.de>\r
39 To: notmuch@notmuchmail.org\r
40 Subject: [PATCH 2/2] python: annotate all calls into libnotmuch with types\r
41 Date: Mon, 10 Oct 2011 00:12:54 +0200\r
42 Message-Id:\r
43  <1318198374-926-2-git-send-email-4winter@informatik.uni-hamburg.de>\r
44 X-Mailer: git-send-email 1.7.6.3\r
45 In-Reply-To:\r
46  <1318198374-926-1-git-send-email-4winter@informatik.uni-hamburg.de>\r
47 References:\r
48  <1318198374-926-1-git-send-email-4winter@informatik.uni-hamburg.de>\r
49 X-BeenThere: notmuch@notmuchmail.org\r
50 X-Mailman-Version: 2.1.13\r
51 Precedence: list\r
52 List-Id: "Use and development of the notmuch mail system."\r
53         <notmuch.notmuchmail.org>\r
54 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
55         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
56 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
57 List-Post: <mailto:notmuch@notmuchmail.org>\r
58 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
59 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
60         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
61 X-List-Received-Date: Sun, 09 Oct 2011 22:13:45 -0000\r
62 \r
63 Add type information to the ctypes._FuncPtr wrappers and\r
64 use the wrapper classes instead of c_void_p for pointers\r
65 to notmuch_*_t.\r
66 \r
67 This enables the ctypes library to type check parameters\r
68 being handed to functions from the notmuch library.\r
69 \r
70 Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de>\r
71 ---\r
72  bindings/python/notmuch/database.py |  127 ++++++++++++++++++++++++++--------\r
73  bindings/python/notmuch/filename.py |   22 +++++-\r
74  bindings/python/notmuch/message.py  |   91 ++++++++++++++++++++-----\r
75  bindings/python/notmuch/tag.py      |   23 +++++--\r
76  bindings/python/notmuch/thread.py   |   63 +++++++++++++----\r
77  5 files changed, 255 insertions(+), 71 deletions(-)\r
78 \r
79 diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py\r
80 index f4bc53e..25b4b1b 100644\r
81 --- a/bindings/python/notmuch/database.py\r
82 +++ b/bindings/python/notmuch/database.py\r
83 @@ -18,9 +18,11 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'\r
84  """\r
85  \r
86  import os\r
87 -from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref\r
88 +from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref, POINTER\r
89  from notmuch.globals import (nmlib, STATUS, NotmuchError, NotInitializedError,\r
90 -     NullPointerError, OutOfMemoryError, XapianError, Enum, _str)\r
91 +     NullPointerError, OutOfMemoryError, XapianError, Enum, _str,\r
92 +     NotmuchDatabaseP, NotmuchDirectoryP, NotmuchMessageP, NotmuchTagsP,\r
93 +     NotmuchQueryP, NotmuchMessagesP, NotmuchThreadsP, NotmuchFilenamesP)\r
94  from notmuch.thread import Threads\r
95  from notmuch.message import Messages, Message\r
96  from notmuch.tag import Tags\r
97 @@ -56,37 +58,48 @@ class Database(object):\r
98  \r
99      """notmuch_database_get_directory"""\r
100      _get_directory = nmlib.notmuch_database_get_directory\r
101 -    _get_directory.restype = c_void_p\r
102 +    _get_directory.argtypes = [NotmuchDatabaseP, c_char_p]\r
103 +    _get_directory.restype = NotmuchDirectoryP\r
104  \r
105      """notmuch_database_get_path"""\r
106      _get_path = nmlib.notmuch_database_get_path\r
107 +    _get_path.argtypes = [NotmuchDatabaseP]\r
108      _get_path.restype = c_char_p\r
109  \r
110      """notmuch_database_get_version"""\r
111      _get_version = nmlib.notmuch_database_get_version\r
112 +    _get_version.argtypes = [NotmuchDatabaseP]\r
113      _get_version.restype = c_uint\r
114  \r
115      """notmuch_database_open"""\r
116      _open = nmlib.notmuch_database_open\r
117 -    _open.restype = c_void_p\r
118 +    _open.argtypes = [c_char_p, c_uint]\r
119 +    _open.restype = NotmuchDatabaseP\r
120  \r
121      """notmuch_database_upgrade"""\r
122      _upgrade = nmlib.notmuch_database_upgrade\r
123 -    _upgrade.argtypes = [c_void_p, c_void_p, c_void_p]\r
124 +    _upgrade.argtypes = [NotmuchDatabaseP, c_void_p, c_void_p]\r
125 +    _upgrade.restype = c_uint\r
126  \r
127      """ notmuch_database_find_message"""\r
128      _find_message = nmlib.notmuch_database_find_message\r
129 +    _find_message.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)]\r
130 +    _find_message.restype = c_uint\r
131  \r
132      """notmuch_database_find_message_by_filename"""\r
133      _find_message_by_filename = nmlib.notmuch_database_find_message_by_filename\r
134 +    _find_message_by_filename.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)]\r
135 +    _find_message_by_filename.restype = c_uint\r
136  \r
137      """notmuch_database_get_all_tags"""\r
138      _get_all_tags = nmlib.notmuch_database_get_all_tags\r
139 -    _get_all_tags.restype = c_void_p\r
140 +    _get_all_tags.argtypes = [NotmuchDatabaseP]\r
141 +    _get_all_tags.restype = NotmuchTagsP\r
142  \r
143      """notmuch_database_create"""\r
144      _create = nmlib.notmuch_database_create\r
145 -    _create.restype = c_void_p\r
146 +    _create.argtypes = [c_char_p]\r
147 +    _create.restype = NotmuchDatabaseP\r
148  \r
149      def __init__(self, path=None, create=False, mode=0):\r
150          """If *path* is `None`, we will try to read a users notmuch\r
151 @@ -186,6 +199,10 @@ class Database(object):\r
152          self._assert_db_is_initialized()\r
153          return Database._get_version(self._db)\r
154  \r
155 +    _needs_upgrade = nmlib.notmuch_database_needs_upgrade\r
156 +    _needs_upgrade.argtypes = [NotmuchDatabaseP]\r
157 +    _needs_upgrade.restype = bool\r
158 +\r
159      def needs_upgrade(self):\r
160          """Does this database need to be upgraded before writing to it?\r
161  \r
162 @@ -197,7 +214,7 @@ class Database(object):\r
163          :returns: `True` or `False`\r
164          """\r
165          self._assert_db_is_initialized()\r
166 -        return nmlib.notmuch_database_needs_upgrade(self._db)\r
167 +        return self._needs_upgrade(self._db)\r
168  \r
169      def upgrade(self):\r
170          """Upgrades the current database\r
171 @@ -219,6 +236,10 @@ class Database(object):\r
172          #TODO: catch exceptions, document return values and etc\r
173          return status\r
174  \r
175 +    _begin_atomic = nmlib.notmuch_database_begin_atomic\r
176 +    _begin_atomic.argtypes = [NotmuchDatabaseP]\r
177 +    _begin_atomic.restype = c_uint\r
178 +\r
179      def begin_atomic(self):\r
180          """Begin an atomic database operation\r
181  \r
182 @@ -236,11 +257,15 @@ class Database(object):\r
183  \r
184          *Added in notmuch 0.9*"""\r
185          self._assert_db_is_initialized()\r
186 -        status = nmlib.notmuch_database_begin_atomic(self._db)\r
187 +        status = self._begin_atomic(self._db)\r
188          if status != STATUS.SUCCESS:\r
189              raise NotmuchError(status)\r
190          return status\r
191  \r
192 +    _end_atomic = nmlib.notmuch_database_end_atomic\r
193 +    _end_atomic.argtypes = [NotmuchDatabaseP]\r
194 +    _end_atomic.restype = c_uint\r
195 +\r
196      def end_atomic(self):\r
197          """Indicate the end of an atomic database operation\r
198  \r
199 @@ -258,7 +283,7 @@ class Database(object):\r
200  \r
201          *Added in notmuch 0.9*"""\r
202          self._assert_db_is_initialized()\r
203 -        status = nmlib.notmuch_database_end_atomic(self._db)\r
204 +        status = self._end_atomic(self._db)\r
205          if status != STATUS.SUCCESS:\r
206              raise NotmuchError(status)\r
207          return status\r
208 @@ -299,6 +324,10 @@ class Database(object):\r
209          # return the Directory, init it with the absolute path\r
210          return Directory(_str(abs_dirpath), dir_p, self)\r
211  \r
212 +    _add_message = nmlib.notmuch_database_add_message\r
213 +    _add_message.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)]\r
214 +    _add_message.restype = c_uint\r
215 +\r
216      def add_message(self, filename, sync_maildir_flags=False):\r
217          """Adds a new message to the database\r
218  \r
219 @@ -350,9 +379,7 @@ class Database(object):\r
220          """\r
221          self._assert_db_is_initialized()\r
222          msg_p = c_void_p()\r
223 -        status = nmlib.notmuch_database_add_message(self._db,\r
224 -                                                  _str(filename),\r
225 -                                                  byref(msg_p))\r
226 +        status = self._add_message(self._db, _str(filename), byref(msg_p))\r
227  \r
228          if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]:\r
229              raise NotmuchError(status)\r
230 @@ -364,6 +391,10 @@ class Database(object):\r
231              msg.maildir_flags_to_tags()\r
232          return (msg, status)\r
233  \r
234 +    _remove_message = nmlib.notmuch_database_remove_message\r
235 +    _remove_message.argtypes = [NotmuchDatabaseP, c_char_p]\r
236 +    _remove_message.restype = c_uint\r
237 +\r
238      def remove_message(self, filename):\r
239          """Removes a message (filename) from the given notmuch database\r
240  \r
241 @@ -392,8 +423,7 @@ class Database(object):\r
242                 removed.\r
243          """\r
244          self._assert_db_is_initialized()\r
245 -        return nmlib.notmuch_database_remove_message(self._db,\r
246 -                                                       filename)\r
247 +        return self._remove_message(self._db, filename)\r
248  \r
249      def find_message(self, msgid):\r
250          """Returns a :class:`Message` as identified by its message ID\r
251 @@ -491,10 +521,14 @@ class Database(object):\r
252      def __repr__(self):\r
253          return "'Notmuch DB " + self.get_path() + "'"\r
254  \r
255 +    _close = nmlib.notmuch_database_close\r
256 +    _close.argtypes = [NotmuchDatabaseP]\r
257 +    _close.restype = None\r
258 +\r
259      def __del__(self):\r
260          """Close and free the notmuch database if needed"""\r
261          if self._db is not None:\r
262 -            nmlib.notmuch_database_close(self._db)\r
263 +            self._close(self._db)\r
264  \r
265      def _get_user_default_db(self):\r
266          """ Reads a user's notmuch config and returns his db location\r
267 @@ -545,18 +579,22 @@ class Query(object):\r
268  \r
269      """notmuch_query_create"""\r
270      _create = nmlib.notmuch_query_create\r
271 -    _create.restype = c_void_p\r
272 +    _create.argtypes = [NotmuchDatabaseP, c_char_p]\r
273 +    _create.restype = NotmuchQueryP\r
274  \r
275      """notmuch_query_search_threads"""\r
276      _search_threads = nmlib.notmuch_query_search_threads\r
277 -    _search_threads.restype = c_void_p\r
278 +    _search_threads.argtypes = [NotmuchQueryP]\r
279 +    _search_threads.restype = NotmuchThreadsP\r
280  \r
281      """notmuch_query_search_messages"""\r
282      _search_messages = nmlib.notmuch_query_search_messages\r
283 -    _search_messages.restype = c_void_p\r
284 +    _search_messages.argtypes = [NotmuchQueryP]\r
285 +    _search_messages.restype = NotmuchMessagesP\r
286  \r
287      """notmuch_query_count_messages"""\r
288      _count_messages = nmlib.notmuch_query_count_messages\r
289 +    _count_messages.argtypes = [NotmuchQueryP]\r
290      _count_messages.restype = c_uint\r
291  \r
292      def __init__(self, db, querystr):\r
293 @@ -602,6 +640,10 @@ class Query(object):\r
294              raise NullPointerError\r
295          self._query = query_p\r
296  \r
297 +    _set_sort = nmlib.notmuch_query_set_sort\r
298 +    _set_sort.argtypes = [NotmuchQueryP, c_uint]\r
299 +    _set_sort.argtypes = None\r
300 +\r
301      def set_sort(self, sort):\r
302          """Set the sort order future results will be delivered in\r
303  \r
304 @@ -609,7 +651,7 @@ class Query(object):\r
305          """\r
306          self._assert_query_is_initialized()\r
307          self.sort = sort\r
308 -        nmlib.notmuch_query_set_sort(self._query, sort)\r
309 +        self._set_sort(self._query, sort)\r
310  \r
311      def search_threads(self):\r
312          """Execute a query for threads\r
313 @@ -661,10 +703,14 @@ class Query(object):\r
314          self._assert_query_is_initialized()\r
315          return Query._count_messages(self._query)\r
316  \r
317 +    _destroy = nmlib.notmuch_query_destroy\r
318 +    _destroy.argtypes = [NotmuchQueryP]\r
319 +    _destroy.restype = None\r
320 +\r
321      def __del__(self):\r
322          """Close and free the Query"""\r
323          if self._query is not None:\r
324 -            nmlib.notmuch_query_destroy(self._query)\r
325 +            self._destroy(self._query)\r
326  \r
327  \r
328  class Directory(object):\r
329 @@ -683,19 +729,23 @@ class Directory(object):\r
330  \r
331      """notmuch_directory_get_mtime"""\r
332      _get_mtime = nmlib.notmuch_directory_get_mtime\r
333 +    _get_mtime.argtypes = [NotmuchDirectoryP]\r
334      _get_mtime.restype = c_long\r
335  \r
336      """notmuch_directory_set_mtime"""\r
337      _set_mtime = nmlib.notmuch_directory_set_mtime\r
338 -    _set_mtime.argtypes = [c_char_p, c_long]\r
339 +    _set_mtime.argtypes = [NotmuchDirectoryP, c_long]\r
340 +    _set_mtime.restype = c_uint\r
341  \r
342      """notmuch_directory_get_child_files"""\r
343      _get_child_files = nmlib.notmuch_directory_get_child_files\r
344 -    _get_child_files.restype = c_void_p\r
345 +    _get_child_files.argtypes = [NotmuchDirectoryP]\r
346 +    _get_child_files.restype = NotmuchFilenamesP\r
347  \r
348      """notmuch_directory_get_child_directories"""\r
349      _get_child_directories = nmlib.notmuch_directory_get_child_directories\r
350 -    _get_child_directories.restype = c_void_p\r
351 +    _get_child_directories.argtypes = [NotmuchDirectoryP]\r
352 +    _get_child_directories.restype = NotmuchFilenamesP\r
353  \r
354      def _assert_dir_is_initialized(self):\r
355          """Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None"""\r
356 @@ -815,10 +865,14 @@ class Directory(object):\r
357          """Object representation"""\r
358          return "<notmuch Directory object '%s'>" % self._path\r
359  \r
360 +    _destroy = nmlib.notmuch_directory_destroy\r
361 +    _destroy.argtypes = [NotmuchDirectoryP]\r
362 +    _destroy.argtypes = None\r
363 +\r
364      def __del__(self):\r
365          """Close and free the Directory"""\r
366          if self._dir_p is not None:\r
367 -            nmlib.notmuch_directory_destroy(self._dir_p)\r
368 +            self._destroy(self._dir_p)\r
369  \r
370  \r
371  class Filenames(object):\r
372 @@ -826,6 +880,7 @@ class Filenames(object):\r
373  \r
374      #notmuch_filenames_get\r
375      _get = nmlib.notmuch_filenames_get\r
376 +    _get.argtypes = [NotmuchFilenamesP]\r
377      _get.restype = c_char_p\r
378  \r
379      def __init__(self, files_p, parent):\r
380 @@ -844,16 +899,24 @@ class Filenames(object):\r
381          """ Make Filenames an iterator """\r
382          return self\r
383  \r
384 +    _valid = nmlib.notmuch_filenames_valid\r
385 +    _valid.argtypes = [NotmuchFilenamesP]\r
386 +    _valid.restype = bool\r
387 +\r
388 +    _move_to_next = nmlib.notmuch_filenames_move_to_next\r
389 +    _move_to_next.argtypes = [NotmuchFilenamesP]\r
390 +    _move_to_next.restype = None\r
391 +\r
392      def next(self):\r
393          if self._files_p is None:\r
394              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
395  \r
396 -        if not nmlib.notmuch_filenames_valid(self._files_p):\r
397 +        if not self._valid(self._files_p):\r
398              self._files_p = None\r
399              raise StopIteration\r
400  \r
401          file = Filenames._get(self._files_p)\r
402 -        nmlib.notmuch_filenames_move_to_next(self._files_p)\r
403 +        self._move_to_next(self._files_p)\r
404          return file\r
405  \r
406      def __len__(self):\r
407 @@ -872,13 +935,17 @@ class Filenames(object):\r
408              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
409  \r
410          i = 0\r
411 -        while nmlib.notmuch_filenames_valid(self._files_p):\r
412 -            nmlib.notmuch_filenames_move_to_next(self._files_p)\r
413 +        while self._valid(self._files_p):\r
414 +            self._move_to_next(self._files_p)\r
415              i += 1\r
416          self._files_p = None\r
417          return i\r
418  \r
419 +    _destroy = nmlib.notmuch_filenames_destroy\r
420 +    _destroy.argtypes = [NotmuchFilenamesP]\r
421 +    _destroy.restype = None\r
422 +\r
423      def __del__(self):\r
424          """Close and free Filenames"""\r
425          if self._files_p is not None:\r
426 -            nmlib.notmuch_filenames_destroy(self._files_p)\r
427 +            self._destroy(self._files_p)\r
428 diff --git a/bindings/python/notmuch/filename.py b/bindings/python/notmuch/filename.py\r
429 index de4d785..077754e 100644\r
430 --- a/bindings/python/notmuch/filename.py\r
431 +++ b/bindings/python/notmuch/filename.py\r
432 @@ -17,7 +17,8 @@ along with notmuch.  If not, see <http://www.gnu.org/licenses/>.\r
433  Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'\r
434  """\r
435  from ctypes import c_char_p\r
436 -from notmuch.globals import nmlib, STATUS, NotmuchError\r
437 +from notmuch.globals import (nmlib, STATUS, NotmuchError,\r
438 +    NotmuchFilenamesP, NotmuchMessagesP, NotmuchMessageP)\r
439  \r
440  \r
441  class Filenames(object):\r
442 @@ -50,6 +51,7 @@ class Filenames(object):\r
443  \r
444      #notmuch_filenames_get\r
445      _get = nmlib.notmuch_filenames_get\r
446 +    _get.argtypes = [NotmuchFilenamesP]\r
447      _get.restype = c_char_p\r
448  \r
449      def __init__(self, files_p, parent):\r
450 @@ -74,6 +76,14 @@ class Filenames(object):\r
451          #save reference to parent object so we keep it alive\r
452          self._parent = parent\r
453  \r
454 +    _valid = nmlib.notmuch_filenames_valid\r
455 +    _valid.argtypes = [NotmuchFilenamesP]\r
456 +    _valid.restype = bool\r
457 +\r
458 +    _move_to_next = nmlib.notmuch_filenames_move_to_next\r
459 +    _move_to_next.argtypes = [NotmuchFilenamesP]\r
460 +    _move_to_next.restype = None\r
461 +\r
462      def as_generator(self):\r
463          """Return generator of Filenames\r
464  \r
465 @@ -82,9 +92,9 @@ class Filenames(object):\r
466          if self._files is None:\r
467              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
468  \r
469 -        while nmlib.notmuch_filenames_valid(self._files):\r
470 +        while self._valid(self._files):\r
471              yield Filenames._get(self._files)\r
472 -            nmlib.notmuch_filenames_move_to_next(self._files)\r
473 +            self._move_to_next(self._files)\r
474  \r
475          self._files = None\r
476  \r
477 @@ -101,7 +111,11 @@ class Filenames(object):\r
478          """\r
479          return "\n".join(self)\r
480  \r
481 +    _destroy = nmlib.notmuch_filenames_destroy\r
482 +    _destroy.argtypes = [NotmuchMessageP]\r
483 +    _destroy.restype = None\r
484 +\r
485      def __del__(self):\r
486          """Close and free the notmuch filenames"""\r
487          if self._files is not None:\r
488 -            nmlib.notmuch_filenames_destroy(self._files)\r
489 +            self._destroy(self._files)\r
490 diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py\r
491 index 4bf90c2..e0c7eda 100644\r
492 --- a/bindings/python/notmuch/message.py\r
493 +++ b/bindings/python/notmuch/message.py\r
494 @@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'\r
495  \r
496  from ctypes import c_char_p, c_void_p, c_long, c_uint, c_int\r
497  from datetime import date\r
498 -from notmuch.globals import nmlib, STATUS, NotmuchError, Enum, _str\r
499 +from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str,\r
500 +    NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP)\r
501  from notmuch.tag import Tags\r
502  from notmuch.filename import Filenames\r
503  import sys\r
504 @@ -92,10 +93,12 @@ class Messages(object):\r
505  \r
506      #notmuch_messages_get\r
507      _get = nmlib.notmuch_messages_get\r
508 -    _get.restype = c_void_p\r
509 +    _get.argtypes = [NotmuchMessagesP]\r
510 +    _get.restype = NotmuchMessageP\r
511  \r
512      _collect_tags = nmlib.notmuch_messages_collect_tags\r
513 -    _collect_tags.restype = c_void_p\r
514 +    _collect_tags.argtypes = [NotmuchMessagesP]\r
515 +    _collect_tags.restype = NotmuchTagsP\r
516  \r
517      def __init__(self, msgs_p, parent=None):\r
518          """\r
519 @@ -146,16 +149,24 @@ class Messages(object):\r
520          """ Make Messages an iterator """\r
521          return self\r
522  \r
523 +    _valid = nmlib.notmuch_messages_valid\r
524 +    _valid.argtypes = [NotmuchMessagesP]\r
525 +    _valid.restype = bool\r
526 +\r
527 +    _move_to_next = nmlib.notmuch_messages_move_to_next\r
528 +    _move_to_next.argtypes = [NotmuchMessagesP]\r
529 +    _move_to_next.restype = None\r
530 +\r
531      def next(self):\r
532          if self._msgs is None:\r
533              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
534  \r
535 -        if not nmlib.notmuch_messages_valid(self._msgs):\r
536 +        if not self._valid(self._msgs):\r
537              self._msgs = None\r
538              raise StopIteration\r
539  \r
540          msg = Message(Messages._get(self._msgs), self)\r
541 -        nmlib.notmuch_messages_move_to_next(self._msgs)\r
542 +        self._move_to_next(self._msgs)\r
543          return msg\r
544  \r
545      def __nonzero__(self):\r
546 @@ -163,12 +174,16 @@ class Messages(object):\r
547          :return: True if there is at least one more thread in the\r
548              Iterator, False if not."""\r
549          return self._msgs is not None and \\r
550 -            nmlib.notmuch_messages_valid(self._msgs) > 0\r
551 +            self._valid(self._msgs) > 0\r
552 +\r
553 +    _destroy = nmlib.notmuch_messages_destroy\r
554 +    _destroy.argtypes = [NotmuchMessagesP]\r
555 +    _destroy.restype = None\r
556  \r
557      def __del__(self):\r
558          """Close and free the notmuch Messages"""\r
559          if self._msgs is not None:\r
560 -            nmlib.notmuch_messages_destroy(self._msgs)\r
561 +            self._destroy(self._msgs)\r
562  \r
563      def print_messages(self, format, indent=0, entire_thread=False):\r
564          """Outputs messages as needed for 'notmuch show' to sys.stdout\r
565 @@ -235,44 +250,60 @@ class Message(object):\r
566  \r
567      """notmuch_message_get_filename (notmuch_message_t *message)"""\r
568      _get_filename = nmlib.notmuch_message_get_filename\r
569 +    _get_filename.argtypes = [NotmuchMessageP]\r
570      _get_filename.restype = c_char_p\r
571  \r
572      """return all filenames for a message"""\r
573      _get_filenames = nmlib.notmuch_message_get_filenames\r
574 -    _get_filenames.restype = c_void_p\r
575 +    _get_filenames.argtypes = [NotmuchMessageP]\r
576 +    _get_filenames.restype = NotmuchFilenamesP\r
577  \r
578      """notmuch_message_get_flag"""\r
579      _get_flag = nmlib.notmuch_message_get_flag\r
580 -    _get_flag.restype = c_uint\r
581 +    _get_flag.argtypes = [NotmuchMessageP, c_uint]\r
582 +    _get_flag.restype = bool\r
583 +\r
584 +    """notmuch_message_set_flag"""\r
585 +    _set_flag = nmlib.notmuch_message_set_flag\r
586 +    _set_flag.argtypes = [NotmuchMessageP, c_uint, c_int]\r
587 +    _set_flag.restype = None\r
588  \r
589      """notmuch_message_get_message_id (notmuch_message_t *message)"""\r
590      _get_message_id = nmlib.notmuch_message_get_message_id\r
591 +    _get_message_id.argtypes = [NotmuchMessageP]\r
592      _get_message_id.restype = c_char_p\r
593  \r
594      """notmuch_message_get_thread_id"""\r
595      _get_thread_id = nmlib.notmuch_message_get_thread_id\r
596 +    _get_thread_id.argtypes = [NotmuchMessageP]\r
597      _get_thread_id.restype = c_char_p\r
598  \r
599      """notmuch_message_get_replies"""\r
600      _get_replies = nmlib.notmuch_message_get_replies\r
601 -    _get_replies.restype = c_void_p\r
602 +    _get_replies.argtypes = [NotmuchMessageP]\r
603 +    _get_replies.restype = NotmuchMessagesP\r
604  \r
605      """notmuch_message_get_tags (notmuch_message_t *message)"""\r
606      _get_tags = nmlib.notmuch_message_get_tags\r
607 -    _get_tags.restype = c_void_p\r
608 +    _get_tags.argtypes = [NotmuchMessageP]\r
609 +    _get_tags.restype = NotmuchTagsP\r
610  \r
611      _get_date = nmlib.notmuch_message_get_date\r
612 +    _get_date.argtypes = [NotmuchMessageP]\r
613      _get_date.restype = c_long\r
614  \r
615      _get_header = nmlib.notmuch_message_get_header\r
616 +    _get_header.argtypes = [NotmuchMessageP, c_char_p]\r
617      _get_header.restype = c_char_p\r
618  \r
619      """notmuch_status_t ..._maildir_flags_to_tags (notmuch_message_t *)"""\r
620      _tags_to_maildir_flags = nmlib.notmuch_message_tags_to_maildir_flags\r
621 +    _tags_to_maildir_flags.argtypes = [NotmuchMessageP]\r
622      _tags_to_maildir_flags.restype = c_int\r
623  \r
624      """notmuch_status_t ..._tags_to_maildir_flags (notmuch_message_t *)"""\r
625      _maildir_flags_to_tags = nmlib.notmuch_message_maildir_flags_to_tags\r
626 +    _maildir_flags_to_tags.argtypes = [NotmuchMessageP]\r
627      _maildir_flags_to_tags.restype = c_int\r
628  \r
629      #Constants: Flags that can be set/get with set_flag\r
630 @@ -450,7 +481,7 @@ class Message(object):\r
631          """\r
632          if self._msg is None:\r
633              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
634 -        nmlib.notmuch_message_set_flag(self._msg, flag, value)\r
635 +        self._set_flag(self._msg, flag, value)\r
636  \r
637      def get_tags(self):\r
638          """Returns the message tags\r
639 @@ -470,6 +501,10 @@ class Message(object):\r
640              raise NotmuchError(STATUS.NULL_POINTER)\r
641          return Tags(tags_p, self)\r
642  \r
643 +    _add_tag = nmlib.notmuch_message_add_tag\r
644 +    _add_tag.argtypes = [NotmuchMessageP, c_char_p]\r
645 +    _add_tag.restype = c_uint\r
646 +\r
647      def add_tag(self, tag, sync_maildir_flags=False):\r
648          """Adds a tag to the given message\r
649  \r
650 @@ -504,7 +539,7 @@ class Message(object):\r
651          if self._msg is None:\r
652              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
653  \r
654 -        status = nmlib.notmuch_message_add_tag(self._msg, _str(tag))\r
655 +        status = self._add_tag(self._msg, _str(tag))\r
656  \r
657          # bail out on failure\r
658          if status != STATUS.SUCCESS:\r
659 @@ -514,6 +549,10 @@ class Message(object):\r
660              self.tags_to_maildir_flags()\r
661          return STATUS.SUCCESS\r
662  \r
663 +    _remove_tag = nmlib.notmuch_message_remove_tag\r
664 +    _remove_tag.argtypes = [NotmuchMessageP, c_char_p]\r
665 +    _remove_tag.restype = c_uint\r
666 +\r
667      def remove_tag(self, tag, sync_maildir_flags=False):\r
668          """Removes a tag from the given message\r
669  \r
670 @@ -548,7 +587,7 @@ class Message(object):\r
671          if self._msg is None:\r
672              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
673  \r
674 -        status = nmlib.notmuch_message_remove_tag(self._msg, _str(tag))\r
675 +        status = self._remove_tag(self._msg, _str(tag))\r
676          # bail out on error\r
677          if status != STATUS.SUCCESS:\r
678              raise NotmuchError(status)\r
679 @@ -557,6 +596,10 @@ class Message(object):\r
680              self.tags_to_maildir_flags()\r
681          return STATUS.SUCCESS\r
682  \r
683 +    _remove_all_tags = nmlib.notmuch_message_remove_all_tags\r
684 +    _remove_all_tags.argtypes = [NotmuchMessageP]\r
685 +    _remove_all_tags.restype = c_uint\r
686 +\r
687      def remove_all_tags(self, sync_maildir_flags=False):\r
688          """Removes all tags from the given message.\r
689  \r
690 @@ -585,7 +628,7 @@ class Message(object):\r
691          if self._msg is None:\r
692              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
693  \r
694 -        status = nmlib.notmuch_message_remove_all_tags(self._msg)\r
695 +        status = self._remove_all_tags(self._msg)\r
696  \r
697          # bail out on error\r
698          if status != STATUS.SUCCESS:\r
699 @@ -595,6 +638,10 @@ class Message(object):\r
700              self.tags_to_maildir_flags()\r
701          return STATUS.SUCCESS\r
702  \r
703 +    _freeze = nmlib.notmuch_message_freeze\r
704 +    _freeze.argtypes = [NotmuchMessageP]\r
705 +    _freeze.restype = c_uint\r
706 +\r
707      def freeze(self):\r
708          """Freezes the current state of 'message' within the database\r
709  \r
710 @@ -639,7 +686,7 @@ class Message(object):\r
711          if self._msg is None:\r
712              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
713  \r
714 -        status = nmlib.notmuch_message_freeze(self._msg)\r
715 +        status = self._freeze(self._msg)\r
716  \r
717          if STATUS.SUCCESS == status:\r
718              # return on success\r
719 @@ -647,6 +694,10 @@ class Message(object):\r
720  \r
721          raise NotmuchError(status)\r
722  \r
723 +    _thaw = nmlib.notmuch_message_thaw\r
724 +    _thaw.argtypes = [NotmuchMessageP]\r
725 +    _thaw.restype = c_uint\r
726 +\r
727      def thaw(self):\r
728          """Thaws the current 'message'\r
729  \r
730 @@ -674,7 +725,7 @@ class Message(object):\r
731          if self._msg is None:\r
732              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
733  \r
734 -        status = nmlib.notmuch_message_thaw(self._msg)\r
735 +        status = self._thaw(self._msg)\r
736  \r
737          if STATUS.SUCCESS == status:\r
738              # return on success\r
739 @@ -896,7 +947,11 @@ class Message(object):\r
740              res = cmp(list(self.get_filenames()), list(other.get_filenames()))\r
741          return res\r
742  \r
743 +    _destroy = nmlib.notmuch_message_destroy\r
744 +    _destroy.argtypes = [NotmuchMessageP]\r
745 +    _destroy.restype = None\r
746 +\r
747      def __del__(self):\r
748          """Close and free the notmuch Message"""\r
749          if self._msg is not None:\r
750 -            nmlib.notmuch_message_destroy(self._msg)\r
751 +            self._destroy(self._msg)\r
752 diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py\r
753 index 50e3686..f3a3d27 100644\r
754 --- a/bindings/python/notmuch/tag.py\r
755 +++ b/bindings/python/notmuch/tag.py\r
756 @@ -17,7 +17,7 @@ along with notmuch.  If not, see <http://www.gnu.org/licenses/>.\r
757  Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'\r
758  """\r
759  from ctypes import c_char_p\r
760 -from notmuch.globals import nmlib, STATUS, NotmuchError\r
761 +from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP\r
762  \r
763  \r
764  class Tags(object):\r
765 @@ -50,6 +50,7 @@ class Tags(object):\r
766  \r
767      #notmuch_tags_get\r
768      _get = nmlib.notmuch_tags_get\r
769 +    _get.argtypes = [NotmuchTagsP]\r
770      _get.restype = c_char_p\r
771  \r
772      def __init__(self, tags_p, parent=None):\r
773 @@ -80,14 +81,22 @@ class Tags(object):\r
774          """ Make Tags an iterator """\r
775          return self\r
776  \r
777 +    _valid = nmlib.notmuch_tags_valid\r
778 +    _valid.argtypes = [NotmuchTagsP]\r
779 +    _valid.restype = bool\r
780 +\r
781 +    _move_to_next = nmlib.notmuch_tags_move_to_next\r
782 +    _move_to_next.argtypes = [NotmuchTagsP]\r
783 +    _move_to_next.restype = None\r
784 +\r
785      def next(self):\r
786          if self._tags is None:\r
787              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
788 -        if not nmlib.notmuch_tags_valid(self._tags):\r
789 +        if not self._valid(self._tags):\r
790              self._tags = None\r
791              raise StopIteration\r
792          tag = Tags._get(self._tags).decode('UTF-8')\r
793 -        nmlib.notmuch_tags_move_to_next(self._tags)\r
794 +        self._move_to_next(self._tags)\r
795          return tag\r
796  \r
797      def __nonzero__(self):\r
798 @@ -99,7 +108,7 @@ class Tags(object):\r
799  \r
800          :returns: True if the Tags() iterator has at least one more Tag\r
801              left."""\r
802 -        return nmlib.notmuch_tags_valid(self._tags) > 0\r
803 +        return self._valid(self._tags) > 0\r
804  \r
805      def __str__(self):\r
806          """The str() representation of Tags() is a space separated list of tags\r
807 @@ -112,7 +121,11 @@ class Tags(object):\r
808          """\r
809          return " ".join(self)\r
810  \r
811 +    _destroy = nmlib.notmuch_tags_destroy\r
812 +    _destroy.argtypes = [NotmuchTagsP]\r
813 +    _destroy.restype = None\r
814 +\r
815      def __del__(self):\r
816          """Close and free the notmuch tags"""\r
817          if self._tags is not None:\r
818 -            nmlib.notmuch_tags_destroy(self._tags)\r
819 +            self._destroy(self._tags)\r
820 diff --git a/bindings/python/notmuch/thread.py b/bindings/python/notmuch/thread.py\r
821 index 5e08eb3..d903c76 100644\r
822 --- a/bindings/python/notmuch/thread.py\r
823 +++ b/bindings/python/notmuch/thread.py\r
824 @@ -17,8 +17,10 @@ along with notmuch.  If not, see <http://www.gnu.org/licenses/>.\r
825  Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'\r
826  """\r
827  \r
828 -from ctypes import c_char_p, c_void_p, c_long\r
829 -from notmuch.globals import nmlib, STATUS, NotmuchError\r
830 +from ctypes import c_char_p, c_void_p, c_long, c_int\r
831 +from notmuch.globals import (nmlib, STATUS,\r
832 +    NotmuchError, NotmuchThreadP, NotmuchThreadsP, NotmuchMessagesP,\r
833 +    NotmuchTagsP,)\r
834  from notmuch.message import Messages\r
835  from notmuch.tag import Tags\r
836  from datetime import date\r
837 @@ -75,7 +77,8 @@ class Threads(object):\r
838  \r
839      #notmuch_threads_get\r
840      _get = nmlib.notmuch_threads_get\r
841 -    _get.restype = c_void_p\r
842 +    _get.argtypes = [NotmuchThreadsP]\r
843 +    _get.restype = NotmuchThreadP\r
844  \r
845      def __init__(self, threads_p, parent=None):\r
846          """\r
847 @@ -105,16 +108,24 @@ class Threads(object):\r
848          """ Make Threads an iterator """\r
849          return self\r
850  \r
851 +    _valid = nmlib.notmuch_threads_valid\r
852 +    _valid.argtypes = [NotmuchThreadsP]\r
853 +    _valid.restype = bool\r
854 +\r
855 +    _move_to_next = nmlib.notmuch_threads_move_to_next\r
856 +    _move_to_next.argtypes = [NotmuchThreadsP]\r
857 +    _move_to_next.restype = None\r
858 +\r
859      def next(self):\r
860          if self._threads is None:\r
861              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
862  \r
863 -        if not nmlib.notmuch_threads_valid(self._threads):\r
864 +        if not self._valid(self._threads):\r
865              self._threads = None\r
866              raise StopIteration\r
867  \r
868          thread = Thread(Threads._get(self._threads), self)\r
869 -        nmlib.notmuch_threads_move_to_next(self._threads)\r
870 +        self._move_to_next(self._threads)\r
871          return thread\r
872  \r
873      def __len__(self):\r
874 @@ -134,8 +145,8 @@ class Threads(object):\r
875  \r
876          i = 0\r
877          # returns 'bool'. On out-of-memory it returns None\r
878 -        while nmlib.notmuch_threads_valid(self._threads):\r
879 -            nmlib.notmuch_threads_move_to_next(self._threads)\r
880 +        while self._valid(self._threads):\r
881 +            self._move_to_next(self._threads)\r
882              i += 1\r
883          # reset self._threads to mark as "exhausted"\r
884          self._threads = None\r
885 @@ -153,12 +164,16 @@ class Threads(object):\r
886             Iterator, False if not. None on a "Out-of-memory" error.\r
887          """\r
888          return self._threads is not None and \\r
889 -            nmlib.notmuch_threads_valid(self._threads) > 0\r
890 +            self._valid(self._threads) > 0\r
891 +\r
892 +    _destroy = nmlib.notmuch_threads_destroy\r
893 +    _destroy.argtypes = [NotmuchThreadsP]\r
894 +    _destroy.argtypes = None\r
895  \r
896      def __del__(self):\r
897          """Close and free the notmuch Threads"""\r
898          if self._threads is not None:\r
899 -            nmlib.notmuch_messages_destroy(self._threads)\r
900 +            self._destroy(self._threads)\r
901  \r
902  \r
903  class Thread(object):\r
904 @@ -166,29 +181,36 @@ class Thread(object):\r
905  \r
906      """notmuch_thread_get_thread_id"""\r
907      _get_thread_id = nmlib.notmuch_thread_get_thread_id\r
908 +    _get_thread_id.argtypes = [NotmuchThreadP]\r
909      _get_thread_id.restype = c_char_p\r
910  \r
911      """notmuch_thread_get_authors"""\r
912      _get_authors = nmlib.notmuch_thread_get_authors\r
913 +    _get_authors.argtypes = [NotmuchThreadP]\r
914      _get_authors.restype = c_char_p\r
915  \r
916      """notmuch_thread_get_subject"""\r
917      _get_subject = nmlib.notmuch_thread_get_subject\r
918 +    _get_subject.argtypes = [NotmuchThreadP]\r
919      _get_subject.restype = c_char_p\r
920  \r
921      """notmuch_thread_get_toplevel_messages"""\r
922      _get_toplevel_messages = nmlib.notmuch_thread_get_toplevel_messages\r
923 -    _get_toplevel_messages.restype = c_void_p\r
924 +    _get_toplevel_messages.argtypes = [NotmuchThreadP]\r
925 +    _get_toplevel_messages.restype = NotmuchMessagesP\r
926  \r
927      _get_newest_date = nmlib.notmuch_thread_get_newest_date\r
928 +    _get_newest_date.argtypes = [NotmuchThreadP]\r
929      _get_newest_date.restype = c_long\r
930  \r
931      _get_oldest_date = nmlib.notmuch_thread_get_oldest_date\r
932 +    _get_oldest_date.argtypes = [NotmuchThreadP]\r
933      _get_oldest_date.restype = c_long\r
934  \r
935      """notmuch_thread_get_tags"""\r
936      _get_tags = nmlib.notmuch_thread_get_tags\r
937 -    _get_tags.restype = c_void_p\r
938 +    _get_tags.argtypes = [NotmuchThreadP]\r
939 +    _get_tags.restype = NotmuchTagsP\r
940  \r
941      def __init__(self, thread_p, parent=None):\r
942          """\r
943 @@ -225,6 +247,11 @@ class Thread(object):\r
944              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
945          return Thread._get_thread_id(self._thread)\r
946  \r
947 +\r
948 +    _get_total_messages = nmlib.notmuch_thread_get_total_messages\r
949 +    _get_total_messages.argtypes = [NotmuchThreadP]\r
950 +    _get_total_messages.restype = c_int\r
951 +\r
952      def get_total_messages(self):\r
953          """Get the total number of messages in 'thread'\r
954  \r
955 @@ -236,7 +263,7 @@ class Thread(object):\r
956          """\r
957          if self._thread is None:\r
958              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
959 -        return nmlib.notmuch_thread_get_total_messages(self._thread)\r
960 +        return self._get_total_messages(self._thread)\r
961  \r
962      def get_toplevel_messages(self):\r
963          """Returns a :class:`Messages` iterator for the top-level messages in\r
964 @@ -267,6 +294,10 @@ class Thread(object):\r
965  \r
966          return Messages(msgs_p, self)\r
967  \r
968 +    _get_matched_messages = nmlib.notmuch_thread_get_matched_messages\r
969 +    _get_matched_messages.argtypes = [NotmuchThreadP]\r
970 +    _get_matched_messages.restype = c_int\r
971 +\r
972      def get_matched_messages(self):\r
973          """Returns the number of messages in 'thread' that matched the query\r
974  \r
975 @@ -278,7 +309,7 @@ class Thread(object):\r
976          """\r
977          if self._thread is None:\r
978              raise NotmuchError(STATUS.NOT_INITIALIZED)\r
979 -        return nmlib.notmuch_thread_get_matched_messages(self._thread)\r
980 +        return self._get_matched_messages(self._thread)\r
981  \r
982      def get_authors(self):\r
983          """Returns the authors of 'thread'\r
984 @@ -387,7 +418,11 @@ class Thread(object):\r
985                                                         thread['subject'],\r
986                                                         thread['tags'])\r
987  \r
988 +    _destroy = nmlib.notmuch_thread_destroy\r
989 +    _destroy.argtypes = [NotmuchThreadP]\r
990 +    _destroy.restype = None\r
991 +\r
992      def __del__(self):\r
993          """Close and free the notmuch Thread"""\r
994          if self._thread is not None:\r
995 -            nmlib.notmuch_thread_destroy(self._thread)\r
996 +            self._destroy(self._thread)\r
997 -- \r
998 1.7.6.3\r
999 \r