blob: 982c4e243a4fcb6cce06f9428e92f9fc25e23efd [file] [log] [blame]
Guido van Rossumcc6764c1995-02-09 17:18:10 +00001"""Manage shelves of pickled objects.
2
3A "shelf" is a persistent, dictionary-like object. The difference
4with dbm databases is that the values (not the keys!) in a shelf can
5be essentially arbitrary Python objects -- anything that the "pickle"
6module can handle. This includes most class instances, recursive data
7types, and objects containing lots of shared sub-objects. The keys
8are ordinary strings.
9
10To summarize the interface (key is a string, data is an arbitrary
11object):
12
Fred Drake13a2c272000-02-10 17:17:14 +000013 import shelve
14 d = shelve.open(filename) # open, with (g)dbm filename -- no suffix
Guido van Rossumcc6764c1995-02-09 17:18:10 +000015
Fred Drake13a2c272000-02-10 17:17:14 +000016 d[key] = data # store data at key (overwrites old data if
17 # using an existing key)
18 data = d[key] # retrieve data at key (raise KeyError if no
19 # such key)
20 del d[key] # delete data stored at key (raises KeyError
21 # if no such key)
Martin v. Löwise4913c92002-10-18 08:58:14 +000022 flag = d.has_key(key) # true if the key exists; same as "key in d"
Fred Drake13a2c272000-02-10 17:17:14 +000023 list = d.keys() # a list of all existing keys (slow!)
Guido van Rossumcc6764c1995-02-09 17:18:10 +000024
Fred Drake13a2c272000-02-10 17:17:14 +000025 d.close() # close it
Guido van Rossumcc6764c1995-02-09 17:18:10 +000026
27Dependent on the implementation, closing a persistent dictionary may
28or may not be necessary to flush changes to disk.
29"""
Guido van Rossuma48061a1995-01-10 00:31:14 +000030
Guido van Rossum914c9381997-06-06 21:12:45 +000031# Try using cPickle and cStringIO if available.
32
33try:
Tim Peters495ad3c2001-01-15 01:36:40 +000034 from cPickle import Pickler, Unpickler
Guido van Rossum914c9381997-06-06 21:12:45 +000035except ImportError:
Tim Peters495ad3c2001-01-15 01:36:40 +000036 from pickle import Pickler, Unpickler
Guido van Rossum914c9381997-06-06 21:12:45 +000037
38try:
Tim Peters495ad3c2001-01-15 01:36:40 +000039 from cStringIO import StringIO
Guido van Rossum914c9381997-06-06 21:12:45 +000040except ImportError:
Tim Peters495ad3c2001-01-15 01:36:40 +000041 from StringIO import StringIO
Guido van Rossuma48061a1995-01-10 00:31:14 +000042
Raymond Hettinger79947162002-11-15 06:46:14 +000043import UserDict
44
Skip Montanaro0de65802001-02-15 22:15:14 +000045__all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]
Guido van Rossumcc6764c1995-02-09 17:18:10 +000046
Raymond Hettinger79947162002-11-15 06:46:14 +000047class Shelf(UserDict.DictMixin):
Tim Peters495ad3c2001-01-15 01:36:40 +000048 """Base class for shelf implementations.
Guido van Rossumcc6764c1995-02-09 17:18:10 +000049
Tim Peters495ad3c2001-01-15 01:36:40 +000050 This is initialized with a dictionary-like object.
51 See the module's __doc__ string for an overview of the interface.
52 """
Guido van Rossuma48061a1995-01-10 00:31:14 +000053
Skip Montanaro3bf99e32002-12-08 18:36:24 +000054 def __init__(self, dict, binary=False):
Tim Peters495ad3c2001-01-15 01:36:40 +000055 self.dict = dict
Skip Montanaro123dc8e2002-12-08 21:25:00 +000056 self._binary = binary
Guido van Rossum2f7df121999-08-11 01:54:05 +000057
Tim Peters495ad3c2001-01-15 01:36:40 +000058 def keys(self):
59 return self.dict.keys()
Guido van Rossuma48061a1995-01-10 00:31:14 +000060
Tim Peters495ad3c2001-01-15 01:36:40 +000061 def __len__(self):
62 return len(self.dict)
Guido van Rossuma48061a1995-01-10 00:31:14 +000063
Tim Peters495ad3c2001-01-15 01:36:40 +000064 def has_key(self, key):
65 return self.dict.has_key(key)
66
Martin v. Löwise4913c92002-10-18 08:58:14 +000067 def __contains__(self, key):
68 return self.dict.has_key(key)
69
Tim Peters495ad3c2001-01-15 01:36:40 +000070 def get(self, key, default=None):
71 if self.dict.has_key(key):
72 return self[key]
73 return default
74
75 def __getitem__(self, key):
76 f = StringIO(self.dict[key])
77 return Unpickler(f).load()
78
79 def __setitem__(self, key, value):
80 f = StringIO()
Skip Montanaro123dc8e2002-12-08 21:25:00 +000081 p = Pickler(f, self._binary)
Tim Peters495ad3c2001-01-15 01:36:40 +000082 p.dump(value)
83 self.dict[key] = f.getvalue()
84
85 def __delitem__(self, key):
86 del self.dict[key]
87
88 def close(self):
89 try:
90 self.dict.close()
91 except:
92 pass
93 self.dict = 0
94
95 def __del__(self):
96 self.close()
97
98 def sync(self):
99 if hasattr(self.dict, 'sync'):
100 self.dict.sync()
101
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000102
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000103class BsdDbShelf(Shelf):
Tim Peters495ad3c2001-01-15 01:36:40 +0000104 """Shelf implementation using the "BSD" db interface.
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000105
Tim Peters495ad3c2001-01-15 01:36:40 +0000106 This adds methods first(), next(), previous(), last() and
107 set_location() that have no counterpart in [g]dbm databases.
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000108
Tim Peters495ad3c2001-01-15 01:36:40 +0000109 The actual database must be opened using one of the "bsddb"
110 modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen or
111 bsddb.rnopen) and passed to the constructor.
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000112
Tim Peters495ad3c2001-01-15 01:36:40 +0000113 See the module's __doc__ string for an overview of the interface.
114 """
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000115
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000116 def __init__(self, dict, binary=False):
117 Shelf.__init__(self, dict, binary)
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000118
Tim Peters495ad3c2001-01-15 01:36:40 +0000119 def set_location(self, key):
120 (key, value) = self.dict.set_location(key)
121 f = StringIO(value)
122 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000123
Tim Peters495ad3c2001-01-15 01:36:40 +0000124 def next(self):
125 (key, value) = self.dict.next()
126 f = StringIO(value)
127 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000128
Tim Peters495ad3c2001-01-15 01:36:40 +0000129 def previous(self):
130 (key, value) = self.dict.previous()
131 f = StringIO(value)
132 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000133
Tim Peters495ad3c2001-01-15 01:36:40 +0000134 def first(self):
135 (key, value) = self.dict.first()
136 f = StringIO(value)
137 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000138
Tim Peters495ad3c2001-01-15 01:36:40 +0000139 def last(self):
140 (key, value) = self.dict.last()
141 f = StringIO(value)
142 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000143
144
145class DbfilenameShelf(Shelf):
Tim Peters495ad3c2001-01-15 01:36:40 +0000146 """Shelf implementation using the "anydbm" generic dbm interface.
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000147
Tim Peters495ad3c2001-01-15 01:36:40 +0000148 This is initialized with the filename for the dbm database.
149 See the module's __doc__ string for an overview of the interface.
150 """
151
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000152 def __init__(self, filename, flag='c', binary=False):
Tim Peters495ad3c2001-01-15 01:36:40 +0000153 import anydbm
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000154 Shelf.__init__(self, anydbm.open(filename, flag), binary)
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000155
156
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000157def open(filename, flag='c', binary=False):
Tim Peters495ad3c2001-01-15 01:36:40 +0000158 """Open a persistent dictionary for reading and writing.
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000159
Skip Montanarob3b22f32003-01-21 01:53:09 +0000160 The filename parameter is the base filename for the underlying database.
161 As a side-effect, an extension may be added to the filename and more
162 than one file may be created. The optional flag parameter has the
163 same interpretation as the flag parameter of anydbm.open(). The
164 optional binary parameter may be set to True to force the use of binary
165 pickles for serializing data values.
166
Tim Peters495ad3c2001-01-15 01:36:40 +0000167 See the module's __doc__ string for an overview of the interface.
168 """
169
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000170 return DbfilenameShelf(filename, flag, binary)