X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=bindings%2Fpython-cffi%2Fnotmuch2%2F_database.py;h=fc55fea8f50bd0260c377dde7fd69919875fe02c;hp=a15c4d0324576261c89a71d59de5edd217314b91;hb=131757907907380213b32934d9e73cec942ace43;hpb=e2df30f7a98f91543d0b3561dbb366eb4b3d812c diff --git a/bindings/python-cffi/notmuch2/_database.py b/bindings/python-cffi/notmuch2/_database.py index a15c4d03..fc55fea8 100644 --- a/bindings/python-cffi/notmuch2/_database.py +++ b/bindings/python-cffi/notmuch2/_database.py @@ -7,6 +7,7 @@ import pathlib import weakref import notmuch2._base as base +import notmuch2._config as config import notmuch2._capi as capi import notmuch2._errors as errors import notmuch2._message as message @@ -45,6 +46,13 @@ class QueryExclude(enum.Enum): ALL = capi.lib.NOTMUCH_EXCLUDE_ALL +class DecryptionPolicy(enum.Enum): + FALSE = capi.lib.NOTMUCH_DECRYPT_FALSE + TRUE = capi.lib.NOTMUCH_DECRYPT_TRUE + AUTO = capi.lib.NOTMUCH_DECRYPT_AUTO + NOSTASH = capi.lib.NOTMUCH_DECRYPT_NOSTASH + + class Database(base.NotmuchObject): """Toplevel access to notmuch. @@ -255,7 +263,7 @@ class Database(base.NotmuchObject): This is returned as a :class:`pathlib.Path` instance. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ try: return self._cache_path @@ -270,7 +278,7 @@ class Database(base.NotmuchObject): This is a positive integer. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ try: return self._cache_version @@ -289,7 +297,7 @@ class Database(base.NotmuchObject): A read-only database will never be upgradable. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ ret = capi.lib.notmuch_database_needs_upgrade(self._db_p) return bool(ret) @@ -313,7 +321,7 @@ class Database(base.NotmuchObject): not imply durability, it only ensures the changes are performed atomically. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ ctx = AtomicContext(self, '_db_p') return ctx @@ -323,7 +331,7 @@ class Database(base.NotmuchObject): Returned as a ``(revision, uuid)`` namedtuple. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ raw_uuid = capi.ffi.new('char**') rev = capi.lib.notmuch_database_get_revision(self._db_p, raw_uuid) @@ -332,7 +340,17 @@ class Database(base.NotmuchObject): def get_directory(self, path): raise NotImplementedError - def add(self, filename, *, sync_flags=False): + def default_indexopts(self): + """Returns default index options for the database. + + :raises ObjectDestroyedError: if used after destroyed. + + :returns: :class:`IndexOptions`. + """ + opts = capi.lib.notmuch_database_get_default_indexopts(self._db_p) + return IndexOptions(self, opts) + + def add(self, filename, *, sync_flags=False, indexopts=None): """Add a message to the database. Add a new message to the notmuch database. The message is @@ -346,6 +364,11 @@ class Database(base.NotmuchObject): :param sync_flags: Whether to sync the known maildir flags to notmuch tags. See :meth:`Message.flags_to_tags` for details. + :type sync_flags: bool + :param indexopts: The indexing options, see + :meth:`default_indexopts`. Leave as `None` to use the + default options configured in the database. + :type indexopts: :class:`IndexOptions` or `None` :returns: A tuple where the first item is the newly inserted messages as a :class:`Message` instance, and the second @@ -365,19 +388,19 @@ class Database(base.NotmuchObject): READ_ONLY mode. :raises UpgradeRequiredError: The database must be upgraded first. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ if not hasattr(os, 'PathLike') and isinstance(filename, pathlib.Path): filename = bytes(filename) msg_pp = capi.ffi.new('notmuch_message_t **') - ret = capi.lib.notmuch_database_add_message(self._db_p, - os.fsencode(filename), - msg_pp) + opts_p = indexopts._opts_p if indexopts else capi.ffi.NULL + ret = capi.lib.notmuch_database_index_file( + self._db_p, os.fsencode(filename), opts_p, msg_pp) ok = [capi.lib.NOTMUCH_STATUS_SUCCESS, capi.lib.NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID] if ret not in ok: raise errors.NotmuchError(ret) - msg = message.Message(self, msg_pp[0], db=self) + msg = message.StandaloneMessage(self, msg_pp[0], db=self) if sync_flags: msg.tags.from_maildir_flags() return self.AddedMessage( @@ -404,7 +427,7 @@ class Database(base.NotmuchObject): READ_ONLY mode. :raises UpgradeRequiredError: The database must be upgraded first. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ if not hasattr(os, 'PathLike') and isinstance(filename, pathlib.Path): filename = bytes(filename) @@ -436,7 +459,7 @@ class Database(base.NotmuchObject): :raises OutOfMemoryError: When there is no memory to allocate the message instance. :raises XapianError: A Xapian exception ocurred. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ msg_pp = capi.ffi.new('notmuch_message_t **') ret = capi.lib.notmuch_database_find_message(self._db_p, @@ -446,7 +469,7 @@ class Database(base.NotmuchObject): msg_p = msg_pp[0] if msg_p == capi.ffi.NULL: raise LookupError - msg = message.Message(self, msg_p, db=self) + msg = message.StandaloneMessage(self, msg_p, db=self) return msg def get(self, filename): @@ -467,7 +490,7 @@ class Database(base.NotmuchObject): :raises OutOfMemoryError: When there is no memory to allocate the message instance. :raises XapianError: A Xapian exception ocurred. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ if not hasattr(os, 'PathLike') and isinstance(filename, pathlib.Path): filename = bytes(filename) @@ -479,7 +502,7 @@ class Database(base.NotmuchObject): msg_p = msg_pp[0] if msg_p == capi.ffi.NULL: raise LookupError - msg = message.Message(self, msg_p, db=self) + msg = message.StandaloneMessage(self, msg_p, db=self) return msg @property @@ -500,7 +523,7 @@ class Database(base.NotmuchObject): :rtype: ImmutableTagSet - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ try: ref = self._cached_tagset @@ -514,6 +537,28 @@ class Database(base.NotmuchObject): self._cached_tagset = weakref.ref(tagset) return tagset + @property + def config(self): + """Return a mutable mapping with the settings stored in this database. + + This returns an mutable dict-like object implementing the + collections.abc.MutableMapping Abstract Base Class. + + :rtype: Config + + :raises ObjectDestroyedError: if used after destroyed. + """ + try: + ref = self._cached_config + except AttributeError: + config_mapping = None + else: + config_mapping = ref() + if config_mapping is None: + config_mapping = config.ConfigMapping(self, '_db_p') + self._cached_config = weakref.ref(config_mapping) + return config_mapping + def _create_query(self, query, *, omit_excluded=EXCLUDE.TRUE, sort=SORT.UNSORTED, # Check this default @@ -548,7 +593,7 @@ class Database(base.NotmuchObject): :raises OutOfMemoryError: if no memory is available to allocate the query. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ query = self._create_query(query, omit_excluded=omit_excluded, @@ -565,7 +610,7 @@ class Database(base.NotmuchObject): :returns: An iterator over the messages found. :rtype: MessageIter - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ query = self._create_query(query, omit_excluded=omit_excluded, @@ -613,7 +658,7 @@ class AtomicContext: section is not active. When it is raised at exit time the atomic section is still active and you may need to try using :meth:`force_end`. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ def __init__(self, db, ptr_name): @@ -653,7 +698,7 @@ class AtomicContext: not ended. :raises UnbalancedAtomicError: If the database was currently not in an atomic section. - :raises ObjectDestroyedError: if used after destoryed. + :raises ObjectDestroyedError: if used after destroyed. """ ret = capi.lib.notmuch_database_end_atomic(self._ptr()) if ret != capi.lib.NOTMUCH_STATUS_SUCCESS: @@ -703,3 +748,61 @@ class DbRevision: def __repr__(self): return 'DbRevision(rev={self.rev}, uuid={self.uuid})'.format(self=self) + + +class IndexOptions(base.NotmuchObject): + """Indexing options. + + This represents the indexing options which can be used to index a + message. See :meth:`Database.default_indexopts` to create an + instance of this. It can be used e.g. when indexing a new message + using :meth:`Database.add`. + """ + _opts_p = base.MemoryPointer() + + def __init__(self, parent, opts_p): + self._parent = parent + self._opts_p = opts_p + + @property + def alive(self): + if not self._parent.alive: + return False + try: + self._opts_p + except errors.ObjectDestroyedError: + return False + else: + return True + + def _destroy(self): + if self.alive: + capi.lib.notmuch_indexopts_destroy(self._opts_p) + self._opts_p = None + + @property + def decrypt_policy(self): + """The decryption policy. + + This is an enum from the :class:`DecryptionPolicy`. See the + `index.decrypt` section in :man:`notmuch-config` for details + on the options. **Do not set this to + :attr:`DecryptionPolicy.TRUE`** without considering the + security of your index. + + You can change this policy by assigning a new + :class:`DecryptionPolicy` to this property. + + :raises ObjectDestroyedError: if used after destroyed. + + :returns: A :class:`DecryptionPolicy` enum instance. + """ + raw = capi.lib.notmuch_indexopts_get_decrypt_policy(self._opts_p) + return DecryptionPolicy(raw) + + @decrypt_policy.setter + def decrypt_policy(self, val): + ret = capi.lib.notmuch_indexopts_set_decrypt_policy( + self._opts_p, val.value) + if ret != capi.lib.NOTMUCH_STATUS_SUCCESS: + raise errors.NotmuchError(ret, msg)