Update bsddb code to version 4.7.3pre2. This code should

be compatible with Python 3.0, also.

  http://www.jcea.es/programacion/pybsddb.htm#bsddb3-4.7.3
This commit is contained in:
Jesus Cea 2008-08-31 14:00:51 +00:00
parent 82358691f7
commit 4907d27c1f
27 changed files with 1020 additions and 447 deletions

View file

@ -218,8 +218,13 @@ class DBShelf(MutableMapping):
def associate(self, secondaryDB, callback, flags=0): def associate(self, secondaryDB, callback, flags=0):
def _shelf_callback(priKey, priData, realCallback=callback): def _shelf_callback(priKey, priData, realCallback=callback):
data = cPickle.loads(priData) # 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 realCallback(priKey, data)
return self.db.associate(secondaryDB, _shelf_callback, flags) return self.db.associate(secondaryDB, _shelf_callback, flags)
@ -232,7 +237,7 @@ class DBShelf(MutableMapping):
data = apply(self.db.get, args, kw) data = apply(self.db.get, args, kw)
try: try:
return cPickle.loads(data) return cPickle.loads(data)
except (TypeError, cPickle.UnpicklingError): except (EOFError, TypeError, cPickle.UnpicklingError):
return data # we may be getting the default value, or None, return data # we may be getting the default value, or None,
# so it doesn't need unpickled. # so it doesn't need unpickled.
@ -350,7 +355,11 @@ class DBShelfCursor:
return None return None
else: else:
key, data = rec key, data = rec
return key, cPickle.loads(data) # 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 # Methods allowed to pass-through to self.dbc

View file

@ -26,17 +26,16 @@ import cPickle as pickle
try: try:
# For Pythons w/distutils pybsddb # For Pythons w/distutils pybsddb
from bsddb3.db import * from bsddb3 import db
except ImportError: except ImportError:
# For Python 2.3 # For Python 2.3
from bsddb.db import * from bsddb import db
# XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c # XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c
try: if not hasattr(db,"DBIncompleteError") :
DBIncompleteError
except NameError:
class DBIncompleteError(Exception): class DBIncompleteError(Exception):
pass pass
db.DBIncompleteError = DBIncompleteError
class TableDBError(StandardError): class TableDBError(StandardError):
pass pass
@ -104,6 +103,7 @@ _rowid = '._ROWID_.' # this+rowid+this key contains a unique entry for each
# row in the table. (no data is stored) # row in the table. (no data is stored)
_rowid_str_len = 8 # length in bytes of the unique rowid strings _rowid_str_len = 8 # length in bytes of the unique rowid strings
def _data_key(table, col, rowid): def _data_key(table, col, rowid):
return table + _data + col + _data + rowid return table + _data + col + _data + rowid
@ -142,37 +142,104 @@ class bsdTableDB :
Use keyword arguments when calling this constructor. Use keyword arguments when calling this constructor.
""" """
self.db = None self.db = None
myflags = DB_THREAD myflags = db.DB_THREAD
if create: if create:
myflags |= DB_CREATE myflags |= db.DB_CREATE
flagsforenv = (DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | flagsforenv = (db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_INIT_LOG |
DB_INIT_TXN | dbflags) db.DB_INIT_TXN | dbflags)
# DB_AUTO_COMMIT isn't a valid flag for env.open() # DB_AUTO_COMMIT isn't a valid flag for env.open()
try: try:
dbflags |= DB_AUTO_COMMIT dbflags |= db.DB_AUTO_COMMIT
except AttributeError: except AttributeError:
pass pass
if recover: if recover:
flagsforenv = flagsforenv | DB_RECOVER flagsforenv = flagsforenv | db.DB_RECOVER
self.env = DBEnv() self.env = db.DBEnv()
# enable auto deadlock avoidance # enable auto deadlock avoidance
self.env.set_lk_detect(DB_LOCK_DEFAULT) self.env.set_lk_detect(db.DB_LOCK_DEFAULT)
self.env.open(dbhome, myflags | flagsforenv) self.env.open(dbhome, myflags | flagsforenv)
if truncate: if truncate:
myflags |= DB_TRUNCATE myflags |= db.DB_TRUNCATE
self.db = DB(self.env) self.db = db.DB(self.env)
# this code relies on DBCursor.set* methods to raise exceptions # this code relies on DBCursor.set* methods to raise exceptions
# rather than returning None # rather than returning None
self.db.set_get_returns_none(1) self.db.set_get_returns_none(1)
# allow duplicate entries [warning: be careful w/ metadata] # allow duplicate entries [warning: be careful w/ metadata]
self.db.set_flags(DB_DUP) self.db.set_flags(db.DB_DUP)
self.db.open(filename, DB_BTREE, dbflags | myflags, mode) self.db.open(filename, db.DB_BTREE, dbflags | myflags, mode)
self.dbfilename = filename self.dbfilename = filename
if sys.version_info[0] >= 3 :
class cursor_py3k(object) :
def __init__(self, dbcursor) :
self._dbcursor = dbcursor
def close(self) :
return self._dbcursor.close()
def set_range(self, search) :
v = self._dbcursor.set_range(bytes(search, "iso8859-1"))
if v != None :
v = (v[0].decode("iso8859-1"),
v[1].decode("iso8859-1"))
return v
def __next__(self) :
v = getattr(self._dbcursor, "next")()
if v != None :
v = (v[0].decode("iso8859-1"),
v[1].decode("iso8859-1"))
return v
class db_py3k(object) :
def __init__(self, db) :
self._db = db
def cursor(self, txn=None) :
return cursor_py3k(self._db.cursor(txn=txn))
def has_key(self, key, txn=None) :
return getattr(self._db,"has_key")(bytes(key, "iso8859-1"),
txn=txn)
def put(self, key, value, flags=0, txn=None) :
key = bytes(key, "iso8859-1")
if value != None :
value = bytes(value, "iso8859-1")
return self._db.put(key, value, flags=flags, txn=txn)
def put_bytes(self, key, value, txn=None) :
key = bytes(key, "iso8859-1")
return self._db.put(key, value, txn=txn)
def get(self, key, txn=None, flags=0) :
key = bytes(key, "iso8859-1")
v = self._db.get(key, txn=txn, flags=flags)
if v != None :
v = v.decode("iso8859-1")
return v
def get_bytes(self, key, txn=None, flags=0) :
key = bytes(key, "iso8859-1")
return self._db.get(key, txn=txn, flags=flags)
def delete(self, key, txn=None) :
key = bytes(key, "iso8859-1")
return self._db.delete(key, txn=txn)
def close (self) :
return self._db.close()
self.db = db_py3k(self.db)
else : # Python 2.x
pass
# Initialize the table names list if this is a new database # Initialize the table names list if this is a new database
txn = self.env.txn_begin() txn = self.env.txn_begin()
try: try:
if not self.db.has_key(_table_names_key, txn): if not getattr(self.db, "has_key")(_table_names_key, txn):
self.db.put(_table_names_key, pickle.dumps([], 1), txn=txn) getattr(self.db, "put_bytes", self.db.put) \
(_table_names_key, pickle.dumps([], 1), txn=txn)
# Yes, bare except # Yes, bare except
except: except:
txn.abort() txn.abort()
@ -196,13 +263,13 @@ class bsdTableDB :
def checkpoint(self, mins=0): def checkpoint(self, mins=0):
try: try:
self.env.txn_checkpoint(mins) self.env.txn_checkpoint(mins)
except DBIncompleteError: except db.DBIncompleteError:
pass pass
def sync(self): def sync(self):
try: try:
self.db.sync() self.db.sync()
except DBIncompleteError: except db.DBIncompleteError:
pass pass
def _db_print(self) : def _db_print(self) :
@ -219,7 +286,7 @@ class bsdTableDB :
else: else:
cur.close() cur.close()
return return
except DBNotFoundError: except db.DBNotFoundError:
cur.close() cur.close()
@ -229,6 +296,7 @@ class bsdTableDB :
raises TableDBError if it already exists or for other DB errors. raises TableDBError if it already exists or for other DB errors.
""" """
assert isinstance(columns, list) assert isinstance(columns, list)
txn = None txn = None
try: try:
# checking sanity of the table and column names here on # checking sanity of the table and column names here on
@ -242,27 +310,32 @@ class bsdTableDB :
"bad column name: contains reserved metastrings") "bad column name: contains reserved metastrings")
columnlist_key = _columns_key(table) columnlist_key = _columns_key(table)
if self.db.has_key(columnlist_key): if getattr(self.db, "has_key")(columnlist_key):
raise TableAlreadyExists, "table already exists" raise TableAlreadyExists, "table already exists"
txn = self.env.txn_begin() txn = self.env.txn_begin()
# store the table's column info # store the table's column info
self.db.put(columnlist_key, pickle.dumps(columns, 1), txn=txn) getattr(self.db, "put_bytes", self.db.put)(columnlist_key,
pickle.dumps(columns, 1), txn=txn)
# add the table name to the tablelist # add the table name to the tablelist
tablelist = pickle.loads(self.db.get(_table_names_key, txn=txn, tablelist = pickle.loads(getattr(self.db, "get_bytes",
flags=DB_RMW)) self.db.get) (_table_names_key, txn=txn, flags=db.DB_RMW))
tablelist.append(table) tablelist.append(table)
# delete 1st, in case we opened with DB_DUP # delete 1st, in case we opened with DB_DUP
self.db.delete(_table_names_key, txn=txn) self.db.delete(_table_names_key, txn=txn)
self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn=txn) getattr(self.db, "put_bytes", self.db.put)(_table_names_key,
pickle.dumps(tablelist, 1), txn=txn)
txn.commit() txn.commit()
txn = None txn = None
except DBError, dberror: except db.DBError, dberror:
if txn: if txn:
txn.abort() txn.abort()
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]
def ListTableColumns(self, table): def ListTableColumns(self, table):
@ -274,9 +347,10 @@ class bsdTableDB :
raise ValueError, "bad table name: contains reserved metastrings" raise ValueError, "bad table name: contains reserved metastrings"
columnlist_key = _columns_key(table) columnlist_key = _columns_key(table)
if not self.db.has_key(columnlist_key): if not getattr(self.db, "has_key")(columnlist_key):
return [] return []
pickledcolumnlist = self.db.get(columnlist_key) pickledcolumnlist = getattr(self.db, "get_bytes",
self.db.get)(columnlist_key)
if pickledcolumnlist: if pickledcolumnlist:
return pickle.loads(pickledcolumnlist) return pickle.loads(pickledcolumnlist)
else: else:
@ -284,7 +358,7 @@ class bsdTableDB :
def ListTables(self): def ListTables(self):
"""Return a list of tables in this database.""" """Return a list of tables in this database."""
pickledtablelist = self.db.get(_table_names_key) pickledtablelist = self.db.get_get(_table_names_key)
if pickledtablelist: if pickledtablelist:
return pickle.loads(pickledtablelist) return pickle.loads(pickledtablelist)
else: else:
@ -300,6 +374,7 @@ class bsdTableDB :
all of its current columns. all of its current columns.
""" """
assert isinstance(columns, list) assert isinstance(columns, list)
try: try:
self.CreateTable(table, columns) self.CreateTable(table, columns)
except TableAlreadyExists: except TableAlreadyExists:
@ -311,7 +386,8 @@ class bsdTableDB :
# load the current column list # load the current column list
oldcolumnlist = pickle.loads( oldcolumnlist = pickle.loads(
self.db.get(columnlist_key, txn=txn, flags=DB_RMW)) getattr(self.db, "get_bytes",
self.db.get)(columnlist_key, txn=txn, flags=db.DB_RMW))
# create a hash table for fast lookups of column names in the # create a hash table for fast lookups of column names in the
# loop below # loop below
oldcolumnhash = {} oldcolumnhash = {}
@ -329,7 +405,7 @@ class bsdTableDB :
if newcolumnlist != oldcolumnlist : if newcolumnlist != oldcolumnlist :
# delete the old one first since we opened with DB_DUP # delete the old one first since we opened with DB_DUP
self.db.delete(columnlist_key, txn=txn) self.db.delete(columnlist_key, txn=txn)
self.db.put(columnlist_key, getattr(self.db, "put_bytes", self.db.put)(columnlist_key,
pickle.dumps(newcolumnlist, 1), pickle.dumps(newcolumnlist, 1),
txn=txn) txn=txn)
@ -337,18 +413,22 @@ class bsdTableDB :
txn = None txn = None
self.__load_column_info(table) self.__load_column_info(table)
except DBError, dberror: except db.DBError, dberror:
if txn: if txn:
txn.abort() txn.abort()
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]
def __load_column_info(self, table) : def __load_column_info(self, table) :
"""initialize the self.__tablecolumns dict""" """initialize the self.__tablecolumns dict"""
# check the column names # check the column names
try: try:
tcolpickles = self.db.get(_columns_key(table)) tcolpickles = getattr(self.db, "get_bytes",
except DBNotFoundError: self.db.get)(_columns_key(table))
except db.DBNotFoundError:
raise TableDBError, "unknown table: %r" % (table,) raise TableDBError, "unknown table: %r" % (table,)
if not tcolpickles: if not tcolpickles:
raise TableDBError, "unknown table: %r" % (table,) raise TableDBError, "unknown table: %r" % (table,)
@ -366,11 +446,14 @@ class bsdTableDB :
blist.append(random.randint(0,255)) blist.append(random.randint(0,255))
newid = struct.pack('B'*_rowid_str_len, *blist) newid = struct.pack('B'*_rowid_str_len, *blist)
if sys.version_info[0] >= 3 :
newid = newid.decode("iso8859-1") # 8 bits
# Guarantee uniqueness by adding this key to the database # Guarantee uniqueness by adding this key to the database
try: try:
self.db.put(_rowid_key(table, newid), None, txn=txn, self.db.put(_rowid_key(table, newid), None, txn=txn,
flags=DB_NOOVERWRITE) flags=db.DB_NOOVERWRITE)
except DBKeyExistError: except db.DBKeyExistError:
pass pass
else: else:
unique = 1 unique = 1
@ -382,9 +465,10 @@ class bsdTableDB :
"""Insert(table, datadict) - Insert a new row into the table """Insert(table, datadict) - Insert a new row into the table
using the keys+values from rowdict as the column values. using the keys+values from rowdict as the column values.
""" """
txn = None txn = None
try: try:
if not self.db.has_key(_columns_key(table)): if not getattr(self.db, "has_key")(_columns_key(table)):
raise TableDBError, "unknown table" raise TableDBError, "unknown table"
# check the validity of each column name # check the validity of each column name
@ -406,7 +490,7 @@ class bsdTableDB :
txn.commit() txn.commit()
txn = None txn = None
except DBError, dberror: except db.DBError, dberror:
# WIBNI we could just abort the txn and re-raise the exception? # WIBNI we could just abort the txn and re-raise the exception?
# But no, because TableDBError is not related to DBError via # But no, because TableDBError is not related to DBError via
# inheritance, so it would be backwards incompatible. Do the next # inheritance, so it would be backwards incompatible. Do the next
@ -415,7 +499,10 @@ class bsdTableDB :
if txn: if txn:
txn.abort() txn.abort()
self.db.delete(_rowid_key(table, rowid)) self.db.delete(_rowid_key(table, rowid))
raise TableDBError, dberror[1], info[2] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1], info[2]
else :
raise TableDBError, dberror.args[1], info[2]
def Modify(self, table, conditions={}, mappings={}): def Modify(self, table, conditions={}, mappings={}):
@ -429,6 +516,7 @@ class bsdTableDB :
condition callable expecting the data string as an argument and condition callable expecting the data string as an argument and
returning the new string for that column. returning the new string for that column.
""" """
try: try:
matching_rowids = self.__Select(table, [], conditions) matching_rowids = self.__Select(table, [], conditions)
@ -447,7 +535,7 @@ class bsdTableDB :
self.db.delete( self.db.delete(
_data_key(table, column, rowid), _data_key(table, column, rowid),
txn=txn) txn=txn)
except DBNotFoundError: except db.DBNotFoundError:
# XXXXXXX row key somehow didn't exist, assume no # XXXXXXX row key somehow didn't exist, assume no
# error # error
dataitem = None dataitem = None
@ -465,8 +553,11 @@ class bsdTableDB :
txn.abort() txn.abort()
raise raise
except DBError, dberror: except db.DBError, dberror:
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]
def Delete(self, table, conditions={}): def Delete(self, table, conditions={}):
"""Delete(table, conditions) - Delete items matching the given """Delete(table, conditions) - Delete items matching the given
@ -476,6 +567,7 @@ class bsdTableDB :
condition functions expecting the data string as an condition functions expecting the data string as an
argument and returning a boolean. argument and returning a boolean.
""" """
try: try:
matching_rowids = self.__Select(table, [], conditions) matching_rowids = self.__Select(table, [], conditions)
@ -490,23 +582,26 @@ class bsdTableDB :
try: try:
self.db.delete(_data_key(table, column, rowid), self.db.delete(_data_key(table, column, rowid),
txn=txn) txn=txn)
except DBNotFoundError: except db.DBNotFoundError:
# XXXXXXX column may not exist, assume no error # XXXXXXX column may not exist, assume no error
pass pass
try: try:
self.db.delete(_rowid_key(table, rowid), txn=txn) self.db.delete(_rowid_key(table, rowid), txn=txn)
except DBNotFoundError: except db.DBNotFoundError:
# XXXXXXX row key somehow didn't exist, assume no error # XXXXXXX row key somehow didn't exist, assume no error
pass pass
txn.commit() txn.commit()
txn = None txn = None
except DBError, dberror: except db.DBError, dberror:
if txn: if txn:
txn.abort() txn.abort()
raise raise
except DBError, dberror: except db.DBError, dberror:
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]
def Select(self, table, columns, conditions={}): def Select(self, table, columns, conditions={}):
@ -525,8 +620,11 @@ class bsdTableDB :
if columns is None: if columns is None:
columns = self.__tablecolumns[table] columns = self.__tablecolumns[table]
matching_rowids = self.__Select(table, columns, conditions) matching_rowids = self.__Select(table, columns, conditions)
except DBError, dberror: except db.DBError, dberror:
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]
# return the matches as a list of dictionaries # return the matches as a list of dictionaries
return matching_rowids.values() return matching_rowids.values()
@ -579,8 +677,19 @@ class bsdTableDB :
# leave all unknown condition callables alone as equals # leave all unknown condition callables alone as equals
return 0 return 0
conditionlist = conditions.items() if sys.version_info[0] < 3 :
conditionlist.sort(cmp_conditions) conditionlist = conditions.items()
conditionlist.sort(cmp_conditions)
else : # Insertion Sort. Please, improve
conditionlist = []
for i in conditions.items() :
for j, k in enumerate(conditionlist) :
r = cmp_conditions(k, i)
if r == 1 :
conditionlist.insert(j, i)
break
else :
conditionlist.append(i)
# Apply conditions to column data to find what we want # Apply conditions to column data to find what we want
cur = self.db.cursor() cur = self.db.cursor()
@ -615,9 +724,13 @@ class bsdTableDB :
key, data = cur.next() key, data = cur.next()
except DBError, dberror: except db.DBError, dberror:
if dberror[0] != DB_NOTFOUND: if sys.version_info[0] < 3 :
raise if dberror[0] != db.DB_NOTFOUND:
raise
else :
if dberror.args[0] != db.DB_NOTFOUND:
raise
continue continue
cur.close() cur.close()
@ -635,9 +748,13 @@ class bsdTableDB :
try: try:
rowdata[column] = self.db.get( rowdata[column] = self.db.get(
_data_key(table, column, rowid)) _data_key(table, column, rowid))
except DBError, dberror: except db.DBError, dberror:
if dberror[0] != DB_NOTFOUND: if sys.version_info[0] < 3 :
raise if dberror[0] != db.DB_NOTFOUND:
raise
else :
if dberror.args[0] != db.DB_NOTFOUND:
raise
rowdata[column] = None rowdata[column] = None
# return the matches # return the matches
@ -660,7 +777,7 @@ class bsdTableDB :
while 1: while 1:
try: try:
key, data = cur.set_range(table_key) key, data = cur.set_range(table_key)
except DBNotFoundError: except db.DBNotFoundError:
break break
# only delete items in this table # only delete items in this table
if key[:len(table_key)] != table_key: if key[:len(table_key)] != table_key:
@ -672,7 +789,7 @@ class bsdTableDB :
while 1: while 1:
try: try:
key, data = cur.set_range(table_key) key, data = cur.set_range(table_key)
except DBNotFoundError: except db.DBNotFoundError:
break break
# only delete items in this table # only delete items in this table
if key[:len(table_key)] != table_key: if key[:len(table_key)] != table_key:
@ -683,7 +800,8 @@ class bsdTableDB :
# delete the tablename from the table name list # delete the tablename from the table name list
tablelist = pickle.loads( tablelist = pickle.loads(
self.db.get(_table_names_key, txn=txn, flags=DB_RMW)) getattr(self.db, "get_bytes", self.db.get)(_table_names_key,
txn=txn, flags=db.DB_RMW))
try: try:
tablelist.remove(table) tablelist.remove(table)
except ValueError: except ValueError:
@ -691,7 +809,8 @@ class bsdTableDB :
pass pass
# delete 1st, incase we opened with DB_DUP # delete 1st, incase we opened with DB_DUP
self.db.delete(_table_names_key, txn=txn) self.db.delete(_table_names_key, txn=txn)
self.db.put(_table_names_key, pickle.dumps(tablelist, 1), txn=txn) getattr(self.db, "put_bytes", self.db.put)(_table_names_key,
pickle.dumps(tablelist, 1), txn=txn)
txn.commit() txn.commit()
txn = None txn = None
@ -699,7 +818,10 @@ class bsdTableDB :
if self.__tablecolumns.has_key(table): if self.__tablecolumns.has_key(table):
del self.__tablecolumns[table] del self.__tablecolumns[table]
except DBError, dberror: except db.DBError, dberror:
if txn: if txn:
txn.abort() txn.abort()
raise TableDBError, dberror[1] if sys.version_info[0] < 3 :
raise TableDBError, dberror[1]
else :
raise TableDBError, dberror.args[1]

View file

@ -61,7 +61,7 @@ def DeadlockWrap(function, *_args, **_kwargs):
""" """
sleeptime = _deadlock_MinSleepTime sleeptime = _deadlock_MinSleepTime
max_retries = _kwargs.get('max_retries', -1) max_retries = _kwargs.get('max_retries', -1)
if 'max_retries' in _kwargs: if _kwargs.has_key('max_retries'):
del _kwargs['max_retries'] del _kwargs['max_retries']
while True: while True:
try: try:

View file

@ -6,21 +6,366 @@ import os
import unittest import unittest
try: try:
# For Pythons w/distutils pybsddb # For Pythons w/distutils pybsddb
from bsddb3 import db
import bsddb3 as bsddb import bsddb3 as bsddb
except ImportError: except ImportError:
# For Python 2.3 # For Python 2.3
from bsddb import db
import bsddb import bsddb
if sys.version_info[0] >= 3 :
charset = "iso8859-1" # Full 8 bit
class cursor_py3k(object) :
def __init__(self, db, *args, **kwargs) :
self._dbcursor = db.cursor(*args, **kwargs)
def __getattr__(self, v) :
return getattr(self._dbcursor, v)
def _fix(self, v) :
if v == None : return None
key, value = v
if isinstance(key, bytes) :
key = key.decode(charset)
return (key, value.decode(charset))
def __next__(self) :
v = getattr(self._dbcursor, "next")()
return self._fix(v)
def previous(self) :
v = self._dbcursor.previous()
return self._fix(v)
def last(self) :
v = self._dbcursor.last()
return self._fix(v)
def set(self, k) :
if isinstance(k, str) :
k = bytes(k, charset)
v = self._dbcursor.set(k)
return self._fix(v)
def set_recno(self, num) :
v = self._dbcursor.set_recno(num)
return self._fix(v)
def set_range(self, k, dlen=-1, doff=-1) :
if isinstance(k, str) :
k = bytes(k, charset)
v = self._dbcursor.set_range(k, dlen=dlen, doff=doff)
return self._fix(v)
def dup(self, flags=0) :
cursor = self._dbcursor.dup(flags)
return dup_cursor_py3k(cursor)
def next_dup(self) :
v = self._dbcursor.next_dup()
return self._fix(v)
def put(self, key, value, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) :
key = bytes(key, charset)
if isinstance(value, str) :
value = bytes(value, charset)
return self._dbcursor.put(key, value, flags=flags, dlen=dlen,
doff=doff)
def current(self, flags=0, dlen=-1, doff=-1) :
v = self._dbcursor.current(flags=flags, dlen=dlen, doff=doff)
return self._fix(v)
def first(self) :
v = self._dbcursor.first()
return self._fix(v)
def pget(self, key=None, data=None, flags=0) :
# Incorrect because key can be a bare number,
# but enough to pass testsuite
if isinstance(key, int) and (data==None) and (flags==0) :
flags = key
key = None
if isinstance(key, str) :
key = bytes(key, charset)
if isinstance(data, int) and (flags==0) :
flags = data
data = None
if isinstance(data, str) :
data = bytes(data, charset)
v=self._dbcursor.pget(key=key, data=data, flags=flags)
if v != None :
v1, v2, v3 = v
if isinstance(v1, bytes) :
v1 = v1.decode(charset)
if isinstance(v2, bytes) :
v2 = v2.decode(charset)
v = (v1, v2, v3.decode(charset))
return v
def join_item(self) :
v = self._dbcursor.join_item()
if v != None :
v = v.decode(charset)
return v
def get(self, *args, **kwargs) :
l = len(args)
if l == 2 :
k, f = args
if isinstance(k, str) :
k = bytes(k, "iso8859-1")
args = (k, f)
elif l == 3 :
k, d, f = args
if isinstance(k, str) :
k = bytes(k, charset)
if isinstance(d, str) :
d = bytes(d, charset)
args =(k, d, f)
v = self._dbcursor.get(*args, **kwargs)
if v != None :
k, v = v
if isinstance(k, bytes) :
k = k.decode(charset)
v = (k, v.decode(charset))
return v
def get_both(self, key, value) :
if isinstance(key, str) :
key = bytes(key, charset)
if isinstance(value, str) :
value = bytes(value, charset)
v=self._dbcursor.get_both(key, value)
return self._fix(v)
class dup_cursor_py3k(cursor_py3k) :
def __init__(self, dbcursor) :
self._dbcursor = dbcursor
class DB_py3k(object) :
def __init__(self, *args, **kwargs) :
args2=[]
for i in args :
if isinstance(i, DBEnv_py3k) :
i = i._dbenv
args2.append(i)
args = tuple(args2)
for k, v in kwargs.items() :
if isinstance(v, DBEnv_py3k) :
kwargs[k] = v._dbenv
self._db = bsddb._db.DB_orig(*args, **kwargs)
def __contains__(self, k) :
if isinstance(k, str) :
k = bytes(k, charset)
return getattr(self._db, "has_key")(k)
def __getitem__(self, k) :
if isinstance(k, str) :
k = bytes(k, charset)
v = self._db[k]
if v != None :
v = v.decode(charset)
return v
def __setitem__(self, k, v) :
if isinstance(k, str) :
k = bytes(k, charset)
if isinstance(v, str) :
v = bytes(v, charset)
self._db[k] = v
def __delitem__(self, k) :
if isinstance(k, str) :
k = bytes(k, charset)
del self._db[k]
def __getattr__(self, v) :
return getattr(self._db, v)
def __len__(self) :
return len(self._db)
def has_key(self, k, txn=None) :
if isinstance(k, str) :
k = bytes(k, charset)
return self._db.has_key(k, txn=txn)
def put(self, key, value, txn=None, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) :
key = bytes(key, charset)
if isinstance(value, str) :
value = bytes(value, charset)
return self._db.put(key, value, flags=flags, txn=txn, dlen=dlen,
doff=doff)
def append(self, value, txn=None) :
if isinstance(value, str) :
value = bytes(value, charset)
return self._db.append(value, txn=txn)
def get_size(self, key) :
if isinstance(key, str) :
key = bytes(key, charset)
return self._db.get_size(key)
def get(self, key, default="MagicCookie", txn=None, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) :
key = bytes(key, charset)
if default != "MagicCookie" : # Magic for 'test_get_none.py'
v=self._db.get(key, default=default, txn=txn, flags=flags,
dlen=dlen, doff=doff)
else :
v=self._db.get(key, txn=txn, flags=flags,
dlen=dlen, doff=doff)
if (v != None) and isinstance(v, bytes) :
v = v.decode(charset)
return v
def pget(self, key, txn=None) :
if isinstance(key, str) :
key = bytes(key, charset)
v=self._db.pget(key, txn=txn)
if v != None :
v1, v2 = v
if isinstance(v1, bytes) :
v1 = v1.decode(charset)
v = (v1, v2.decode(charset))
return v
def get_both(self, key, value, txn=None, flags=0) :
if isinstance(key, str) :
key = bytes(key, charset)
if isinstance(value, str) :
value = bytes(value, charset)
v=self._db.get_both(key, value, txn=txn, flags=flags)
if v != None :
v = v.decode(charset)
return v
def delete(self, key, txn=None) :
if isinstance(key, str) :
key = bytes(key, charset)
return self._db.delete(key, txn=txn)
def keys(self) :
k = self._db.keys()
if len(k) and isinstance(k[0], bytes) :
return [i.decode(charset) for i in self._db.keys()]
else :
return k
def items(self) :
data = self._db.items()
if not len(data) : return data
data2 = []
for k, v in data :
if isinstance(k, bytes) :
k = k.decode(charset)
data2.append((k, v.decode(charset)))
return data2
def associate(self, secondarydb, callback, flags=0, txn=None) :
class associate_callback(object) :
def __init__(self, callback) :
self._callback = callback
def callback(self, key, data) :
if isinstance(key, str) :
key = key.decode(charset)
data = data.decode(charset)
key = self._callback(key, data)
if (key != bsddb._db.DB_DONOTINDEX) and isinstance(key,
str) :
key = bytes(key, charset)
return key
return self._db.associate(secondarydb._db,
associate_callback(callback).callback, flags=flags, txn=txn)
def cursor(self, txn=None, flags=0) :
return cursor_py3k(self._db, txn=txn, flags=flags)
def join(self, cursor_list) :
cursor_list = [i._dbcursor for i in cursor_list]
return dup_cursor_py3k(self._db.join(cursor_list))
class DBEnv_py3k(object) :
def __init__(self, *args, **kwargs) :
self._dbenv = bsddb._db.DBEnv_orig(*args, **kwargs)
def __getattr__(self, v) :
return getattr(self._dbenv, v)
class DBSequence_py3k(object) :
def __init__(self, db, *args, **kwargs) :
self._db=db
self._dbsequence = bsddb._db.DBSequence_orig(db._db, *args, **kwargs)
def __getattr__(self, v) :
return getattr(self._dbsequence, v)
def open(self, key, *args, **kwargs) :
return self._dbsequence.open(bytes(key, charset), *args, **kwargs)
def get_key(self) :
return self._dbsequence.get_key().decode(charset)
def get_dbp(self) :
return self._db
import string
string.letters=[chr(i) for i in xrange(65,91)]
bsddb._db.DBEnv_orig = bsddb._db.DBEnv
bsddb._db.DB_orig = bsddb._db.DB
bsddb._db.DBSequence_orig = bsddb._db.DBSequence
def do_proxy_db_py3k(flag) :
flag2 = do_proxy_db_py3k.flag
do_proxy_db_py3k.flag = flag
if flag :
bsddb.DBEnv = bsddb.db.DBEnv = bsddb._db.DBEnv = DBEnv_py3k
bsddb.DB = bsddb.db.DB = bsddb._db.DB = DB_py3k
bsddb._db.DBSequence = DBSequence_py3k
else :
bsddb.DBEnv = bsddb.db.DBEnv = bsddb._db.DBEnv = bsddb._db.DBEnv_orig
bsddb.DB = bsddb.db.DB = bsddb._db.DB = bsddb._db.DB_orig
bsddb._db.DBSequence = bsddb._db.DBSequence_orig
return flag2
do_proxy_db_py3k.flag = False
do_proxy_db_py3k(True)
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbtables, dbutils, dbshelve, \
hashopen, btopen, rnopen, dbobj
except ImportError:
# For Python 2.3
from bsddb import db, dbtables, dbutils, dbshelve, \
hashopen, btopen, rnopen, dbobj
try: try:
from bsddb3 import test_support from bsddb3 import test_support
except ImportError: except ImportError:
from test import test_support from test import test_support
try: try:
from threading import Thread, currentThread if sys.version_info[0] < 3 :
del Thread, currentThread from threading import Thread, currentThread
del Thread, currentThread
else :
from threading import Thread, current_thread
del Thread, current_thread
have_threads = True have_threads = True
except ImportError: except ImportError:
have_threads = False have_threads = False

