home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Freeware 31 / FreelogHS31.iso / Texte / scribus / scribus-1.3.3.9-win32-install.exe / lib / bsddb / dbshelve.py < prev    next >
Text File  |  2004-06-01  |  9KB  |  300 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 db.DBError, "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.     def append(self, value, txn=None):
  153.         if self.get_type() != db.DB_RECNO:
  154.             self.append = self.__append
  155.             return self.append(value, txn=txn)
  156.         raise db.DBError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO"
  157.  
  158.  
  159.     def associate(self, secondaryDB, callback, flags=0):
  160.         def _shelf_callback(priKey, priData, realCallback=callback):
  161.             data = cPickle.loads(priData)
  162.             return realCallback(priKey, data)
  163.         return self.db.associate(secondaryDB, _shelf_callback, flags)
  164.  
  165.  
  166.     #def get(self, key, default=None, txn=None, flags=0):
  167.     def get(self, *args, **kw):
  168.         # We do it with *args and **kw so if the default value wasn't
  169.         # given nothing is passed to the extension module.  That way
  170.         # an exception can be raised if set_get_returns_none is turned
  171.         # off.
  172.         data = apply(self.db.get, args, kw)
  173.         try:
  174.             return cPickle.loads(data)
  175.         except (TypeError, cPickle.UnpicklingError):
  176.             return data  # we may be getting the default value, or None,
  177.                          # so it doesn't need unpickled.
  178.  
  179.     def get_both(self, key, value, txn=None, flags=0):
  180.         data = cPickle.dumps(value, self.binary)
  181.         data = self.db.get(key, data, txn, flags)
  182.         return cPickle.loads(data)
  183.  
  184.  
  185.     def cursor(self, txn=None, flags=0):
  186.         c = DBShelfCursor(self.db.cursor(txn, flags))
  187.         c.binary = self.binary
  188.         return c
  189.  
  190.  
  191.     def put(self, key, value, txn=None, flags=0):
  192.         data = cPickle.dumps(value, self.binary)
  193.         return self.db.put(key, data, txn, flags)
  194.  
  195.  
  196.     def join(self, cursorList, flags=0):
  197.         raise NotImplementedError
  198.  
  199.  
  200.     #----------------------------------------------
  201.     # Methods allowed to pass-through to self.db
  202.     #
  203.     #    close,  delete, fd, get_byteswapped, get_type, has_key,
  204.     #    key_range, open, remove, rename, stat, sync,
  205.     #    upgrade, verify, and all set_* methods.
  206.  
  207.  
  208. #---------------------------------------------------------------------------
  209.  
  210. class DBShelfCursor:
  211.     """
  212.     """
  213.     def __init__(self, cursor):
  214.         self.dbc = cursor
  215.  
  216.     def __del__(self):
  217.         self.close()
  218.  
  219.  
  220.     def __getattr__(self, name):
  221.         """Some methods we can just pass through to the cursor object.  (See below)"""
  222.         return getattr(self.dbc, name)
  223.  
  224.  
  225.     #----------------------------------------------
  226.  
  227.     def dup(self, flags=0):
  228.         return DBShelfCursor(self.dbc.dup(flags))
  229.  
  230.  
  231.     def put(self, key, value, flags=0):
  232.         data = cPickle.dumps(value, self.binary)
  233.         return self.dbc.put(key, data, flags)
  234.  
  235.  
  236.     def get(self, *args):
  237.         count = len(args)  # a method overloading hack
  238.         method = getattr(self, 'get_%d' % count)
  239.         apply(method, args)
  240.  
  241.     def get_1(self, flags):
  242.         rec = self.dbc.get(flags)
  243.         return self._extract(rec)
  244.  
  245.     def get_2(self, key, flags):
  246.         rec = self.dbc.get(key, flags)
  247.         return self._extract(rec)
  248.  
  249.     def get_3(self, key, value, flags):
  250.         data = cPickle.dumps(value, self.binary)
  251.         rec = self.dbc.get(key, flags)
  252.         return self._extract(rec)
  253.  
  254.  
  255.     def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
  256.     def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
  257.     def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
  258.     def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
  259.     def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
  260.     def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
  261.     def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
  262.     def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
  263.     def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)
  264.  
  265.  
  266.     def get_both(self, key, value, flags=0):
  267.         data = cPickle.dumps(value, self.binary)
  268.         rec = self.dbc.get_both(key, flags)
  269.         return self._extract(rec)
  270.  
  271.  
  272.     def set(self, key, flags=0):
  273.         rec = self.dbc.set(key, flags)
  274.         return self._extract(rec)
  275.  
  276.     def set_range(self, key, flags=0):
  277.         rec = self.dbc.set_range(key, flags)
  278.         return self._extract(rec)
  279.  
  280.     def set_recno(self, recno, flags=0):
  281.         rec = self.dbc.set_recno(recno, flags)
  282.         return self._extract(rec)
  283.  
  284.     set_both = get_both
  285.  
  286.     def _extract(self, rec):
  287.         if rec is None:
  288.             return None
  289.         else:
  290.             key, data = rec
  291.             return key, cPickle.loads(data)
  292.  
  293.     #----------------------------------------------
  294.     # Methods allowed to pass-through to self.dbc
  295.     #
  296.     # close, count, delete, get_recno, join_item
  297.  
  298.  
  299. #---------------------------------------------------------------------------
  300.