3f541046ff495bc65cb6f28f50eb5fff2e64b0b3
[notmuch] / bindings / python / notmuch / filename.py
1 """
2 This file is part of notmuch.
3
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.
8
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
12 for more details.
13
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/>.
16
17 Copyright 2010 Sebastian Spaeth <Sebastian@SSpaeth.de>'
18 """
19 from ctypes import c_char_p
20 from notmuch.globals import (nmlib, STATUS, NotmuchError,
21     NotmuchFilenamesP, NotmuchMessageP, _str, Python3StringMixIn)
22
23
24 class Filenames(Python3StringMixIn):
25     """Represents a list of filenames as returned by notmuch
26
27     This object contains the Filenames iterator. The main function is
28     as_generator() which will return a generator so we can do a Filenamesth an
29     iterator over a list of notmuch filenames. Do note that the underlying
30     library only provides a one-time iterator (it cannot reset the iterator to
31     the start). Thus iterating over the function will "exhaust" the list of
32     tags, and a subsequent iteration attempt will raise a :exc:`NotmuchError`
33     STATUS.NOT_INITIALIZED. Also note, that any function that uses iteration
34     (nearly all) will also exhaust the tags. So both::
35
36       for name in filenames: print name
37
38     as well as::
39
40        number_of_names = len(names)
41
42     and even a simple::
43
44        #str() iterates over all tags to construct a space separated list
45        print(str(filenames))
46
47     will "exhaust" the Filenames. However, you can use
48     :meth:`Message.get_filenames` repeatedly to get fresh Filenames
49     objects to perform various actions on filenames.
50     """
51
52     #notmuch_filenames_get
53     _get = nmlib.notmuch_filenames_get
54     _get.argtypes = [NotmuchFilenamesP]
55     _get.restype = c_char_p
56
57     def __init__(self, files_p, parent):
58         """
59         :param files_p: A pointer to an underlying *notmuch_tags_t*
60              structure. These are not publically exposed, so a user
61              will almost never instantiate a :class:`Tags` object
62              herself. They are usually handed back as a result,
63              e.g. in :meth:`Database.get_all_tags`.  *tags_p* must be
64              valid, we will raise an :exc:`NotmuchError`
65              (STATUS.NULL_POINTER) if it is `None`.
66         :type files_p: :class:`ctypes.c_void_p`
67         :param parent: The parent object (ie :class:`Message` these
68              filenames are derived from, and saves a
69              reference to it, so we can automatically delete the db object
70              once all derived objects are dead.
71         """
72         if not files_p:
73             raise NotmuchError(STATUS.NULL_POINTER)
74
75         self._files = files_p
76         #save reference to parent object so we keep it alive
77         self._parent = parent
78
79     _valid = nmlib.notmuch_filenames_valid
80     _valid.argtypes = [NotmuchFilenamesP]
81     _valid.restype = bool
82
83     _move_to_next = nmlib.notmuch_filenames_move_to_next
84     _move_to_next.argtypes = [NotmuchFilenamesP]
85     _move_to_next.restype = None
86
87     def as_generator(self):
88         """Return generator of Filenames
89
90         This is the main function that will usually be used by the
91         user."""
92         if self._files is None:
93             raise NotmuchError(STATUS.NOT_INITIALIZED)
94
95         while self._valid(self._files):
96             yield Filenames._get(self._files).decode('utf-8', 'ignore')
97             self._move_to_next(self._files)
98
99         self._files = None
100
101     def __unicode__(self):
102         """Represent Filenames() as newline-separated list of full paths
103
104         .. note:: As this iterates over the filenames, we will not be
105                able to iterate over them again (as in retrieve them)! If
106                the tags have been exhausted already, this will raise a
107                :exc:`NotmuchError` STATUS.NOT_INITIALIZED on subsequent
108                attempts. However, you can use
109                :meth:`Message.get_filenames` repeatedly to perform
110                various actions on filenames.
111         """
112         return "\n".join(self)
113
114     _destroy = nmlib.notmuch_filenames_destroy
115     _destroy.argtypes = [NotmuchMessageP]
116     _destroy.restype = None
117
118     def __del__(self):
119         """Close and free the notmuch filenames"""
120         if self._files is not None:
121             self._destroy(self._files)