1
2
3
4 import cPickle
5 import time
6 import shutil
7 import os
8 import types
9 import __builtin__
10
11 keep_all_files = 00000
12 ignore_corrupt_dbfiles = 0
13
15 print "Warning: Discarding corrupt database:", filename
16
17 if hasattr(types, 'UnicodeType'):
19 t = type(s)
20 return t is types.StringType or t is types.UnicodeType
21 else:
23 return type(s) is types.StringType
24
25 try:
26 unicode('a')
27 except NameError:
29
30 dblite_suffix = '.dblite'
31 tmp_suffix = '.tmp'
32
34
35
36
37
38
39
40
41
42
43
44
45 _open = __builtin__.open
46 _cPickle_dump = cPickle.dump
47 _os_chmod = os.chmod
48 _os_rename = os.rename
49 _os_unlink = os.unlink
50 _shutil_copyfile = shutil.copyfile
51 _time_time = time.time
52
53 - def __init__(self, file_base_name, flag, mode):
54 assert flag in (None, "r", "w", "c", "n")
55 if (flag is None): flag = "r"
56 base, ext = os.path.splitext(file_base_name)
57 if ext == dblite_suffix:
58
59 self._file_name = file_base_name
60 self._tmp_name = base + tmp_suffix
61 else:
62 self._file_name = file_base_name + dblite_suffix
63 self._tmp_name = file_base_name + tmp_suffix
64 self._flag = flag
65 self._mode = mode
66 self._dict = {}
67 self._needs_sync = 00000
68 if (self._flag == "n"):
69 self._open(self._file_name, "wb", self._mode)
70 else:
71 try:
72 f = self._open(self._file_name, "rb")
73 except IOError, e:
74 if (self._flag != "c"):
75 raise e
76 self._open(self._file_name, "wb", self._mode)
77 else:
78 p = f.read()
79 if (len(p) > 0):
80 try:
81 self._dict = cPickle.loads(p)
82 except (cPickle.UnpicklingError, EOFError):
83 if (ignore_corrupt_dbfiles == 0): raise
84 if (ignore_corrupt_dbfiles == 1):
85 corruption_warning(self._file_name)
86
88 if (self._needs_sync):
89 self.sync()
90
92 self._check_writable()
93 f = self._open(self._tmp_name, "wb", self._mode)
94 self._cPickle_dump(self._dict, f, 1)
95 f.close()
96
97
98
99
100
101
102 try: self._os_chmod(self._file_name, 0777)
103 except OSError: pass
104 self._os_unlink(self._file_name)
105 self._os_rename(self._tmp_name, self._file_name)
106 self._needs_sync = 00000
107 if (keep_all_files):
108 self._shutil_copyfile(
109 self._file_name,
110 self._file_name + "_" + str(int(self._time_time())))
111
113 if (self._flag == "r"):
114 raise IOError("Read-only database: %s" % self._file_name)
115
117 return self._dict[key]
118
120 self._check_writable()
121 if (not is_string(key)):
122 raise TypeError, "key `%s' must be a string but is %s" % (key, type(key))
123 if (not is_string(value)):
124 raise TypeError, "value `%s' must be a string but is %s" % (value, type(value))
125 self._dict[key] = value
126 self._needs_sync = 0001
127
129 return self._dict.keys()
130
132 return key in self._dict
133
135 return key in self._dict
136
139
140 __iter__ = iterkeys
141
143 return len(self._dict)
144
145 -def open(file, flag=None, mode=0666):
146 return dblite(file, flag, mode)
147
149 db = open("tmp", "n")
150 assert len(db) == 0
151 db["foo"] = "bar"
152 assert db["foo"] == "bar"
153 db[unicode("ufoo")] = unicode("ubar")
154 assert db[unicode("ufoo")] == unicode("ubar")
155 db.sync()
156 db = open("tmp", "c")
157 assert len(db) == 2, len(db)
158 assert db["foo"] == "bar"
159 db["bar"] = "foo"
160 assert db["bar"] == "foo"
161 db[unicode("ubar")] = unicode("ufoo")
162 assert db[unicode("ubar")] == unicode("ufoo")
163 db.sync()
164 db = open("tmp", "r")
165 assert len(db) == 4, len(db)
166 assert db["foo"] == "bar"
167 assert db["bar"] == "foo"
168 assert db[unicode("ufoo")] == unicode("ubar")
169 assert db[unicode("ubar")] == unicode("ufoo")
170 try:
171 db.sync()
172 except IOError, e:
173 assert str(e) == "Read-only database: tmp.dblite"
174 else:
175 raise RuntimeError, "IOError expected."
176 db = open("tmp", "w")
177 assert len(db) == 4
178 db["ping"] = "pong"
179 db.sync()
180 try:
181 db[(1,2)] = "tuple"
182 except TypeError, e:
183 assert str(e) == "key `(1, 2)' must be a string but is <type 'tuple'>", str(e)
184 else:
185 raise RuntimeError, "TypeError exception expected"
186 try:
187 db["list"] = [1,2]
188 except TypeError, e:
189 assert str(e) == "value `[1, 2]' must be a string but is <type 'list'>", str(e)
190 else:
191 raise RuntimeError, "TypeError exception expected"
192 db = open("tmp", "r")
193 assert len(db) == 5
194 db = open("tmp", "n")
195 assert len(db) == 0
196 _open("tmp.dblite", "w")
197 db = open("tmp", "r")
198 _open("tmp.dblite", "w").write("x")
199 try:
200 db = open("tmp", "r")
201 except cPickle.UnpicklingError:
202 pass
203 else:
204 raise RuntimeError, "cPickle exception expected."
205 global ignore_corrupt_dbfiles
206 ignore_corrupt_dbfiles = 2
207 db = open("tmp", "r")
208 assert len(db) == 0
209 os.unlink("tmp.dblite")
210 try:
211 db = open("tmp", "w")
212 except IOError, e:
213 assert str(e) == "[Errno 2] No such file or directory: 'tmp.dblite'", str(e)
214 else:
215 raise RuntimeError, "IOError expected."
216 print "OK"
217
218 if (__name__ == "__main__"):
219 _exercise()
220