56
56
the persistent dictionary on disk, if feasible).
57
57
"""
58
58
59
- from pickle import DEFAULT_PROTOCOL , Pickler , Unpickler
59
+ from pickle import DEFAULT_PROTOCOL , dumps , loads
60
60
from io import BytesIO
61
61
62
62
import collections .abc
63
63
64
- __all__ = ["Shelf" , "BsdDbShelf" , "DbfilenameShelf" , "open" ]
64
+ __all__ = ["ShelveError" , "Shelf" , "BsdDbShelf" , "DbfilenameShelf" , "open" ]
65
+
66
+
67
+ class ShelveError (Exception ):
68
+ pass
69
+
65
70
66
71
class _ClosedDict (collections .abc .MutableMapping ):
67
72
'Marker for a closed dict. Access attempts raise a ValueError.'
@@ -82,7 +87,7 @@ class Shelf(collections.abc.MutableMapping):
82
87
"""
83
88
84
89
def __init__ (self , dict , protocol = None , writeback = False ,
85
- keyencoding = "utf-8" ):
90
+ keyencoding = "utf-8" , * , serializer = None , deserializer = None ):
86
91
self .dict = dict
87
92
if protocol is None :
88
93
protocol = DEFAULT_PROTOCOL
@@ -91,6 +96,16 @@ def __init__(self, dict, protocol=None, writeback=False,
91
96
self .cache = {}
92
97
self .keyencoding = keyencoding
93
98
99
+ if serializer is None and deserializer is None :
100
+ self .serializer = dumps
101
+ self .deserializer = loads
102
+ elif (serializer is None ) ^ (deserializer is None ):
103
+ raise ShelveError ("serializer and deserializer must be "
104
+ "defined together" )
105
+ else :
106
+ self .serializer = serializer
107
+ self .deserializer = deserializer
108
+
94
109
def __iter__ (self ):
95
110
for k in self .dict .keys ():
96
111
yield k .decode (self .keyencoding )
@@ -110,19 +125,17 @@ def __getitem__(self, key):
110
125
try :
111
126
value = self .cache [key ]
112
127
except KeyError :
113
- f = BytesIO ( self .dict [key .encode (self .keyencoding )])
114
- value = Unpickler ( f ). load ( )
128
+ f = self .dict [key .encode (self .keyencoding )]
129
+ value = self . deserializer ( f )
115
130
if self .writeback :
116
131
self .cache [key ] = value
117
132
return value
118
133
119
134
def __setitem__ (self , key , value ):
120
135
if self .writeback :
121
136
self .cache [key ] = value
122
- f = BytesIO ()
123
- p = Pickler (f , self ._protocol )
124
- p .dump (value )
125
- self .dict [key .encode (self .keyencoding )] = f .getvalue ()
137
+ serialized_value = self .serializer (value , self ._protocol )
138
+ self .dict [key .encode (self .keyencoding )] = serialized_value
126
139
127
140
def __delitem__ (self , key ):
128
141
del self .dict [key .encode (self .keyencoding )]
@@ -191,33 +204,29 @@ class BsdDbShelf(Shelf):
191
204
"""
192
205
193
206
def __init__ (self , dict , protocol = None , writeback = False ,
194
- keyencoding = "utf-8" ):
195
- Shelf .__init__ (self , dict , protocol , writeback , keyencoding )
207
+ keyencoding = "utf-8" , * , serializer = None , deserializer = None ):
208
+ Shelf .__init__ (self , dict , protocol , writeback , keyencoding ,
209
+ serializer = serializer , deserializer = deserializer )
196
210
197
211
def set_location (self , key ):
198
212
(key , value ) = self .dict .set_location (key )
199
- f = BytesIO (value )
200
- return (key .decode (self .keyencoding ), Unpickler (f ).load ())
213
+ return (key .decode (self .keyencoding ), self .deserializer (value ))
201
214
202
215
def next (self ):
203
216
(key , value ) = next (self .dict )
204
- f = BytesIO (value )
205
- return (key .decode (self .keyencoding ), Unpickler (f ).load ())
217
+ return (key .decode (self .keyencoding ), self .deserializer (value ))
206
218
207
219
def previous (self ):
208
220
(key , value ) = self .dict .previous ()
209
- f = BytesIO (value )
210
- return (key .decode (self .keyencoding ), Unpickler (f ).load ())
221
+ return (key .decode (self .keyencoding ), self .deserializer (value ))
211
222
212
223
def first (self ):
213
224
(key , value ) = self .dict .first ()
214
- f = BytesIO (value )
215
- return (key .decode (self .keyencoding ), Unpickler (f ).load ())
225
+ return (key .decode (self .keyencoding ), self .deserializer (value ))
216
226
217
227
def last (self ):
218
228
(key , value ) = self .dict .last ()
219
- f = BytesIO (value )
220
- return (key .decode (self .keyencoding ), Unpickler (f ).load ())
229
+ return (key .decode (self .keyencoding ), self .deserializer (value ))
221
230
222
231
223
232
class DbfilenameShelf (Shelf ):
@@ -227,9 +236,11 @@ class DbfilenameShelf(Shelf):
227
236
See the module's __doc__ string for an overview of the interface.
228
237
"""
229
238
230
- def __init__ (self , filename , flag = 'c' , protocol = None , writeback = False ):
239
+ def __init__ (self , filename , flag = 'c' , protocol = None , writeback = False , * ,
240
+ serializer = None , deserializer = None ):
231
241
import dbm
232
- Shelf .__init__ (self , dbm .open (filename , flag ), protocol , writeback )
242
+ Shelf .__init__ (self , dbm .open (filename , flag ), protocol , writeback ,
243
+ serializer = serializer , deserializer = deserializer )
233
244
234
245
def clear (self ):
235
246
"""Remove all items from the shelf."""
@@ -238,8 +249,8 @@ def clear(self):
238
249
self .cache .clear ()
239
250
self .dict .clear ()
240
251
241
-
242
- def open ( filename , flag = 'c' , protocol = None , writeback = False ):
252
+ def open ( filename , flag = 'c' , protocol = None , writeback = False , * ,
253
+ serializer = None , deserializer = None ):
243
254
"""Open a persistent dictionary for reading and writing.
244
255
245
256
The filename parameter is the base filename for the underlying
@@ -252,4 +263,5 @@ def open(filename, flag='c', protocol=None, writeback=False):
252
263
See the module's __doc__ string for an overview of the interface.
253
264
"""
254
265
255
- return DbfilenameShelf (filename , flag , protocol , writeback )
266
+ return DbfilenameShelf (filename , flag , protocol , writeback ,
267
+ serializer = serializer , deserializer = deserializer )
0 commit comments