]> git.notmuchmail.org Git - notmuch/blob - cnotmuch/database.py
Tags: clarify documentation: we can only iterate once over Tags, and free underlying...
[notmuch] / cnotmuch / database.py
1 import ctypes
2 from ctypes import c_int, c_char_p, c_void_p
3 from cnotmuch.globals import nmlib, STATUS, NotmuchError
4
5
6 class Database(object):
7     """ Wrapper around a notmuch_database_t
8
9     Do note that as soon as we tear down this object, all derived queries,
10     threads, and messages will be freed as well.
11     """
12     #constants
13     MODE_READ_ONLY = 0
14     MODE_READ_WRITE = 1
15
16     _std_db_path = None
17     """Class attribute of users default database"""
18
19     """notmuch_database_get_path (notmuch_database_t *database)"""
20     _get_path = nmlib.notmuch_database_get_path
21     _get_path.restype = c_char_p
22
23     """notmuch_database_open (const char *path, notmuch_database_mode_t mode)"""
24     _open = nmlib.notmuch_database_open 
25     _open.restype = c_void_p
26
27     """notmuch_database_get_all_tags (notmuch_database_t *database)"""
28     _get_all_tags = nmlib.notmuch_database_get_all_tags
29     _get_all_tags.restype = c_void_p
30
31     class notmuch_database_t(ctypes.Structure):
32         """the opaque database that is returned by functions."""
33         pass
34
35     def __init__(self, path=None, create=False, status= MODE_READ_ONLY):
36         """ Open or create a notmuch database"""
37         self._db = None
38         if create == False:
39             self.open(path, status)
40         else:
41             #TODO: implement
42             raise NotmuchError(message="Not implemented yet")
43
44     #TODO: make a proper function
45     create=nmlib.notmuch_database_create
46     """ notmuch_database_create(const char *path):"""
47
48     def open(self, path=None, status= MODE_READ_ONLY): 
49         """calls notmuch_database_open
50
51         If path is None, we will try to read a users notmuch configuration and
52         use his default database.
53         :returns: Raises :exc:`notmuch.NotmuchError` in case
54                   of any failure (after printing an error message on stderr).
55         """
56         if path is None:
57             if Database._std_db_path is None:
58                 from ConfigParser import SafeConfigParser
59                 import os.path
60                 config = SafeConfigParser()
61                 config.read(os.path.expanduser('~/.notmuch-config'))
62                 if not config.has_option('database','path'):
63                     raise NotmuchError(message=
64                               "No DB path specified and no user default found")
65                 Database._std_db_path=config.get('database','path')
66             path = Database._std_db_path
67
68         res = Database._open(path, status)
69
70         if res is None:
71             raise NotmuchError(
72                 message="Could not open the specified database")
73         self._db = res
74
75     def get_path(self):
76         """notmuch_database_get_path (notmuch_database_t *database);  """
77         return Database._get_path(self._db)
78
79     #TODO:implement
80     #If no message is found with the given message_id or if an
81     #out-of-memory situation occurs, this function returns NULL.
82     #notmuch_message_t *
83     #notmuch_database_find_message (notmuch_database_t *database,
84     #                               const char *message_id);
85
86     def get_all_tags(self):
87         """Return a Tags() object (list of all tags found in the database)
88
89         :returns: Tags() object or raises :exc:`NotmuchError` with 
90                   STATUS.NULL_POINTER on error
91         """
92         tags_p = Database._get_all_tags (self._db)
93         if tags_p == None:
94             raise NotmuchError(STATUS.NULL_POINTER)
95         return Tags(tags_p, self)
96
97     def __repr__(self):
98         return "'Notmuch DB " + self.get_path() + "'"
99
100     def __del__(self):
101         """Close and free the notmuch database if needed"""
102         if self._db is not None:
103             print("Freeing the database now")
104             nmlib.notmuch_database_close(self._db)
105
106     @property
107     def db_p(self):
108         """Returns a pointer to the current notmuch_database_t or None"""
109         return self._db
110
111
112 #------------------------------------------------------------------------------
113 class Tags(object):
114     """Wrapper around notmuch_tags_t"""
115     class notmuch_tags_t(ctypes.Structure):
116         """the opaque tags struct that is returned by functions."""
117         pass
118
119     #notmuch_tags_get
120     _get = nmlib.notmuch_tags_get
121     _get.restype = c_char_p
122
123     def __init__(self, tags_p, db=None):
124         """ Is passed the db these tags are derived from, and saves a
125         reference to it, so we can automatically delete the db object
126         once all derived objects are dead.
127
128         Tags() provides an iterator over all contained tags. However, you will
129         only be able to iterate over the Tags once, because the underlying C
130         function only allows iterating once.
131         #TODO: make the iterator work more than once and cache the tags in 
132                the Python object.
133         """
134         self._tags = tags_p
135         self._db = db
136         print "inited tags with %d %s" %(tags_p, str(db))
137     
138     def __iter__(self):
139         """ Make Tags an iterator """
140         return self
141
142     def next(self):
143         if self._tags is None:
144             raise StopIteration
145         nmlib.notmuch_tags_move_to_next(self._tags)
146         if not nmlib.notmuch_tags_valid(self._tags):
147             print("Freeing the Tags now")
148             nmlib.notmuch_tags_destroy (self._tags)
149             raise StopIteration
150         return Tags._get (self._tags)
151
152     def __del__(self):
153         """Close and free the notmuch tags"""
154         if self._tags is not None:
155             print("Freeing the Tags now")
156             nmlib.notmuch_tags_destroy (self._tags)