mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 02:15:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """Manage shelves of pickled objects.
 | |
| 
 | |
| A "shelf" is a persistent, dictionary-like object.  The difference
 | |
| with dbm databases is that the values (not the keys!) in a shelf can
 | |
| be essentially arbitrary Python objects -- anything that the "pickle"
 | |
| module can handle.  This includes most class instances, recursive data
 | |
| types, and objects containing lots of shared sub-objects.  The keys
 | |
| are ordinary strings.
 | |
| 
 | |
| To summarize the interface (key is a string, data is an arbitrary
 | |
| object):
 | |
| 
 | |
|         import shelve
 | |
|         d = shelve.open(filename) # open, with (g)dbm filename -- no suffix
 | |
| 
 | |
|         d[key] = data   # store data at key (overwrites old data if
 | |
|                         # using an existing key)
 | |
|         data = d[key]   # retrieve data at key (raise KeyError if no
 | |
|                         # such key)
 | |
|         del d[key]      # delete data stored at key (raises KeyError
 | |
|                         # if no such key)
 | |
|         flag = d.has_key(key)   # true if the key exists; same as "key in d"
 | |
|         list = d.keys() # a list of all existing keys (slow!)
 | |
| 
 | |
|         d.close()       # close it
 | |
| 
 | |
| Dependent on the implementation, closing a persistent dictionary may
 | |
| or may not be necessary to flush changes to disk.
 | |
| """
 | |
| 
 | |
| # Try using cPickle and cStringIO if available.
 | |
| 
 | |
| try:
 | |
|     from cPickle import Pickler, Unpickler
 | |
| except ImportError:
 | |
|     from pickle import Pickler, Unpickler
 | |
| 
 | |
| try:
 | |
|     from cStringIO import StringIO
 | |
| except ImportError:
 | |
|     from StringIO import StringIO
 | |
| 
 | |
| import UserDict
 | |
| 
 | |
| __all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]
 | |
| 
 | |
| class Shelf(UserDict.DictMixin):
 | |
|     """Base class for shelf implementations.
 | |
| 
 | |
|     This is initialized with a dictionary-like object.
 | |
|     See the module's __doc__ string for an overview of the interface.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, dict, binary=False):
 | |
|         self.dict = dict
 | |
|         self._binary = binary
 | |
| 
 | |
|     def keys(self):
 | |
|         return self.dict.keys()
 | |
| 
 | |
|     def __len__(self):
 | |
|         return len(self.dict)
 | |
| 
 | |
|     def has_key(self, key):
 | |
|         return self.dict.has_key(key)
 | |
| 
 | |
|     def __contains__(self, key):
 | |
|         return self.dict.has_key(key)
 | |
| 
 | |
|     def get(self, key, default=None):
 | |
|         if self.dict.has_key(key):
 | |
|             return self[key]
 | |
|         return default
 | |
| 
 | |
|     def __getitem__(self, key):
 | |
|         f = StringIO(self.dict[key])
 | |
|         return Unpickler(f).load()
 | |
| 
 | |
|     def __setitem__(self, key, value):
 | |
|         f = StringIO()
 | |
|         p = Pickler(f, self._binary)
 | |
|         p.dump(value)
 | |
|         self.dict[key] = f.getvalue()
 | |
| 
 | |
|     def __delitem__(self, key):
 | |
|         del self.dict[key]
 | |
| 
 | |
|     def close(self):
 | |
|         try:
 | |
|             self.dict.close()
 | |
|         except:
 | |
|             pass
 | |
|         self.dict = 0
 | |
| 
 | |
|     def __del__(self):
 | |
|         self.close()
 | |
| 
 | |
|     def sync(self):
 | |
|         if hasattr(self.dict, 'sync'):
 | |
|             self.dict.sync()
 | |
| 
 | |
| 
 | |
| class BsdDbShelf(Shelf):
 | |
|     """Shelf implementation using the "BSD" db interface.
 | |
| 
 | |
|     This adds methods first(), next(), previous(), last() and
 | |
|     set_location() that have no counterpart in [g]dbm databases.
 | |
| 
 | |
|     The actual database must be opened using one of the "bsddb"
 | |
|     modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen or
 | |
|     bsddb.rnopen) and passed to the constructor.
 | |
| 
 | |
|     See the module's __doc__ string for an overview of the interface.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, dict, binary=False):
 | |
|         Shelf.__init__(self, dict, binary)
 | |
| 
 | |
|     def set_location(self, key):
 | |
|         (key, value) = self.dict.set_location(key)
 | |
|         f = StringIO(value)
 | |
|         return (key, Unpickler(f).load())
 | |
| 
 | |
|     def next(self):
 | |
|         (key, value) = self.dict.next()
 | |
|         f = StringIO(value)
 | |
|         return (key, Unpickler(f).load())
 | |
| 
 | |
|     def previous(self):
 | |
|         (key, value) = self.dict.previous()
 | |
|         f = StringIO(value)
 | |
|         return (key, Unpickler(f).load())
 | |
| 
 | |
|     def first(self):
 | |
|         (key, value) = self.dict.first()
 | |
|         f = StringIO(value)
 | |
|         return (key, Unpickler(f).load())
 | |
| 
 | |
|     def last(self):
 | |
|         (key, value) = self.dict.last()
 | |
|         f = StringIO(value)
 | |
|         return (key, Unpickler(f).load())
 | |
| 
 | |
| 
 | |
| class DbfilenameShelf(Shelf):
 | |
|     """Shelf implementation using the "anydbm" generic dbm interface.
 | |
| 
 | |
|     This is initialized with the filename for the dbm database.
 | |
|     See the module's __doc__ string for an overview of the interface.
 | |
|     """
 | |
| 
 | |
|     def __init__(self, filename, flag='c', binary=False):
 | |
|         import anydbm
 | |
|         Shelf.__init__(self, anydbm.open(filename, flag), binary)
 | |
| 
 | |
| 
 | |
| def open(filename, flag='c', binary=False):
 | |
|     """Open a persistent dictionary for reading and writing.
 | |
| 
 | |
|     The filename parameter is the base filename for the underlying database.
 | |
|     As a side-effect, an extension may be added to the filename and more
 | |
|     than one file may be created.  The optional flag parameter has the
 | |
|     same interpretation as the flag parameter of anydbm.open().  The
 | |
|     optional binary parameter may be set to True to force the use of binary
 | |
|     pickles for serializing data values.
 | |
| 
 | |
|     See the module's __doc__ string for an overview of the interface.
 | |
|     """
 | |
| 
 | |
|     return DbfilenameShelf(filename, flag, binary)
 | 
