blob: e262d79ec35f6befdc3c0accbe2a74aaeccc35c6 [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 Montanaro3bf99e32002-12-08 18:36:24 +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 Montanaro3bf99e32002-12-08 18:36:24 +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
Tim Peters495ad3c2001-01-15 01:36:40 +0000160 Argument is the filename for the dbm database.
161 See the module's __doc__ string for an overview of the interface.
162 """
163
Skip Montanaro3bf99e32002-12-08 18:36:24 +0000164 return DbfilenameShelf(filename, flag, binary)