mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-21 18:38:08 +01:00
bindings/python: Implement Message().get_filenames()
Message().get_filenames() will return a generator that allows to iterator over the recorded filenames for a certain Message. Do ntoe that as all generators, these are one-time use only. You will have to reget them to perform various actions. So this works:: len(Message().get_filenames()) list(Message().get_filenames()) for n in Message().get_filenames(): print n But this won't:: names = Message().get_filenames() len(names) #uses up the iterator list(names) #outch, already used up... Signed-off-by: Sebastian Spaeth <Sebastian@SSpaeth.de>
This commit is contained in:
parent
e2afcd2594
commit
b31247c354
2 changed files with 126 additions and 0 deletions
108
bindings/python/notmuch/filename.py
Normal file
108
bindings/python/notmuch/filename.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
"""
|
||||
This file is part of notmuch.
|
||||
|
||||
Notmuch is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
Notmuch is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with notmuch. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
|
||||
"""
|
||||
from ctypes import c_char_p
|
||||
from notmuch.globals import nmlib, STATUS, NotmuchError
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
class Filenames(object):
|
||||
"""Represents a list of filenames as returned by notmuch
|
||||
|
||||
This object contains the Filenames iterator. The main function is as_generator() which will return a generator so we can do a Filenamesth an iterator over a list of notmuch filenames. Do
|
||||
note that the underlying library only provides a one-time iterator
|
||||
(it cannot reset the iterator to the start). Thus iterating over
|
||||
the function will "exhaust" the list of tags, and a subsequent
|
||||
iteration attempt will raise a :exc:`NotmuchError`
|
||||
STATUS.NOT_INITIALIZED. Also note, that any function that uses
|
||||
iteration (nearly all) will also exhaust the tags. So both::
|
||||
|
||||
for name in filenames: print name
|
||||
|
||||
as well as::
|
||||
|
||||
number_of_names = len(names)
|
||||
|
||||
and even a simple::
|
||||
|
||||
#str() iterates over all tags to construct a space separated list
|
||||
print(str(filenames))
|
||||
|
||||
will "exhaust" the Filenames. However, you can use
|
||||
:meth:`Message.get_filenames` repeatedly to get fresh Filenames
|
||||
objects to perform various actions on filenames.
|
||||
"""
|
||||
|
||||
#notmuch_filenames_get
|
||||
_get = nmlib.notmuch_filenames_get
|
||||
_get.restype = c_char_p
|
||||
|
||||
def __init__(self, files_p, parent):
|
||||
"""
|
||||
:param files_p: A pointer to an underlying *notmuch_tags_t*
|
||||
structure. These are not publically exposed, so a user
|
||||
will almost never instantiate a :class:`Tags` object
|
||||
herself. They are usually handed back as a result,
|
||||
e.g. in :meth:`Database.get_all_tags`. *tags_p* must be
|
||||
valid, we will raise an :exc:`NotmuchError`
|
||||
(STATUS.NULL_POINTER) if it is `None`.
|
||||
:type files_p: :class:`ctypes.c_void_p`
|
||||
:param parent: The parent object (ie :class:`Message` these
|
||||
filenames are derived from, and saves a
|
||||
reference to it, so we can automatically delete the db object
|
||||
once all derived objects are dead.
|
||||
"""
|
||||
if files_p is None:
|
||||
NotmuchError(STATUS.NULL_POINTER)
|
||||
|
||||
self._files = files_p
|
||||
#save reference to parent object so we keep it alive
|
||||
self._parent = parent
|
||||
|
||||
def as_generator(self):
|
||||
"""Return generator of Filenames
|
||||
|
||||
This is the main function that will usually be used by the
|
||||
user."""
|
||||
if self._files is None:
|
||||
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||
|
||||
if not nmlib.notmuch_filenames_valid(self._files):
|
||||
self._files = None
|
||||
return
|
||||
|
||||
file = Filenames._get (self._files)
|
||||
nmlib.notmuch_filenames_move_to_next(self._files)
|
||||
yield file
|
||||
|
||||
def __str__(self):
|
||||
"""Represent Filenames() as newline-separated list of full paths
|
||||
|
||||
.. note:: As this iterates over the filenames, we will not be
|
||||
able to iterate over them again (as in retrieve them)! If
|
||||
the tags have been exhausted already, this will raise a
|
||||
:exc:`NotmuchError` STATUS.NOT_INITIALIZED on subsequent
|
||||
attempts. However, you can use
|
||||
:meth:`Message.get_filenames` repeatedly to perform
|
||||
various actions on filenames.
|
||||
"""
|
||||
return "\n".join(self)
|
||||
|
||||
def __del__(self):
|
||||
"""Close and free the notmuch filenames"""
|
||||
if self._files is not None:
|
||||
nmlib.notmuch_filenames_destroy (self._files)
|
|
@ -23,6 +23,7 @@ from ctypes import c_char_p, c_void_p, c_long, c_uint
|
|||
from datetime import date
|
||||
from notmuch.globals import nmlib, STATUS, NotmuchError, Enum
|
||||
from notmuch.tag import Tags
|
||||
from notmuch.filename import Filenames
|
||||
import sys
|
||||
import email
|
||||
import types
|
||||
|
@ -244,6 +245,10 @@ class Message(object):
|
|||
_get_filename = nmlib.notmuch_message_get_filename
|
||||
_get_filename.restype = c_char_p
|
||||
|
||||
"""return all filenames for a message"""
|
||||
_get_filenames = nmlib.notmuch_message_get_filenames
|
||||
_get_filenames.restype = c_void_p
|
||||
|
||||
"""notmuch_message_get_flag"""
|
||||
_get_flag = nmlib.notmuch_message_get_flag
|
||||
_get_flag.restype = c_uint
|
||||
|
@ -400,6 +405,19 @@ class Message(object):
|
|||
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||
return Message._get_filename(self._msg)
|
||||
|
||||
def get_filenames(self):
|
||||
"""Get all filenames for the email corresponding to 'message'
|
||||
|
||||
Returns a Filenames() generator with all absolute filepaths for
|
||||
messages recorded to have the same Message-ID. These files must
|
||||
not necessarily have identical content."""
|
||||
if self._msg is None:
|
||||
raise NotmuchError(STATUS.NOT_INITIALIZED)
|
||||
|
||||
files_p = Message._get_filenames(self._msg)
|
||||
|
||||
return Filenames(files_p, self).as_generator()
|
||||
|
||||
def get_flag(self, flag):
|
||||
"""Checks whether a specific flag is set for this message
|
||||
|
||||
|
|
Loading…
Reference in a new issue