X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;ds=sidebyside;f=bindings%2Fpython%2Fnotmuch%2Fdatabase.py;h=a054be76e1ba4a72ee8d678b3950fa659508cb01;hb=1736488ecfd9b18a380ce04ac2df0303c0ea3c80;hp=6edb18b69d845514dbbe5ad9e7a960e96ad4b184;hpb=be851ad39de11f38e1cd4f7f15f1fa952232efe2;p=notmuch diff --git a/bindings/python/notmuch/database.py b/bindings/python/notmuch/database.py index 6edb18b6..a054be76 100644 --- a/bindings/python/notmuch/database.py +++ b/bindings/python/notmuch/database.py @@ -23,8 +23,11 @@ from ctypes import c_char_p, c_void_p, c_uint, c_long, byref, POINTER from notmuch.globals import ( nmlib, STATUS, + FileError, NotmuchError, + NullPointerError, NotInitializedError, + ReadOnlyDatabaseError, Enum, _str, NotmuchDatabaseP, @@ -120,7 +123,8 @@ class Database(object): _create.argtypes = [c_char_p] _create.restype = NotmuchDatabaseP - def __init__(self, path=None, create=False, mode=0): + def __init__(self, path = None, create = False, + mode = MODE.READ_ONLY): """If *path* is `None`, we will try to read a users notmuch configuration and use his configured database. The location of the configuration file can be specified through the environment variable @@ -138,10 +142,11 @@ class Database(object): :param mode: Mode to open a database in. Is always :attr:`MODE`.READ_WRITE when creating a new one. :type mode: :attr:`MODE` - :exception: :exc:`NotmuchError` or derived exception in case of + :raises: :exc:`NotmuchError` or derived exception in case of failure. """ self._db = None + self.mode = mode if path is None: # no path specified. use a user's default database if Database._std_db_path is None: @@ -174,8 +179,7 @@ class Database(object): :param path: A directory in which we should create the database. :type path: str - :returns: Nothing - :exception: :exc:`NotmuchError` in case of any failure + :raises: :exc:`NotmuchError` in case of any failure (possibly after printing an error message on stderr). """ if self._db is not None: @@ -198,8 +202,7 @@ 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 + :raises: Raises :exc:`NotmuchError` in case of any failure (possibly after printing an error message on stderr). """ res = Database._open(_str(path), mode) @@ -294,7 +297,7 @@ 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 + :raises: :exc:`NotmuchError`: :attr:`STATUS`.XAPIAN_EXCEPTION Xapian exception occurred; atomic section not entered. *Added in notmuch 0.9*""" @@ -315,7 +318,7 @@ class Database(object): :returns: :attr:`STATUS`.SUCCESS or raises - :exception: + :raises: :exc:`NotmuchError`: :attr:`STATUS`.XAPIAN_EXCEPTION A Xapian exception occurred; atomic section not @@ -334,30 +337,31 @@ 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! - :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'. :returns: :class:`Directory` or raises an exception. - :exception: - :exc:`NotmuchError` with :attr:`STATUS`.FILE_ERROR - If path is not relative database or absolute with initial - components same as database. + :raises: :exc:`FileError` if path is not relative database or absolute + with initial components same as database. + :raises: :exc:`ReadOnlyDatabaseError` if the database has not been + opened in read-write mode """ self._assert_db_is_initialized() + + # work around libnotmuch calling exit(3), see + # id:20120221002921.8534.57091@thinkbox.jade-hamburg.de + # TODO: remove once this issue is resolved + if self.mode != Database.MODE.READ_WRITE: + raise ReadOnlyDatabaseError('The database has to be opened in ' + 'read-write mode for get_directory') + # sanity checking if path is valid, and make path absolute - if path[0] == os.sep: + if path and path[0] == os.sep: # we got an absolute path if not path.startswith(self.get_path()): # but its initial components are not equal to the db path - raise NotmuchError(STATUS.FILE_ERROR, - message="Database().get_directory() called " - "with a wrong absolute path.") + raise FileError('Database().get_directory() called ' + 'with a wrong absolute path') abs_dirpath = path else: #we got a relative path, make it absolute @@ -366,7 +370,7 @@ class Database(object): dir_p = Database._get_directory(self._db, _str(path)) # return the Directory, init it with the absolute path - return Directory(_str(abs_dirpath), dir_p, self) + return Directory(abs_dirpath, dir_p, self) _add_message = nmlib.notmuch_database_add_message _add_message.argtypes = [NotmuchDatabaseP, c_char_p, @@ -409,7 +413,7 @@ class Database(object): :rtype: 2-tuple(:class:`Message`, :attr:`STATUS`) - :exception: Raises a :exc:`NotmuchError` with the following meaning. + :raises: Raises a :exc:`NotmuchError` with the following meaning. If such an exception occurs, nothing was added to the database. :attr:`STATUS`.FILE_ERROR @@ -459,7 +463,7 @@ class Database(object): This filename was removed but the message persists in the database with at least one other filename. - :exception: Raises a :exc:`NotmuchError` with the following meaning. + :raises: Raises a :exc:`NotmuchError` with the following meaning. If such an exception occurs, nothing was removed from the database. @@ -478,7 +482,7 @@ class Database(object): :param msgid: The message ID :type msgid: unicode or str :returns: :class:`Message` or `None` if no message is found. - :exception: + :raises: :exc:`OutOfMemoryError` If an Out-of-memory occured while constructing the message. :exc:`XapianError` @@ -500,31 +504,34 @@ 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! - :returns: If the database contains a message with the given filename, then a class:`Message:` is returned. This function returns None if no message is found with the given filename. - :exception: - :exc:`OutOfMemoryError` - If an Out-of-memory occured while constructing the message. - :exc:`XapianError` - In case of a Xapian Exception. These exceptions - include "Database modified" situations, e.g. when the - notmuch database has been modified by another program - in the meantime. In this case, you should close and - reopen the database and retry. - :exc:`NotInitializedError` if - the database was not intitialized. + :raises: :exc:`OutOfMemoryError` if an Out-of-memory occured while + constructing the message. + :raises: :exc:`XapianError` in case of a Xapian Exception. + These exceptions include "Database modified" + situations, e.g. when the notmuch database has been + modified by another program in the meantime. In this + case, you should close and reopen the database and + retry. + :raises: :exc:`NotInitializedError` if the database was not + intitialized. + :raises: :exc:`ReadOnlyDatabaseError` if the database has not been + opened in read-write mode *Added in notmuch 0.9*""" self._assert_db_is_initialized() + + # work around libnotmuch calling exit(3), see + # id:20120221002921.8534.57091@thinkbox.jade-hamburg.de + # TODO: remove once this issue is resolved + if self.mode != Database.MODE.READ_WRITE: + raise ReadOnlyDatabaseError('The database has to be opened in ' + 'read-write mode for get_directory') + msg_p = NotmuchMessageP() status = Database._find_message_by_filename(self._db, _str(filename), byref(msg_p)) @@ -542,7 +549,7 @@ class Database(object): self._assert_db_is_initialized() tags_p = Database._get_all_tags(self._db) if tags_p == None: - raise NotmuchError(STATUS.NULL_POINTER) + raise NullPointerError() return Tags(tags_p, self) def create_query(self, querystring): @@ -636,11 +643,11 @@ class Directory(object): """Raises a NotmuchError(:attr:`STATUS`.NOT_INITIALIZED) if dir_p is None""" if not self._dir_p: - raise NotmuchError(STATUS.NOT_INITIALIZED) + raise NotInitializedError() def __init__(self, path, dir_p, parent): """ - :param path: The absolute path of the directory object as unicode. + :param path: The absolute path of the directory object. :param dir_p: The pointer to an internal notmuch_directory_t object. :param parent: The object this Directory is derived from (usually a :class:`Database`). We do not directly use @@ -648,7 +655,6 @@ class Directory(object): this Directory object lives. This keeps the parent object alive. """ - assert isinstance(path, unicode), "Path needs to be an UNICODE object" self._path = path self._dir_p = dir_p self._parent = parent @@ -678,27 +684,19 @@ class Directory(object): 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. - :exception: :exc:`NotmuchError`: - - :attr:`STATUS`.XAPIAN_EXCEPTION - A Xapian exception occurred, mtime not stored. - :attr:`STATUS`.READ_ONLY_DATABASE - Database was opened in read-only mode so directory - mtime cannot be modified. - :attr:`STATUS`.NOT_INITIALIZED - The directory has not been initialized + :param mtime: A (time_t) timestamp + :raises: :exc:`XapianError` a Xapian exception occurred, mtime + not stored + :raises: :exc:`ReadOnlyDatabaseError` the database was opened + in read-only mode so directory mtime cannot be modified + :raises: :exc:`NotInitializedError` the directory object has not + been initialized """ self._assert_dir_is_initialized() - #TODO: make sure, we convert the mtime parameter to a 'c_long' status = Directory._set_mtime(self._dir_p, mtime) - #return on success - if status == STATUS.SUCCESS: - return - #fail with Exception otherwise - raise NotmuchError(status) + if status != STATUS.SUCCESS: + raise NotmuchError(status) def get_mtime(self): """Gets the mtime value of this directory in the database @@ -706,8 +704,7 @@ class Directory(object): Retrieves a previously stored mtime for this directory. :param mtime: A (time_t) timestamp - :returns: Nothing on success, raising an exception on failure. - :exception: :exc:`NotmuchError`: + :raises: :exc:`NotmuchError`: :attr:`STATUS`.NOT_INITIALIZED The directory has not been initialized @@ -797,7 +794,7 @@ class Filenames(object): def __next__(self): if not self._files_p: - raise NotmuchError(STATUS.NOT_INITIALIZED) + raise NotInitializedError() if not self._valid(self._files_p): self._files_p = None @@ -824,7 +821,7 @@ class Filenames(object): for file in files: print file """ if not self._files_p: - raise NotmuchError(STATUS.NOT_INITIALIZED) + raise NotInitializedError() i = 0 while self._valid(self._files_p):