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>'
20 from ctypes import c_char_p, c_uint
21 from notmuch.globals import (
32 from notmuch.thread import Threads
33 from notmuch.message import Messages
37 """Represents a search query on an opened :class:`Database`.
39 A query selects and filters a subset of messages from the notmuch
40 database we derive from.
42 :class:`Query` provides an instance attribute :attr:`sort`, which
43 contains the sort order (if specified via :meth:`set_sort`) or
46 Any function in this class may throw an :exc:`NotInitializedError`
47 in case the underlying query object was not set up correctly.
49 .. note:: Do remember that as soon as we tear down this object,
50 all underlying derived objects such as threads,
51 messages, tags etc will be freed by the underlying library
52 as well. Accessing these objects will lead to segfaults and
53 other unexpected behavior. See above for more details.
56 SORT = Enum(['OLDEST_FIRST', 'NEWEST_FIRST', 'MESSAGE_ID', 'UNSORTED'])
57 """Constants: Sort order in which to return results"""
59 def __init__(self, db, querystr):
61 :param db: An open database which we derive the Query from.
62 :type db: :class:`Database`
63 :param querystr: The query string for the message.
64 :type querystr: utf-8 encoded str or unicode
69 self.create(db, querystr)
71 def _assert_query_is_initialized(self):
72 """Raises :exc:`NotInitializedError` if self._query is `None`"""
73 if self._query is None:
74 raise NotInitializedError()
76 """notmuch_query_create"""
77 _create = nmlib.notmuch_query_create
78 _create.argtypes = [NotmuchDatabaseP, c_char_p]
79 _create.restype = NotmuchQueryP
81 def create(self, db, querystr):
82 """Creates a new query derived from a Database
84 This function is utilized by __init__() and usually does not need to
87 :param db: Database to create the query from.
88 :type db: :class:`Database`
89 :param querystr: The query string
90 :type querystr: utf-8 encoded str or unicode
93 :exc:`NullPointerError` if the query creation failed
94 (e.g. too little memory).
95 :exc:`NotInitializedError` if the underlying db was not
98 db._assert_db_is_initialized()
99 # create reference to parent db to keep it alive
101 # create query, return None if too little mem available
102 query_p = Query._create(db.db_p, _str(querystr))
104 raise NullPointerError
105 self._query = query_p
107 _set_sort = nmlib.notmuch_query_set_sort
108 _set_sort.argtypes = [NotmuchQueryP, c_uint]
109 _set_sort.argtypes = None
111 def set_sort(self, sort):
112 """Set the sort order future results will be delivered in
114 :param sort: Sort order (see :attr:`Query.SORT`)
116 self._assert_query_is_initialized()
118 self._set_sort(self._query, sort)
120 """notmuch_query_search_threads"""
121 _search_threads = nmlib.notmuch_query_search_threads
122 _search_threads.argtypes = [NotmuchQueryP]
123 _search_threads.restype = NotmuchThreadsP
125 def search_threads(self):
126 """Execute a query for threads
128 Execute a query for threads, returning a :class:`Threads` iterator.
129 The returned threads are owned by the query and as such, will only be
130 valid until the Query is deleted.
132 The method sets :attr:`Message.FLAG`\.MATCH for those messages that
133 match the query. The method :meth:`Message.get_flag` allows us
134 to get the value of this flag.
136 :returns: :class:`Threads`
137 :exception: :exc:`NullPointerError` if search_threads failed
139 self._assert_query_is_initialized()
140 threads_p = Query._search_threads(self._query)
143 raise NullPointerError
144 return Threads(threads_p, self)
146 """notmuch_query_search_messages"""
147 _search_messages = nmlib.notmuch_query_search_messages
148 _search_messages.argtypes = [NotmuchQueryP]
149 _search_messages.restype = NotmuchMessagesP
151 def search_messages(self):
152 """Filter messages according to the query and return
153 :class:`Messages` in the defined sort order
155 :returns: :class:`Messages`
156 :exception: :exc:`NullPointerError` if search_messages failed
158 self._assert_query_is_initialized()
159 msgs_p = Query._search_messages(self._query)
162 raise NullPointerError
163 return Messages(msgs_p, self)
165 _count_messages = nmlib.notmuch_query_count_messages
166 _count_messages.argtypes = [NotmuchQueryP]
167 _count_messages.restype = c_uint
169 def count_messages(self):
171 This function performs a search and returns Xapian's best
172 guess as to the number of matching messages.
174 :returns: the estimated number of messages matching this query
177 self._assert_query_is_initialized()
178 return Query._count_messages(self._query)
180 _count_threads = nmlib.notmuch_query_count_threads
181 _count_threads.argtypes = [NotmuchQueryP]
182 _count_threads.restype = c_uint
184 def count_threads(self):
186 This function performs a search and returns the number of
187 unique thread IDs in the matching messages. This is the same
188 as number of threads matching a search.
190 Note that this is a significantly heavier operation than
191 meth:`Query.count_messages`.
193 :returns: the number of threads returned by this query
196 self._assert_query_is_initialized()
197 return Query._count_threads(self._query)
199 _destroy = nmlib.notmuch_query_destroy
200 _destroy.argtypes = [NotmuchQueryP]
201 _destroy.restype = None
204 """Close and free the Query"""
205 if self._query is not None:
206 self._destroy(self._query)