home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / dbshelve.py < prev    next >
Text File  |  2003-12-30  |  9KB  |  294 lines

  1. #!/bin/env python
  2. #------------------------------------------------------------------------
  3. #           Copyright (c) 1997-2001 by Total Control Software
  4. #                         All Rights Reserved
  5. #------------------------------------------------------------------------
  6. #
  7. # Module Name:  dbShelve.py
  8. #
  9. # Description:  A reimplementation of the standard shelve.py that
  10. #               forces the use of cPickle, and DB.
  11. #
  12. # Creation Date:    11/3/97 3:39:04PM
  13. #
  14. # License:      This is free software.  You may use this software for any
  15. #               purpose including modification/redistribution, so long as
  16. #               this header remains intact and that you do not claim any
  17. #               rights of ownership or authorship of this software.  This
  18. #               software has been tested, but no warranty is expressed or
  19. #               implied.
  20. #
  21. # 13-Dec-2000:  Updated to be used with the new bsddb3 package.
  22. #               Added DBShelfCursor class.
  23. #
  24. #------------------------------------------------------------------------
  25.  
  26. """Manage shelves of pickled objects using bsddb database files for the
  27. storage.
  28. """
  29.  
  30. #------------------------------------------------------------------------
  31.  
  32. import cPickle
  33. try:
  34.     from UserDict import DictMixin
  35. except ImportError:
  36.     # DictMixin is new in Python 2.3
  37.     class DictMixin: pass
  38. import db
  39.  
  40. #------------------------------------------------------------------------
  41.  
  42.  
  43. def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
  44.          dbenv=None, dbname=None):
  45.     """
  46.     A simple factory function for compatibility with the standard
  47.     shleve.py module.  It can be used like this, where key is a string
  48.     and data is a pickleable object:
  49.  
  50.         from bsddb import dbshelve
  51.         db = dbshelve.open(filename)
  52.  
  53.         db[key] = data
  54.  
  55.         db.close()
  56.     """
  57.     if type(flags) == type(''):
  58.         sflag = flags
  59.         if sflag == 'r':
  60.             flags = db.DB_RDONLY
  61.         elif sflag == 'rw':
  62.             flags = 0
  63.         elif sflag == 'w':
  64.             flags =  db.DB_CREATE
  65.         elif sflag == 'c':
  66.             flags =  db.DB_CREATE
  67.         elif sflag == 'n':
  68.             flags = db.DB_TRUNCATE | db.DB_CREATE
  69.         else:
  70.             raise error, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"
  71.  
  72.     d = DBShelf(dbenv)
  73.     d.open(filename, dbname, filetype, flags, mode)
  74.     return d
  75.  
  76. #---------------------------------------------------------------------------
  77.  
  78. class DBShelf(DictMixin):
  79.     """A shelf to hold pickled objects, built upon a bsddb DB object.  It
  80.     automatically pickles/unpickles data objects going to/from the DB.
  81.     """
  82.     def __init__(self, dbenv=None):
  83.         self.db = db.DB(dbenv)
  84.         self.binary = 1
  85.  
  86.  
  87.     def __del__(self):
  88.         self.close()
  89.  
  90.  
  91.     def __getattr__(self, name):
  92.         """Many methods we can just pass through to the DB object.
  93.         (See below)
  94.         """
  95.         return getattr(self.db, name)
  96.  
  97.  
  98.     #-----------------------------------
  99.     # Dictionary access methods
  100.  
  101.     def __len__(self):
  102.         return len(self.db)
  103.  
  104.  
  105.     def __getitem__(self, key):
  106.         data = self.db[key]
  107.         return cPickle.loads(data)
  108.  
  109.  
  110.     def __setitem__(self, key, value):
  111.         data = cPickle.dumps(value, self.binary)
  112.         self.db[key] = data
  113.  
  114.  
  115.     def __delitem__(self, key):
  116.         del self.db[key]
  117.  
  118.  
  119.     def keys(self, txn=None):
  120.         if txn != None:
  121.             return self.db.keys(txn)
  122.         else:
  123.             return self.db.keys()
  124.  
  125.  
  126.     def items(self, txn=None):
  127.         if txn != None:
  128.             items = self.db.items(txn)
  129.         else:
  130.             items = self.db.items()
  131.         newitems = []
  132.  
  133.         for k, v in items:
  134.             newitems.append( (k, cPickle.loads(v)) )
  135.         return newitems
  136.  
  137.     def values(self, txn=None):
  138.         if txn != None:
  139.             values = self.db.values(txn)
  140.         else:
  141.             values = self.db.values()
  142.  
  143.         return map(cPickle.loads, values)
  144.  
  145.     #-----------------------------------
  146.     # Other methods
  147.  
  148.     def append(self, value, txn=None):
  149.         data = cPickle.dumps(value, self.binary)
  150.         return self.db.append(data, txn)
  151.  
  152.  
  153.     def associate(self, secondaryDB, callback, flags=0):
  154.         def _shelf_callback(priKey, priData, realCallback=callback):
  155.             data = cPickle.loads(priData)
  156.             return realCallback(priKey, data)
  157.         return self.db.associate(secondaryDB, _shelf_callback, flags)
  158.  
  159.  
  160.     #def get(self, key, default=None, txn=None, flags=0):
  161.     def get(self, *args, **kw):
  162.         # We do it with *args and **kw so if the default value wasn't
  163.         # given nothing is passed to the extension module.  That way
  164.         # an exception can be raised if set_get_returns_none is turned
  165.         # off.
  166.         data = apply(self.db.get, args, kw)
  167.         try:
  168.             return cPickle.loads(data)
  169.         except (TypeError, cPickle.UnpicklingError):
  170.             return data  # we may be getting the default value, or None,
  171.                          # so it doesn't need unpickled.
  172.  
  173.     def get_both(self, key, value, txn=None, flags=0):
  174.         data = cPickle.dumps(value, self.binary)
  175.         data = self.db.get(key, data, txn, flags)
  176.         return cPickle.loads(data)
  177.  
  178.  
  179.     def cursor(self, txn=None, flags=0):
  180.         c = DBShelfCursor(self.db.cursor(txn, flags))
  181.         c.binary = self.binary
  182.         return c
  183.  
  184.  
  185.     def put(self, key, value, txn=None, flags=0):
  186.         data = cPickle.dumps(value, self.binary)
  187.         return self.db.put(key, data, txn, flags)
  188.  
  189.  
  190.     def join(self, cursorList, flags=0):
  191.         raise NotImplementedError
  192.  
  193.  
  194.     #----------------------------------------------
  195.     # Methods allowed to pass-through to self.db
  196.     #
  197.     #    close,  delete, fd, get_byteswapped, get_type, has_key,
  198.     #    key_range, open, remove, rename, stat, sync,
  199.     #    upgrade, verify, and all set_* methods.
  200.  
  201.  
  202. #---------------------------------------------------------------------------
  203.  
  204. class DBShelfCursor:
  205.     """
  206.     """
  207.     def __init__(self, cursor):
  208.         self.dbc = cursor
  209.  
  210.     def __del__(self):
  211.         self.close()
  212.  
  213.  
  214.     def __getattr__(self, name):
  215.         """Some methods we can just pass through to the cursor object.  (See below)"""
  216.         return getattr(self.dbc, name)
  217.  
  218.  
  219.     #----------------------------------------------
  220.  
  221.     def dup(self, flags=0):
  222.         return DBShelfCursor(self.dbc.dup(flags))
  223.  
  224.  
  225.     def put(self, key, value, flags=0):
  226.         data = cPickle.dumps(value, self.binary)
  227.         return self.dbc.put(key, data, flags)
  228.  
  229.  
  230.     def get(self, *args):
  231.         count = len(args)  # a method overloading hack
  232.         method = getattr(self, 'get_%d' % count)
  233.         apply(method, args)
  234.  
  235.     def get_1(self, flags):
  236.         rec = self.dbc.get(flags)
  237.         return self._extract(rec)
  238.  
  239.     def get_2(self, key, flags):
  240.         rec = self.dbc.get(key, flags)
  241.         return self._extract(rec)
  242.  
  243.     def get_3(self, key, value, flags):
  244.         data = cPickle.dumps(value, self.binary)
  245.         rec = self.dbc.get(key, flags)
  246.         return self._extract(rec)
  247.  
  248.  
  249.     def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
  250.     def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
  251.     def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
  252.     def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
  253.     def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
  254.     def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
  255.     def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
  256.     def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
  257.     def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)
  258.  
  259.  
  260.     def get_both(self, key, value, flags=0):
  261.         data = cPickle.dumps(value, self.binary)
  262.         rec = self.dbc.get_both(key, flags)
  263.         return self._extract(rec)
  264.  
  265.  
  266.     def set(self, key, flags=0):
  267.         rec = self.dbc.set(key, flags)
  268.         return self._extract(rec)
  269.  
  270.     def set_range(self, key, flags=0):
  271.         rec = self.dbc.set_range(key, flags)
  272.         return self._extract(rec)
  273.  
  274.     def set_recno(self, recno, flags=0):
  275.         rec = self.dbc.set_recno(recno, flags)
  276.         return self._extract(rec)
  277.  
  278.     set_both = get_both
  279.  
  280.     def _extract(self, rec):
  281.         if rec is None:
  282.             return None
  283.         else:
  284.             key, data = rec
  285.             return key, cPickle.loads(data)
  286.  
  287.     #----------------------------------------------
  288.     # Methods allowed to pass-through to self.dbc
  289.     #
  290.     # close, count, delete, get_recno, join_item
  291.  
  292.  
  293. #---------------------------------------------------------------------------
  294.