def get_directory(self, path): """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. """ self._assert_db_is_initialized() # sanity checking if path is valid, and make path absolute if 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.") abs_dirpath = path else: #we got a relative path, make it absolute abs_dirpath = os.path.abspath(os.path.join(self.get_path(), path)) 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)
def create(self, path): """Creates a new notmuch database This function is used by __init__() and usually does not need to be called directly. It wraps the underlying *notmuch_database_create* function and creates a new notmuch database at *path*. It will always return a database in :attr:`MODE` .READ_WRITE mode as creating an empty database for reading only does not make a great deal of sense. :param path: A directory in which we should create the database. :type path: str :returns: Nothing :exception: :exc:`NotmuchError` in case of any failure (possibly after printing an error message on stderr). """ if self._db is not None: raise NotmuchError(message="Cannot create db, this Database() " "already has an open one.") res = Database._create(_str(path), Database.MODE.READ_WRITE) if not res: raise NotmuchError( message="Could not create the specified database") self._db = res
def get_header(self, header): """Get the value of the specified header. The value will be read from the actual message file, not from the notmuch database. The header name is case insensitive. Returns an empty string ("") if the message does not contain a header line matching 'header'. :param header: The name of the header to be retrieved. It is not case-sensitive. :type header: str :returns: The header value as string :exception: :exc:`NotmuchError` * STATUS.NOT_INITIALIZED if the message is not initialized. * STATUS.NULL_POINTER if any error occured. """ if self._msg is None: raise NotmuchError(STATUS.NOT_INITIALIZED) #Returns NULL if any error occurs. header = Message._get_header(self._msg, _str(header)) if header == None: raise NotmuchError(STATUS.NULL_POINTER) return header.decode('UTF-8', 'ignore')
def create(self, db, querystr): """Creates a new query derived from a Database This function is utilized by __init__() and usually does not need to be called directly. :param db: Database to create the query from. :type db: :class:`Database` :param querystr: The query string :type querystr: utf-8 encoded str or unicode :returns: Nothing :exception: :exc:`NullPointerError` if the query creation failed (e.g. too little memory). :exc:`NotInitializedError` if the underlying db was not intitialized. """ db._assert_db_is_initialized() # create reference to parent db to keep it alive self._db = db # create query, return None if too little mem available query_p = Query._create(db.db_p, _str(querystr)) if query_p is None: raise NullPointerError self._query = query_p
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. *Added in notmuch 0.9*""" self._assert_db_is_initialized() msg_p = c_void_p() status = Database._find_message_by_filename(self._db, _str(filename), byref(msg_p)) if status != STATUS.SUCCESS: raise NotmuchError(status) return msg_p and Message(msg_p, self) or None
def find_message(self, msgid): """Returns a :class:`Message` as identified by its message ID Wraps the underlying *notmuch_database_find_message* function. :param msgid: The message ID :type msgid: unicode or str :returns: :class:`Message` or `None` if no message is found. :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. """ self._assert_db_is_initialized() msg_p = c_void_p() status = Database._find_message(self._db, _str(msgid), byref(msg_p)) if status != STATUS.SUCCESS: raise NotmuchError(status) return msg_p and Message(msg_p, self) or None
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. *Added in notmuch 0.9*""" self._assert_db_is_initialized() msg_p = NotmuchMessageP() status = Database._find_message_by_filename(self._db, _str(filename), byref(msg_p)) if status != STATUS.SUCCESS: raise NotmuchError(status) return msg_p and Message(msg_p, self) or None
def remove_message(self, filename): """Removes a message (filename) from the given notmuch database Note that only this particular filename association is removed from the database. If the same message (as determined by the message ID) is still available via other filenames, then the message will persist in the database for those filenames. When the last filename is removed for a particular message, the database content for that message will be entirely removed. :returns: A :attr:`STATUS` value with the following meaning: :attr:`STATUS`.SUCCESS The last filename was removed and the message was removed from the database. :attr:`STATUS`.DUPLICATE_MESSAGE_ID 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. If such an exception occurs, nothing was removed from the database. :attr:`STATUS`.READ_ONLY_DATABASE Database was opened in read-only mode so no message can be removed. """ self._assert_db_is_initialized() return self._remove_message(self._db, _str(filename))
def create(self, db, querystr): """Creates a new query derived from a Database This function is utilized by __init__() and usually does not need to be called directly. :param db: Database to create the query from. :type db: :class:`Database` :param querystr: The query string :type querystr: utf-8 encoded str or unicode :returns: Nothing :exception: :exc:`NotmuchError` * :attr:`STATUS`.NOT_INITIALIZED if db is not inited * :attr:`STATUS`.NULL_POINTER if the query creation failed (too little memory) """ if db.db_p is None: raise NotmuchError(STATUS.NOT_INITIALIZED) # create reference to parent db to keep it alive self._db = db # create query, return None if too little mem available query_p = Query._create(db.db_p, _str(querystr)) if query_p is None: raise NotmuchError(STATUS.NULL_POINTER) self._query = query_p
def create(self, db, querystr): """Creates a new query derived from a Database This function is utilized by __init__() and usually does not need to be called directly. :param db: Database to create the query from. :type db: :class:`Database` :param querystr: The query string :type querystr: utf-8 encoded str or unicode :returns: Nothing :exception: :exc:`NullPointerError` if the query creation failed (e.g. too little memory). :exc:`NotInitializedError` if the underlying db was not intitialized. """ db._assert_db_is_initialized() # create reference to parent db to keep it alive self._db = db # create query, return None if too little mem available query_p = Query._create(db.db_p, _str(querystr)) if not query_p: raise NullPointerError self._query = query_p
def create(self, path): """Creates a new notmuch database This function is used by __init__() and usually does not need to be called directly. It wraps the underlying *notmuch_database_create* function and creates a new notmuch database at *path*. It will always return a database in :attr:`MODE` .READ_WRITE mode as creating an empty database for reading only does not make a great deal of sense. :param path: A directory in which we should create the database. :type path: str :returns: Nothing :exception: :exc:`NotmuchError` in case of any failure (after printing an error message on stderr). """ if self._db is not None: raise NotmuchError(message="Cannot create db, this Database() " "already has an open one.") res = Database._create(_str(path), Database.MODE.READ_WRITE) if res is None: raise NotmuchError( message="Could not create the specified database") self._db = res
def find_message(self, msgid): """Returns a :class:`Message` as identified by its message ID Wraps the underlying *notmuch_database_find_message* function. :param msgid: The message ID :type msgid: unicode or str :returns: :class:`Message` or `None` if no message is found. :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. """ self._assert_db_is_initialized() msg_p = NotmuchMessageP() status = Database._find_message(self._db, _str(msgid), byref(msg_p)) if status != STATUS.SUCCESS: raise NotmuchError(status) return msg_p and Message(msg_p, self) or None
def open(self, path, mode=0): """Opens an existing database This function is used by __init__() and usually does not need to be called directly. It wraps the underlying *notmuch_database_open* function. :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 (after printing an error message on stderr). """ res = Database._open(_str(path), mode) if res is None: raise NotmuchError(message="Could not open the specified database") self._db = res
def open(self, path, mode=0): """Opens an existing database This function is used by __init__() and usually does not need to be called directly. It wraps the underlying *notmuch_database_open* function. :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). """ res = Database._open(_str(path), mode) if not res: raise NotmuchError(message="Could not open the specified database") self._db = res
def add_tag(self, tag, sync_maildir_flags=False): """Adds a tag to the given message Adds a tag to the current message. The maximal tag length is defined in the notmuch library and is currently 200 bytes. :param tag: String with a 'tag' to be added. :param sync_maildir_flags: If notmuch configuration is set to do this, add maildir flags corresponding to notmuch tags. See underlying method :meth:`tags_to_maildir_flags`. Use False if you want to add/remove many tags on a message without having to physically rename the file every time. Do note, that this will do nothing when a message is frozen, as tag changes will not be committed to the database yet. :returns: STATUS.SUCCESS if the tag was successfully added. Raises an exception otherwise. :exception: :exc:`NotmuchError`. They have the following meaning: STATUS.NULL_POINTER The 'tag' argument is NULL STATUS.TAG_TOO_LONG The length of 'tag' is too long (exceeds Message.NOTMUCH_TAG_MAX) STATUS.READ_ONLY_DATABASE Database was opened in read-only mode so message cannot be modified. STATUS.NOT_INITIALIZED The message has not been initialized. """ if self._msg is None: raise NotmuchError(STATUS.NOT_INITIALIZED) status = self._add_tag(self._msg, _str(tag)) # bail out on failure if status != STATUS.SUCCESS: raise NotmuchError(status) if sync_maildir_flags: self.tags_to_maildir_flags() return STATUS.SUCCESS
def add_tag(self, tag, sync_maildir_flags=False): """Adds a tag to the given message Adds a tag to the current message. The maximal tag length is defined in the notmuch library and is currently 200 bytes. :param tag: String with a 'tag' to be added. :param sync_maildir_flags: If notmuch configuration is set to do this, add maildir flags corresponding to notmuch tags. See underlying method :meth:`tags_to_maildir_flags`. Use False if you want to add/remove many tags on a message without having to physically rename the file every time. Do note, that this will do nothing when a message is frozen, as tag changes will not be committed to the database yet. :returns: STATUS.SUCCESS if the tag was successfully added. Raises an exception otherwise. :exception: :exc:`NotmuchError`. They have the following meaning: STATUS.NULL_POINTER The 'tag' argument is NULL STATUS.TAG_TOO_LONG The length of 'tag' is too long (exceeds Message.NOTMUCH_TAG_MAX) STATUS.READ_ONLY_DATABASE Database was opened in read-only mode so message cannot be modified. STATUS.NOT_INITIALIZED The message has not been initialized. """ if self._msg is None: raise NotmuchError(STATUS.NOT_INITIALIZED) status = nmlib.notmuch_message_add_tag(self._msg, _str(tag)) # bail out on failure if status != STATUS.SUCCESS: raise NotmuchError(status) if sync_maildir_flags: self.tags_to_maildir_flags() return STATUS.SUCCESS
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 in the following situations: * No message is found with the given filename * An out-of-memory situation occurs * A Xapian exception occurs *Added in notmuch 0.9*""" self._assert_db_is_initialized() msg_p = Database._find_message_by_filename(self._db, _str(filename)) return msg_p and Message(msg_p, self) or None
def find_message(self, msgid): """Returns a :class:`Message` as identified by its message ID Wraps the underlying *notmuch_database_find_message* function. :param msgid: The message ID :type msgid: string :returns: :class:`Message` or `None` if no message is found or if any xapian exception or out-of-memory situation occurs. Do note that Xapian Exceptions include "Database modified" situations, e.g. when the notmuch database has been modified by another program in the meantime. A return value of `None` is therefore no guarantee that the message does not exist. :exception: :exc:`NotmuchError` with :attr:`STATUS`.NOT_INITIALIZED if the database was not intitialized. """ self._assert_db_is_initialized() msg_p = Database._find_message(self._db, _str(msgid)) return msg_p and Message(msg_p, self) or None
def add_message(self, filename, sync_maildir_flags=False): """Adds a new message to the database :param filename: should be a path relative to the path of the open database (see :meth:`get_path`), or else should be an absolute filename with initial components that match the path of the database. The file should be a single mail message (not a multi-message mbox) that is expected to remain at its current location, since the notmuch database will reference the filename, and will not copy the entire contents of the file. :param sync_maildir_flags: If the message contains Maildir flags, we will -depending on the notmuch configuration- sync those tags to initial notmuch tags, if set to `True`. It is `False` by default to remain consistent with the libnotmuch API. You might want to look into the underlying method :meth:`Message.maildir_flags_to_tags`. :returns: On success, we return 1) a :class:`Message` object that can be used for things such as adding tags to the just-added message. 2) one of the following :attr:`STATUS` values: :attr:`STATUS`.SUCCESS Message successfully added to database. :attr:`STATUS`.DUPLICATE_MESSAGE_ID Message has the same message ID as another message already in the database. The new filename was successfully added to the list of the filenames for the existing message. :rtype: 2-tuple(:class:`Message`, :attr:`STATUS`) :exception: Raises a :exc:`NotmuchError` with the following meaning. If such an exception occurs, nothing was added to the database. :attr:`STATUS`.FILE_ERROR An error occurred trying to open the file, (such as permission denied, or file not found, etc.). :attr:`STATUS`.FILE_NOT_EMAIL The contents of filename don't look like an email message. :attr:`STATUS`.READ_ONLY_DATABASE Database was opened in read-only mode so no message can be added. :attr:`STATUS`.NOT_INITIALIZED The database has not been initialized. """ self._assert_db_is_initialized() msg_p = c_void_p() status = nmlib.notmuch_database_add_message(self._db, _str(filename), byref(msg_p)) if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]: raise NotmuchError(status) #construct Message() and return msg = Message(msg_p, self) #automatic sync initial tags from Maildir flags if sync_maildir_flags: msg.maildir_flags_to_tags() return (msg, status)
def add_message(self, filename, sync_maildir_flags=False): """Adds a new message to the database :param filename: should be a path relative to the path of the open database (see :meth:`get_path`), or else should be an absolute filename with initial components that match the path of the database. The file should be a single mail message (not a multi-message mbox) that is expected to remain at its current location, since the notmuch database will reference the filename, and will not copy the entire contents of the file. :param sync_maildir_flags: If the message contains Maildir flags, we will -depending on the notmuch configuration- sync those tags to initial notmuch tags, if set to `True`. It is `False` by default to remain consistent with the libnotmuch API. You might want to look into the underlying method :meth:`Message.maildir_flags_to_tags`. :returns: On success, we return 1) a :class:`Message` object that can be used for things such as adding tags to the just-added message. 2) one of the following :attr:`STATUS` values: :attr:`STATUS`.SUCCESS Message successfully added to database. :attr:`STATUS`.DUPLICATE_MESSAGE_ID Message has the same message ID as another message already in the database. The new filename was successfully added to the list of the filenames for the existing message. :rtype: 2-tuple(:class:`Message`, :attr:`STATUS`) :exception: Raises a :exc:`NotmuchError` with the following meaning. If such an exception occurs, nothing was added to the database. :attr:`STATUS`.FILE_ERROR An error occurred trying to open the file, (such as permission denied, or file not found, etc.). :attr:`STATUS`.FILE_NOT_EMAIL The contents of filename don't look like an email message. :attr:`STATUS`.READ_ONLY_DATABASE Database was opened in read-only mode so no message can be added. """ self._assert_db_is_initialized() msg_p = NotmuchMessageP() status = self._add_message(self._db, _str(filename), byref(msg_p)) if not status in [STATUS.SUCCESS, STATUS.DUPLICATE_MESSAGE_ID]: raise NotmuchError(status) #construct Message() and return msg = Message(msg_p, self) #automatic sync initial tags from Maildir flags if sync_maildir_flags: msg.maildir_flags_to_tags() return (msg, status)