From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Sun, 9 Oct 2011 22:12:54 +0000 (+0200) Subject: [PATCH 2/2] python: annotate all calls into libnotmuch with types X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7e4b4a950d4c1b74663b919d2f07bb93ff5df7e1;p=notmuch-archives.git [PATCH 2/2] python: annotate all calls into libnotmuch with types --- diff --git a/ab/2ad867f139112094b0c49c9b043f13ace38ac8 b/ab/2ad867f139112094b0c49c9b043f13ace38ac8 new file mode 100644 index 000000000..8052e50ff --- /dev/null +++ b/ab/2ad867f139112094b0c49c9b043f13ace38ac8 @@ -0,0 +1,999 @@ +Return-Path: +X-Original-To: notmuch@notmuchmail.org +Delivered-To: notmuch@notmuchmail.org +Received: from localhost (localhost [127.0.0.1]) + by olra.theworths.org (Postfix) with ESMTP id C0C7E429E25 + for ; Sun, 9 Oct 2011 15:13:45 -0700 (PDT) +X-Virus-Scanned: Debian amavisd-new at olra.theworths.org +X-Spam-Flag: NO +X-Spam-Score: 0.001 +X-Spam-Level: +X-Spam-Status: No, score=0.001 tagged_above=-999 required=5 + tests=[UNPARSEABLE_RELAY=0.001] autolearn=disabled +Received: from olra.theworths.org ([127.0.0.1]) + by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) + with ESMTP id KcPOLsTVLwUh for ; + Sun, 9 Oct 2011 15:13:43 -0700 (PDT) +Received: from mail.cryptobitch.de (cryptobitch.de [88.198.7.68]) + (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) + (No client certificate requested) + by olra.theworths.org (Postfix) with ESMTPS id 344A8431FB6 + for ; Sun, 9 Oct 2011 15:13:43 -0700 (PDT) +Received: from mail.jade-hamburg.de (unknown [85.183.11.228]) + (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) + (No client certificate requested) + by mail.cryptobitch.de (Postfix) with ESMTPSA id E1747509367 + for ; Mon, 10 Oct 2011 00:13:41 +0200 (CEST) +Received: by mail.jade-hamburg.de (Postfix, from userid 401) + id 60011DF2A1; Mon, 10 Oct 2011 00:13:41 +0200 (CEST) +Received: from thinkbox.jade-hamburg.de (unknown + [IPv6:fe80::216:d3ff:fe3e:5058%br0]) + (using TLSv1 with cipher AES256-SHA (256/256 bits)) + (No client certificate requested) (Authenticated sender: teythoon) + by mail.jade-hamburg.de (Postfix) with ESMTPSA id 680C2DF29F; + Mon, 10 Oct 2011 00:13:22 +0200 (CEST) +Received: from teythoon by thinkbox.jade-hamburg.de with local (Exim 4.76) + (envelope-from ) + id 1RD1cX-0000HM-JH; Mon, 10 Oct 2011 00:13:21 +0200 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +To: notmuch@notmuchmail.org +Subject: [PATCH 2/2] python: annotate all calls into libnotmuch with types +Date: Mon, 10 Oct 2011 00:12:54 +0200 +Message-Id: + <1318198374-926-2-git-send-email-4winter@informatik.uni-hamburg.de> +X-Mailer: git-send-email 1.7.6.3 +In-Reply-To: + <1318198374-926-1-git-send-email-4winter@informatik.uni-hamburg.de> +References: + <1318198374-926-1-git-send-email-4winter@informatik.uni-hamburg.de> +X-BeenThere: notmuch@notmuchmail.org +X-Mailman-Version: 2.1.13 +Precedence: list +List-Id: "Use and development of the notmuch mail system." + +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +X-List-Received-Date: Sun, 09 Oct 2011 22:13:45 -0000 + +Add type information to the ctypes._FuncPtr wrappers and +use the wrapper classes instead of c_void_p for pointers +to notmuch_*_t. + +This enables the ctypes library to type check parameters +being handed to functions from the notmuch library. + +Signed-off-by: Justus Winter <4winter@informatik.uni-hamburg.de> +--- + bindings/python/notmuch/database.py | 127 ++++++++++++++++++++++++++-------- + bindings/python/notmuch/filename.py | 22 +++++- + bindings/python/notmuch/message.py | 91 ++++++++++++++++++++----- + bindings/python/notmuch/tag.py | 23 +++++-- + bindings/python/notmuch/thread.py | 63 +++++++++++++---- + 5 files changed, 255 insertions(+), 71 deletions(-) + +diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py +index f4bc53e..25b4b1b 100644 +--- a/bindings/python/notmuch/database.py ++++ b/bindings/python/notmuch/database.py +@@ -18,9 +18,11 @@ Copyright 2010 Sebastian Spaeth ' + """ + + import os +-from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref ++from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref, POINTER + from notmuch.globals import (nmlib, STATUS, NotmuchError, NotInitializedError, +- NullPointerError, OutOfMemoryError, XapianError, Enum, _str) ++ NullPointerError, OutOfMemoryError, XapianError, Enum, _str, ++ NotmuchDatabaseP, NotmuchDirectoryP, NotmuchMessageP, NotmuchTagsP, ++ NotmuchQueryP, NotmuchMessagesP, NotmuchThreadsP, NotmuchFilenamesP) + from notmuch.thread import Threads + from notmuch.message import Messages, Message + from notmuch.tag import Tags +@@ -56,37 +58,48 @@ class Database(object): + + """notmuch_database_get_directory""" + _get_directory = nmlib.notmuch_database_get_directory +- _get_directory.restype = c_void_p ++ _get_directory.argtypes = [NotmuchDatabaseP, c_char_p] ++ _get_directory.restype = NotmuchDirectoryP + + """notmuch_database_get_path""" + _get_path = nmlib.notmuch_database_get_path ++ _get_path.argtypes = [NotmuchDatabaseP] + _get_path.restype = c_char_p + + """notmuch_database_get_version""" + _get_version = nmlib.notmuch_database_get_version ++ _get_version.argtypes = [NotmuchDatabaseP] + _get_version.restype = c_uint + + """notmuch_database_open""" + _open = nmlib.notmuch_database_open +- _open.restype = c_void_p ++ _open.argtypes = [c_char_p, c_uint] ++ _open.restype = NotmuchDatabaseP + + """notmuch_database_upgrade""" + _upgrade = nmlib.notmuch_database_upgrade +- _upgrade.argtypes = [c_void_p, c_void_p, c_void_p] ++ _upgrade.argtypes = [NotmuchDatabaseP, c_void_p, c_void_p] ++ _upgrade.restype = c_uint + + """ notmuch_database_find_message""" + _find_message = nmlib.notmuch_database_find_message ++ _find_message.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)] ++ _find_message.restype = c_uint + + """notmuch_database_find_message_by_filename""" + _find_message_by_filename = nmlib.notmuch_database_find_message_by_filename ++ _find_message_by_filename.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)] ++ _find_message_by_filename.restype = c_uint + + """notmuch_database_get_all_tags""" + _get_all_tags = nmlib.notmuch_database_get_all_tags +- _get_all_tags.restype = c_void_p ++ _get_all_tags.argtypes = [NotmuchDatabaseP] ++ _get_all_tags.restype = NotmuchTagsP + + """notmuch_database_create""" + _create = nmlib.notmuch_database_create +- _create.restype = c_void_p ++ _create.argtypes = [c_char_p] ++ _create.restype = NotmuchDatabaseP + + def __init__(self, path=None, create=False, mode=0): + """If *path* is `None`, we will try to read a users notmuch +@@ -186,6 +199,10 @@ class Database(object): + self._assert_db_is_initialized() + return Database._get_version(self._db) + ++ _needs_upgrade = nmlib.notmuch_database_needs_upgrade ++ _needs_upgrade.argtypes = [NotmuchDatabaseP] ++ _needs_upgrade.restype = bool ++ + def needs_upgrade(self): + """Does this database need to be upgraded before writing to it? + +@@ -197,7 +214,7 @@ class Database(object): + :returns: `True` or `False` + """ + self._assert_db_is_initialized() +- return nmlib.notmuch_database_needs_upgrade(self._db) ++ return self._needs_upgrade(self._db) + + def upgrade(self): + """Upgrades the current database +@@ -219,6 +236,10 @@ class Database(object): + #TODO: catch exceptions, document return values and etc + return status + ++ _begin_atomic = nmlib.notmuch_database_begin_atomic ++ _begin_atomic.argtypes = [NotmuchDatabaseP] ++ _begin_atomic.restype = c_uint ++ + def begin_atomic(self): + """Begin an atomic database operation + +@@ -236,11 +257,15 @@ class Database(object): + + *Added in notmuch 0.9*""" + self._assert_db_is_initialized() +- status = nmlib.notmuch_database_begin_atomic(self._db) ++ status = self._begin_atomic(self._db) + if status != STATUS.SUCCESS: + raise NotmuchError(status) + return status + ++ _end_atomic = nmlib.notmuch_database_end_atomic ++ _end_atomic.argtypes = [NotmuchDatabaseP] ++ _end_atomic.restype = c_uint ++ + def end_atomic(self): + """Indicate the end of an atomic database operation + +@@ -258,7 +283,7 @@ class Database(object): + + *Added in notmuch 0.9*""" + self._assert_db_is_initialized() +- status = nmlib.notmuch_database_end_atomic(self._db) ++ status = self._end_atomic(self._db) + if status != STATUS.SUCCESS: + raise NotmuchError(status) + return status +@@ -299,6 +324,10 @@ class Database(object): + # return the Directory, init it with the absolute path + return Directory(_str(abs_dirpath), dir_p, self) + ++ _add_message = nmlib.notmuch_database_add_message ++ _add_message.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)] ++ _add_message.restype = c_uint ++ + def add_message(self, filename, sync_maildir_flags=False): + """Adds a new message to the database + +@@ -350,9 +379,7 @@ class Database(object): + """ + self._assert_db_is_initialized() + msg_p = c_void_p() +- status = nmlib.notmuch_database_add_message(self._db, +- _str(filename), +- byref(msg_p)) ++ status = self._add_message(self._db, _str(filename), byref(msg_p)) + + if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]: + raise NotmuchError(status) +@@ -364,6 +391,10 @@ class Database(object): + msg.maildir_flags_to_tags() + return (msg, status) + ++ _remove_message = nmlib.notmuch_database_remove_message ++ _remove_message.argtypes = [NotmuchDatabaseP, c_char_p] ++ _remove_message.restype = c_uint ++ + def remove_message(self, filename): + """Removes a message (filename) from the given notmuch database + +@@ -392,8 +423,7 @@ class Database(object): + removed. + """ + self._assert_db_is_initialized() +- return nmlib.notmuch_database_remove_message(self._db, +- filename) ++ return self._remove_message(self._db, filename) + + def find_message(self, msgid): + """Returns a :class:`Message` as identified by its message ID +@@ -491,10 +521,14 @@ class Database(object): + def __repr__(self): + return "'Notmuch DB " + self.get_path() + "'" + ++ _close = nmlib.notmuch_database_close ++ _close.argtypes = [NotmuchDatabaseP] ++ _close.restype = None ++ + def __del__(self): + """Close and free the notmuch database if needed""" + if self._db is not None: +- nmlib.notmuch_database_close(self._db) ++ self._close(self._db) + + def _get_user_default_db(self): + """ Reads a user's notmuch config and returns his db location +@@ -545,18 +579,22 @@ class Query(object): + + """notmuch_query_create""" + _create = nmlib.notmuch_query_create +- _create.restype = c_void_p ++ _create.argtypes = [NotmuchDatabaseP, c_char_p] ++ _create.restype = NotmuchQueryP + + """notmuch_query_search_threads""" + _search_threads = nmlib.notmuch_query_search_threads +- _search_threads.restype = c_void_p ++ _search_threads.argtypes = [NotmuchQueryP] ++ _search_threads.restype = NotmuchThreadsP + + """notmuch_query_search_messages""" + _search_messages = nmlib.notmuch_query_search_messages +- _search_messages.restype = c_void_p ++ _search_messages.argtypes = [NotmuchQueryP] ++ _search_messages.restype = NotmuchMessagesP + + """notmuch_query_count_messages""" + _count_messages = nmlib.notmuch_query_count_messages ++ _count_messages.argtypes = [NotmuchQueryP] + _count_messages.restype = c_uint + + def __init__(self, db, querystr): +@@ -602,6 +640,10 @@ class Query(object): + raise NullPointerError + self._query = query_p + ++ _set_sort = nmlib.notmuch_query_set_sort ++ _set_sort.argtypes = [NotmuchQueryP, c_uint] ++ _set_sort.argtypes = None ++ + def set_sort(self, sort): + """Set the sort order future results will be delivered in + +@@ -609,7 +651,7 @@ class Query(object): + """ + self._assert_query_is_initialized() + self.sort = sort +- nmlib.notmuch_query_set_sort(self._query, sort) ++ self._set_sort(self._query, sort) + + def search_threads(self): + """Execute a query for threads +@@ -661,10 +703,14 @@ class Query(object): + self._assert_query_is_initialized() + return Query._count_messages(self._query) + ++ _destroy = nmlib.notmuch_query_destroy ++ _destroy.argtypes = [NotmuchQueryP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free the Query""" + if self._query is not None: +- nmlib.notmuch_query_destroy(self._query) ++ self._destroy(self._query) + + + class Directory(object): +@@ -683,19 +729,23 @@ class Directory(object): + + """notmuch_directory_get_mtime""" + _get_mtime = nmlib.notmuch_directory_get_mtime ++ _get_mtime.argtypes = [NotmuchDirectoryP] + _get_mtime.restype = c_long + + """notmuch_directory_set_mtime""" + _set_mtime = nmlib.notmuch_directory_set_mtime +- _set_mtime.argtypes = [c_char_p, c_long] ++ _set_mtime.argtypes = [NotmuchDirectoryP, c_long] ++ _set_mtime.restype = c_uint + + """notmuch_directory_get_child_files""" + _get_child_files = nmlib.notmuch_directory_get_child_files +- _get_child_files.restype = c_void_p ++ _get_child_files.argtypes = [NotmuchDirectoryP] ++ _get_child_files.restype = NotmuchFilenamesP + + """notmuch_directory_get_child_directories""" + _get_child_directories = nmlib.notmuch_directory_get_child_directories +- _get_child_directories.restype = c_void_p ++ _get_child_directories.argtypes = [NotmuchDirectoryP] ++ _get_child_directories.restype = NotmuchFilenamesP + + def _assert_dir_is_initialized(self): + """Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None""" +@@ -815,10 +865,14 @@ class Directory(object): + """Object representation""" + return "" % self._path + ++ _destroy = nmlib.notmuch_directory_destroy ++ _destroy.argtypes = [NotmuchDirectoryP] ++ _destroy.argtypes = None ++ + def __del__(self): + """Close and free the Directory""" + if self._dir_p is not None: +- nmlib.notmuch_directory_destroy(self._dir_p) ++ self._destroy(self._dir_p) + + + class Filenames(object): +@@ -826,6 +880,7 @@ class Filenames(object): + + #notmuch_filenames_get + _get = nmlib.notmuch_filenames_get ++ _get.argtypes = [NotmuchFilenamesP] + _get.restype = c_char_p + + def __init__(self, files_p, parent): +@@ -844,16 +899,24 @@ class Filenames(object): + """ Make Filenames an iterator """ + return self + ++ _valid = nmlib.notmuch_filenames_valid ++ _valid.argtypes = [NotmuchFilenamesP] ++ _valid.restype = bool ++ ++ _move_to_next = nmlib.notmuch_filenames_move_to_next ++ _move_to_next.argtypes = [NotmuchFilenamesP] ++ _move_to_next.restype = None ++ + def next(self): + if self._files_p is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- if not nmlib.notmuch_filenames_valid(self._files_p): ++ if not self._valid(self._files_p): + self._files_p = None + raise StopIteration + + file = Filenames._get(self._files_p) +- nmlib.notmuch_filenames_move_to_next(self._files_p) ++ self._move_to_next(self._files_p) + return file + + def __len__(self): +@@ -872,13 +935,17 @@ class Filenames(object): + raise NotmuchError(STATUS.NOT_INITIALIZED) + + i = 0 +- while nmlib.notmuch_filenames_valid(self._files_p): +- nmlib.notmuch_filenames_move_to_next(self._files_p) ++ while self._valid(self._files_p): ++ self._move_to_next(self._files_p) + i += 1 + self._files_p = None + return i + ++ _destroy = nmlib.notmuch_filenames_destroy ++ _destroy.argtypes = [NotmuchFilenamesP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free Filenames""" + if self._files_p is not None: +- nmlib.notmuch_filenames_destroy(self._files_p) ++ self._destroy(self._files_p) +diff --git a/bindings/python/notmuch/filename.py b/bindings/python/notmuch/filename.py +index de4d785..077754e 100644 +--- a/bindings/python/notmuch/filename.py ++++ b/bindings/python/notmuch/filename.py +@@ -17,7 +17,8 @@ along with notmuch. If not, see . + Copyright 2010 Sebastian Spaeth ' + """ + from ctypes import c_char_p +-from notmuch.globals import nmlib, STATUS, NotmuchError ++from notmuch.globals import (nmlib, STATUS, NotmuchError, ++ NotmuchFilenamesP, NotmuchMessagesP, NotmuchMessageP) + + + class Filenames(object): +@@ -50,6 +51,7 @@ class Filenames(object): + + #notmuch_filenames_get + _get = nmlib.notmuch_filenames_get ++ _get.argtypes = [NotmuchFilenamesP] + _get.restype = c_char_p + + def __init__(self, files_p, parent): +@@ -74,6 +76,14 @@ class Filenames(object): + #save reference to parent object so we keep it alive + self._parent = parent + ++ _valid = nmlib.notmuch_filenames_valid ++ _valid.argtypes = [NotmuchFilenamesP] ++ _valid.restype = bool ++ ++ _move_to_next = nmlib.notmuch_filenames_move_to_next ++ _move_to_next.argtypes = [NotmuchFilenamesP] ++ _move_to_next.restype = None ++ + def as_generator(self): + """Return generator of Filenames + +@@ -82,9 +92,9 @@ class Filenames(object): + if self._files is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- while nmlib.notmuch_filenames_valid(self._files): ++ while self._valid(self._files): + yield Filenames._get(self._files) +- nmlib.notmuch_filenames_move_to_next(self._files) ++ self._move_to_next(self._files) + + self._files = None + +@@ -101,7 +111,11 @@ class Filenames(object): + """ + return "\n".join(self) + ++ _destroy = nmlib.notmuch_filenames_destroy ++ _destroy.argtypes = [NotmuchMessageP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free the notmuch filenames""" + if self._files is not None: +- nmlib.notmuch_filenames_destroy(self._files) ++ self._destroy(self._files) +diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py +index 4bf90c2..e0c7eda 100644 +--- a/bindings/python/notmuch/message.py ++++ b/bindings/python/notmuch/message.py +@@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth ' + + 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, _str ++from notmuch.globals import (nmlib, STATUS, NotmuchError, Enum, _str, ++ NotmuchTagsP, NotmuchMessagesP, NotmuchMessageP, NotmuchFilenamesP) + from notmuch.tag import Tags + from notmuch.filename import Filenames + import sys +@@ -92,10 +93,12 @@ class Messages(object): + + #notmuch_messages_get + _get = nmlib.notmuch_messages_get +- _get.restype = c_void_p ++ _get.argtypes = [NotmuchMessagesP] ++ _get.restype = NotmuchMessageP + + _collect_tags = nmlib.notmuch_messages_collect_tags +- _collect_tags.restype = c_void_p ++ _collect_tags.argtypes = [NotmuchMessagesP] ++ _collect_tags.restype = NotmuchTagsP + + def __init__(self, msgs_p, parent=None): + """ +@@ -146,16 +149,24 @@ class Messages(object): + """ Make Messages an iterator """ + return self + ++ _valid = nmlib.notmuch_messages_valid ++ _valid.argtypes = [NotmuchMessagesP] ++ _valid.restype = bool ++ ++ _move_to_next = nmlib.notmuch_messages_move_to_next ++ _move_to_next.argtypes = [NotmuchMessagesP] ++ _move_to_next.restype = None ++ + def next(self): + if self._msgs is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- if not nmlib.notmuch_messages_valid(self._msgs): ++ if not self._valid(self._msgs): + self._msgs = None + raise StopIteration + + msg = Message(Messages._get(self._msgs), self) +- nmlib.notmuch_messages_move_to_next(self._msgs) ++ self._move_to_next(self._msgs) + return msg + + def __nonzero__(self): +@@ -163,12 +174,16 @@ class Messages(object): + :return: True if there is at least one more thread in the + Iterator, False if not.""" + return self._msgs is not None and \ +- nmlib.notmuch_messages_valid(self._msgs) > 0 ++ self._valid(self._msgs) > 0 ++ ++ _destroy = nmlib.notmuch_messages_destroy ++ _destroy.argtypes = [NotmuchMessagesP] ++ _destroy.restype = None + + def __del__(self): + """Close and free the notmuch Messages""" + if self._msgs is not None: +- nmlib.notmuch_messages_destroy(self._msgs) ++ self._destroy(self._msgs) + + def print_messages(self, format, indent=0, entire_thread=False): + """Outputs messages as needed for 'notmuch show' to sys.stdout +@@ -235,44 +250,60 @@ class Message(object): + + """notmuch_message_get_filename (notmuch_message_t *message)""" + _get_filename = nmlib.notmuch_message_get_filename ++ _get_filename.argtypes = [NotmuchMessageP] + _get_filename.restype = c_char_p + + """return all filenames for a message""" + _get_filenames = nmlib.notmuch_message_get_filenames +- _get_filenames.restype = c_void_p ++ _get_filenames.argtypes = [NotmuchMessageP] ++ _get_filenames.restype = NotmuchFilenamesP + + """notmuch_message_get_flag""" + _get_flag = nmlib.notmuch_message_get_flag +- _get_flag.restype = c_uint ++ _get_flag.argtypes = [NotmuchMessageP, c_uint] ++ _get_flag.restype = bool ++ ++ """notmuch_message_set_flag""" ++ _set_flag = nmlib.notmuch_message_set_flag ++ _set_flag.argtypes = [NotmuchMessageP, c_uint, c_int] ++ _set_flag.restype = None + + """notmuch_message_get_message_id (notmuch_message_t *message)""" + _get_message_id = nmlib.notmuch_message_get_message_id ++ _get_message_id.argtypes = [NotmuchMessageP] + _get_message_id.restype = c_char_p + + """notmuch_message_get_thread_id""" + _get_thread_id = nmlib.notmuch_message_get_thread_id ++ _get_thread_id.argtypes = [NotmuchMessageP] + _get_thread_id.restype = c_char_p + + """notmuch_message_get_replies""" + _get_replies = nmlib.notmuch_message_get_replies +- _get_replies.restype = c_void_p ++ _get_replies.argtypes = [NotmuchMessageP] ++ _get_replies.restype = NotmuchMessagesP + + """notmuch_message_get_tags (notmuch_message_t *message)""" + _get_tags = nmlib.notmuch_message_get_tags +- _get_tags.restype = c_void_p ++ _get_tags.argtypes = [NotmuchMessageP] ++ _get_tags.restype = NotmuchTagsP + + _get_date = nmlib.notmuch_message_get_date ++ _get_date.argtypes = [NotmuchMessageP] + _get_date.restype = c_long + + _get_header = nmlib.notmuch_message_get_header ++ _get_header.argtypes = [NotmuchMessageP, 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.argtypes = [NotmuchMessageP] + _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.argtypes = [NotmuchMessageP] + _maildir_flags_to_tags.restype = c_int + + #Constants: Flags that can be set/get with set_flag +@@ -450,7 +481,7 @@ class Message(object): + """ + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) +- nmlib.notmuch_message_set_flag(self._msg, flag, value) ++ self._set_flag(self._msg, flag, value) + + def get_tags(self): + """Returns the message tags +@@ -470,6 +501,10 @@ class Message(object): + raise NotmuchError(STATUS.NULL_POINTER) + return Tags(tags_p, self) + ++ _add_tag = nmlib.notmuch_message_add_tag ++ _add_tag.argtypes = [NotmuchMessageP, c_char_p] ++ _add_tag.restype = c_uint ++ + def add_tag(self, tag, sync_maildir_flags=False): + """Adds a tag to the given message + +@@ -504,7 +539,7 @@ class Message(object): + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- status = nmlib.notmuch_message_add_tag(self._msg, _str(tag)) ++ status = self._add_tag(self._msg, _str(tag)) + + # bail out on failure + if status != STATUS.SUCCESS: +@@ -514,6 +549,10 @@ class Message(object): + self.tags_to_maildir_flags() + return STATUS.SUCCESS + ++ _remove_tag = nmlib.notmuch_message_remove_tag ++ _remove_tag.argtypes = [NotmuchMessageP, c_char_p] ++ _remove_tag.restype = c_uint ++ + def remove_tag(self, tag, sync_maildir_flags=False): + """Removes a tag from the given message + +@@ -548,7 +587,7 @@ class Message(object): + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- status = nmlib.notmuch_message_remove_tag(self._msg, _str(tag)) ++ status = self._remove_tag(self._msg, _str(tag)) + # bail out on error + if status != STATUS.SUCCESS: + raise NotmuchError(status) +@@ -557,6 +596,10 @@ class Message(object): + self.tags_to_maildir_flags() + return STATUS.SUCCESS + ++ _remove_all_tags = nmlib.notmuch_message_remove_all_tags ++ _remove_all_tags.argtypes = [NotmuchMessageP] ++ _remove_all_tags.restype = c_uint ++ + def remove_all_tags(self, sync_maildir_flags=False): + """Removes all tags from the given message. + +@@ -585,7 +628,7 @@ class Message(object): + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- status = nmlib.notmuch_message_remove_all_tags(self._msg) ++ status = self._remove_all_tags(self._msg) + + # bail out on error + if status != STATUS.SUCCESS: +@@ -595,6 +638,10 @@ class Message(object): + self.tags_to_maildir_flags() + return STATUS.SUCCESS + ++ _freeze = nmlib.notmuch_message_freeze ++ _freeze.argtypes = [NotmuchMessageP] ++ _freeze.restype = c_uint ++ + def freeze(self): + """Freezes the current state of 'message' within the database + +@@ -639,7 +686,7 @@ class Message(object): + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- status = nmlib.notmuch_message_freeze(self._msg) ++ status = self._freeze(self._msg) + + if STATUS.SUCCESS == status: + # return on success +@@ -647,6 +694,10 @@ class Message(object): + + raise NotmuchError(status) + ++ _thaw = nmlib.notmuch_message_thaw ++ _thaw.argtypes = [NotmuchMessageP] ++ _thaw.restype = c_uint ++ + def thaw(self): + """Thaws the current 'message' + +@@ -674,7 +725,7 @@ class Message(object): + if self._msg is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- status = nmlib.notmuch_message_thaw(self._msg) ++ status = self._thaw(self._msg) + + if STATUS.SUCCESS == status: + # return on success +@@ -896,7 +947,11 @@ class Message(object): + res = cmp(list(self.get_filenames()), list(other.get_filenames())) + return res + ++ _destroy = nmlib.notmuch_message_destroy ++ _destroy.argtypes = [NotmuchMessageP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free the notmuch Message""" + if self._msg is not None: +- nmlib.notmuch_message_destroy(self._msg) ++ self._destroy(self._msg) +diff --git a/bindings/python/notmuch/tag.py b/bindings/python/notmuch/tag.py +index 50e3686..f3a3d27 100644 +--- a/bindings/python/notmuch/tag.py ++++ b/bindings/python/notmuch/tag.py +@@ -17,7 +17,7 @@ along with notmuch. If not, see . + Copyright 2010 Sebastian Spaeth ' + """ + from ctypes import c_char_p +-from notmuch.globals import nmlib, STATUS, NotmuchError ++from notmuch.globals import nmlib, STATUS, NotmuchError, NotmuchTagsP + + + class Tags(object): +@@ -50,6 +50,7 @@ class Tags(object): + + #notmuch_tags_get + _get = nmlib.notmuch_tags_get ++ _get.argtypes = [NotmuchTagsP] + _get.restype = c_char_p + + def __init__(self, tags_p, parent=None): +@@ -80,14 +81,22 @@ class Tags(object): + """ Make Tags an iterator """ + return self + ++ _valid = nmlib.notmuch_tags_valid ++ _valid.argtypes = [NotmuchTagsP] ++ _valid.restype = bool ++ ++ _move_to_next = nmlib.notmuch_tags_move_to_next ++ _move_to_next.argtypes = [NotmuchTagsP] ++ _move_to_next.restype = None ++ + def next(self): + if self._tags is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) +- if not nmlib.notmuch_tags_valid(self._tags): ++ if not self._valid(self._tags): + self._tags = None + raise StopIteration + tag = Tags._get(self._tags).decode('UTF-8') +- nmlib.notmuch_tags_move_to_next(self._tags) ++ self._move_to_next(self._tags) + return tag + + def __nonzero__(self): +@@ -99,7 +108,7 @@ class Tags(object): + + :returns: True if the Tags() iterator has at least one more Tag + left.""" +- return nmlib.notmuch_tags_valid(self._tags) > 0 ++ return self._valid(self._tags) > 0 + + def __str__(self): + """The str() representation of Tags() is a space separated list of tags +@@ -112,7 +121,11 @@ class Tags(object): + """ + return " ".join(self) + ++ _destroy = nmlib.notmuch_tags_destroy ++ _destroy.argtypes = [NotmuchTagsP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free the notmuch tags""" + if self._tags is not None: +- nmlib.notmuch_tags_destroy(self._tags) ++ self._destroy(self._tags) +diff --git a/bindings/python/notmuch/thread.py b/bindings/python/notmuch/thread.py +index 5e08eb3..d903c76 100644 +--- a/bindings/python/notmuch/thread.py ++++ b/bindings/python/notmuch/thread.py +@@ -17,8 +17,10 @@ along with notmuch. If not, see . + Copyright 2010 Sebastian Spaeth ' + """ + +-from ctypes import c_char_p, c_void_p, c_long +-from notmuch.globals import nmlib, STATUS, NotmuchError ++from ctypes import c_char_p, c_void_p, c_long, c_int ++from notmuch.globals import (nmlib, STATUS, ++ NotmuchError, NotmuchThreadP, NotmuchThreadsP, NotmuchMessagesP, ++ NotmuchTagsP,) + from notmuch.message import Messages + from notmuch.tag import Tags + from datetime import date +@@ -75,7 +77,8 @@ class Threads(object): + + #notmuch_threads_get + _get = nmlib.notmuch_threads_get +- _get.restype = c_void_p ++ _get.argtypes = [NotmuchThreadsP] ++ _get.restype = NotmuchThreadP + + def __init__(self, threads_p, parent=None): + """ +@@ -105,16 +108,24 @@ class Threads(object): + """ Make Threads an iterator """ + return self + ++ _valid = nmlib.notmuch_threads_valid ++ _valid.argtypes = [NotmuchThreadsP] ++ _valid.restype = bool ++ ++ _move_to_next = nmlib.notmuch_threads_move_to_next ++ _move_to_next.argtypes = [NotmuchThreadsP] ++ _move_to_next.restype = None ++ + def next(self): + if self._threads is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) + +- if not nmlib.notmuch_threads_valid(self._threads): ++ if not self._valid(self._threads): + self._threads = None + raise StopIteration + + thread = Thread(Threads._get(self._threads), self) +- nmlib.notmuch_threads_move_to_next(self._threads) ++ self._move_to_next(self._threads) + return thread + + def __len__(self): +@@ -134,8 +145,8 @@ class Threads(object): + + i = 0 + # returns 'bool'. On out-of-memory it returns None +- while nmlib.notmuch_threads_valid(self._threads): +- nmlib.notmuch_threads_move_to_next(self._threads) ++ while self._valid(self._threads): ++ self._move_to_next(self._threads) + i += 1 + # reset self._threads to mark as "exhausted" + self._threads = None +@@ -153,12 +164,16 @@ class Threads(object): + Iterator, False if not. None on a "Out-of-memory" error. + """ + return self._threads is not None and \ +- nmlib.notmuch_threads_valid(self._threads) > 0 ++ self._valid(self._threads) > 0 ++ ++ _destroy = nmlib.notmuch_threads_destroy ++ _destroy.argtypes = [NotmuchThreadsP] ++ _destroy.argtypes = None + + def __del__(self): + """Close and free the notmuch Threads""" + if self._threads is not None: +- nmlib.notmuch_messages_destroy(self._threads) ++ self._destroy(self._threads) + + + class Thread(object): +@@ -166,29 +181,36 @@ class Thread(object): + + """notmuch_thread_get_thread_id""" + _get_thread_id = nmlib.notmuch_thread_get_thread_id ++ _get_thread_id.argtypes = [NotmuchThreadP] + _get_thread_id.restype = c_char_p + + """notmuch_thread_get_authors""" + _get_authors = nmlib.notmuch_thread_get_authors ++ _get_authors.argtypes = [NotmuchThreadP] + _get_authors.restype = c_char_p + + """notmuch_thread_get_subject""" + _get_subject = nmlib.notmuch_thread_get_subject ++ _get_subject.argtypes = [NotmuchThreadP] + _get_subject.restype = c_char_p + + """notmuch_thread_get_toplevel_messages""" + _get_toplevel_messages = nmlib.notmuch_thread_get_toplevel_messages +- _get_toplevel_messages.restype = c_void_p ++ _get_toplevel_messages.argtypes = [NotmuchThreadP] ++ _get_toplevel_messages.restype = NotmuchMessagesP + + _get_newest_date = nmlib.notmuch_thread_get_newest_date ++ _get_newest_date.argtypes = [NotmuchThreadP] + _get_newest_date.restype = c_long + + _get_oldest_date = nmlib.notmuch_thread_get_oldest_date ++ _get_oldest_date.argtypes = [NotmuchThreadP] + _get_oldest_date.restype = c_long + + """notmuch_thread_get_tags""" + _get_tags = nmlib.notmuch_thread_get_tags +- _get_tags.restype = c_void_p ++ _get_tags.argtypes = [NotmuchThreadP] ++ _get_tags.restype = NotmuchTagsP + + def __init__(self, thread_p, parent=None): + """ +@@ -225,6 +247,11 @@ class Thread(object): + raise NotmuchError(STATUS.NOT_INITIALIZED) + return Thread._get_thread_id(self._thread) + ++ ++ _get_total_messages = nmlib.notmuch_thread_get_total_messages ++ _get_total_messages.argtypes = [NotmuchThreadP] ++ _get_total_messages.restype = c_int ++ + def get_total_messages(self): + """Get the total number of messages in 'thread' + +@@ -236,7 +263,7 @@ class Thread(object): + """ + if self._thread is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) +- return nmlib.notmuch_thread_get_total_messages(self._thread) ++ return self._get_total_messages(self._thread) + + def get_toplevel_messages(self): + """Returns a :class:`Messages` iterator for the top-level messages in +@@ -267,6 +294,10 @@ class Thread(object): + + return Messages(msgs_p, self) + ++ _get_matched_messages = nmlib.notmuch_thread_get_matched_messages ++ _get_matched_messages.argtypes = [NotmuchThreadP] ++ _get_matched_messages.restype = c_int ++ + def get_matched_messages(self): + """Returns the number of messages in 'thread' that matched the query + +@@ -278,7 +309,7 @@ class Thread(object): + """ + if self._thread is None: + raise NotmuchError(STATUS.NOT_INITIALIZED) +- return nmlib.notmuch_thread_get_matched_messages(self._thread) ++ return self._get_matched_messages(self._thread) + + def get_authors(self): + """Returns the authors of 'thread' +@@ -387,7 +418,11 @@ class Thread(object): + thread['subject'], + thread['tags']) + ++ _destroy = nmlib.notmuch_thread_destroy ++ _destroy.argtypes = [NotmuchThreadP] ++ _destroy.restype = None ++ + def __del__(self): + """Close and free the notmuch Thread""" + if self._thread is not None: +- nmlib.notmuch_thread_destroy(self._thread) ++ self._destroy(self._thread) +-- +1.7.6.3 +