X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=bindings%2Fpython%2Fnotmuch%2Fdatabase.py;h=2eae69ed72ae6aebde5671a55df97500899b4161;hp=25b4b1b1ca33a3202f9f8042ff2cad05d8412823;hb=83b256b12be25b29f915587342b5ccb139864268;hpb=3434d194026ff65217d9342ffe511f67fd71e79f diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index 25b4b1b1..2eae69ed 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -18,15 +18,16 @@ Copyright 2010 Sebastian Spaeth ' """ import os -from ctypes import c_int, c_char_p, c_void_p, c_uint, c_long, byref, POINTER +from ctypes import 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, 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 + class Database(object): """The :class:`Database` is the highest-level object that notmuch provides. It references a notmuch database, and can be opened in @@ -39,16 +40,19 @@ class Database(object): :exc:`XapianError` as the underlying database has been modified. Close and reopen the database to continue working with it. - .. note:: Any function in this class can and will throw an - :exc:`NotInitializedError` if the database was not - intitialized properly. + .. note:: + + Any function in this class can and will throw an + :exc:`NotInitializedError` if the database was not intitialized + properly. + + .. note:: - .. note:: Do remember that as soon as we tear down (e.g. via `del - db`) this object, all underlying derived objects such as - queries, threads, messages, tags etc will be freed by the - underlying library as well. Accessing these objects will lead - to segfaults and other unexpected behavior. See above for - more details. + Do remember that as soon as we tear down (e.g. via `del db`) this + object, all underlying derived objects such as queries, threads, + messages, tags etc will be freed by the underlying library as well. + Accessing these objects will lead to segfaults and other unexpected + behavior. See above for more details. """ _std_db_path = None """Class attribute to cache user's default database""" @@ -83,12 +87,14 @@ class Database(object): """ notmuch_database_find_message""" _find_message = nmlib.notmuch_database_find_message - _find_message.argtypes = [NotmuchDatabaseP, c_char_p, POINTER(NotmuchMessageP)] + _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.argtypes = [NotmuchDatabaseP, c_char_p, + POINTER(NotmuchMessageP)] _find_message_by_filename.restype = c_uint """notmuch_database_get_all_tags""" @@ -177,8 +183,8 @@ class Database(object): :param status: Open the database in read-only or read-write mode :type status: :attr:`MODE` :returns: Nothing - :exception: Raises :exc:`NotmuchError` in case - of any failure (possibly after printing an error message on stderr). + :exception: Raises :exc:`NotmuchError` in case of any failure + (possibly after printing an error message on stderr). """ res = Database._open(_str(path), mode) @@ -250,10 +256,8 @@ class Database(object): neither begin nor end necessarily flush modifications to disk. :returns: :attr:`STATUS`.SUCCESS or raises - - :exception: :exc:`NotmuchError`: - :attr:`STATUS`.XAPIAN_EXCEPTION - Xapian exception occurred; atomic section not entered. + :exception: :exc:`NotmuchError`: :attr:`STATUS`.XAPIAN_EXCEPTION + Xapian exception occurred; atomic section not entered. *Added in notmuch 0.9*""" self._assert_db_is_initialized() @@ -292,13 +296,15 @@ class Database(object): """Returns a :class:`Directory` of path, (creating it if it does not exist(?)) - .. warning:: This call needs a writeable database in - :attr:`Database.MODE`.READ_WRITE mode. The underlying library will exit the - program if this method is used on a read-only database! + .. warning:: + + This call needs a writeable database in + :attr:`Database.MODE`.READ_WRITE mode. The underlying library will + exit the program if this method is used on a read-only database! :param path: An unicode string containing the path relative to the path - of database (see :meth:`get_path`), or else should be an absolute path - with initial components that match the path of 'database'. + of database (see :meth:`get_path`), or else should be an absolute + path with initial components that match the path of 'database'. :returns: :class:`Directory` or raises an exception. :exception: :exc:`NotmuchError` with :attr:`STATUS`.FILE_ERROR @@ -325,7 +331,8 @@ class Database(object): 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.argtypes = [NotmuchDatabaseP, c_char_p, + POINTER(NotmuchMessageP)] _add_message.restype = c_uint def add_message(self, filename, sync_maildir_flags=False): @@ -378,7 +385,7 @@ class Database(object): be added. """ self._assert_db_is_initialized() - msg_p = c_void_p() + msg_p = NotmuchMessageP() status = self._add_message(self._db, _str(filename), byref(msg_p)) if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]: @@ -423,7 +430,7 @@ class Database(object): removed. """ self._assert_db_is_initialized() - return self._remove_message(self._db, filename) + return self._remove_message(self._db, _str(filename)) def find_message(self, msgid): """Returns a :class:`Message` as identified by its message ID @@ -446,7 +453,7 @@ class Database(object): the database was not intitialized. """ self._assert_db_is_initialized() - msg_p = c_void_p() + msg_p = NotmuchMessageP() status = Database._find_message(self._db, _str(msgid), byref(msg_p)) if status != STATUS.SUCCESS: raise NotmuchError(status) @@ -455,10 +462,11 @@ class Database(object): def find_message_by_filename(self, filename): """Find a message with the given filename - .. warning:: This call needs a writeable database in - :attr:`Database.MODE`.READ_WRITE mode. The underlying library will - exit the program if this method is used on a read-only - database! + .. warning:: + + This call needs a writeable database in + :attr:`Database.MODE`.READ_WRITE mode. The underlying library will + exit the program if this method is used on a read-only database! :returns: If the database contains a message with the given filename, then a class:`Message:` is returned. This @@ -479,7 +487,7 @@ class Database(object): *Added in notmuch 0.9*""" self._assert_db_is_initialized() - msg_p = c_void_p() + msg_p = NotmuchMessageP() status = Database._find_message_by_filename(self._db, _str(filename), byref(msg_p)) if status != STATUS.SUCCESS: @@ -490,7 +498,8 @@ class Database(object): """Returns :class:`Tags` with a list of all tags found in the database :returns: :class:`Tags` - :execption: :exc:`NotmuchError` with :attr:`STATUS`.NULL_POINTER on error + :execption: :exc:`NotmuchError` with :attr:`STATUS`.NULL_POINTER + on error """ self._assert_db_is_initialized() tags_p = Database._get_all_tags(self._db) @@ -534,7 +543,13 @@ class Database(object): """ Reads a user's notmuch config and returns his db location Throws a NotmuchError if it cannot find it""" - from ConfigParser import SafeConfigParser + try: + # python3.x + from configparser import SafeConfigParser + except ImportError: + # python2.x + from ConfigParser import SafeConfigParser + config = SafeConfigParser() conf_f = os.getenv('NOTMUCH_CONFIG', os.path.expanduser('~/.notmuch-config')) @@ -748,7 +763,8 @@ class Directory(object): _get_child_directories.restype = NotmuchFilenamesP def _assert_dir_is_initialized(self): - """Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None""" + """Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) + if dir_p is None""" if self._dir_p is None: raise NotmuchError(STATUS.NOT_INITIALIZED) @@ -785,10 +801,12 @@ class Directory(object): and know that it only needs to add files if the mtime of the directory and files are newer than the stored timestamp. - .. note:: :meth:`get_mtime` function does not allow the caller - to distinguish a timestamp of 0 from a non-existent - timestamp. So don't store a timestamp of 0 unless you are - comfortable with that. + .. note:: + + :meth:`get_mtime` function does not allow the caller to + distinguish a timestamp of 0 from a non-existent timestamp. So + don't store a timestamp of 0 unless you are comfortable with + that. :param mtime: A (time_t) timestamp :returns: Nothing on success, raising an exception on failure. @@ -907,7 +925,7 @@ class Filenames(object): _move_to_next.argtypes = [NotmuchFilenamesP] _move_to_next.restype = None - def next(self): + def __next__(self): if self._files_p is None: raise NotmuchError(STATUS.NOT_INITIALIZED) @@ -915,20 +933,24 @@ class Filenames(object): self._files_p = None raise StopIteration - file = Filenames._get(self._files_p) + file_ = Filenames._get(self._files_p) self._move_to_next(self._files_p) - return file + return file_.decode('utf-8', errors='ignore') + next = __next__ # python2.x iterator protocol compatibility def __len__(self): """len(:class:`Filenames`) returns the number of contained files - .. note:: As this iterates over the files, we will not be able to - iterate over them again! So this will fail:: + .. note:: + + As this iterates over the files, we will not be able to + iterate over them again! So this will fail:: #THIS FAILS files = Database().get_directory('').get_child_files() - if len(files) > 0: #this 'exhausts' msgs - # next line raises NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)!!! + if len(files) > 0: # this 'exhausts' msgs + # next line raises + # NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) for file in files: print file """ if self._files_p is None: