#!/usr/bin/env python
#------------------------------------------------------------------------
#           Copyright (c) 1997-2001 by Total Control Software
#                         All Rights Reserved
#------------------------------------------------------------------------
#
# Module Name:  dbShelve.py
#
# Description:  A reimplementation of the standard shelve.py that
#               forces the use of cPickle, and DB.
#
# Creation Date:    11/3/97 3:39:04PM
#
# License:      This is free software.  You may use this software for any
#               purpose including modification/redistribution, so long as
#               this header remains intact and that you do not claim any
#               rights of ownership or authorship of this software.  This
#               software has been tested, but no warranty is expressed or
#               implied.
#
# 13-Dec-2000:  Updated to be used with the new bsddb3 package.
#               Added DBShelfCursor class.
#
#------------------------------------------------------------------------

"""Manage shelves of pickled objects using bsddb database files for the
storage.
"""

#------------------------------------------------------------------------

import sys
absolute_import = (sys.version_info[0] >= 3)
if absolute_import :
    # Because this syntaxis is not valid before Python 2.5
    exec("from . import db")
else :
    import db

if sys.version_info[0] >= 3 :
    import cPickle  # Will be converted to "pickle" by "2to3"
else :
    if sys.version_info < (2, 6) :
        import cPickle
    else :
        # When we drop support for python 2.4
        # we could use: (in 2.5 we need a __future__ statement)
        #
        #    with warnings.catch_warnings():
        #        warnings.filterwarnings(...)
        #        ...
        #
        # We can not use "with" as is, because it would be invalid syntax
        # in python 2.4 and (with no __future__) 2.5.
        # Here we simulate "with" following PEP 343 :
        import warnings
        w = warnings.catch_warnings()
        w.__enter__()
        try :
            warnings.filterwarnings('ignore',
                message='the cPickle module has been removed in Python 3.0',
                category=DeprecationWarning)
            import cPickle
        finally :
            w.__exit__()
        del w

HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL
def _dumps(object, protocol):
    return cPickle.dumps(object, protocol=protocol)

if sys.version_info < (2, 6) :
    from UserDict import DictMixin as MutableMapping
else :
    import collections
    MutableMapping = collections.MutableMapping

#------------------------------------------------------------------------


def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
         dbenv=None, dbname=None):
    """
    A simple factory function for compatibility with the standard
    shleve.py module.  It can be used like this, where key is a string
    and data is a pickleable object:

        from bsddb import dbshelve
        db = dbshelve.open(filename)

        db[key] = data

        db.close()
    """
    if type(flags) == type(''):
        sflag = flags
        if sflag == 'r':
            flags = db.DB_RDONLY
        elif sflag == 'rw':
            flags = 0
        elif sflag == 'w':
            flags =  db.DB_CREATE
        elif sflag == 'c':
            flags =  db.DB_CREATE
        elif sflag == 'n':
            flags = db.DB_TRUNCATE | db.DB_CREATE
        else:
            raise db.DBError, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"

    d = DBShelf(dbenv)
    d.open(filename, dbname, filetype, flags, mode)
    return d

#---------------------------------------------------------------------------

class DBShelveError(db.DBError): pass


class DBShelf(MutableMapping):
    """A shelf to hold pickled objects, built upon a bsddb DB object.  It
    automatically pickles/unpickles data objects going to/from the DB.
    """
    def __init__(self, dbenv=None):
        self.db = db.DB(dbenv)
        self._closed = True
        if HIGHEST_PROTOCOL:
            self.protocol = HIGHEST_PROTOCOL
        else:
            self.protocol = 1


    def __del__(self):
        self.close()


    def __getattr__(self, name):
        """Many methods we can just pass through to the DB object.
        (See below)
        """
        return getattr(self.db, name)


    #-----------------------------------
    # Dictionary access methods

    def __len__(self):
        return len(self.db)


    def __getitem__(self, key):
        data = self.db[key]
        return cPickle.loads(data)


    def __setitem__(self, key, value):
        data = _dumps(value, self.protocol)
        self.db[key] = data


    def __delitem__(self, key):
        del self.db[key]


    def keys(self, txn=None):
        if txn is not None:
            return self.db.keys(txn)
        else:
            return self.db.keys()

    if sys.version_info >= (2, 6) :
        def __iter__(self) :  # XXX: Load all keys in memory :-(
            for k in self.db.keys() :
                yield k

        # Do this when "DB"  support iteration
        # Or is it enough to pass thru "getattr"?
        #
        # def __iter__(self) :
        #    return self.db.__iter__()


    def open(self, *args, **kwargs):
        self.db.open(*args, **kwargs)
        self._closed = False


    def close(self, *args, **kwargs):
        self.db.close(*args, **kwargs)
        self._closed = True


    def __repr__(self):
        if self._closed:
            return '<DBShelf @ 0x%x - closed>' % (id(self))
        else:
            return repr(dict(self.iteritems()))


    def items(self, txn=None):
        if txn is not None:
            items = self.db.items(txn)
        else:
            items = self.db.items()
        newitems = []

        for k, v in items:
            newitems.append( (k, cPickle.loads(v)) )
        return newitems

    def values(self, txn=None):
        if txn is not None:
            values = self.db.values(txn)
        else:
            values = self.db.values()

        return map(cPickle.loads, values)

    #-----------------------------------
    # Other methods

    def __append(self, value, txn=None):
        data = _dumps(value, self.protocol)
        return self.db.append(data, txn)

    def append(self, value, txn=None):
        if self.get_type() == db.DB_RECNO:
            return self.__append(value, txn=txn)
        raise DBShelveError, "append() only supported when dbshelve opened with filetype=dbshelve.db.DB_RECNO"


    def associate(self, secondaryDB, callback, flags=0):
        def _shelf_callback(priKey, priData, realCallback=callback):
            # Safe in Python 2.x because expresion short circuit
            if sys.version_info[0] < 3 or isinstance(priData, bytes) :
                data = cPickle.loads(priData)
            else :
                data = cPickle.loads(bytes(priData, "iso8859-1"))  # 8 bits
            return realCallback(priKey, data)

        return self.db.associate(secondaryDB, _shelf_callback, flags)


    #def get(self, key, default=None, txn=None, flags=0):
    def get(self, *args, **kw):
        # We do it with *args and **kw so if the default value wasn't
        # given nothing is passed to the extension module.  That way
        # an exception can be raised if set_get_returns_none is turned
        # off.
        data = self.db.get(*args, **kw)
        try:
            return cPickle.loads(data)
        except (EOFError, TypeError, cPickle.UnpicklingError):
            return data  # we may be getting the default value, or None,
                         # so it doesn't need unpickled.

    def get_both(self, key, value, txn=None, flags=0):
        data = _dumps(value, self.protocol)
        data = self.db.get(key, data, txn, flags)
        return cPickle.loads(data)


    def cursor(self, txn=None, flags=0):
        c = DBShelfCursor(self.db.cursor(txn, flags))
        c.protocol = self.protocol
        return c


    def put(self, key, value, txn=None, flags=0):
        data = _dumps(value, self.protocol)
        return self.db.put(key, data, txn, flags)


    def join(self, cursorList, flags=0):
        raise NotImplementedError


    #----------------------------------------------
    # Methods allowed to pass-through to self.db
    #
    #    close,  delete, fd, get_byteswapped, get_type, has_key,
    #    key_range, open, remove, rename, stat, sync,
    #    upgrade, verify, and all set_* methods.


#---------------------------------------------------------------------------

class DBShelfCursor:
    """
    """
    def __init__(self, cursor):
        self.dbc = cursor

    def __del__(self):
        self.close()


    def __getattr__(self, name):
        """Some methods we can just pass through to the cursor object.  (See below)"""
        return getattr(self.dbc, name)


    #----------------------------------------------

    def dup(self, flags=0):
        c = DBShelfCursor(self.dbc.dup(flags))
        c.protocol = self.protocol
        return c


    def put(self, key, value, flags=0):
        data = _dumps(value, self.protocol)
        return self.dbc.put(key, data, flags)


    def get(self, *args):
        count = len(args)  # a method overloading hack
        method = getattr(self, 'get_%d' % count)
        method(*args)

    def get_1(self, flags):
        rec = self.dbc.get(flags)
        return self._extract(rec)

    def get_2(self, key, flags):
        rec = self.dbc.get(key, flags)
        return self._extract(rec)

    def get_3(self, key, value, flags):
        data = _dumps(value, self.protocol)
        rec = self.dbc.get(key, flags)
        return self._extract(rec)


    def current(self, flags=0): return self.get_1(flags|db.DB_CURRENT)
    def first(self, flags=0): return self.get_1(flags|db.DB_FIRST)
    def last(self, flags=0): return self.get_1(flags|db.DB_LAST)
    def next(self, flags=0): return self.get_1(flags|db.DB_NEXT)
    def prev(self, flags=0): return self.get_1(flags|db.DB_PREV)
    def consume(self, flags=0): return self.get_1(flags|db.DB_CONSUME)
    def next_dup(self, flags=0): return self.get_1(flags|db.DB_NEXT_DUP)
    def next_nodup(self, flags=0): return self.get_1(flags|db.DB_NEXT_NODUP)
    def prev_nodup(self, flags=0): return self.get_1(flags|db.DB_PREV_NODUP)


    def get_both(self, key, value, flags=0):
        data = _dumps(value, self.protocol)
        rec = self.dbc.get_both(key, flags)
        return self._extract(rec)


    def set(self, key, flags=0):
        rec = self.dbc.set(key, flags)
        return self._extract(rec)

    def set_range(self, key, flags=0):
        rec = self.dbc.set_range(key, flags)
        return self._extract(rec)

    def set_recno(self, recno, flags=0):
        rec = self.dbc.set_recno(recno, flags)
        return self._extract(rec)

    set_both = get_both

    def _extract(self, rec):
        if rec is None:
            return None
        else:
            key, data = rec
            # Safe in Python 2.x because expresion short circuit
            if sys.version_info[0] < 3 or isinstance(data, bytes) :
                return key, cPickle.loads(data)
            else :
                return key, cPickle.loads(bytes(data, "iso8859-1"))  # 8 bits

    #----------------------------------------------
    # Methods allowed to pass-through to self.dbc
    #
    # close, count, delete, get_recno, join_item


#---------------------------------------------------------------------------
