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 (
31 class Tags(Python3StringMixIn):
32 """Represents a list of notmuch tags
34 This object provides an iterator over a list of notmuch tags (which
35 are unicode instances).
37 Do note that the underlying library only provides a one-time
38 iterator (it cannot reset the iterator to the start). Thus iterating
39 over the function will "exhaust" the list of tags, and a subsequent
40 iteration attempt will raise a :exc:`NotInitializedError`.
41 Also note, that any function that uses iteration (nearly all) will
42 also exhaust the tags. So both::
44 for tag in tags: print tag
48 number_of_tags = len(tags)
52 #str() iterates over all tags to construct a space separated list
55 will "exhaust" the Tags. If you need to re-iterate over a list of
56 tags you will need to retrieve a new :class:`Tags` object.
60 _get = nmlib.notmuch_tags_get
61 _get.argtypes = [NotmuchTagsP]
62 _get.restype = c_char_p
64 def __init__(self, tags_p, parent=None):
66 :param tags_p: A pointer to an underlying *notmuch_tags_t*
67 structure. These are not publically exposed, so a user
68 will almost never instantiate a :class:`Tags` object
69 herself. They are usually handed back as a result,
70 e.g. in :meth:`Database.get_all_tags`. *tags_p* must be
71 valid, we will raise an :exc:`NullPointerError` if it is
73 :type tags_p: :class:`ctypes.c_void_p`
74 :param parent: The parent object (ie :class:`Database` or
75 :class:`Message` these tags are derived from, and saves a
76 reference to it, so we can automatically delete the db object
77 once all derived objects are dead.
78 :TODO: Make the iterator optionally work more than once by
79 cache the tags in the Python object(?)
82 raise NullPointerError()
85 #save reference to parent object so we keep it alive
89 """ Make Tags an iterator """
92 _valid = nmlib.notmuch_tags_valid
93 _valid.argtypes = [NotmuchTagsP]
96 _move_to_next = nmlib.notmuch_tags_move_to_next
97 _move_to_next.argtypes = [NotmuchTagsP]
98 _move_to_next.restype = None
102 raise NotInitializedError()
103 if not self._valid(self._tags):
106 tag = Tags._get(self._tags).decode('UTF-8')
107 self._move_to_next(self._tags)
109 next = __next__ # python2.x iterator protocol compatibility
111 def __nonzero__(self):
113 Implement truth value testing. If __nonzero__ is not
114 implemented, the python runtime would fall back to `len(..) >
115 0` thus exhausting the iterator.
117 :returns: True if the wrapped iterator has at least one more object
120 return self._tags and self._valid(self._tags)
122 def __unicode__(self):
123 """string representation of :class:`Tags`: a space separated list of tags
127 As this iterates over the tags, we will not be able to iterate over
128 them again (as in retrieve them)! If the tags have been exhausted
129 already, this will raise a :exc:`NotInitializedError`on subsequent
132 return " ".join(self)
134 _destroy = nmlib.notmuch_tags_destroy
135 _destroy.argtypes = [NotmuchTagsP]
136 _destroy.restype = None
139 """Close and free the notmuch tags"""
141 self._destroy(self._tags)