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