Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: third_party/twisted_8_1/twisted/persisted/dirdbm.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 # -*- test-case-name: twisted.test.test_dirdbm -*-
2 #
3 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7
8 """
9 DBM-style interface to a directory.
10
11 Each key is stored as a single file. This is not expected to be very fast or
12 efficient, but it's good for easy debugging.
13
14 DirDBMs are *not* thread-safe, they should only be accessed by one thread at
15 a time.
16
17 No files should be placed in the working directory of a DirDBM save those
18 created by the DirDBM itself!
19
20 Maintainer: U{Itamar Shtull-Trauring<mailto:twisted@itamarst.org>}
21 """
22
23
24 import os
25 import types
26 import base64
27 import glob
28
29 try:
30 import cPickle as pickle
31 except ImportError:
32 import pickle
33
34 try:
35 _open
36 except NameError:
37 _open = open
38
39
40 class DirDBM:
41 """A directory with a DBM interface.
42
43 This class presents a hash-like interface to a directory of small,
44 flat files. It can only use strings as keys or values.
45 """
46
47 def __init__(self, name):
48 """
49 @type name: str
50 @param name: Base path to use for the directory storage.
51 """
52 self.dname = os.path.abspath(name)
53 if not os.path.isdir(self.dname):
54 os.mkdir(self.dname)
55 else:
56 # Run recovery, in case we crashed. we delete all files ending
57 # with ".new". Then we find all files who end with ".rpl". If a
58 # corresponding file exists without ".rpl", we assume the write
59 # failed and delete the ".rpl" file. If only a ".rpl" exist we
60 # assume the program crashed right after deleting the old entry
61 # but before renaming the replacement entry.
62 #
63 # NOTE: '.' is NOT in the base64 alphabet!
64 for f in glob.glob(os.path.join(self.dname, "*.new")):
65 os.remove(f)
66 replacements = glob.glob(os.path.join(self.dname, "*.rpl"))
67 for f in replacements:
68 old = f[:-4]
69 if os.path.exists(old):
70 os.remove(f)
71 else:
72 os.rename(f, old)
73
74 def _encode(self, k):
75 """Encode a key so it can be used as a filename.
76 """
77 # NOTE: '_' is NOT in the base64 alphabet!
78 return base64.encodestring(k).replace('\n', '_').replace("/", "-")
79
80 def _decode(self, k):
81 """Decode a filename to get the key.
82 """
83 return base64.decodestring(k.replace('_', '\n').replace("-", "/"))
84
85 def _readFile(self, path):
86 """Read in the contents of a file.
87
88 Override in subclasses to e.g. provide transparently encrypted dirdbm.
89 """
90 f = _open(path, "rb")
91 s = f.read()
92 f.close()
93 return s
94
95 def _writeFile(self, path, data):
96 """Write data to a file.
97
98 Override in subclasses to e.g. provide transparently encrypted dirdbm.
99 """
100 f = _open(path, "wb")
101 f.write(data)
102 f.flush()
103 f.close()
104
105 def __len__(self):
106 """
107 @return: The number of key/value pairs in this Shelf
108 """
109 return len(os.listdir(self.dname))
110
111 def __setitem__(self, k, v):
112 """
113 C{dirdbm[k] = v}
114 Create or modify a textfile in this directory
115
116 @type k: str
117 @param k: key to set
118
119 @type v: str
120 @param v: value to associate with C{k}
121 """
122 assert type(k) == types.StringType, "DirDBM key must be a string"
123 assert type(v) == types.StringType, "DirDBM value must be a string"
124 k = self._encode(k)
125
126 # we create a new file with extension .new, write the data to it, and
127 # if the write succeeds delete the old file and rename the new one.
128 old = os.path.join(self.dname, k)
129 if os.path.exists(old):
130 new = old + ".rpl" # replacement entry
131 else:
132 new = old + ".new" # new entry
133 try:
134 self._writeFile(new, v)
135 except:
136 os.remove(new)
137 raise
138 else:
139 if os.path.exists(old): os.remove(old)
140 os.rename(new, old)
141
142 def __getitem__(self, k):
143 """
144 C{dirdbm[k]}
145 Get the contents of a file in this directory as a string.
146
147 @type k: str
148 @param k: key to lookup
149
150 @return: The value associated with C{k}
151 @raise KeyError: Raised when there is no such key
152 """
153 assert type(k) == types.StringType, "DirDBM key must be a string"
154 path = os.path.join(self.dname, self._encode(k))
155 try:
156 return self._readFile(path)
157 except:
158 raise KeyError, k
159
160 def __delitem__(self, k):
161 """
162 C{del dirdbm[foo]}
163 Delete a file in this directory.
164
165 @type k: str
166 @param k: key to delete
167
168 @raise KeyError: Raised when there is no such key
169 """
170 assert type(k) == types.StringType, "DirDBM key must be a string"
171 k = self._encode(k)
172 try: os.remove(os.path.join(self.dname, k))
173 except (OSError, IOError): raise KeyError(self._decode(k))
174
175 def keys(self):
176 """
177 @return: a C{list} of filenames (keys).
178 """
179 return map(self._decode, os.listdir(self.dname))
180
181 def values(self):
182 """
183 @return: a C{list} of file-contents (values).
184 """
185 vals = []
186 keys = self.keys()
187 for key in keys:
188 vals.append(self[key])
189 return vals
190
191 def items(self):
192 """
193 @return: a C{list} of 2-tuples containing key/value pairs.
194 """
195 items = []
196 keys = self.keys()
197 for key in keys:
198 items.append((key, self[key]))
199 return items
200
201 def has_key(self, key):
202 """
203 @type key: str
204 @param key: The key to test
205
206 @return: A true value if this dirdbm has the specified key, a faluse
207 value otherwise.
208 """
209 assert type(key) == types.StringType, "DirDBM key must be a string"
210 key = self._encode(key)
211 return os.path.isfile(os.path.join(self.dname, key))
212
213 def setdefault(self, key, value):
214 """
215 @type key: str
216 @param key: The key to lookup
217
218 @param value: The value to associate with key if key is not already
219 associated with a value.
220 """
221 if not self.has_key(key):
222 self[key] = value
223 return value
224 return self[key]
225
226 def get(self, key, default = None):
227 """
228 @type key: str
229 @param key: The key to lookup
230
231 @param default: The value to return if the given key does not exist
232
233 @return: The value associated with C{key} or C{default} if not
234 C{self.has_key(key)}
235 """
236 if self.has_key(key):
237 return self[key]
238 else:
239 return default
240
241 def __contains__(self, key):
242 """
243 C{key in dirdbm}
244
245 @type key: str
246 @param key: The key to test
247
248 @return: A true value if C{self.has_key(key)}, a false value otherwise.
249 """
250 assert type(key) == types.StringType, "DirDBM key must be a string"
251 key = self._encode(key)
252 return os.path.isfile(os.path.join(self.dname, key))
253
254 def update(self, dict):
255 """
256 Add all the key/value pairs in C{dict} to this dirdbm. Any conflicting
257 keys will be overwritten with the values from C{dict}.
258
259 @type dict: mapping
260 @param dict: A mapping of key/value pairs to add to this dirdbm.
261 """
262 for key, val in dict.items():
263 self[key]=val
264
265 def copyTo(self, path):
266 """
267 Copy the contents of this dirdbm to the dirdbm at C{path}.
268
269 @type path: C{str}
270 @param path: The path of the dirdbm to copy to. If a dirdbm
271 exists at the destination path, it is cleared first.
272
273 @rtype: C{DirDBM}
274 @return: The dirdbm this dirdbm was copied to.
275 """
276 path = os.path.abspath(path)
277 assert path != self.dname
278
279 d = self.__class__(path)
280 d.clear()
281 for k in self.keys():
282 d[k] = self[k]
283 return d
284
285 def clear(self):
286 """
287 Delete all key/value pairs in this dirdbm.
288 """
289 for k in self.keys():
290 del self[k]
291
292 def close(self):
293 """
294 Close this dbm: no-op, for dbm-style interface compliance.
295 """
296
297 def getModificationTime(self, key):
298 """
299 Returns modification time of an entry.
300
301 @return: Last modification date (seconds since epoch) of entry C{key}
302 @raise KeyError: Raised when there is no such key
303 """
304 assert type(key) == types.StringType, "DirDBM key must be a string"
305 path = os.path.join(self.dname, self._encode(key))
306 if os.path.isfile(path):
307 return os.path.getmtime(path)
308 else:
309 raise KeyError, key
310
311
312 class Shelf(DirDBM):
313 """A directory with a DBM shelf interface.
314
315 This class presents a hash-like interface to a directory of small,
316 flat files. Keys must be strings, but values can be any given object.
317 """
318
319 def __setitem__(self, k, v):
320 """
321 C{shelf[foo] = bar}
322 Create or modify a textfile in this directory.
323
324 @type k: str
325 @param k: The key to set
326
327 @param v: The value to associate with C{key}
328 """
329 v = pickle.dumps(v)
330 DirDBM.__setitem__(self, k, v)
331
332 def __getitem__(self, k):
333 """
334 C{dirdbm[foo]}
335 Get and unpickle the contents of a file in this directory.
336
337 @type k: str
338 @param k: The key to lookup
339
340 @return: The value associated with the given key
341 @raise KeyError: Raised if the given key does not exist
342 """
343 return pickle.loads(DirDBM.__getitem__(self, k))
344
345
346 def open(file, flag = None, mode = None):
347 """
348 This is for 'anydbm' compatibility.
349
350 @param file: The parameter to pass to the DirDBM constructor.
351
352 @param flag: ignored
353 @param mode: ignored
354 """
355 return DirDBM(file)
356
357
358 __all__ = ["open", "DirDBM", "Shelf"]
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/persisted/crefutil.py ('k') | third_party/twisted_8_1/twisted/persisted/journal/__init__.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698