View file

@ -7,19 +7,8 @@ import time
from pprint import pprint from pprint import pprint
import unittest import unittest
from test_all import verbose, have_threads, get_new_environment_path from test_all import db, dbshelve, test_support, verbose, have_threads, \
get_new_environment_path
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbshelve
except ImportError:
# For Python 2.3
from bsddb import db, dbshelve
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -152,7 +141,7 @@ class AssociateTestCase(unittest.TestCase):
for key, value in musicdata.items(): for key, value in musicdata.items():
if type(self.keytype) == type(''): if type(self.keytype) == type(''):
key = "%02d" % key key = "%02d" % key
d.put(key, string.join(value, '|'), txn=txn) d.put(key, '|'.join(value), txn=txn)
def createDB(self, txn=None): def createDB(self, txn=None):
self.cur = None self.cur = None
@ -238,13 +227,13 @@ class AssociateTestCase(unittest.TestCase):
rec = self.cur.first() rec = self.cur.first()
while rec is not None: while rec is not None:
if type(self.keytype) == type(''): if type(self.keytype) == type(''):
self.assert_(string.atoi(rec[0])) # for primary db, key is a number self.assert_(int(rec[0])) # for primary db, key is a number
else: else:
self.assert_(rec[0] and type(rec[0]) == type(0)) self.assert_(rec[0] and type(rec[0]) == type(0))
count = count + 1 count = count + 1
if verbose: if verbose:
print rec print rec
rec = self.cur.next() rec = getattr(self.cur, "next")()
self.assertEqual(count, len(musicdata)) # all items accounted for self.assertEqual(count, len(musicdata)) # all items accounted for
@ -270,7 +259,7 @@ class AssociateTestCase(unittest.TestCase):
count = count + 1 count = count + 1
if verbose: if verbose:
print rec print rec
rec = self.cur.next() rec = getattr(self.cur, "next")()
# all items accounted for EXCEPT for 1 with "Blues" genre # all items accounted for EXCEPT for 1 with "Blues" genre
self.assertEqual(count, len(musicdata)-1) self.assertEqual(count, len(musicdata)-1)
@ -278,9 +267,11 @@ class AssociateTestCase(unittest.TestCase):
def getGenre(self, priKey, priData): def getGenre(self, priKey, priData):
self.assertEqual(type(priData), type("")) self.assertEqual(type(priData), type(""))
genre = priData.split('|')[2]
if verbose: if verbose:
print 'getGenre key: %r data: %r' % (priKey, priData) print 'getGenre key: %r data: %r' % (priKey, priData)
genre = string.split(priData, '|')[2]
if genre == 'Blues': if genre == 'Blues':
return db.DB_DONOTINDEX return db.DB_DONOTINDEX
else: else:
@ -404,13 +395,13 @@ class ThreadedAssociateTestCase(AssociateTestCase):
for key, value in musicdata.items(): for key, value in musicdata.items():
if type(self.keytype) == type(''): if type(self.keytype) == type(''):
key = "%02d" % key key = "%02d" % key
d.put(key, string.join(value, '|')) d.put(key, '|'.join(value))
def writer2(self, d): def writer2(self, d):
for x in range(100, 600): for x in range(100, 600):
key = 'z%2d' % x key = 'z%2d' % x
value = [key] * 4 value = [key] * 4
d.put(key, string.join(value, '|')) d.put(key, '|'.join(value))
class ThreadedAssociateHashTestCase(ShelveAssociateTestCase): class ThreadedAssociateHashTestCase(ShelveAssociateTestCase):

View file

@ -10,19 +10,8 @@ from pprint import pprint
import unittest import unittest
import time import time
try: from test_all import db, test_support, verbose, get_new_environment_path, \
# For Pythons w/distutils pybsddb get_new_database_path
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
from test_all import verbose, get_new_environment_path, get_new_database_path
DASH = '-' DASH = '-'
@ -150,7 +139,11 @@ class BasicTestCase(unittest.TestCase):
try: try:
d.delete('abcd') d.delete('abcd')
except db.DBNotFoundError, val: except db.DBNotFoundError, val:
self.assertEqual(val[0], db.DB_NOTFOUND) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_NOTFOUND)
else :
self.assertEqual(val.args[0], db.DB_NOTFOUND)
if verbose: print val if verbose: print val
else: else:
self.fail("expected exception") self.fail("expected exception")
@ -169,7 +162,11 @@ class BasicTestCase(unittest.TestCase):
try: try:
d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE) d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE)
except db.DBKeyExistError, val: except db.DBKeyExistError, val:
self.assertEqual(val[0], db.DB_KEYEXIST) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_KEYEXIST)
else :
self.assertEqual(val.args[0], db.DB_KEYEXIST)
if verbose: print val if verbose: print val
else: else:
self.fail("expected exception") self.fail("expected exception")
@ -255,8 +252,10 @@ class BasicTestCase(unittest.TestCase):
self.assertEqual(d['new record'], 'a replacement record') self.assertEqual(d['new record'], 'a replacement record')
self.assertEqual(d.has_key('0001'), 1) # We check also the positional parameter
self.assertEqual(d.has_key('spam'), 0) self.assertEqual(d.has_key('0001', None), 1)
# We check also the keyword parameter
self.assertEqual(d.has_key('spam', txn=None), 0)
items = d.items() items = d.items()
self.assertEqual(len(items), self._numKeys+1) self.assertEqual(len(items), self._numKeys+1)
@ -302,7 +301,11 @@ class BasicTestCase(unittest.TestCase):
rec = c.next() rec = c.next()
except db.DBNotFoundError, val: except db.DBNotFoundError, val:
if get_raises_error: if get_raises_error:
self.assertEqual(val[0], db.DB_NOTFOUND) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_NOTFOUND)
else :
self.assertEqual(val.args[0], db.DB_NOTFOUND)
if verbose: print val if verbose: print val
rec = None rec = None
else: else:
@ -323,7 +326,11 @@ class BasicTestCase(unittest.TestCase):
rec = c.prev() rec = c.prev()
except db.DBNotFoundError, val: except db.DBNotFoundError, val:
if get_raises_error: if get_raises_error:
self.assertEqual(val[0], db.DB_NOTFOUND) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_NOTFOUND)
else :
self.assertEqual(val.args[0], db.DB_NOTFOUND)
if verbose: print val if verbose: print val
rec = None rec = None
else: else:
@ -346,7 +353,11 @@ class BasicTestCase(unittest.TestCase):
try: try:
n = c.set('bad key') n = c.set('bad key')
except db.DBNotFoundError, val: except db.DBNotFoundError, val:
self.assertEqual(val[0], db.DB_NOTFOUND) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_NOTFOUND)
else :
self.assertEqual(val.args[0], db.DB_NOTFOUND)
if verbose: print val if verbose: print val
else: else:
if set_raises_error: if set_raises_error:
@ -360,7 +371,11 @@ class BasicTestCase(unittest.TestCase):
try: try:
n = c.get_both('0404', 'bad data') n = c.get_both('0404', 'bad data')
except db.DBNotFoundError, val: except db.DBNotFoundError, val:
self.assertEqual(val[0], db.DB_NOTFOUND) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_NOTFOUND)
else :
self.assertEqual(val.args[0], db.DB_NOTFOUND)
if verbose: print val if verbose: print val
else: else:
if get_raises_error: if get_raises_error:
@ -389,7 +404,11 @@ class BasicTestCase(unittest.TestCase):
rec = c.current() rec = c.current()
except db.DBKeyEmptyError, val: except db.DBKeyEmptyError, val:
if get_raises_error: if get_raises_error:
self.assertEqual(val[0], db.DB_KEYEMPTY) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.DB_KEYEMPTY)
else :
self.assertEqual(val.args[0], db.DB_KEYEMPTY)
if verbose: print val if verbose: print val
else: else:
self.fail("unexpected DBKeyEmptyError") self.fail("unexpected DBKeyEmptyError")
@ -434,7 +453,11 @@ class BasicTestCase(unittest.TestCase):
# a bug may cause a NULL pointer dereference... # a bug may cause a NULL pointer dereference...
apply(getattr(c, method), args) apply(getattr(c, method), args)
except db.DBError, val: except db.DBError, val:
self.assertEqual(val[0], 0) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], 0)
else :
self.assertEqual(val.args[0], 0)
if verbose: print val if verbose: print val
else: else:
self.fail("no exception raised when using a buggy cursor's" self.fail("no exception raised when using a buggy cursor's"
@ -803,8 +826,8 @@ class BasicDUPTestCase(BasicTestCase):
rec = c.set("dup1") rec = c.set("dup1")
self.assertEqual(rec, ('dup1', 'The')) self.assertEqual(rec, ('dup1', 'The'))
next = c.next() next_reg = c.next()
self.assertEqual(next, ('dup1', 'quick')) self.assertEqual(next_reg, ('dup1', 'quick'))
rec = c.set("dup1") rec = c.set("dup1")
count = c.count() count = c.count()
@ -919,7 +942,7 @@ class BasicMultiDBTestCase(BasicTestCase):
if verbose: if verbose:
print rec print rec
rec = c3.next() rec = c3.next()
self.assertEqual(count, 52) self.assertEqual(count, len(string.letters))
c1.close() c1.close()

View file

@ -7,19 +7,10 @@ import test_all
from cStringIO import StringIO from cStringIO import StringIO
import unittest import unittest
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbshelve
except ImportError:
# For Python 2.3
from bsddb import db, dbshelve
from test_all import get_new_environment_path, get_new_database_path from test_all import db, dbshelve, test_support, \
get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
lexical_cmp = cmp lexical_cmp = cmp
@ -37,7 +28,25 @@ _expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf
class ComparatorTests (unittest.TestCase): class ComparatorTests (unittest.TestCase):
def comparator_test_helper (self, comparator, expected_data): def comparator_test_helper (self, comparator, expected_data):
data = expected_data[:] data = expected_data[:]
data.sort (comparator)
import sys
if sys.version_info[0] < 3 :
if sys.version_info[:3] < (2, 4, 0):
data.sort(comparator)
else :
data.sort(cmp=comparator)
else : # Insertion Sort. Please, improve
data2 = []
for i in data :
for j, k in enumerate(data2) :
r = comparator(k, i)
if r == 1 :
data2.insert(j, i)
break
else :
data2.append(i)
data = data2
self.failUnless (data == expected_data, self.failUnless (data == expected_data,
"comparator `%s' is not right: %s vs. %s" "comparator `%s' is not right: %s vs. %s"
% (comparator, expected_data, data)) % (comparator, expected_data, data))

View file

@ -6,16 +6,10 @@ regression test suite.
import os, string import os, string
import unittest import unittest
from test_all import verbose, get_new_database_path from test_all import db, hashopen, btopen, rnopen, verbose, \
get_new_database_path
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, hashopen, btopen, rnopen
except ImportError:
# For Python 2.3
from bsddb import db, hashopen, btopen, rnopen
class CompatibilityTestCase(unittest.TestCase): class CompatibilityTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
self.filename = get_new_database_path() self.filename = get_new_database_path()
@ -34,7 +28,7 @@ class CompatibilityTestCase(unittest.TestCase):
self.do_bthash_test(hashopen, 'hashopen') self.do_bthash_test(hashopen, 'hashopen')
def test03_rnopen(self): def test03_rnopen(self):
data = string.split("The quick brown fox jumped over the lazy dog.") data = "The quick brown fox jumped over the lazy dog.".split()
if verbose: if verbose:
print "\nTesting: rnopen" print "\nTesting: rnopen"

View file

@ -1,19 +1,8 @@
import unittest import unittest
import os, glob import os, glob
try: from test_all import db, test_support, get_new_environment_path, \
# For Pythons w/distutils pybsddb get_new_database_path
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View file

@ -2,19 +2,8 @@
import os, string import os, string
import unittest import unittest
try: from test_all import db, dbobj, test_support, get_new_environment_path, \
# For Pythons w/distutils pybsddb get_new_database_path
from bsddb3 import db, dbobj
except ImportError:
# For Python 2.3
from bsddb import db, dbobj
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -36,7 +25,7 @@ class dbobjTestCase(unittest.TestCase):
class TestDBEnv(dbobj.DBEnv): pass class TestDBEnv(dbobj.DBEnv): pass
class TestDB(dbobj.DB): class TestDB(dbobj.DB):
def put(self, key, *args, **kwargs): def put(self, key, *args, **kwargs):
key = string.upper(key) key = key.upper()
# call our parent classes put method with an upper case key # call our parent classes put method with an upper case key
return apply(dbobj.DB.put, (self, key) + args, kwargs) return apply(dbobj.DB.put, (self, key) + args, kwargs)
self.env = TestDBEnv() self.env = TestDBEnv()

View file

@ -4,22 +4,11 @@ TestCases for checking dbShelve objects.
import os, string import os, string
import random import random
from types import *
import unittest import unittest
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbshelve
except ImportError:
# For Python 2.3
from bsddb import db, dbshelve
try: from test_all import db, dbshelve, test_support, verbose, \
from bsddb3 import test_support get_new_environment_path, get_new_database_path
except ImportError:
from test import test_support
from test_all import verbose, get_new_environment_path, get_new_database_path
@ -31,22 +20,38 @@ class DataClass:
def __init__(self): def __init__(self):
self.value = random.random() self.value = random.random()
def __cmp__(self, other): def __repr__(self) : # For Python 3.0 comparison
return "DataClass %f" %self.value
def __cmp__(self, other): # For Python 2.x comparison
return cmp(self.value, other) return cmp(self.value, other)
class DBShelveTestCase(unittest.TestCase): class DBShelveTestCase(unittest.TestCase):
def setUp(self): def setUp(self):
import sys
if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k
self._flag_proxy_db_py3k = do_proxy_db_py3k(False)
self.filename = get_new_database_path() self.filename = get_new_database_path()
self.do_open() self.do_open()
def tearDown(self): def tearDown(self):
import sys
if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k
do_proxy_db_py3k(self._flag_proxy_db_py3k)
self.do_close() self.do_close()
test_support.unlink(self.filename) test_support.unlink(self.filename)
def mk(self, key): def mk(self, key):
"""Turn key into an appropriate key type for this db""" """Turn key into an appropriate key type for this db"""
# override in child class for RECNO # override in child class for RECNO
return key import sys
if sys.version_info[0] < 3 :
return key
else :
return bytes(key, "iso8859-1") # 8 bits
def populateDB(self, d): def populateDB(self, d):
for x in string.letters: for x in string.letters:
@ -112,9 +117,15 @@ class DBShelveTestCase(unittest.TestCase):
dbvalues = d.values() dbvalues = d.values()
self.assertEqual(len(dbvalues), len(d.keys())) self.assertEqual(len(dbvalues), len(d.keys()))
values.sort() import sys
dbvalues.sort() if sys.version_info[0] < 3 :
self.assertEqual(values, dbvalues) values.sort()
dbvalues.sort()
self.assertEqual(values, dbvalues)
else : # XXX: Convert all to strings. Please, improve
values.sort(key=lambda x : str(x))
dbvalues.sort(key=lambda x : str(x))
self.assertEqual(repr(values), repr(dbvalues))
items = d.items() items = d.items()
self.assertEqual(len(items), len(values)) self.assertEqual(len(items), len(values))
@ -154,7 +165,8 @@ class DBShelveTestCase(unittest.TestCase):
print rec print rec
key, value = rec key, value = rec
self.checkrec(key, value) self.checkrec(key, value)
rec = c.next() # Hack to avoid conversion by 2to3 tool
rec = getattr(c, "next")()
del c del c
self.assertEqual(count, len(d)) self.assertEqual(count, len(d))
@ -190,21 +202,33 @@ class DBShelveTestCase(unittest.TestCase):
def checkrec(self, key, value): def checkrec(self, key, value):
# override this in a subclass if the key type is different # override this in a subclass if the key type is different
import sys
if sys.version_info[0] >= 3 :
if isinstance(key, bytes) :
key = key.decode("iso8859-1") # 8 bits
x = key[1] x = key[1]
if key[0] == 'S': if key[0] == 'S':
self.assertEqual(type(value), StringType) self.assertEqual(type(value), str)
self.assertEqual(value, 10 * x) self.assertEqual(value, 10 * x)
elif key[0] == 'I': elif key[0] == 'I':
self.assertEqual(type(value), IntType) self.assertEqual(type(value), int)
self.assertEqual(value, ord(x)) self.assertEqual(value, ord(x))
elif key[0] == 'L': elif key[0] == 'L':
self.assertEqual(type(value), ListType) self.assertEqual(type(value), list)
self.assertEqual(value, [x] * 10) self.assertEqual(value, [x] * 10)
elif key[0] == 'O': elif key[0] == 'O':
self.assertEqual(type(value), InstanceType) import sys
if sys.version_info[0] < 3 :
from types import InstanceType
self.assertEqual(type(value), InstanceType)
else :
self.assertEqual(type(value), DataClass)
self.assertEqual(value.S, 10 * x) self.assertEqual(value.S, 10 * x)
self.assertEqual(value.I, ord(x)) self.assertEqual(value.I, ord(x))
self.assertEqual(value.L, [x] * 10) self.assertEqual(value.L, [x] * 10)
@ -266,6 +290,10 @@ class BasicEnvShelveTestCase(DBShelveTestCase):
DBShelveTestCase.setUp(self) DBShelveTestCase.setUp(self)
def tearDown(self): def tearDown(self):
import sys
if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k
do_proxy_db_py3k(self._flag_proxy_db_py3k)
self.do_close() self.do_close()
test_support.rmtree(self.homeDir) test_support.rmtree(self.homeDir)

View file

@ -28,20 +28,8 @@ except ImportError:
import pickle import pickle
import unittest import unittest
from test_all import verbose, get_new_environment_path, get_new_database_path from test_all import db, dbtables, test_support, verbose, \
get_new_environment_path, get_new_database_path
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbtables
except ImportError:
# For Python 2.3
from bsddb import db, dbtables
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -49,12 +37,21 @@ class TableDBTestCase(unittest.TestCase):
db_name = 'test-table.db' db_name = 'test-table.db'
def setUp(self): def setUp(self):
import sys
if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k
self._flag_proxy_db_py3k = do_proxy_db_py3k(False)
self.testHomeDir = get_new_environment_path() self.testHomeDir = get_new_environment_path()
self.tdb = dbtables.bsdTableDB( self.tdb = dbtables.bsdTableDB(
filename='tabletest.db', dbhome=self.testHomeDir, create=1) filename='tabletest.db', dbhome=self.testHomeDir, create=1)
def tearDown(self): def tearDown(self):
self.tdb.close() self.tdb.close()
import sys
if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k
do_proxy_db_py3k(self._flag_proxy_db_py3k)
test_support.rmtree(self.testHomeDir) test_support.rmtree(self.testHomeDir)
def test01(self): def test01(self):
@ -65,7 +62,12 @@ class TableDBTestCase(unittest.TestCase):
except dbtables.TableDBError: except dbtables.TableDBError:
pass pass
self.tdb.CreateTable(tabname, [colname]) self.tdb.CreateTable(tabname, [colname])
self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)}) import sys
if sys.version_info[0] < 3 :
self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)})
else :
self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159,
1).decode("iso8859-1")}) # 8 bits
if verbose: if verbose:
self.tdb._db_print() self.tdb._db_print()
@ -73,7 +75,11 @@ class TableDBTestCase(unittest.TestCase):
values = self.tdb.Select( values = self.tdb.Select(
tabname, [colname], conditions={colname: None}) tabname, [colname], conditions={colname: None})
colval = pickle.loads(values[0][colname]) import sys
if sys.version_info[0] < 3 :
colval = pickle.loads(values[0][colname])
else :
colval = pickle.loads(bytes(values[0][colname], "iso8859-1"))
self.assert_(colval > 3.141) self.assert_(colval > 3.141)
self.assert_(colval < 3.142) self.assert_(colval < 3.142)
@ -83,11 +89,23 @@ class TableDBTestCase(unittest.TestCase):
col0 = 'coolness factor' col0 = 'coolness factor'
col1 = 'but can it fly?' col1 = 'but can it fly?'
col2 = 'Species' col2 = 'Species'
testinfo = [
{col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'}, import sys
{col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'}, if sys.version_info[0] < 3 :
{col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'} testinfo = [
] {col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'},
{col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'},
{col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'}
]
else :
testinfo = [
{col0: pickle.dumps(8, 1).decode("iso8859-1"),
col1: 'no', col2: 'Penguin'},
{col0: pickle.dumps(-1, 1).decode("iso8859-1"),
col1: 'no', col2: 'Turkey'},
{col0: pickle.dumps(9, 1).decode("iso8859-1"),
col1: 'yes', col2: 'SR-71A Blackbird'}
]
try: try:
self.tdb.Drop(tabname) self.tdb.Drop(tabname)
@ -97,8 +115,14 @@ class TableDBTestCase(unittest.TestCase):
for row in testinfo : for row in testinfo :
self.tdb.Insert(tabname, row) self.tdb.Insert(tabname, row)
values = self.tdb.Select(tabname, [col2], import sys
conditions={col0: lambda x: pickle.loads(x) >= 8}) if sys.version_info[0] < 3 :
values = self.tdb.Select(tabname, [col2],
conditions={col0: lambda x: pickle.loads(x) >= 8})
else :
values = self.tdb.Select(tabname, [col2],
conditions={col0: lambda x:
pickle.loads(bytes(x, "iso8859-1")) >= 8})
self.assertEqual(len(values), 2) self.assertEqual(len(values), 2)
if values[0]['Species'] == 'Penguin' : if values[0]['Species'] == 'Penguin' :

View file

@ -4,19 +4,8 @@
import os import os
import unittest import unittest
try: from test_all import db, test_support, get_new_environment_path, \
# For Pythons w/distutils pybsddb get_new_database_path
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
try : try :
a=set() a=set()
@ -79,12 +68,16 @@ class DBTxn_distributed(unittest.TestCase):
def test01_distributed_transactions(self) : def test01_distributed_transactions(self) :
txns=set() txns=set()
adapt = lambda x : x
import sys
if sys.version_info[0] >= 3 :
adapt = lambda x : bytes(x, "ascii")
# Create transactions, "prepare" them, and # Create transactions, "prepare" them, and
# let them be garbage collected. # let them be garbage collected.
for i in xrange(self.num_txns) : for i in xrange(self.num_txns) :
txn=self.dbenv.txn_begin() txn = self.dbenv.txn_begin()
gid="%%%dd" %db.DB_XIDDATASIZE gid = "%%%dd" %db.DB_XIDDATASIZE
gid=gid %i gid = adapt(gid %i)
self.db.put(i, gid, txn=txn, flags=db.DB_APPEND) self.db.put(i, gid, txn=txn, flags=db.DB_APPEND)
txns.add(gid) txns.add(gid)
txn.prepare(gid) txn.prepare(gid)

View file

@ -5,19 +5,7 @@ is closed before its DB objects.
import os import os
import unittest import unittest
try: from test_all import db, test_support, verbose, get_new_environment_path, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
from test_all import verbose, get_new_environment_path, get_new_database_path
# We're going to get warnings in this module about trying to close the db when # We're going to get warnings in this module about trying to close the db when
# its env is already closed. Let's just ignore those. # its env is already closed. Let's just ignore those.

View file

@ -5,14 +5,7 @@ TestCases for checking set_get_returns_none.
import os, string import os, string
import unittest import unittest
try: from test_all import db, verbose, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
from test_all import verbose, get_new_database_path
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -39,8 +32,8 @@ class GetReturnsNoneTestCase(unittest.TestCase):
data = d.get('bad key') data = d.get('bad key')
self.assertEqual(data, None) self.assertEqual(data, None)
data = d.get('a') data = d.get(string.letters[0])
self.assertEqual(data, 'a'*40) self.assertEqual(data, string.letters[0]*40)
count = 0 count = 0
c = d.cursor() c = d.cursor()
@ -50,7 +43,7 @@ class GetReturnsNoneTestCase(unittest.TestCase):
rec = c.next() rec = c.next()
self.assertEqual(rec, None) self.assertEqual(rec, None)
self.assertEqual(count, 52) self.assertEqual(count, len(string.letters))
c.close() c.close()
d.close() d.close()
@ -67,8 +60,8 @@ class GetReturnsNoneTestCase(unittest.TestCase):
self.assertRaises(db.DBNotFoundError, d.get, 'bad key') self.assertRaises(db.DBNotFoundError, d.get, 'bad key')
self.assertRaises(KeyError, d.get, 'bad key') self.assertRaises(KeyError, d.get, 'bad key')
data = d.get('a') data = d.get(string.letters[0])
self.assertEqual(data, 'a'*40) self.assertEqual(data, string.letters[0]*40)
count = 0 count = 0
exceptionHappened = 0 exceptionHappened = 0
@ -84,7 +77,7 @@ class GetReturnsNoneTestCase(unittest.TestCase):
self.assertNotEqual(rec, None) self.assertNotEqual(rec, None)
self.assert_(exceptionHappened) self.assert_(exceptionHappened)
self.assertEqual(count, 52) self.assertEqual(count, len(string.letters))
c.close() c.close()
d.close() d.close()

View file

@ -4,22 +4,9 @@
import os import os
import unittest import unittest
from test_all import verbose
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbshelve
except ImportError:
# For Python 2.3
from bsddb import db, dbshelve
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
from test_all import db, dbshelve, test_support, verbose, \
get_new_environment_path, get_new_database_path
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View file

@ -5,23 +5,16 @@ TestCases for testing the locking sub-system.
import time import time
import unittest import unittest
from test_all import verbose, have_threads, get_new_environment_path, get_new_database_path from test_all import db, test_support, verbose, have_threads, \
get_new_environment_path, get_new_database_path
if have_threads : if have_threads :
from threading import Thread, currentThread from threading import Thread
import sys
try: if sys.version_info[0] < 3 :
# For Pythons w/distutils pybsddb from threading import currentThread
from bsddb3 import db else :
except ImportError: from threading import current_thread as currentThread
# For Python 2.3
from bsddb import db
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -87,7 +80,11 @@ class LockingTestCase(unittest.TestCase):
args=(db.DB_LOCK_WRITE,))) args=(db.DB_LOCK_WRITE,)))
for t in threads: for t in threads:
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
for t in threads: for t in threads:
t.join() t.join()
@ -111,7 +108,11 @@ class LockingTestCase(unittest.TestCase):
deadlock_detection.end=False deadlock_detection.end=False
deadlock_detection.count=0 deadlock_detection.count=0
t=Thread(target=deadlock_detection) t=Thread(target=deadlock_detection)
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
self.env.set_timeout(100000, db.DB_SET_LOCK_TIMEOUT) self.env.set_timeout(100000, db.DB_SET_LOCK_TIMEOUT)
anID = self.env.lock_id() anID = self.env.lock_id()
@ -134,7 +135,12 @@ class LockingTestCase(unittest.TestCase):
self.assertTrue(deadlock_detection.count>0) self.assertTrue(deadlock_detection.count>0)
def theThread(self, lockType): def theThread(self, lockType):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
if lockType == db.DB_LOCK_WRITE: if lockType == db.DB_LOCK_WRITE:
lt = "write" lt = "write"
else: else:

View file

@ -4,19 +4,7 @@
import os import os
import unittest import unittest
try: from test_all import db, dbshelve, hashopen, test_support, get_new_environment_path, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db, dbshelve, hashopen
except ImportError:
# For Python 2.3
from bsddb import db, dbshelve, hashopen
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -39,7 +27,11 @@ class MiscTestCase(unittest.TestCase):
# check for crash fixed when db_home is used before open() # check for crash fixed when db_home is used before open()
self.assert_(env.db_home is None) self.assert_(env.db_home is None)
env.open(self.homeDir, db.DB_CREATE) env.open(self.homeDir, db.DB_CREATE)
self.assertEqual(self.homeDir, env.db_home) import sys
if sys.version_info[0] < 3 :
self.assertEqual(self.homeDir, env.db_home)
else :
self.assertEqual(bytes(self.homeDir, "ascii"), env.db_home)
def test03_repr_closed_db(self): def test03_repr_closed_db(self):
db = hashopen(self.filename) db = hashopen(self.filename)

View file

@ -7,20 +7,7 @@ except ImportError:
cPickle = None cPickle = None
import unittest import unittest
try: from test_all import db, test_support, get_new_environment_path, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError, e:
# For Python 2.3
from bsddb import db
from test_all import get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View file

@ -6,15 +6,7 @@ import os, string
from pprint import pprint from pprint import pprint
import unittest import unittest
try: from test_all import db, verbose, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
from test_all import verbose, get_new_database_path
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -47,14 +39,14 @@ class SimpleQueueTestCase(unittest.TestCase):
for x in string.letters: for x in string.letters:
d.append(x * 40) d.append(x * 40)
self.assertEqual(len(d), 52) self.assertEqual(len(d), len(string.letters))
d.put(100, "some more data") d.put(100, "some more data")
d.put(101, "and some more ") d.put(101, "and some more ")
d.put(75, "out of order") d.put(75, "out of order")
d.put(1, "replacement data") d.put(1, "replacement data")
self.assertEqual(len(d), 55) self.assertEqual(len(d), len(string.letters)+3)
if verbose: if verbose:
print "before close" + '-' * 30 print "before close" + '-' * 30
@ -69,7 +61,11 @@ class SimpleQueueTestCase(unittest.TestCase):
print "after open" + '-' * 30 print "after open" + '-' * 30
pprint(d.stat()) pprint(d.stat())
d.append("one more") # Test "txn" as a positional parameter
d.append("one more", None)
# Test "txn" as a keyword parameter
d.append("another one", txn=None)
c = d.cursor() c = d.cursor()
if verbose: if verbose:
@ -119,14 +115,14 @@ class SimpleQueueTestCase(unittest.TestCase):
for x in string.letters: for x in string.letters:
d.append(x * 40) d.append(x * 40)
self.assertEqual(len(d), 52) self.assertEqual(len(d), len(string.letters))
d.put(100, "some more data") d.put(100, "some more data")
d.put(101, "and some more ") d.put(101, "and some more ")
d.put(75, "out of order") d.put(75, "out of order")
d.put(1, "replacement data") d.put(1, "replacement data")
self.assertEqual(len(d), 55) self.assertEqual(len(d), len(string.letters)+3)
if verbose: if verbose:
print "before close" + '-' * 30 print "before close" + '-' * 30

View file

@ -6,19 +6,7 @@ import errno
from pprint import pprint from pprint import pprint
import unittest import unittest
from test_all import verbose, get_new_environment_path, get_new_database_path from test_all import db, test_support, verbose, get_new_environment_path, get_new_database_path
try:
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
@ -72,7 +60,11 @@ class SimpleRecnoTestCase(unittest.TestCase):
try: try:
data = d[0] # This should raise a KeyError!?!?! data = d[0] # This should raise a KeyError!?!?!
except db.DBInvalidArgError, val: except db.DBInvalidArgError, val:
self.assertEqual(val[0], db.EINVAL) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.EINVAL)
else :
self.assertEqual(val.args[0], db.EINVAL)
if verbose: print val if verbose: print val
else: else:
self.fail("expected exception") self.fail("expected exception")
@ -277,7 +269,11 @@ class SimpleRecnoTestCase(unittest.TestCase):
try: # this one will fail try: # this one will fail
d.append('bad' * 20) d.append('bad' * 20)
except db.DBInvalidArgError, val: except db.DBInvalidArgError, val:
self.assertEqual(val[0], db.EINVAL) import sys
if sys.version_info[0] < 3 :
self.assertEqual(val[0], db.EINVAL)
else :
self.assertEqual(val.args[0], db.EINVAL)
if verbose: print val if verbose: print val
else: else:
self.fail("expected exception") self.fail("expected exception")

View file

@ -5,21 +5,9 @@ import os
import time import time
import unittest import unittest
try: from test_all import db, test_support, have_threads, verbose, \
# For Pythons w/distutils pybsddb get_new_environment_path, get_new_database_path
from bsddb3 import db
except ImportError:
# For Python 2.3
from bsddb import db
from test_all import have_threads, get_new_environment_path, get_new_database_path
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
from test_all import verbose
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -254,9 +242,14 @@ class DBBaseReplication(DBReplicationManager):
from threading import Thread from threading import Thread
t_m=Thread(target=thread_master) t_m=Thread(target=thread_master)
t_m.setDaemon(True)
t_c=Thread(target=thread_client) t_c=Thread(target=thread_client)
t_c.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t_m.setDaemon(True)
t_c.setDaemon(True)
else :
t_m.daemon = True
t_c.daemon = True
self.t_m = t_m self.t_m = t_m
self.t_c = t_c self.t_c = t_c
@ -400,7 +393,11 @@ class DBBaseReplication(DBReplicationManager):
from threading import Thread from threading import Thread
election_status[0] = True election_status[0] = True
t=Thread(target=elect) t=Thread(target=elect)
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
self.thread_do = thread_do self.thread_do = thread_do

View file

@ -1,18 +1,7 @@
import unittest import unittest
import os import os
try: from test_all import db, test_support, get_new_environment_path, get_new_database_path
# For Pythons w/distutils pybsddb
from bsddb3 import db
except ImportError:
from bsddb import db
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
from test_all import get_new_environment_path, get_new_database_path
class DBSequenceTest(unittest.TestCase): class DBSequenceTest(unittest.TestCase):

