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 .globals import (
34 from .threads import Threads
35 from .messages import Messages
39 """Represents a search query on an opened :class:`Database`.
41 A query selects and filters a subset of messages from the notmuch
42 database we derive from.
44 :class:`Query` provides an instance attribute :attr:`sort`, which
45 contains the sort order (if specified via :meth:`set_sort`) or
48 Any function in this class may throw an :exc:`NotInitializedError`
49 in case the underlying query object was not set up correctly.
51 .. note:: Do remember that as soon as we tear down this object,
52 all underlying derived objects such as threads,
53 messages, tags etc will be freed by the underlying library
54 as well. Accessing these objects will lead to segfaults and
55 other unexpected behavior. See above for more details.
58 SORT = Enum(['OLDEST_FIRST', 'NEWEST_FIRST', 'MESSAGE_ID', 'UNSORTED'])
59 """Constants: Sort order in which to return results"""
61 def __init__(self, db, querystr):
63 :param db: An open database which we derive the Query from.
64 :type db: :class:`Database`
65 :param querystr: The query string for the message.
66 :type querystr: utf-8 encoded str or unicode
71 self.create(db, querystr)
73 def _assert_query_is_initialized(self):
74 """Raises :exc:`NotInitializedError` if self._query is `None`"""
76 raise NotInitializedError()
78 """notmuch_query_create"""
79 _create = nmlib.notmuch_query_create
80 _create.argtypes = [NotmuchDatabaseP, c_char_p]
81 _create.restype = NotmuchQueryP
83 def create(self, db, querystr):
84 """Creates a new query derived from a Database
86 This function is utilized by __init__() and usually does not need to
89 :param db: Database to create the query from.
90 :type db: :class:`Database`
91 :param querystr: The query string
92 :type querystr: utf-8 encoded str or unicode
94 :exc:`NullPointerError` if the query creation failed
95 (e.g. too little memory).
96 :exc:`NotInitializedError` if the underlying db was not
99 db._assert_db_is_initialized()
100 # create reference to parent db to keep it alive
102 # create query, return None if too little mem available
103 query_p = Query._create(db._db, _str(querystr))
105 raise NullPointerError
106 self._query = query_p
108 _set_sort = nmlib.notmuch_query_set_sort
109 _set_sort.argtypes = [NotmuchQueryP, c_uint]
110 _set_sort.argtypes = None
112 def set_sort(self, sort):
113 """Set the sort order future results will be delivered in
115 :param sort: Sort order (see :attr:`Query.SORT`)
117 self._assert_query_is_initialized()
119 self._set_sort(self._query, sort)
121 _exclude_tag = nmlib.notmuch_query_add_tag_exclude
122 _exclude_tag.argtypes = [NotmuchQueryP, c_char_p]
123 _exclude_tag.resttype = None
125 def exclude_tag(self, tagname):
126 """Add a tag that will be excluded from the query results by default.
128 This exclusion will be overridden if this tag appears explicitly in the
131 :param tagname: Name of the tag to be excluded
133 self._assert_query_is_initialized()
134 self._exclude_tag(self._query, _str(tagname))
136 """notmuch_query_search_threads"""
137 _search_threads = nmlib.notmuch_query_search_threads
138 _search_threads.argtypes = [NotmuchQueryP]
139 _search_threads.restype = NotmuchThreadsP
141 def search_threads(self):
142 """Execute a query for threads
144 Execute a query for threads, returning a :class:`Threads` iterator.
145 The returned threads are owned by the query and as such, will only be
146 valid until the Query is deleted.
148 The method sets :attr:`Message.FLAG`\.MATCH for those messages that
149 match the query. The method :meth:`Message.get_flag` allows us
150 to get the value of this flag.
152 :returns: :class:`Threads`
153 :raises: :exc:`NullPointerError` if search_threads failed
155 self._assert_query_is_initialized()
156 threads_p = Query._search_threads(self._query)
159 raise NullPointerError
160 return Threads(threads_p, self)
162 """notmuch_query_search_messages"""
163 _search_messages = nmlib.notmuch_query_search_messages
164 _search_messages.argtypes = [NotmuchQueryP]
165 _search_messages.restype = NotmuchMessagesP
167 def search_messages(self):
168 """Filter messages according to the query and return
169 :class:`Messages` in the defined sort order
171 :returns: :class:`Messages`
172 :raises: :exc:`NullPointerError` if search_messages failed
174 self._assert_query_is_initialized()
175 msgs_p = Query._search_messages(self._query)
178 raise NullPointerError
179 return Messages(msgs_p, self)
181 _count_messages = nmlib.notmuch_query_count_messages
182 _count_messages.argtypes = [NotmuchQueryP]
183 _count_messages.restype = c_uint
185 def count_messages(self):
187 This function performs a search and returns Xapian's best
188 guess as to the number of matching messages.
190 :returns: the estimated number of messages matching this query
193 self._assert_query_is_initialized()
194 return Query._count_messages(self._query)
196 _count_threads = nmlib.notmuch_query_count_threads
197 _count_threads.argtypes = [NotmuchQueryP]
198 _count_threads.restype = c_uint
200 def count_threads(self):
202 This function performs a search and returns the number of
203 unique thread IDs in the matching messages. This is the same
204 as number of threads matching a search.
206 Note that this is a significantly heavier operation than
207 meth:`Query.count_messages`.
209 :returns: the number of threads returned by this query
212 self._assert_query_is_initialized()
213 return Query._count_threads(self._query)
215 _destroy = nmlib.notmuch_query_destroy
216 _destroy.argtypes = [NotmuchQueryP]
217 _destroy.restype = None
220 """Close and free the Query"""
222 self._destroy(self._query)