PyXR

c:\python24\lib \ bsddb \ dbshelve.py



0001 #!/bin/env python
0002 #------------------------------------------------------------------------
0003 #           Copyright (c) 1997-2001 by Total Control Software
0004 #                         All Rights Reserved
0005 #------------------------------------------------------------------------
0006 #
0007 # Module Name:  dbShelve.py
0008 #
0009 # Description:  A reimplementation of the standard shelve.py that
0010 #               forces the use of cPickle, and DB.
0011 #
0012 # Creation Date:    11/3/97 3:39:04PM
0013 #
0014 # License:      This is free software.  You may use this software for any
0015 #               purpose including modification/redistribution, so long as
0016 #               this header remains intact and that you do not claim any
0017 #               rights of ownership or authorship of this software.  This
0018 #               software has been tested, but no warranty is expressed or
0019 #               implied.
0020 #
0021 # 13-Dec-2000:  Updated to be used with the new bsddb3 package.
0022 #               Added DBShelfCursor class.
0023 #
0024 #------------------------------------------------------------------------
0025 
0026 """Manage shelves of pickled objects using bsddb database files for the
0027 storage.
0028 """
0029 
0030 #------------------------------------------------------------------------
0031 
0032 import cPickle
0033 try:
0034     from UserDict import DictMixin
0035 except ImportError:
0036     # DictMixin is new in Python 2.3
0037     class DictMixin: pass
0038 import db
0039 
0040 #------------------------------------------------------------------------
0041 
0042 
0043 def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
0044          dbenv=None, dbname=None):
0045     """
0046     A simple factory function for compatibility with the standard
0047     shleve.py module.  It can be used like this, where key is a string
0048     and data is a pickleable object:
0049 
0050         from bsddb import dbshelve
0051         db = dbshelve.open(filename)
0052 
0053         db[key] = data
0054 
0055         db.close()
0056     """
0057     if type(flags) == type(''):
0058         sflag = flags
0059         if sflag == 'r':
0060             flags = db.DB_RDONLY
0061         elif sflag == 'rw':
0062             flags = 0
0063         elif sflag == 'w':
0064             flags =  db.DB_CREATE
0065         elif sflag == 'c':
0066             flags =  db.DB_CREATE
0067         elif sflag == 'n':
0068             flags = db.DB_TRUNCATE | db.DB_CREATE
0069         else:
0070             raise db.DBError, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"
0071 
0072     d = DBShelf(dbenv)
0073     d.open(filename, dbname, filetype, flags, mode)
0074     return d
0075 
0076 #---------------------------------------------------------------------------
0077 
0078 class DBShelf(DictMixin):
0079     """A shelf to hold pickled objects, built upon a bsddb DB object.  It
0080     automatically pickles/unpickles data objects going to/from the DB.
0081     """
0082     def __init__(self, dbenv=None):
0083         self.db = db.DB(dbenv)
0084         self.binary = 1
0085 
0086 
0087     def __del__(self):
0088         self.close()
0089 
0090 
0091     def __getattr__(self, name):
0092         """Many methods we can just pass through to the DB object.
0093         (See below)
0094         """
0095         return getattr(self.db, name)
0096 
0097 
0098     #-----------------------------------
0099     # Dictionary access methods
0100 
0101     def __len__(self):
0102         return len(self.db)
0103 
0104 
0105     def __getitem__(self, key):
0106         data = self.db[key]
0107         return cPickle.loads(data)
0108 
0109 
0110     def __setitem__(self, key, value):
0111         data = cPickle.dumps(value, self.binary)
0112         self.db[key] = data
0113 
0114 
0115     def __delitem__(self, key):
0116         del self.db[key]
0117 
0118 
0119     def keys(self, txn=None):
0120         if txn != None:
0121             return self.db.keys(txn)
0122         else:
0123             return self.db.keys()
0124 
0125 
0126     def items(self, txn=None):
0127         if txn != None:
0128             items = self.db.items(txn)
0129         else:
0130             items = self.db.items()
0131         newitems = []
0132 
0133         for k, v in items:
0134             newitems.append( (k, cPickle.loads(v)) )
0135         return newitems
0136 
0137     def values(self, txn=None):
0138         if txn != None:
0139             values = self.db.values(txn)
0140         else:
0141             values = self.db.values()
0142 
0143         return map(cPickle.loads, values)
0144 
0145     #-----------------------------------
0146     # Other methods
0147 
0148     def __append(self, value, txn=None):
0149         data = cPickle.dumps(value, self.binary)
0150         return self.db.append(data, txn)
0151 
0152     def append(self, value, txn=None):
0153         if self.get_type() != db.DB_RECNO:
0154             self.append = self.__append
0155             return self.append(value, txn=txn)
0156         raise db.DBError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO"
0157 
0158 
0159     def associate(self, secondaryDB, callback, flags=0):
0160         def _shelf_callback(priKey, priData, realCallback=callback):
0161             data = cPickle.loads(priData)
0162             return realCallback(priKey, data)
0163         return self.db.associate(secondaryDB, _shelf_callback, flags)
0164 
0165 
0166     #def get(self, key, default=None, txn=None, flags=0):
0167     def get(self, *args, **kw):
0168         # We do it with *args and **kw so if the default value wasn't
0169         # given nothing is passed to the extension module.  That way
0170         # an exception can be raised if set_get_returns_none is turned
0171         # off.
0172         data = apply(self.db.get, args, kw)
0173         try:
0174             return cPickle.loads(data)
0175         except (TypeError, cPickle.UnpicklingError):
0176             return data  # we may be getting the default value, or None,
0177                          # so it doesn't need unpickled.
0178 
0179     def get_both(self, key, value, txn=None, flags=0):
0180         data = cPickle.dumps(value, self.binary)
0181         data = self.db.get(key, data, txn, flags)
0182         return cPickle.loads(data)
0183 
0184 
0185     def cursor(self, txn=None, flags=0):
0186         c = DBShelfCursor(self.db.cursor(txn, flags))
0187         c.binary = self.binary
0188         return c
0189 
0190 
0191     def put(self, key, value, txn=None, flags=0):
0192         data = cPickle.dumps(value, self.binary)
0193         return self.db.put(key, data, txn, flags)
0194 
0195 
0196     def join(self, cursorList, flags=0):
0197         raise NotImplementedError
0198 
0199 
0200     #----------------------------------------------
0201     # Methods allowed to pass-through to self.db
0202     #
0203     #    close,  delete, fd, get_byteswapped, get_type, has_key,
0204     #    key_range, open, remove, rename, stat, sync,
0205     #    upgrade, verify, and all set_* methods.
0206 
0207 
0208 #---------------------------------------------------------------------------
0209 
0210 class DBShelfCursor:
0211     """
0212     """
0213     def __init__(self, cursor):
0214         self.dbc = cursor
0215 
0216     def __del__(self):
0217         self.close()
0218 
0219 
0220     def __getattr__(self, name):
0221         """Some methods we can just pass through to the cursor object.  (See below)"""
0222         return getattr(self.dbc, name)
0223 
0224 
0225     #----------------------------------------------
0226 
0227     def dup(self, flags=0):
0228         return DBShelfCursor(self.dbc.dup(flags))
0229 
0230 
0231     def put(self, key, value, flags=0):
0232         data = cPickle.dumps(value, self.binary)
0233         return self.dbc.put(key, data, flags)
0234 
0235 
0236     def get(self, *args):
0237         count = len(args)  # a method overloading hack
0238         method = getattr(self, 'get_%d' % count)
0239         apply(method, args)
0240 
0241     def get_1(self, flags):
0242         rec = self.dbc.get(flags)
0243         return self._extract(rec)
0244 
0245     def get_2(self, key, flags):
0246         rec = self.dbc.get(key, flags)
0247         return self._extract(rec)
0248 
0249     def get_3(self, key, value, flags):
0250         data = cPickle.dumps(value, self.binary)
0251         rec = self.dbc.get(key, flags)
0252         return self._extract(rec)
0253 
0254 
0255     def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
0256     def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
0257     def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
0258     def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
0259     def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
0260     def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
0261     def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
0262     def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
0263     def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)
0264 
0265 
0266     def get_both(self, key, value, flags=0):
0267         data = cPickle.dumps(value, self.binary)
0268         rec = self.dbc.get_both(key, flags)
0269         return self._extract(rec)
0270 
0271 
0272     def set(self, key, flags=0):
0273         rec = self.dbc.set(key, flags)
0274         return self._extract(rec)
0275 
0276     def set_range(self, key, flags=0):
0277         rec = self.dbc.set_range(key, flags)
0278         return self._extract(rec)
0279 
0280     def set_recno(self, recno, flags=0):
0281         rec = self.dbc.set_recno(recno, flags)
0282         return self._extract(rec)
0283 
0284     set_both = get_both
0285 
0286     def _extract(self, rec):
0287         if rec is None:
0288             return None
0289         else:
0290             key, data = rec
0291             return key, cPickle.loads(data)
0292 
0293     #----------------------------------------------
0294     # Methods allowed to pass-through to self.dbc
0295     #
0296     # close, count, delete, get_recno, join_item
0297 
0298 
0299 #---------------------------------------------------------------------------
0300 

Generated by PyXR 0.9.4
SourceForge.net Logo