View file

@ -16,23 +16,16 @@ except NameError:
pass pass
import unittest import unittest
from test_all import verbose, have_threads, get_new_environment_path, get_new_database_path from test_all import db, dbutils, test_support, verbose, have_threads, \
get_new_environment_path, get_new_database_path
if have_threads : if have_threads :
from threading import Thread, currentThread from threading import Thread
import sys
if sys.version_info[0] < 3 :
try: from threading import currentThread
# For Pythons w/distutils pybsddb else :
from bsddb3 import db, dbutils from threading import current_thread as currentThread
except ImportError:
# For Python 2.3
from bsddb import db, dbutils
try:
from bsddb3 import test_support
except ImportError:
from test import test_support
#---------------------------------------------------------------------- #----------------------------------------------------------------------
@ -106,7 +99,11 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
rt.setDaemon(True) import sys
if sys.version_info[0] < 3 :
rt.setDaemon(True)
else :
rt.daemon = True
readers.append(rt) readers.append(rt)
writers=[] writers=[]
@ -121,7 +118,11 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
for t in writers: for t in writers:
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
for t in writers: for t in writers:
@ -130,7 +131,12 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
t.join() t.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
if verbose: if verbose:
print "%s: creating records %d - %d" % (name, start, stop) print "%s: creating records %d - %d" % (name, start, stop)
@ -155,7 +161,11 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
for i in xrange(5) : for i in xrange(5) :
c = d.cursor() c = d.cursor()
@ -221,7 +231,11 @@ class SimpleThreadedBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
rt.setDaemon(True) import sys
if sys.version_info[0] < 3 :
rt.setDaemon(True)
else :
rt.daemon = True
readers.append(rt) readers.append(rt)
writers = [] writers = []
@ -236,7 +250,11 @@ class SimpleThreadedBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
for t in writers: for t in writers:
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
for t in writers: for t in writers:
@ -245,7 +263,11 @@ class SimpleThreadedBase(BaseThreadedTestCase):
t.join() t.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
if verbose: if verbose:
print "%s: creating records %d - %d" % (name, start, stop) print "%s: creating records %d - %d" % (name, start, stop)
@ -268,7 +290,11 @@ class SimpleThreadedBase(BaseThreadedTestCase):
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
c = d.cursor() c = d.cursor()
count = 0 count = 0
@ -335,7 +361,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
rt.setDaemon(True) import sys
if sys.version_info[0] < 3 :
rt.setDaemon(True)
else :
rt.daemon = True
readers.append(rt) readers.append(rt)
writers = [] writers = []
@ -349,11 +379,19 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
dt = Thread(target = self.deadlockThread) dt = Thread(target = self.deadlockThread)
dt.setDaemon(True) import sys
if sys.version_info[0] < 3 :
dt.setDaemon(True)
else :
dt.daemon = True
dt.start() dt.start()
for t in writers: for t in writers:
t.setDaemon(True) import sys
if sys.version_info[0] < 3 :
t.setDaemon(True)
else :
t.daemon = True
t.start() t.start()
for t in writers: for t in writers:
@ -365,7 +403,12 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
dt.join() dt.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
count=len(keys)//len(readers) count=len(keys)//len(readers)
while len(keys): while len(keys):
try: try:
@ -388,7 +431,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
name = currentThread().getName() import sys
if sys.version_info[0] < 3 :
name = currentThread().getName()
else :
name = currentThread().name
finished = False finished = False
while not finished: while not finished:

View file

@ -488,8 +488,9 @@ Extension Modules
- Support for Windows 9x has been removed from the winsound module. - Support for Windows 9x has been removed from the winsound module.
- bsddb module updated to version 4.7.0. - bsddb module updated to version 4.7.3pre2.
http://www.jcea.es/programacion/pybsddb.htm#bsddb3-4.7.0 http://www.jcea.es/programacion/pybsddb.htm#bsddb3-4.7.3. This
code should be compatible with Python 3.0.
- Issue #2858: Fix potential memory corruption when - Issue #2858: Fix potential memory corruption when
bsddb.db.DBEnv.lock_get and other bsddb.db object constructors bsddb.db.DBEnv.lock_get and other bsddb.db object constructors
@ -2655,8 +2656,8 @@ Extension Modules
- fixed a bug with bsddb.DB.stat: the flags and txn keyword arguments - fixed a bug with bsddb.DB.stat: the flags and txn keyword arguments
were transposed. were transposed.
- Added support for linking the bsddb module against BerkeleyDB 4.5.x - Added support for linking the bsddb module against BerkeleyDB 4.5.x,
and 4.6.x. 4.6.x and 4.7.x.
- Bug #1633621: if curses.resizeterm() or curses.resize_term() is - Bug #1633621: if curses.resizeterm() or curses.resize_term() is
called, update _curses.LINES, _curses.COLS, curses.LINES and called, update _curses.LINES, _curses.COLS, curses.LINES and

View file

