mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-12-22 17:34:54 +01:00
python: annotate all calls into libnotmuch with types
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>
This commit is contained in:
parent
e92b438f46
commit
3434d19402
5 changed files with 255 additions and 71 deletions
|
@ -18,9 +18,11 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
|||
"""
|
||||
|
||||
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 "<notmuch Directory object '%s'>" % 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)
|
||||
|
|
|
@ -17,7 +17,8 @@ along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
|||
Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||
"""
|
||||
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)
|
||||
|
|
|
@ -21,7 +21,8 @@ Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
|||
|
||||
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)
|
||||
|
|
|
@ -17,7 +17,7 @@ along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
|||
Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||
"""
|
||||
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)
|
||||
|
|
|
@ -17,8 +17,10 @@ along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
|||
Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||
"""
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue