X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=bindings%2Fpython-cffi%2Fnotmuch2%2F_message.py;h=d4b34e91e2f88ff367a73cfa5b311d11cbfa6b9a;hb=HEAD;hp=c5fdbf6df94a635853d45daf18feec7b51550467;hpb=93cc4b99dff2dea1f4af3b39f1864eb976c37648;p=notmuch diff --git a/bindings/python-cffi/notmuch2/_message.py b/bindings/python-cffi/notmuch2/_message.py index c5fdbf6d..79485238 100644 --- a/bindings/python-cffi/notmuch2/_message.py +++ b/bindings/python-cffi/notmuch2/_message.py @@ -14,7 +14,7 @@ __all__ = ['Message'] class Message(base.NotmuchObject): - """An email message stored in the notmuch database. + """An email message stored in the notmuch database retrieved via a query. This should not be directly created, instead it will be returned by calling methods on :class:`Database`. A message keeps a @@ -26,7 +26,7 @@ class Message(base.NotmuchObject): package from Python's standard library. You could e.g. create this as such:: - notmuch_msg = db.get_message(msgid) # or from a query + notmuch_msg = db.find(msgid) # or from a query parser = email.parser.BytesParser(policy=email.policy.default) with notmuch_msg.path.open('rb) as fp: email_msg = parser.parse(fp) @@ -47,9 +47,7 @@ class Message(base.NotmuchObject): :type db: Database :param msg_p: The C pointer to the ``notmuch_message_t``. :type msg_p: - :param dup: Whether the message was a duplicate on insertion. - :type dup: None or bool """ _msg_p = base.MemoryPointer() @@ -82,12 +80,6 @@ class Message(base.NotmuchObject): def messageid(self): """The message ID as a string. - The message ID is decoded with the ignore error handler. This - is fine as long as the message ID is well formed. If it is - not valid ASCII then this will be lossy. So if you need to be - able to write the exact same message ID back you should use - :attr:`messageidb`. - Note that notmuch will decode the message ID value and thus strip off the surrounding ``<`` and ``>`` characters. This is different from Python's :mod:`email` package behaviour which @@ -149,7 +141,7 @@ class Message(base.NotmuchObject): """Return an iterator of all files for this message. If multiple files contained the same message ID they will all - be returned here. The files are returned as intances of + be returned here. The files are returned as instances of :class:`pathlib.Path`. :returns: Iterator yielding :class:`pathlib.Path` instances. @@ -207,6 +199,20 @@ class Message(base.NotmuchObject): self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_EXCLUDED) return bool(ret) + @property + def matched(self): + """Indicates whether this message was matched by the query. + + When a thread is created from a search, some of the + messages may not match the original query. This property + is set to *True* for those that do match. + + :raises ObjectDestroyedError: if used after destroyed. + """ + ret = capi.lib.notmuch_message_get_flag( + self._msg_p, capi.lib.NOTMUCH_MESSAGE_FLAG_MATCH) + return bool(ret) + @property def date(self): """The message date as an integer. @@ -234,8 +240,7 @@ class Message(base.NotmuchObject): :param header: Case-insensitive header name to retrieve. :type header: str or bytes - :returns: The header value, an empty string if the header is - not present. + :returns: The header value. :rtype: str :raises LookupError: if the header is not present. @@ -337,9 +342,9 @@ class Message(base.NotmuchObject): and thus are only recommended if you know there to be only one value. - Instead the map has an additional :meth:`PropertiesMap.all` + Instead the map has an additional :meth:`PropertiesMap.getall` method which can be used to retrieve all properties of a given - key. This method also allows iterating of a a subset of the + key. This method also allows iterating of a subset of the keys starting with a given prefix. """ try: @@ -359,14 +364,14 @@ class Message(base.NotmuchObject): This method will only work if the message was created from a thread. Otherwise it will yield no results. - :returns: An iterator yielding :class:`Message` instances. + :returns: An iterator yielding :class:`OwnedMessage` instances. :rtype: MessageIter """ # The notmuch_messages_valid call accepts NULL and this will # become an empty iterator, raising StopIteration immediately. # Hence no return value checking here. msgs_p = capi.lib.notmuch_message_get_replies(self._msg_p) - return MessageIter(self, msgs_p, db=self._db) + return MessageIter(self, msgs_p, db=self._db, msg_cls=OwnedMessage) def __hash__(self): return hash(self.messageid) @@ -376,6 +381,26 @@ class Message(base.NotmuchObject): return self.messageid == other.messageid +class OwnedMessage(Message): + """An email message owned by parent thread object. + + This subclass of Message is used for messages that are retrieved + from the notmuch database via a parent :class:`notmuch2.Thread` + object, which "owns" this message. This means that when this + message object is destroyed, by calling :func:`del` or + :meth:`_destroy` directly or indirectly, the message is not freed + in the notmuch API and the parent :class:`notmuch2.Thread` object + can return the same object again when needed. + """ + + @property + def alive(self): + return self._parent.alive + + def _destroy(self): + pass + + class FilenamesIter(base.NotmuchIter): """Iterator for binary filenames objects.""" @@ -403,7 +428,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): """A mutable mapping to manage properties. Both keys and values of properties are supposed to be UTF-8 - strings in libnotmuch. However since the uderlying API uses + strings in libnotmuch. However since the underlying API uses bytestrings you can use either str or bytes to represent keys and all returned keys and values use :class:`BinString`. @@ -413,7 +438,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): means the former will yield duplicate keys while the latter won't. It also means ``len(list(iter(this_map)))`` could be different than ``len(this_map.keys())``. ``len(this_map)`` will correspond - with the lenght of the default iterator. + with the length of the default iterator. Be aware that libnotmuch exposes all of this as iterators, so quite a few operations have O(n) performance instead of the usual @@ -461,7 +486,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): return len(list(it)) def __getitem__(self, key): - """Return **the first** peroperty associated with a key.""" + """Return **the first** property associated with a key.""" if isinstance(key, str): key = key.encode('utf-8') value_pp = capi.ffi.new('char**') @@ -484,7 +509,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): """Return a :class:`collections.abc.ItemsView` for this map. The ItemsView treats a ``(key, value)`` pair as unique, so - dupcliate ``(key, value)`` pairs will be merged together. + duplicate ``(key, value)`` pairs will be merged together. However duplicate keys with different values will be returned. """ items = set() @@ -499,7 +524,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): return PropertiesItemsView(items) def values(self): - """Return a :class:`collecions.abc.ValuesView` for this map. + """Return a :class:`collections.abc.ValuesView` for this map. All unique property values are included in the view. """ @@ -578,7 +603,7 @@ class PropertiesMap(base.NotmuchObject, collections.abc.MutableMapping): def getall(self, prefix='', *, exact=False): """Return an iterator yielding all properties for a given key prefix. - The returned iterator yields all peroperties which start with + The returned iterator yields all properties which start with a given key prefix as ``(key, value)`` namedtuples. If called with ``exact=True`` then only properties which exactly match the prefix are returned, those a key longer than the prefix @@ -623,7 +648,6 @@ class PropertiesIter(base.NotmuchIter): def __next__(self): if not self._fn_valid(self._iter_p): - self._destroy() raise StopIteration key = capi.lib.notmuch_message_properties_key(self._iter_p) value = capi.lib.notmuch_message_properties_value(self._iter_p) @@ -678,8 +702,9 @@ collections.abc.ValuesView.register(PropertiesValuesView) class MessageIter(base.NotmuchIter): - def __init__(self, parent, msgs_p, *, db): + def __init__(self, parent, msgs_p, *, db, msg_cls=Message): self._db = db + self._msg_cls = msg_cls super().__init__(parent, msgs_p, fn_destroy=capi.lib.notmuch_messages_destroy, fn_valid=capi.lib.notmuch_messages_valid, @@ -688,4 +713,4 @@ class MessageIter(base.NotmuchIter): def __next__(self): msg_p = super().__next__() - return Message(self, msg_p, db=self._db) + return self._msg_cls(self, msg_p, db=self._db)