@ -396,7 +396,11 @@ static int make_dbt(PyObject* obj, DBT* dbt)
} }
else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) { else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
#if (PY_VERSION_HEX < 0x03000000)
"Data values must be of type string or None."); "Data values must be of type string or None.");
#else
"Data values must be of type bytes or None.");
#endif
return 0; return 0;
} }
return 1; return 1;
@ -435,7 +439,11 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
if (type == DB_RECNO || type == DB_QUEUE) { if (type == DB_RECNO || type == DB_QUEUE) {
PyErr_SetString( PyErr_SetString(
PyExc_TypeError, PyExc_TypeError,
#if (PY_VERSION_HEX < 0x03000000)
"String keys not allowed for Recno and Queue DB's"); "String keys not allowed for Recno and Queue DB's");
#else
"Bytes keys not allowed for Recno and Queue DB's");
#endif
return 0; return 0;
} }
@ -488,7 +496,11 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
} }
else { else {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
#if (PY_VERSION_HEX < 0x03000000)
"String or Integer object expected for key, %s found", "String or Integer object expected for key, %s found",
#else
"Bytes or Integer object expected for key, %s found",
#endif
Py_TYPE(keyobj)->tp_name); Py_TYPE(keyobj)->tp_name);
return 0; return 0;
} }
@ -573,11 +585,13 @@ static PyObject *BuildValue_S(const void *p,int s)
p=DummyString; p=DummyString;
assert(s==0); assert(s==0);
} }
return Py_BuildValue("s#",p,s); return PyBytes_FromStringAndSize(p, s);
} }
static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2) static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
{ {
PyObject *a, *b, *r;
if (!p1) { if (!p1) {
p1=DummyString; p1=DummyString;
assert(s1==0); assert(s1==0);
@ -586,25 +600,59 @@ static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
p2=DummyString; p2=DummyString;
assert(s2==0); assert(s2==0);
} }
return Py_BuildValue("s#s#",p1,s1,p2,s2);
if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
return NULL;
}
if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
Py_DECREF(a);
return NULL;
}
#if (PY_VERSION_HEX >= 0x02040000)
r = PyTuple_Pack(2, a, b) ;
#else
r = Py_BuildValue("OO", a, b);
#endif
Py_DECREF(a);
Py_DECREF(b);
return r;
} }
static PyObject *BuildValue_IS(int i,const void *p,int s) static PyObject *BuildValue_IS(int i,const void *p,int s)
{ {
PyObject *a, *r;
if (!p) { if (!p) {
p=DummyString; p=DummyString;
assert(s==0); assert(s==0);
} }
return Py_BuildValue("is#",i,p,s);
if (!(a = PyBytes_FromStringAndSize(p, s))) {
return NULL;
}
r = Py_BuildValue("iO", i, a);
Py_DECREF(a);
return r;
} }
static PyObject *BuildValue_LS(long i,const void *p,int s) static PyObject *BuildValue_LS(long l,const void *p,int s)
{ {
PyObject *a, *r;
if (!p) { if (!p) {
p=DummyString; p=DummyString;
assert(s==0); assert(s==0);
} }
return Py_BuildValue("ls#",i,p,s);
if (!(a = PyBytes_FromStringAndSize(p, s))) {
return NULL;
}
r = Py_BuildValue("lO", l, a);
Py_DECREF(a);
return r;
} }
@ -895,7 +943,7 @@ newDBObject(DBEnvObject* arg, int flags)
self->btCompareCallback = NULL; self->btCompareCallback = NULL;
self->primaryDBType = 0; self->primaryDBType = 0;
Py_INCREF(Py_None); Py_INCREF(Py_None);
self->private = Py_None; self->private_obj = Py_None;
self->in_weakreflist = NULL; self->in_weakreflist = NULL;
/* keep a reference to our python DBEnv object */ /* keep a reference to our python DBEnv object */
@ -967,7 +1015,7 @@ DB_dealloc(DBObject* self)
Py_DECREF(self->btCompareCallback); Py_DECREF(self->btCompareCallback);
self->btCompareCallback = NULL; self->btCompareCallback = NULL;
} }
Py_DECREF(self->private); Py_DECREF(self->private_obj);
PyObject_Del(self); PyObject_Del(self);
} }
@ -1030,7 +1078,7 @@ newDBEnvObject(int flags)
self->children_dbs = NULL; self->children_dbs = NULL;
self->children_txns = NULL; self->children_txns = NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
self->private = Py_None; self->private_obj = Py_None;
Py_INCREF(Py_None); Py_INCREF(Py_None);
self->rep_transport = Py_None; self->rep_transport = Py_None;
self->in_weakreflist = NULL; self->in_weakreflist = NULL;
@ -1045,7 +1093,7 @@ newDBEnvObject(int flags)
} }
else { else {
self->db_env->set_errcall(self->db_env, _db_errorCallback); self->db_env->set_errcall(self->db_env, _db_errorCallback);
self->db_env->app_private=self; self->db_env->app_private = self;
} }
return self; return self;
} }
@ -1069,7 +1117,7 @@ DBEnv_dealloc(DBEnvObject* self)
if (self->in_weakreflist != NULL) { if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self); PyObject_ClearWeakRefs((PyObject *) self);
} }
Py_DECREF(self->private); Py_DECREF(self->private_obj);
Py_DECREF(self->rep_transport); Py_DECREF(self->rep_transport);
PyObject_Del(self); PyObject_Del(self);
} }
@ -1248,15 +1296,17 @@ DBSequence_dealloc(DBSequenceObject* self)
/* DB methods */ /* DB methods */
static PyObject* static PyObject*
DB_append(DBObject* self, PyObject* args) DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
{ {
PyObject* txnobj = NULL; PyObject* txnobj = NULL;
PyObject* dataobj; PyObject* dataobj;
db_recno_t recno; db_recno_t recno;
DBT key, data; DBT key, data;
DB_TXN *txn = NULL; DB_TXN *txn = NULL;
static char* kwnames[] = { "data", "txn", NULL };
if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj)) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
&dataobj, &txnobj))
return NULL; return NULL;
CHECK_DB_NOT_CLOSED(self); CHECK_DB_NOT_CLOSED(self);
@ -1443,6 +1493,7 @@ DB_close_internal(DBObject* self, int flags)
if (self->db != NULL) { if (self->db != NULL) {
/* Can be NULL if db is not in an environment */ /* Can be NULL if db is not in an environment */
EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self); EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
if (self->txn) { if (self->txn) {
EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
self->txn=NULL; self->txn=NULL;
@ -2168,7 +2219,12 @@ DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
return NULL; return NULL;
CHECK_DB_NOT_CLOSED(self); CHECK_DB_NOT_CLOSED(self);
EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
MYDB_BEGIN_ALLOW_THREADS;
err = self->db->remove(self->db, filename, database, flags); err = self->db->remove(self->db, filename, database, flags);
MYDB_END_ALLOW_THREADS;
self->db = NULL; self->db = NULL;
RETURN_IF_ERR(); RETURN_IF_ERR();
RETURN_NONE(); RETURN_NONE();
@ -2201,17 +2257,17 @@ static PyObject*
DB_get_private(DBObject* self) DB_get_private(DBObject* self)
{ {
/* We can give out the private field even if db is closed */ /* We can give out the private field even if db is closed */
Py_INCREF(self->private); Py_INCREF(self->private_obj);
return self->private; return self->private_obj;
} }
static PyObject* static PyObject*
DB_set_private(DBObject* self, PyObject* private) DB_set_private(DBObject* self, PyObject* private_obj)
{ {
/* We can set the private field even if db is closed */ /* We can set the private field even if db is closed */
Py_DECREF(self->private); Py_DECREF(self->private_obj);
Py_INCREF(private); Py_INCREF(private_obj);
self->private = private; self->private_obj = private_obj;
RETURN_NONE(); RETURN_NONE();
} }
@ -2990,16 +3046,19 @@ DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
static PyObject* static PyObject*
DB_has_key(DBObject* self, PyObject* args) DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
{ {
int err; int err;
PyObject* keyobj; PyObject* keyobj;
DBT key, data; DBT key, data;
PyObject* txnobj = NULL; PyObject* txnobj = NULL;
DB_TXN *txn = NULL; DB_TXN *txn = NULL;
static char* kwnames[] = {"key","txn", NULL};
if (!PyArg_UnpackTuple(args,"has_key", 1, 2, &keyobj, &txnobj)) if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
&keyobj, &txnobj))
return NULL; return NULL;
CHECK_DB_NOT_CLOSED(self); CHECK_DB_NOT_CLOSED(self);
if (!make_key_dbt(self, keyobj, &key, NULL)) if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL; return NULL;
@ -4920,17 +4979,17 @@ static PyObject*
DBEnv_get_private(DBEnvObject* self) DBEnv_get_private(DBEnvObject* self)
{ {
/* We can give out the private field even if dbenv is closed */ /* We can give out the private field even if dbenv is closed */
Py_INCREF(self->private); Py_INCREF(self->private_obj);
return self->private; return self->private_obj;
} }
static PyObject* static PyObject*
DBEnv_set_private(DBEnvObject* self, PyObject* private) DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
{ {
/* We can set the private field even if dbenv is closed */ /* We can set the private field even if dbenv is closed */
Py_DECREF(self->private); Py_DECREF(self->private_obj);
Py_INCREF(private); Py_INCREF(private_obj);
self->private = private; self->private_obj = private_obj;
RETURN_NONE(); RETURN_NONE();
} }
@ -5116,8 +5175,18 @@ DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
return Py_BuildValue("(iO)", err, Py_None); return Py_BuildValue("(iO)", err, Py_None);
break; break;
case DB_REP_NEWSITE : case DB_REP_NEWSITE :
return Py_BuildValue("(is#)", err, rec.data, rec.size); {
break; PyObject *tmp, *r;
if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
return NULL;
}
r = Py_BuildValue("(iO)", err, tmp);
Py_DECREF(tmp);
return r;
break;
}
#if (DBVER >= 42) #if (DBVER >= 42)
case DB_REP_NOTPERM : case DB_REP_NOTPERM :
case DB_REP_ISPERM : case DB_REP_ISPERM :
@ -5136,6 +5205,7 @@ _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
DBEnvObject *dbenv; DBEnvObject *dbenv;
PyObject* rep_transport; PyObject* rep_transport;
PyObject* args; PyObject* args;
PyObject *a, *b;
PyObject* result = NULL; PyObject* result = NULL;
int ret=0; int ret=0;
@ -5143,15 +5213,21 @@ _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
dbenv = (DBEnvObject *)db_env->app_private; dbenv = (DBEnvObject *)db_env->app_private;
rep_transport = dbenv->rep_transport; rep_transport = dbenv->rep_transport;
/*
** The errors in 'a' or 'b' are detected in "Py_BuildValue".
*/
a = PyBytes_FromStringAndSize(control->data, control->size);
b = PyBytes_FromStringAndSize(rec->data, rec->size);
args = Py_BuildValue( args = Py_BuildValue(
#if (PY_VERSION_HEX >= 0x02040000) #if (PY_VERSION_HEX >= 0x02040000)
"(Os#s#(ll)iI)", "(OOO(ll)iI)",
#else #else
"(Os#s#(ll)ii)", "(OOO(ll)ii)",
#endif #endif
dbenv, dbenv,
control->data, control->size, a, b,
rec->data, rec->size, lsn->file, lsn->offset, envid, flags); lsn->file, lsn->offset, envid, flags);
if (args) { if (args) {
result = PyEval_CallObject(rep_transport, args); result = PyEval_CallObject(rep_transport, args);
} }
@ -5160,6 +5236,8 @@ _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
PyErr_Print(); PyErr_Print();
ret = -1; ret = -1;
} }
Py_XDECREF(a);
Py_XDECREF(b);
Py_XDECREF(args); Py_XDECREF(args);
Py_XDECREF(result); Py_XDECREF(result);
MYDB_END_BLOCK_THREADS; MYDB_END_BLOCK_THREADS;
@ -6259,7 +6337,7 @@ DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
/* Method definition tables and type objects */ /* Method definition tables and type objects */
static PyMethodDef DB_methods[] = { static PyMethodDef DB_methods[] = {
{"append", (PyCFunction)DB_append, METH_VARARGS}, {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
{"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS}, {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
{"close", (PyCFunction)DB_close, METH_VARARGS}, {"close", (PyCFunction)DB_close, METH_VARARGS},
{"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS}, {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
@ -6275,7 +6353,7 @@ static PyMethodDef DB_methods[] = {
{"get_type", (PyCFunction)DB_get_type, METH_NOARGS}, {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
{"join", (PyCFunction)DB_join, METH_VARARGS}, {"join", (PyCFunction)DB_join, METH_VARARGS},
{"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS}, {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
{"has_key", (PyCFunction)DB_has_key, METH_VARARGS}, {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
{"items", (PyCFunction)DB_items, METH_VARARGS}, {"items", (PyCFunction)DB_items, METH_VARARGS},
{"keys", (PyCFunction)DB_keys, METH_VARARGS}, {"keys", (PyCFunction)DB_keys, METH_VARARGS},
{"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS}, {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},

View file

@ -105,7 +105,7 @@
#error "eek! DBVER can't handle minor versions > 9" #error "eek! DBVER can't handle minor versions > 9"
#endif #endif
#define PY_BSDDB_VERSION "4.7.2devel9" #define PY_BSDDB_VERSION "4.7.3pre2"
/* Python object definitions */ /* Python object definitions */
@ -134,7 +134,7 @@ typedef struct {
PyObject* event_notifyCallback; PyObject* event_notifyCallback;
struct DBObject *children_dbs; struct DBObject *children_dbs;
struct DBTxnObject *children_txns; struct DBTxnObject *children_txns;
PyObject *private; PyObject *private_obj;
PyObject *rep_transport; PyObject *rep_transport;
PyObject *in_weakreflist; /* List of weak references */ PyObject *in_weakreflist; /* List of weak references */
} DBEnvObject; } DBEnvObject;
@ -159,7 +159,7 @@ typedef struct DBObject {
PyObject* associateCallback; PyObject* associateCallback;
PyObject* btCompareCallback; PyObject* btCompareCallback;
int primaryDBType; int primaryDBType;
PyObject *private; PyObject *private_obj;
PyObject *in_weakreflist; /* List of weak references */ PyObject *in_weakreflist; /* List of weak references */
} DBObject; } DBObject;