]> git.notmuchmail.org Git - notmuch/blob - cnotmuch/tag.py
README: update changelog
[notmuch] / cnotmuch / tag.py
1 from ctypes import c_char_p
2 from cnotmuch.globals import nmlib, STATUS, NotmuchError
3
4 #------------------------------------------------------------------------------
5 class Tags(object):
6     """Represents a list of notmuch tags
7
8     This object provides an iterator over a list of notmuch tags. Do
9     note that the underlying library only provides a one-time iterator
10     (it cannot reset the iterator to the start). Thus iterating over
11     the function will "exhaust" the list of tags, and a subsequent
12     iteration attempt will raise a :exc:`NotmuchError`
13     STATUS.NOT_INITIALIZED. Also note, that any function that uses
14     iteration (nearly all) will also exhaust the tags. So both::
15
16       for tag in tags: print tag 
17
18     as well as::
19
20        number_of_tags = len(tags)
21
22     and even a simple::
23
24        #str() iterates over all tags to construct a space separated list
25        print(str(tags))
26
27     will "exhaust" the Tags. If you need to re-iterate over a list of
28     tags you will need to retrieve a new :class:`Tags` object.
29     """
30
31     #notmuch_tags_get
32     _get = nmlib.notmuch_tags_get
33     _get.restype = c_char_p
34
35     def __init__(self, tags_p, parent=None):
36         """
37         :param tags_p: A pointer to an underlying *notmuch_tags_t*
38              structure. These are not publically exposed, so a user
39              will almost never instantiate a :class:`Tags` object
40              herself. They are usually handed back as a result,
41              e.g. in :meth:`Database.get_all_tags`.  *tags_p* must be
42              valid, we will raise an :exc:`NotmuchError`
43              (STATUS.NULL_POINTER) if it is `None`.
44         :type tags_p: :class:`ctypes.c_void_p`
45         :param parent: The parent object (ie :class:`Database` or 
46              :class:`Message` these tags are derived from, and saves a
47              reference to it, so we can automatically delete the db object
48              once all derived objects are dead.
49         :TODO: Make the iterator optionally work more than once by
50                cache the tags in the Python object(?)
51         """
52         if tags_p is None:
53             NotmuchError(STATUS.NULL_POINTER)
54
55         self._tags = tags_p
56         #save reference to parent object so we keep it alive
57         self._parent = parent
58     
59     def __iter__(self):
60         """ Make Tags an iterator """
61         return self
62
63     def next(self):
64         if self._tags is None:
65             raise NotmuchError(STATUS.NOT_INITIALIZED)
66
67         if not nmlib.notmuch_tags_valid(self._tags):
68             self._tags = None
69             raise StopIteration
70
71         tag = Tags._get (self._tags)
72         nmlib.notmuch_tags_move_to_next(self._tags)
73         return tag
74
75     def __len__(self):
76         """len(:class:`Tags`) returns the number of contained tags
77
78         .. note:: As this iterates over the tags, we will not be able
79                to iterate over them again (as in retrieve them)! If
80                the tags have been exhausted already, this will raise a
81                :exc:`NotmuchError` STATUS.NOT_INITIALIZED on
82                subsequent attempts.
83         """
84         if self._tags is None:
85             raise NotmuchError(STATUS.NOT_INITIALIZED)
86
87         i=0
88         while nmlib.notmuch_tags_valid(self._msgs):
89             nmlib.notmuch_tags_move_to_next(self._msgs)
90             i += 1
91         self._tags = None
92         return i
93
94     def __str__(self):
95         """The str() representation of Tags() is a space separated list of tags
96
97         .. note:: As this iterates over the tags, we will not be able
98                to iterate over them again (as in retrieve them)! If
99                the tags have been exhausted already, this will raise a
100                :exc:`NotmuchError` STATUS.NOT_INITIALIZED on
101                subsequent attempts.
102         """
103         return " ".join(self)
104
105     def __del__(self):
106         """Close and free the notmuch tags"""
107         if self._tags is not None:
108             nmlib.notmuch_tags_destroy (self._tags)