1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 Provides an in-memory store, which can read and save the database in
23 Pyblio's XML format.
24
25 This store is useful for relatively small databases (up to a few
26 thousand entries) and that are processed in batch once for instance,
27 as the reading and writing can be slow.
28 """
29 import weakref
30 from gettext import gettext as _
31
32 import os, copy, string
33
34 from Pyblio import Store, Callback, Attribute, Exceptions, Tools, Query, Sort
35 from Pyblio.Stores import resultset
36
37 from Pyblio.Arrays import KeyArray, match_arrays
38
39 -class RODict(Callback.Publisher):
40 """ Read-only dictionnary """
41
46
47 - def view(self, criterion):
49
52
55
58
59 __iter__ = iterkeys
60
63
65 """ forward messages. the message name is passed last """
66 args, msg = args [:-1], args [-1]
67 return apply (self.emit, (msg,) + args)
68
69
72 self._db = weakref.ref(db)
73 self._id = 1
74 return
75
76 - def new(self, rsid=None):
77 """ Create an empty result set """
78 db = self._db()
79 assert db is not None
80 (self._id, rsid) = Tools.id_make(self._id, rsid)
81
82
83 rs = resultset.ResultSet(rsid, db)
84 return rs
85
88
90 self[result_set.id] = result_set
91
92
93
94 -class Database (Query.Queryable, Store.Database, Callback.Publisher):
95
96 - def __init__ (self, schema = None, file = None,
97 create = False):
126
128 """ Return the result set that contains all the entries. """
129
130 return self._rodict
131
132 entries = property(_entries_get, None)
133
134
135 - def add(self, record, key = None):
136 """ Insert a new entry in the database.
137
138 New entries MUST be added with this method, not via an update
139 with a hand-made Key.
140
141 key is only useful for importing an existing database, by
142 proposing a key choice.
143 """
144
145 self._id, key = Tools.id_make (self._id, key)
146
147 key = Store.Key (key)
148
149 assert not self.has_key (key), \
150 _("a duplicate key has been generated: %d") % key
151
152 record = copy.copy (record)
153 record.key = key
154
155 record = self.validate (record)
156
157 self._dict [key] = record
158
159 if self._indexed:
160 self._idxadd(key, record)
161
162 self.emit ('add-item', key)
163
164 return key
165
166
168
169 del self._dict [k]
170 self.emit ('delete-item', k)
171
172 if self._indexed:
173 self._idxdel(k)
174 return
175
176
179
180
182
183
184 assert self.has_key (key), \
185 _("use self.add () to add a new entry")
186
187 value = copy.deepcopy (value)
188 value.key = key
189
190 value = self.validate (value)
191
192 self._dict [key] = value
193
194 if self._indexed:
195 self._idxdel(key)
196 self._idxadd(key, value)
197
198 self.emit ('update-item', key)
199 return
200
201
203 return self._dict [key]
204
205
207
208 if self.file is None:
209 return
210
211 try:
212 os.unlink (self.file + '.bak')
213 except OSError:
214 pass
215
216 if os.path.exists (self.file):
217 os.rename (self.file, self.file + '.bak')
218
219 fd = open (self.file, 'w')
220 self.xmlwrite (fd)
221 fd.close ()
222
223 return
224
226
227 for attribs in val.values():
228 for attrib in attribs:
229
230 for idx in attrib.index():
231 self._idx_b.setdefault(key, {})[idx] = True
232
233 try:
234 self._idx_f[idx].add(key)
235 except KeyError:
236 a = KeyArray()
237 a.add(key)
238
239 self._idx_f[idx] = a
240 return
241
243
244 try:
245 ws = self._idx_b[key]
246
247 except KeyError:
248 return
249
250 del self._idx_b[key]
251
252 for w in ws:
253 del self._idx_f[w][key]
254
255 return
256
258 """ Turn on indexing of the db content. """
259
260 if self._indexed:
261 return
262
263 self._idx_f = {}
264 self._idx_b = {}
265
266 for key, rec in self.entries.iteritems():
267 self._idxadd(key, rec)
268
269 self._indexed = True
270 return
271
282
284 os.unlink(path)
285 if nobackup:
286 try:
287 os.unlink (path + '.bak')
288 except OSError:
289 pass
290 return
291
293
294 try:
295 fd = os.open(path, os.O_CREAT|os.O_EXCL|os.O_WRONLY, 0666)
296 except OSError, msg:
297 raise Store.StoreError (_("cannot create database '%s': %s") % (
298 path, msg))
299 os.close(fd)
300 db = Database (schema=schema, file=path, create=True)
301 db.save ()
302 return db
303
306
308 db = Database(file=source)
309 db.file = target
310 return db
311
312 description = _("Flat XML file storage")
313