1 """filedict.py
2 a Persistent Dictionary in Python
3
4 Author: Erez Shinan
5 Date : 24-May-2009
6 """
7
8 import sqlite3
9 import cPickle as pickle
13
16
18 "A dictionary that stores its data persistantly in a file"
19
21 assert solution == Solutions.Sqlite3
22 try:
23 self.__conn = options.pop('connection')
24 except KeyError:
25 filename = options.pop('filename')
26 self.__conn = sqlite3.connect(filename)
27
28 self.__tablename = options.pop('table', 'dict')
29
30 self._nocommit = False
31
32 assert not options, "Unrecognized options: %s" % options
33
34 self.__conn.execute('create table if not exists %s (hash integer, key blob, value blob);'%self.__tablename)
35 self.__conn.execute('create index if not exists %s_index ON %s(hash);' % (self.__tablename, self.__tablename))
36 self.__conn.commit()
37
39 if self._nocommit:
40 return
41
42 self.__conn.commit()
43
45 return sqlite3.Binary(pickle.dumps(key, 1))
47 return sqlite3.Binary(pickle.dumps(value, -1))
49 return pickle.loads(str(value))
50
51 - def get(self, key, default=None):
52 try:
53 return self.__getitem__(key)
54 except KeyError:
55 return default
56
58 tbl = self.__tablename
59 key_hash = hash(key)
60 key_pickle = self.__pack_key(key)
61 c = self.__conn.execute('select value from %s where hash=? and key=?;'%tbl, (key_hash, key_pickle))
62 res = c.fetchone()
63 if res is None:
64 raise KeyError(key)
65
66 [value_pickle] = res
67 return self.__unpack_value(value_pickle)
68
70 tbl = self.__tablename
71 key_hash = hash(key)
72 key_pickle = self.__pack_key(key)
73 value_pickle = self.__pack_value(value)
74
75 res = self.__conn.execute('update %s set value=? where hash=? and key=?;'%tbl, (value_pickle, key_hash, key_pickle) )
76 if res.rowcount <= 0:
77 res = self.__conn.execute('insert into %s values (?, ?, ?);'%tbl, (key_hash, key_pickle, value_pickle) )
78
79 assert res.rowcount == 1
80
84
86 tbl = self.__tablename
87 key_hash = hash(key)
88 key_pickle = self.__pack_key(key)
89
90 res = self.__conn.execute('delete from %s where hash=? and key=?;'%tbl, (key_hash, key_pickle))
91 if res.rowcount <= 0:
92 raise KeyError(key)
93
94 self._commit()
95
100
102 try:
103 value = self[key]
104 except KeyError:
105 if default is DefaultArg:
106 raise
107 else:
108 value = self.get(key, default)
109 else:
110 del self[key]
111 return value
112
114 return (self.__unpack_value(x[0]) for x in self.__conn.execute('select key from %s;'%self.__tablename) )
116 return (self.__unpack_value(x[0]) for x in self.__conn.execute('select value from %s;'%self.__tablename) )
118 return (map(self.__unpack_value, x) for x in self.__conn.execute('select key,value from %s;'%self.__tablename) )
125
127 tbl = self.__tablename
128 key_hash = hash(key)
129 key_pickle = self.__pack_key(key)
130 c = self.__conn.execute('select count(*) from %(tbl)s where hash=%(key_hash)d and key=%(key_pickle)r;' % locals())
131 res = c.fetchone()
132 assert res
133 assert 0 <= res[0] <= 1
134
135 return bool(res[0])
136
139
141 return self.__conn.execute('select count(*) from %s;' % self.__tablename).fetchone()[0]
142
144 try:
145 self.__conn
146 except AttributeError:
147 pass
148 else:
149 self.__conn.commit()
150 self.__conn.close()
151
152 @property
155
159
161 self.__d._nocommit = True
162 return self.__d
163
164 - def __exit__(self, type, value, traceback):
165 self.__d._nocommit = False
166 self.__d._commit()
167 return True
168