2 This file is part of notmuch.
4 Notmuch is free software: you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation, either version 3 of the License, or (at your
7 option) any later version.
9 Notmuch is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with notmuch. If not, see <http://www.gnu.org/licenses/>.
17 Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>
19 from ctypes import c_char_p
20 from notmuch.globals import (
32 class Filenames(Python3StringMixIn):
33 """Represents a list of filenames as returned by notmuch
35 Objects of this class implement the iterator protocol.
39 The underlying library only provides a one-time iterator (it
40 cannot reset the iterator to the start). Thus iterating over
41 the function will "exhaust" the list of tags, and a subsequent
42 iteration attempt will raise a
43 :exc:`NotInitializedError`. Also note, that any function that
44 uses iteration (nearly all) will also exhaust the tags. So
47 for name in filenames: print name
51 number_of_names = len(names)
55 #str() iterates over all tags to construct a space separated list
58 will "exhaust" the Filenames. However, you can use
59 :meth:`Message.get_filenames` repeatedly to get fresh
60 Filenames objects to perform various actions on filenames.
63 #notmuch_filenames_get
64 _get = nmlib.notmuch_filenames_get
65 _get.argtypes = [NotmuchFilenamesP]
66 _get.restype = c_char_p
68 def __init__(self, files_p, parent):
70 :param files_p: A pointer to an underlying *notmuch_tags_t*
71 structure. These are not publically exposed, so a user
72 will almost never instantiate a :class:`Tags` object
73 herself. They are usually handed back as a result,
74 e.g. in :meth:`Database.get_all_tags`. *tags_p* must be
75 valid, we will raise an :exc:`NullPointerError`
77 :type files_p: :class:`ctypes.c_void_p`
78 :param parent: The parent object (ie :class:`Message` these
79 filenames are derived from, and saves a
80 reference to it, so we can automatically delete the db object
81 once all derived objects are dead.
84 raise NullPointerError()
86 self._files_p = files_p
87 #save reference to parent object so we keep it alive
91 """ Make Filenames an iterator """
94 _valid = nmlib.notmuch_filenames_valid
95 _valid.argtypes = [NotmuchFilenamesP]
98 _move_to_next = nmlib.notmuch_filenames_move_to_next
99 _move_to_next.argtypes = [NotmuchFilenamesP]
100 _move_to_next.restype = None
103 if not self._files_p:
104 raise NotInitializedError()
106 if not self._valid(self._files_p):
110 file_ = Filenames._get(self._files_p)
111 self._move_to_next(self._files_p)
112 return file_.decode('utf-8', 'ignore')
113 next = __next__ # python2.x iterator protocol compatibility
115 def __unicode__(self):
116 """Represent Filenames() as newline-separated list of full paths
118 .. note:: As this iterates over the filenames, we will not be
119 able to iterate over them again (as in retrieve them)! If
120 the tags have been exhausted already, this will raise a
121 :exc:`NotInitializedError` on subsequent
122 attempts. However, you can use
123 :meth:`Message.get_filenames` repeatedly to perform
124 various actions on filenames.
126 return "\n".join(self)
128 _destroy = nmlib.notmuch_filenames_destroy
129 _destroy.argtypes = [NotmuchMessageP]
130 _destroy.restype = None
133 """Close and free the notmuch filenames"""
134 if self._files_p is not None:
135 self._destroy(self._files_p)
138 """len(:class:`Filenames`) returns the number of contained files
142 As this iterates over the files, we will not be able to
143 iterate over them again! So this will fail::
146 files = Database().get_directory('').get_child_files()
147 if len(files) > 0: # this 'exhausts' msgs
149 # NotmuchError(:attr:`STATUS`.NOT_INITIALIZED)
150 for file in files: print file
152 if not self._files_p:
153 raise NotInitializedError()
156 while self._valid(self._files_p):
157 self._move_to_next(self._files_p)