blob: a06853663bd90d44f1e464a2efcb833f7a1a2df7 [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)
22 flag = d.has_key(key) # true if the key exists
23 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:
Fred Drake13a2c272000-02-10 17:17:14 +000034 from cPickle import Pickler, Unpickler
Guido van Rossum914c9381997-06-06 21:12:45 +000035except ImportError:
Fred Drake13a2c272000-02-10 17:17:14 +000036 from pickle import Pickler, Unpickler
Guido van Rossum914c9381997-06-06 21:12:45 +000037
38try:
Fred Drake13a2c272000-02-10 17:17:14 +000039 from cStringIO import StringIO
Guido van Rossum914c9381997-06-06 21:12:45 +000040except ImportError:
Fred Drake13a2c272000-02-10 17:17:14 +000041 from StringIO import StringIO
Guido van Rossuma48061a1995-01-10 00:31:14 +000042
Guido van Rossumcc6764c1995-02-09 17:18:10 +000043
Guido van Rossuma48061a1995-01-10 00:31:14 +000044class Shelf:
Fred Drake13a2c272000-02-10 17:17:14 +000045 """Base class for shelf implementations.
Guido van Rossumcc6764c1995-02-09 17:18:10 +000046
Fred Drake13a2c272000-02-10 17:17:14 +000047 This is initialized with a dictionary-like object.
48 See the module's __doc__ string for an overview of the interface.
49 """
Guido van Rossuma48061a1995-01-10 00:31:14 +000050
Fred Drake13a2c272000-02-10 17:17:14 +000051 def __init__(self, dict):
52 self.dict = dict
53
54 def keys(self):
55 return self.dict.keys()
56
57 def __len__(self):
58 return len(self.dict)
59
60 def has_key(self, key):
61 return self.dict.has_key(key)
Guido van Rossum2f7df121999-08-11 01:54:05 +000062
Fred Drake13a2c272000-02-10 17:17:14 +000063 def get(self, key, default=None):
64 if self.dict.has_key(key):
65 return self[key]
66 return default
67
68 def __getitem__(self, key):
69 f = StringIO(self.dict[key])
70 return Unpickler(f).load()
71
72 def __setitem__(self, key, value):
73 f = StringIO()
74 p = Pickler(f)
75 p.dump(value)
76 self.dict[key] = f.getvalue()
77
78 def __delitem__(self, key):
79 del self.dict[key]
80
81 def close(self):
82 try:
83 self.dict.close()
84 except:
85 pass
86 self.dict = 0
Guido van Rossuma48061a1995-01-10 00:31:14 +000087
Fred Drake13a2c272000-02-10 17:17:14 +000088 def __del__(self):
89 self.close()
Guido van Rossuma48061a1995-01-10 00:31:14 +000090
Fred Drake13a2c272000-02-10 17:17:14 +000091 def sync(self):
92 if hasattr(self.dict, 'sync'):
93 self.dict.sync()
94
Guido van Rossumcc6764c1995-02-09 17:18:10 +000095
Guido van Rossumabad1cc1995-08-11 14:19:16 +000096class BsdDbShelf(Shelf):
Fred Drake13a2c272000-02-10 17:17:14 +000097 """Shelf implementation using the "BSD" db interface.
Guido van Rossumabad1cc1995-08-11 14:19:16 +000098
Fred Drake13a2c272000-02-10 17:17:14 +000099 This adds methods first(), next(), previous(), last() and
100 set_location() that have no counterpart in [g]dbm databases.
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000101
Fred Drake13a2c272000-02-10 17:17:14 +0000102 The actual database must be opened using one of the "bsddb"
103 modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen or
104 bsddb.rnopen) and passed to the constructor.
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000105
Fred Drake13a2c272000-02-10 17:17:14 +0000106 See the module's __doc__ string for an overview of the interface.
107 """
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000108
Fred Drake13a2c272000-02-10 17:17:14 +0000109 def __init__(self, dict):
110 Shelf.__init__(self, dict)
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000111
Fred Drake13a2c272000-02-10 17:17:14 +0000112 def set_location(self, key):
113 (key, value) = self.dict.set_location(key)
114 f = StringIO(value)
115 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000116
Fred Drake13a2c272000-02-10 17:17:14 +0000117 def next(self):
118 (key, value) = self.dict.next()
119 f = StringIO(value)
120 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000121
Fred Drake13a2c272000-02-10 17:17:14 +0000122 def previous(self):
123 (key, value) = self.dict.previous()
124 f = StringIO(value)
125 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000126
Fred Drake13a2c272000-02-10 17:17:14 +0000127 def first(self):
128 (key, value) = self.dict.first()
129 f = StringIO(value)
130 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000131
Fred Drake13a2c272000-02-10 17:17:14 +0000132 def last(self):
133 (key, value) = self.dict.last()
134 f = StringIO(value)
135 return (key, Unpickler(f).load())
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000136
137
138class DbfilenameShelf(Shelf):
Fred Drake13a2c272000-02-10 17:17:14 +0000139 """Shelf implementation using the "anydbm" generic dbm interface.
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000140
Fred Drake13a2c272000-02-10 17:17:14 +0000141 This is initialized with the filename for the dbm database.
142 See the module's __doc__ string for an overview of the interface.
143 """
144
145 def __init__(self, filename, flag='c'):
146 import anydbm
147 Shelf.__init__(self, anydbm.open(filename, flag))
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000148
149
Guido van Rossumabad1cc1995-08-11 14:19:16 +0000150def open(filename, flag='c'):
Fred Drake13a2c272000-02-10 17:17:14 +0000151 """Open a persistent dictionary for reading and writing.
Guido van Rossumcc6764c1995-02-09 17:18:10 +0000152
Fred Drake13a2c272000-02-10 17:17:14 +0000153 Argument is the filename for the dbm database.
154 See the module's __doc__ string for an overview of the interface.
155 """
156
157 return DbfilenameShelf(filename, flag)