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 <https://www.gnu.org/licenses/>.
17 Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>
20 from .globals import (
30 from .thread import Thread
32 class Threads(Python3StringMixIn):
33 """Represents a list of notmuch threads
35 This object provides an iterator over a list of notmuch threads
36 (Technically, it provides a wrapper for the underlying
37 *notmuch_threads_t* structure). Do note that the underlying
38 library only provides a one-time iterator (it cannot reset the
39 iterator to the start). Thus iterating over the function will
40 "exhaust" the list of threads, and a subsequent iteration attempt
41 will raise a :exc:`NotInitializedError`. Also
42 note, that any function that uses iteration will also
43 exhaust the messages. So both::
45 for thread in threads: print thread
49 list_of_threads = list(threads)
51 will "exhaust" the threads. If you need to re-iterate over a list of
52 messages you will need to retrieve a new :class:`Threads` object.
54 Things are not as bad as it seems though, you can store and reuse
55 the single Thread objects as often as you want as long as you
56 keep the parent Threads object around. (Recall that due to
57 hierarchical memory allocation, all derived Threads objects will
58 be invalid when we delete the parent Threads() object, even if it
59 was already "exhausted".) So this works::
62 threads = Query(db,'').search_threads() #get a Threads() object
64 for thread in threads:
65 threadlist.append(thread)
67 # threads is "exhausted" now.
68 # However it will be kept around until all retrieved Thread() objects are
69 # also deleted. If you did e.g. an explicit del(threads) here, the
70 # following lines would fail.
72 # You can reiterate over *threadlist* however as often as you want.
73 # It is simply a list with Thread objects.
75 print (threadlist[0].get_thread_id())
76 print (threadlist[1].get_thread_id())
77 print (threadlist[0].get_total_messages())
81 _get = nmlib.notmuch_threads_get
82 _get.argtypes = [NotmuchThreadsP]
83 _get.restype = NotmuchThreadP
85 def __init__(self, threads_p, parent=None):
87 :param threads_p: A pointer to an underlying *notmuch_threads_t*
88 structure. These are not publicly exposed, so a user
89 will almost never instantiate a :class:`Threads` object
90 herself. They are usually handed back as a result,
91 e.g. in :meth:`Query.search_threads`. *threads_p* must be
92 valid, we will raise an :exc:`NullPointerError` if it is
94 :type threads_p: :class:`ctypes.c_void_p`
95 :param parent: The parent object
96 (ie :class:`Query`) these tags are derived from. It saves
97 a reference to it, so we can automatically delete the db
98 object once all derived objects are dead.
99 :TODO: Make the iterator work more than once and cache the tags in
100 the Python object.(?)
103 raise NullPointerError()
105 self._threads = threads_p
106 #store parent, so we keep them alive as long as self is alive
107 self._parent = parent
110 """ Make Threads an iterator """
113 _valid = nmlib.notmuch_threads_valid
114 _valid.argtypes = [NotmuchThreadsP]
115 _valid.restype = bool
117 _move_to_next = nmlib.notmuch_threads_move_to_next
118 _move_to_next.argtypes = [NotmuchThreadsP]
119 _move_to_next.restype = None
122 if not self._threads:
123 raise NotInitializedError()
125 if not self._valid(self._threads):
129 thread = Thread(Threads._get(self._threads), self)
130 self._move_to_next(self._threads)
132 next = __next__ # python2.x iterator protocol compatibility
134 def __nonzero__(self):
136 Implement truth value testing. If __nonzero__ is not
137 implemented, the python runtime would fall back to `len(..) >
138 0` thus exhausting the iterator.
140 :returns: True if the wrapped iterator has at least one more object
143 return self._threads and self._valid(self._threads)
145 _destroy = nmlib.notmuch_threads_destroy
146 _destroy.argtypes = [NotmuchThreadsP]
147 _destroy.restype = None
150 """Close and free the notmuch Threads"""
152 self._destroy(self._threads)