X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=bindings%2Fpython%2Fnotmuch%2Fmessage.py;h=e71dbe3e9933011d334d3ed18990d6fa2844693d;hp=fc177eb2b1557cb68c7c5c17bcedaf974b563869;hb=HEAD;hpb=07dff496304d6dc2e8033a18691b095ed9cd212f diff --git a/bindings/python/notmuch/message.py b/bindings/python/notmuch/message.py index fc177eb2..e71dbe3e 100644 --- a/bindings/python/notmuch/message.py +++ b/bindings/python/notmuch/message.py @@ -19,7 +19,7 @@ Copyright 2010 Sebastian Spaeth """ -from ctypes import c_char_p, c_long, c_uint, c_int +from ctypes import c_char_p, c_long, c_uint, c_int, POINTER, byref from datetime import date from .globals import ( nmlib, @@ -29,6 +29,7 @@ from .globals import ( NotmuchTagsP, NotmuchMessageP, NotmuchMessagesP, + NotmuchMessagePropertiesP, NotmuchFilenamesP, ) from .errors import ( @@ -41,10 +42,11 @@ from .tag import Tags from .filenames import Filenames import email +import sys class Message(Python3StringMixIn): - """Represents a single Email message + r"""Represents a single Email message Technically, this wraps the underlying *notmuch_message_t* structure. A user will usually not create these objects themselves @@ -112,6 +114,36 @@ class Message(Python3StringMixIn): _maildir_flags_to_tags.argtypes = [NotmuchMessageP] _maildir_flags_to_tags.restype = c_int + """notmuch_message_get_property""" + _get_property = nmlib.notmuch_message_get_property + _get_property.argtypes = [NotmuchMessageP, c_char_p, POINTER(c_char_p)] + _get_property.restype = c_int + + """notmuch_message_get_properties""" + _get_properties = nmlib.notmuch_message_get_properties + _get_properties.argtypes = [NotmuchMessageP, c_char_p, c_int] + _get_properties.restype = NotmuchMessagePropertiesP + + """notmuch_message_properties_valid""" + _properties_valid = nmlib.notmuch_message_properties_valid + _properties_valid.argtypes = [NotmuchMessagePropertiesP] + _properties_valid.restype = bool + + """notmuch_message_properties_value""" + _properties_value = nmlib.notmuch_message_properties_value + _properties_value.argtypes = [NotmuchMessagePropertiesP] + _properties_value.restype = c_char_p + + """notmuch_message_properties_key""" + _properties_key = nmlib.notmuch_message_properties_key + _properties_key.argtypes = [NotmuchMessagePropertiesP] + _properties_key.restype = c_char_p + + """notmuch_message_properties_move_to_next""" + _properties_move_to_next = nmlib.notmuch_message_properties_move_to_next + _properties_move_to_next.argtypes = [NotmuchMessagePropertiesP] + _properties_move_to_next.restype = None + #Constants: Flags that can be set/get with set_flag FLAG = Enum(['MATCH']) @@ -222,7 +254,7 @@ class Message(Python3StringMixIn): :returns: The header value as string :raises: :exc:`NotInitializedError` if the message is not initialized - :raises: :exc:`NullPointerError` if any error occured + :raises: :exc:`NullPointerError` if any error occurred """ if not self._msg: raise NotInitializedError() @@ -294,7 +326,7 @@ class Message(Python3StringMixIn): :returns: A :class:`Tags` iterator. :raises: :exc:`NotInitializedError` if the message is not initialized - :raises: :exc:`NullPointerError` if any error occured + :raises: :exc:`NullPointerError` if any error occurred """ if not self._msg: raise NotInitializedError() @@ -432,6 +464,55 @@ class Message(Python3StringMixIn): _freeze.argtypes = [NotmuchMessageP] _freeze.restype = c_uint + def get_property(self, prop): + """ Retrieve the value for a single property key + + :param prop: The name of the property to get. + :returns: String with the property value or None if there is no such + key. In the case of multiple values for the given key, the + first one is retrieved. + :raises: :exc:`NotInitializedError` if message has not been + initialized + """ + if not self._msg: + raise NotInitializedError() + + value = c_char_p() + status = Message._get_property(self._msg, _str(prop), byref(value)) + if status != 0: + raise NotmuchError(status) + + if value is None or value.value is None: + return None + return value.value.decode('utf-8') + + def get_properties(self, prop="", exact=False): + """ Get the properties of the message, returning a generator of + name, value pairs. + + The generator will yield once per value. There might be more than one + value on each name, so the generator might yield the same name several + times. + + :param prop: The name of the property to get. Otherwise it will return + the full list of properties of the message. + :param exact: if True, require exact match with key. Otherwise + treat as prefix. + :yields: Each property values as a pair of `name, value` + :ytype: pairs of str + :raises: :exc:`NotInitializedError` if message has not been + initialized + """ + if not self._msg: + raise NotInitializedError() + + properties = Message._get_properties(self._msg, _str(prop), exact) + while Message._properties_valid(properties): + key = Message._properties_key(properties) + value = Message._properties_value(properties) + yield key.decode("utf-8"), value.decode("utf-8") + Message._properties_move_to_next(properties) + def freeze(self): """Freezes the current state of 'message' within the database @@ -566,7 +647,7 @@ class Message(Python3StringMixIn): logical OR operator.) As a convenience, you can set the sync_maildir_flags parameter in - :meth:`Database.add_message` to implicitly call this. + :meth:`Database.index_file` to implicitly call this. :returns: a :class:`STATUS`. In short, you want to see notmuch.STATUS.SUCCESS here. See there for details.""" @@ -587,8 +668,11 @@ class Message(Python3StringMixIn): def get_message_parts(self): """Output like notmuch show""" - fp = open(self.get_filename()) - email_msg = email.message_from_file(fp) + fp = open(self.get_filename(), 'rb') + if sys.version_info[0] < 3: + email_msg = email.message_from_file(fp) + else: + email_msg = email.message_from_binary_file(fp) fp.close() out = []