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