Commit 6557aac5 authored by Jesus Cea's avatar Jesus Cea

pybsddb 4.8.4 integration. Please, comment in issue #8156

parent 31e928eb
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#---------------------------------------------------------------------- #----------------------------------------------------------------------
"""Support for Berkeley DB 4.0 through 4.7 with a simple interface. """Support for Berkeley DB 4.1 through 4.8 with a simple interface.
For the full featured object oriented interface use the bsddb.db module For the full featured object oriented interface use the bsddb.db module
instead. It mirrors the Oracle Berkeley DB C API. instead. It mirrors the Oracle Berkeley DB C API.
...@@ -42,7 +42,8 @@ instead. It mirrors the Oracle Berkeley DB C API. ...@@ -42,7 +42,8 @@ instead. It mirrors the Oracle Berkeley DB C API.
import sys import sys
absolute_import = (sys.version_info[0] >= 3) absolute_import = (sys.version_info[0] >= 3)
if sys.py3kwarning: if (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) :
if sys.py3kwarning and (__name__ != 'bsddb3') :
import warnings import warnings
warnings.warnpy3k("in 3.x, the bsddb module has been removed; " warnings.warnpy3k("in 3.x, the bsddb module has been removed; "
"please use the pybsddb project instead", "please use the pybsddb project instead",
...@@ -81,7 +82,7 @@ import sys, os ...@@ -81,7 +82,7 @@ import sys, os
from weakref import ref from weakref import ref
if sys.version_info[0:2] <= (2, 5) : if sys.version_info < (2, 6) :
import UserDict import UserDict
MutableMapping = UserDict.DictMixin MutableMapping = UserDict.DictMixin
else : else :
...@@ -256,7 +257,7 @@ class _DBWithCursor(_iter_mixin): ...@@ -256,7 +257,7 @@ class _DBWithCursor(_iter_mixin):
self._checkOpen() self._checkOpen()
return _DeadlockWrap(lambda: len(self.db)) # len(self.db) return _DeadlockWrap(lambda: len(self.db)) # len(self.db)
if sys.version_info[0:2] >= (2, 6) : if sys.version_info >= (2, 6) :
def __repr__(self) : def __repr__(self) :
if self.isOpen() : if self.isOpen() :
return repr(dict(_DeadlockWrap(self.db.items))) return repr(dict(_DeadlockWrap(self.db.items)))
...@@ -442,8 +443,10 @@ def _checkflag(flag, file): ...@@ -442,8 +443,10 @@ def _checkflag(flag, file):
# Berkeley DB was too. # Berkeley DB was too.
try: try:
import thread # 2to3 automatically changes "import thread" to "import _thread"
del thread import thread as T
del T
except ImportError: except ImportError:
db.DB_THREAD = 0 db.DB_THREAD = 0
......
...@@ -29,7 +29,7 @@ if absolute_import : ...@@ -29,7 +29,7 @@ if absolute_import :
else : else :
import db import db
if sys.version_info[0:2] <= (2, 5) : if sys.version_info < (2, 6) :
try: try:
from UserDict import DictMixin from UserDict import DictMixin
except ImportError: except ImportError:
...@@ -110,7 +110,6 @@ class DBEnv: ...@@ -110,7 +110,6 @@ class DBEnv:
def log_stat(self, *args, **kwargs): def log_stat(self, *args, **kwargs):
return self._cobj.log_stat(*args, **kwargs) return self._cobj.log_stat(*args, **kwargs)
if db.version() >= (4,1):
def dbremove(self, *args, **kwargs): def dbremove(self, *args, **kwargs):
return self._cobj.dbremove(*args, **kwargs) return self._cobj.dbremove(*args, **kwargs)
def dbrename(self, *args, **kwargs): def dbrename(self, *args, **kwargs):
...@@ -119,6 +118,9 @@ class DBEnv: ...@@ -119,6 +118,9 @@ class DBEnv:
return self._cobj.set_encrypt(*args, **kwargs) return self._cobj.set_encrypt(*args, **kwargs)
if db.version() >= (4,4): if db.version() >= (4,4):
def fileid_reset(self, *args, **kwargs):
return self._cobj.fileid_reset(*args, **kwargs)
def lsn_reset(self, *args, **kwargs): def lsn_reset(self, *args, **kwargs):
return self._cobj.lsn_reset(*args, **kwargs) return self._cobj.lsn_reset(*args, **kwargs)
...@@ -138,7 +140,7 @@ class DB(MutableMapping): ...@@ -138,7 +140,7 @@ class DB(MutableMapping):
def __delitem__(self, arg): def __delitem__(self, arg):
del self._cobj[arg] del self._cobj[arg]
if sys.version_info[0:2] >= (2, 6) : if sys.version_info >= (2, 6) :
def __iter__(self) : def __iter__(self) :
return self._cobj.__iter__() return self._cobj.__iter__()
...@@ -229,7 +231,6 @@ class DB(MutableMapping): ...@@ -229,7 +231,6 @@ class DB(MutableMapping):
def set_get_returns_none(self, *args, **kwargs): def set_get_returns_none(self, *args, **kwargs):
return self._cobj.set_get_returns_none(*args, **kwargs) return self._cobj.set_get_returns_none(*args, **kwargs)
if db.version() >= (4,1):
def set_encrypt(self, *args, **kwargs): def set_encrypt(self, *args, **kwargs):
return self._cobj.set_encrypt(*args, **kwargs) return self._cobj.set_encrypt(*args, **kwargs)
......
...@@ -29,9 +29,6 @@ storage. ...@@ -29,9 +29,6 @@ storage.
#------------------------------------------------------------------------ #------------------------------------------------------------------------
import cPickle
import sys
import sys import sys
absolute_import = (sys.version_info[0] >= 3) absolute_import = (sys.version_info[0] >= 3)
if absolute_import : if absolute_import :
...@@ -40,13 +37,41 @@ if absolute_import : ...@@ -40,13 +37,41 @@ if absolute_import :
else : else :
import db 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.3 and 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.3, 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
#At version 2.3 cPickle switched to using protocol instead of bin #At version 2.3 cPickle switched to using protocol instead of bin
if sys.version_info[:3] >= (2, 3, 0): if sys.version_info >= (2, 3):
HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL
# In python 2.3.*, "cPickle.dumps" accepts no # In python 2.3.*, "cPickle.dumps" accepts no
# named parameters. "pickle.dumps" accepts them, # named parameters. "pickle.dumps" accepts them,
# so this seems a bug. # so this seems a bug.
if sys.version_info[:3] < (2, 4, 0): if sys.version_info < (2, 4):
def _dumps(object, protocol): def _dumps(object, protocol):
return cPickle.dumps(object, protocol) return cPickle.dumps(object, protocol)
else : else :
...@@ -59,11 +84,16 @@ else: ...@@ -59,11 +84,16 @@ else:
return cPickle.dumps(object, bin=protocol) return cPickle.dumps(object, bin=protocol)
try: if sys.version_info < (2, 6) :
try:
from UserDict import DictMixin from UserDict import DictMixin
except ImportError: except ImportError:
# DictMixin is new in Python 2.3 # DictMixin is new in Python 2.3
class DictMixin: pass class DictMixin: pass
MutableMapping = DictMixin
else :
import collections
MutableMapping = collections.MutableMapping
#------------------------------------------------------------------------ #------------------------------------------------------------------------
...@@ -106,7 +136,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH, ...@@ -106,7 +136,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
class DBShelveError(db.DBError): pass class DBShelveError(db.DBError): pass
class DBShelf(DictMixin): class DBShelf(MutableMapping):
"""A shelf to hold pickled objects, built upon a bsddb DB object. It """A shelf to hold pickled objects, built upon a bsddb DB object. It
automatically pickles/unpickles data objects going to/from the DB. automatically pickles/unpickles data objects going to/from the DB.
""" """
...@@ -157,6 +187,17 @@ class DBShelf(DictMixin): ...@@ -157,6 +187,17 @@ class DBShelf(DictMixin):
else: else:
return self.db.keys() 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): def open(self, *args, **kwargs):
self.db.open(*args, **kwargs) self.db.open(*args, **kwargs)
......
...@@ -22,7 +22,35 @@ import sys ...@@ -22,7 +22,35 @@ import sys
import copy import copy
import random import random
import struct import struct
import cPickle as pickle
if sys.version_info[0] >= 3 :
import pickle
else :
if sys.version_info < (2, 6) :
import cPickle as pickle
else :
# When we drop support for python 2.3 and 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.3, 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 as pickle
finally :
w.__exit__()
del w
try: try:
# For Pythons w/distutils pybsddb # For Pythons w/distutils pybsddb
...@@ -31,12 +59,6 @@ except ImportError: ...@@ -31,12 +59,6 @@ except ImportError:
# For Python 2.3 # For Python 2.3
from bsddb import db from bsddb import db
# XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c
if not hasattr(db,"DBIncompleteError") :
class DBIncompleteError(Exception):
pass
db.DBIncompleteError = DBIncompleteError
class TableDBError(StandardError): class TableDBError(StandardError):
pass pass
class TableAlreadyExists(TableDBError): class TableAlreadyExists(TableDBError):
...@@ -261,16 +283,10 @@ class bsdTableDB : ...@@ -261,16 +283,10 @@ class bsdTableDB :
self.env = None self.env = None
def checkpoint(self, mins=0): def checkpoint(self, mins=0):
try:
self.env.txn_checkpoint(mins) self.env.txn_checkpoint(mins)
except db.DBIncompleteError:
pass
def sync(self): def sync(self):
try:
self.db.sync() self.db.sync()
except db.DBIncompleteError:
pass
def _db_print(self) : def _db_print(self) :
"""Print the database to stdout for debugging""" """Print the database to stdout for debugging"""
...@@ -659,6 +675,13 @@ class bsdTableDB : ...@@ -659,6 +675,13 @@ class bsdTableDB :
a = atuple[1] a = atuple[1]
b = btuple[1] b = btuple[1]
if type(a) is type(b): if type(a) is type(b):
# Needed for python 3. "cmp" vanished in 3.0.1
def cmp(a, b) :
if a==b : return 0
if a<b : return -1
return 1
if isinstance(a, PrefixCond) and isinstance(b, PrefixCond): if isinstance(a, PrefixCond) and isinstance(b, PrefixCond):
# longest prefix first # longest prefix first
return cmp(len(b.prefix), len(a.prefix)) return cmp(len(b.prefix), len(a.prefix))
......
...@@ -15,6 +15,51 @@ except ImportError: ...@@ -15,6 +15,51 @@ except ImportError:
if sys.version_info[0] >= 3 : if sys.version_info[0] >= 3 :
charset = "iso8859-1" # Full 8 bit charset = "iso8859-1" # Full 8 bit
class logcursor_py3k(object) :
def __init__(self, env) :
self._logcursor = env.log_cursor()
def __getattr__(self, v) :
return getattr(self._logcursor, v)
def __next__(self) :
v = getattr(self._logcursor, "next")()
if v is not None :
v = (v[0], v[1].decode(charset))
return v
next = __next__
def first(self) :
v = self._logcursor.first()
if v is not None :
v = (v[0], v[1].decode(charset))
return v
def last(self) :
v = self._logcursor.last()
if v is not None :
v = (v[0], v[1].decode(charset))
return v
def prev(self) :
v = self._logcursor.prev()
if v is not None :
v = (v[0], v[1].decode(charset))
return v
def current(self) :
v = self._logcursor.current()
if v is not None :
v = (v[0], v[1].decode(charset))
return v
def set(self, lsn) :
v = self._logcursor.set(lsn)
if v is not None :
v = (v[0], v[1].decode(charset))
return v
class cursor_py3k(object) : class cursor_py3k(object) :
def __init__(self, db, *args, **kwargs) : def __init__(self, db, *args, **kwargs) :
self._dbcursor = db.cursor(*args, **kwargs) self._dbcursor = db.cursor(*args, **kwargs)
...@@ -71,12 +116,12 @@ if sys.version_info[0] >= 3 : ...@@ -71,12 +116,12 @@ if sys.version_info[0] >= 3 :
v = self._dbcursor.next_nodup() v = self._dbcursor.next_nodup()
return self._fix(v) return self._fix(v)
def put(self, key, value, flags=0, dlen=-1, doff=-1) : def put(self, key, data, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) : if isinstance(key, str) :
key = bytes(key, charset) key = bytes(key, charset)
if isinstance(value, str) : if isinstance(data, str) :
value = bytes(value, charset) value = bytes(data, charset)
return self._dbcursor.put(key, value, flags=flags, dlen=dlen, return self._dbcursor.put(key, data, flags=flags, dlen=dlen,
doff=doff) doff=doff)
def current(self, flags=0, dlen=-1, doff=-1) : def current(self, flags=0, dlen=-1, doff=-1) :
...@@ -203,12 +248,26 @@ if sys.version_info[0] >= 3 : ...@@ -203,12 +248,26 @@ if sys.version_info[0] >= 3 :
k = bytes(k, charset) k = bytes(k, charset)
return self._db.has_key(k, txn=txn) return self._db.has_key(k, txn=txn)
def put(self, key, value, txn=None, flags=0, dlen=-1, doff=-1) : def set_re_delim(self, c) :
if isinstance(c, str) : # We can use a numeric value byte too
c = bytes(c, charset)
return self._db.set_re_delim(c)
def set_re_pad(self, c) :
if isinstance(c, str) : # We can use a numeric value byte too
c = bytes(c, charset)
return self._db.set_re_pad(c)
def get_re_source(self) :
source = self._db.get_re_source()
return source.decode(charset)
def put(self, key, data, txn=None, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) : if isinstance(key, str) :
key = bytes(key, charset) key = bytes(key, charset)
if isinstance(value, str) : if isinstance(data, str) :
value = bytes(value, charset) value = bytes(data, charset)
return self._db.put(key, value, flags=flags, txn=txn, dlen=dlen, return self._db.put(key, data, flags=flags, txn=txn, dlen=dlen,
doff=doff) doff=doff)
def append(self, value, txn=None) : def append(self, value, txn=None) :
...@@ -221,6 +280,11 @@ if sys.version_info[0] >= 3 : ...@@ -221,6 +280,11 @@ if sys.version_info[0] >= 3 :
key = bytes(key, charset) key = bytes(key, charset)
return self._db.get_size(key) return self._db.get_size(key)
def exists(self, key, *args, **kwargs) :
if isinstance(key, str) :
key = bytes(key, charset)
return self._db.exists(key, *args, **kwargs)
def get(self, key, default="MagicCookie", txn=None, flags=0, dlen=-1, doff=-1) : def get(self, key, default="MagicCookie", txn=None, flags=0, dlen=-1, doff=-1) :
if isinstance(key, str) : if isinstance(key, str) :
key = bytes(key, charset) key = bytes(key, charset)
...@@ -288,13 +352,21 @@ if sys.version_info[0] >= 3 : ...@@ -288,13 +352,21 @@ if sys.version_info[0] >= 3 :
key = key.decode(charset) key = key.decode(charset)
data = data.decode(charset) data = data.decode(charset)
key = self._callback(key, data) key = self._callback(key, data)
if (key != bsddb._db.DB_DONOTINDEX) and isinstance(key, if (key != bsddb._db.DB_DONOTINDEX) :
str) : if isinstance(key, str) :
key = bytes(key, charset) key = bytes(key, charset)
elif isinstance(key, list) :
key2 = []
for i in key :
if isinstance(i, str) :
i = bytes(i, charset)
key2.append(i)
key = key2
return key return key
return self._db.associate(secondarydb._db, return self._db.associate(secondarydb._db,
associate_callback(callback).callback, flags=flags, txn=txn) associate_callback(callback).callback, flags=flags,
txn=txn)
def cursor(self, txn=None, flags=0) : def cursor(self, txn=None, flags=0) :
return cursor_py3k(self._db, txn=txn, flags=flags) return cursor_py3k(self._db, txn=txn, flags=flags)
...@@ -310,6 +382,21 @@ if sys.version_info[0] >= 3 : ...@@ -310,6 +382,21 @@ if sys.version_info[0] >= 3 :
def __getattr__(self, v) : def __getattr__(self, v) :
return getattr(self._dbenv, v) return getattr(self._dbenv, v)
def log_cursor(self, flags=0) :
return logcursor_py3k(self._dbenv)
def get_lg_dir(self) :
return self._dbenv.get_lg_dir().decode(charset)
def get_tmp_dir(self) :
return self._dbenv.get_tmp_dir().decode(charset)
def get_data_dirs(self) :
# Have to use a list comprehension and not
# generators, because we are supporting Python 2.3.
return tuple(
[i.decode(charset) for i in self._dbenv.get_data_dirs()])
class DBSequence_py3k(object) : class DBSequence_py3k(object) :
def __init__(self, db, *args, **kwargs) : def __init__(self, db, *args, **kwargs) :
self._db=db self._db=db
...@@ -332,6 +419,9 @@ if sys.version_info[0] >= 3 : ...@@ -332,6 +419,9 @@ if sys.version_info[0] >= 3 :
bsddb._db.DBEnv_orig = bsddb._db.DBEnv bsddb._db.DBEnv_orig = bsddb._db.DBEnv
bsddb._db.DB_orig = bsddb._db.DB bsddb._db.DB_orig = bsddb._db.DB
if bsddb.db.version() <= (4, 3) :
bsddb._db.DBSequence_orig = None
else :
bsddb._db.DBSequence_orig = bsddb._db.DBSequence bsddb._db.DBSequence_orig = bsddb._db.DBSequence
def do_proxy_db_py3k(flag) : def do_proxy_db_py3k(flag) :
...@@ -396,8 +486,12 @@ def print_versions(): ...@@ -396,8 +486,12 @@ def print_versions():
print 'bsddb.db.version(): %s' % (db.version(), ) print 'bsddb.db.version(): %s' % (db.version(), )
print 'bsddb.db.__version__: %s' % db.__version__ print 'bsddb.db.__version__: %s' % db.__version__
print 'bsddb.db.cvsid: %s' % db.cvsid print 'bsddb.db.cvsid: %s' % db.cvsid
print 'py module: %s' % bsddb.__file__
print 'extension module: %s' % bsddb._bsddb.__file__ # Workaround for allowing generating an EGGs as a ZIP files.
suffix="__"
print 'py module: %s' % getattr(bsddb, "__file"+suffix)
print 'extension module: %s' % getattr(bsddb, "__file"+suffix)
print 'python version: %s' % sys.version print 'python version: %s' % sys.version
print 'My pid: %s' % os.getpid() print 'My pid: %s' % os.getpid()
print '-=' * 38 print '-=' * 38
...@@ -481,6 +575,8 @@ def suite(module_prefix='', timing_check=None): ...@@ -481,6 +575,8 @@ def suite(module_prefix='', timing_check=None):
test_modules = [ test_modules = [
'test_associate', 'test_associate',
'test_basics', 'test_basics',
'test_dbenv',
'test_db',
'test_compare', 'test_compare',
'test_compat', 'test_compat',
'test_cursor_pget_bug', 'test_cursor_pget_bug',
...@@ -489,6 +585,7 @@ def suite(module_prefix='', timing_check=None): ...@@ -489,6 +585,7 @@ def suite(module_prefix='', timing_check=None):
'test_dbtables', 'test_dbtables',
'test_distributed_transactions', 'test_distributed_transactions',
'test_early_close', 'test_early_close',
'test_fileid',
'test_get_none', 'test_get_none',
'test_join', 'test_join',
'test_lock', 'test_lock',
......
...@@ -148,12 +148,8 @@ class AssociateTestCase(unittest.TestCase): ...@@ -148,12 +148,8 @@ class AssociateTestCase(unittest.TestCase):
self.secDB = None self.secDB = None
self.primary = db.DB(self.env) self.primary = db.DB(self.env)
self.primary.set_get_returns_none(2) self.primary.set_get_returns_none(2)
if db.version() >= (4, 1):
self.primary.open(self.filename, "primary", self.dbtype, self.primary.open(self.filename, "primary", self.dbtype,
db.DB_CREATE | db.DB_THREAD | self.dbFlags, txn=txn) db.DB_CREATE | db.DB_THREAD | self.dbFlags, txn=txn)
else:
self.primary.open(self.filename, "primary", self.dbtype,
db.DB_CREATE | db.DB_THREAD | self.dbFlags)
def closeDB(self): def closeDB(self):
if self.cur: if self.cur:
...@@ -169,12 +165,7 @@ class AssociateTestCase(unittest.TestCase): ...@@ -169,12 +165,7 @@ class AssociateTestCase(unittest.TestCase):
return self.primary return self.primary
def test01_associateWithDB(self): def _associateWithDB(self, getGenre):
if verbose:
print '\n', '-=' * 30
print "Running %s.test01_associateWithDB..." % \
self.__class__.__name__
self.createDB() self.createDB()
self.secDB = db.DB(self.env) self.secDB = db.DB(self.env)
...@@ -182,19 +173,21 @@ class AssociateTestCase(unittest.TestCase): ...@@ -182,19 +173,21 @@ class AssociateTestCase(unittest.TestCase):
self.secDB.set_get_returns_none(2) self.secDB.set_get_returns_none(2)
self.secDB.open(self.filename, "secondary", db.DB_BTREE, self.secDB.open(self.filename, "secondary", db.DB_BTREE,
db.DB_CREATE | db.DB_THREAD | self.dbFlags) db.DB_CREATE | db.DB_THREAD | self.dbFlags)
self.getDB().associate(self.secDB, self.getGenre) self.getDB().associate(self.secDB, getGenre)
self.addDataToDB(self.getDB()) self.addDataToDB(self.getDB())
self.finish_test(self.secDB) self.finish_test(self.secDB)
def test01_associateWithDB(self):
def test02_associateAfterDB(self):
if verbose: if verbose:
print '\n', '-=' * 30 print '\n', '-=' * 30
print "Running %s.test02_associateAfterDB..." % \ print "Running %s.test01_associateWithDB..." % \
self.__class__.__name__ self.__class__.__name__
return self._associateWithDB(self.getGenre)
def _associateAfterDB(self, getGenre) :
self.createDB() self.createDB()
self.addDataToDB(self.getDB()) self.addDataToDB(self.getDB())
...@@ -204,10 +197,35 @@ class AssociateTestCase(unittest.TestCase): ...@@ -204,10 +197,35 @@ class AssociateTestCase(unittest.TestCase):
db.DB_CREATE | db.DB_THREAD | self.dbFlags) db.DB_CREATE | db.DB_THREAD | self.dbFlags)
# adding the DB_CREATE flag will cause it to index existing records # adding the DB_CREATE flag will cause it to index existing records
self.getDB().associate(self.secDB, self.getGenre, db.DB_CREATE) self.getDB().associate(self.secDB, getGenre, db.DB_CREATE)
self.finish_test(self.secDB) self.finish_test(self.secDB)
def test02_associateAfterDB(self):
if verbose:
print '\n', '-=' * 30
print "Running %s.test02_associateAfterDB..." % \
self.__class__.__name__
return self._associateAfterDB(self.getGenre)
if db.version() >= (4, 6):
def test03_associateWithDB(self):
if verbose:
print '\n', '-=' * 30
print "Running %s.test03_associateWithDB..." % \
self.__class__.__name__
return self._associateWithDB(self.getGenreList)
def test04_associateAfterDB(self):
if verbose:
print '\n', '-=' * 30
print "Running %s.test04_associateAfterDB..." % \
self.__class__.__name__
return self._associateAfterDB(self.getGenreList)
def finish_test(self, secDB, txn=None): def finish_test(self, secDB, txn=None):
# 'Blues' should not be in the secondary database # 'Blues' should not be in the secondary database
...@@ -277,6 +295,12 @@ class AssociateTestCase(unittest.TestCase): ...@@ -277,6 +295,12 @@ class AssociateTestCase(unittest.TestCase):
else: else:
return genre return genre
def getGenreList(self, priKey, PriData) :
v = self.getGenre(priKey, PriData)
if type(v) == type("") :
v = [v]
return v
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -322,10 +346,7 @@ class AssociateBTreeTxnTestCase(AssociateBTreeTestCase): ...@@ -322,10 +346,7 @@ class AssociateBTreeTxnTestCase(AssociateBTreeTestCase):
self.secDB.set_get_returns_none(2) self.secDB.set_get_returns_none(2)
self.secDB.open(self.filename, "secondary", db.DB_BTREE, self.secDB.open(self.filename, "secondary", db.DB_BTREE,
db.DB_CREATE | db.DB_THREAD, txn=txn) db.DB_CREATE | db.DB_THREAD, txn=txn)
if db.version() >= (4,1):
self.getDB().associate(self.secDB, self.getGenre, txn=txn) self.getDB().associate(self.secDB, self.getGenre, txn=txn)
else:
self.getDB().associate(self.secDB, self.getGenre)
self.addDataToDB(self.getDB(), txn=txn) self.addDataToDB(self.getDB(), txn=txn)
except: except:
...@@ -426,7 +447,6 @@ def test_suite(): ...@@ -426,7 +447,6 @@ def test_suite():
suite.addTest(unittest.makeSuite(AssociateBTreeTestCase)) suite.addTest(unittest.makeSuite(AssociateBTreeTestCase))
suite.addTest(unittest.makeSuite(AssociateRecnoTestCase)) suite.addTest(unittest.makeSuite(AssociateRecnoTestCase))
if db.version() >= (4, 1):
suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase)) suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase))
suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase)) suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase))
......
This diff is collapsed.
...@@ -12,6 +12,12 @@ from test_all import db, dbshelve, test_support, \ ...@@ -12,6 +12,12 @@ from test_all import db, dbshelve, test_support, \
get_new_environment_path, get_new_database_path get_new_environment_path, get_new_database_path
# Needed for python 3. "cmp" vanished in 3.0.1
def cmp(a, b) :
if a==b : return 0
if a<b : return -1
return 1
lexical_cmp = cmp lexical_cmp = cmp
def lowercase_cmp(left, right): def lowercase_cmp(left, right):
...@@ -26,12 +32,16 @@ _expected_lexical_test_data = ['', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf ...@@ -26,12 +32,16 @@ _expected_lexical_test_data = ['', 'CCCP', 'a', 'aaa', 'b', 'c', 'cccce', 'ccccf
_expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP'] _expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP']
class ComparatorTests (unittest.TestCase): class ComparatorTests (unittest.TestCase):
if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None) :
return self.failUnless(expr,msg=msg)
def comparator_test_helper (self, comparator, expected_data): def comparator_test_helper (self, comparator, expected_data):
data = expected_data[:] data = expected_data[:]
import sys import sys
if sys.version_info[:3] < (2, 6, 0): if sys.version_info < (2, 6) :
if sys.version_info[:3] < (2, 4, 0): if sys.version_info < (2, 4) :
data.sort(comparator) data.sort(comparator)
else : else :
data.sort(cmp=comparator) data.sort(cmp=comparator)
...@@ -47,7 +57,7 @@ class ComparatorTests (unittest.TestCase): ...@@ -47,7 +57,7 @@ class ComparatorTests (unittest.TestCase):
data2.append(i) data2.append(i)
data = data2 data = data2
self.assertEqual (data, expected_data, self.assertEqual(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))
def test_lexical_comparator (self): def test_lexical_comparator (self):
...@@ -65,6 +75,15 @@ class AbstractBtreeKeyCompareTestCase (unittest.TestCase): ...@@ -65,6 +75,15 @@ class AbstractBtreeKeyCompareTestCase (unittest.TestCase):
env = None env = None
db = None db = None
if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None):
self.failUnless(expr,msg=msg)
if (sys.version_info < (2, 7)) or ((sys.version_info >= (3,0)) and
(sys.version_info < (3, 2))) :
def assertLess(self, a, b, msg=None) :
return self.assertTrue(a<b, msg=msg)
def setUp (self): def setUp (self):
self.filename = self.__class__.__name__ + '.db' self.filename = self.__class__.__name__ + '.db'
self.homeDir = get_new_environment_path() self.homeDir = get_new_environment_path()
...@@ -115,14 +134,14 @@ class AbstractBtreeKeyCompareTestCase (unittest.TestCase): ...@@ -115,14 +134,14 @@ class AbstractBtreeKeyCompareTestCase (unittest.TestCase):
rec = curs.first () rec = curs.first ()
while rec: while rec:
key, ignore = rec key, ignore = rec
self.assertLess (index, len (expected), self.assertLess(index, len (expected),
"to many values returned from cursor") "to many values returned from cursor")
self.assertEqual (expected[index], key, self.assertEqual(expected[index], key,
"expected value `%s' at %d but got `%s'" "expected value `%s' at %d but got `%s'"
% (expected[index], index, key)) % (expected[index], index, key))
index = index + 1 index = index + 1
rec = curs.next () rec = curs.next ()
self.assertEqual (index, len (expected), self.assertEqual(index, len (expected),
"not enough values returned from cursor") "not enough values returned from cursor")
finally: finally:
curs.close () curs.close ()
...@@ -193,6 +212,7 @@ class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase): ...@@ -193,6 +212,7 @@ class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase):
errorOut = temp.getvalue() errorOut = temp.getvalue()
if not successRe.search(errorOut): if not successRe.search(errorOut):
self.fail("unexpected stderr output:\n"+errorOut) self.fail("unexpected stderr output:\n"+errorOut)
if sys.version_info < (3, 0) : # XXX: How to do this in Py3k ???
sys.exc_traceback = sys.last_traceback = None sys.exc_traceback = sys.last_traceback = None
def _test_compare_function_exception (self): def _test_compare_function_exception (self):
...@@ -237,8 +257,8 @@ class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase): ...@@ -237,8 +257,8 @@ class BtreeExceptionsTestCase (AbstractBtreeKeyCompareTestCase):
def my_compare (a, b): def my_compare (a, b):
return 0 return 0
self.startTest () self.startTest()
self.createDB (my_compare) self.createDB(my_compare)
self.assertRaises (RuntimeError, self.db.set_bt_compare, my_compare) self.assertRaises (RuntimeError, self.db.set_bt_compare, my_compare)
def test_suite (): def test_suite ():
......
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
TestCases for checking dbShelve objects. TestCases for checking dbShelve objects.
""" """
import os, string import os, string, sys
import random import random
import unittest import unittest
import warnings
from test_all import db, dbshelve, test_support, verbose, \ from test_all import db, dbshelve, test_support, verbose, \
...@@ -13,6 +12,11 @@ from test_all import db, dbshelve, test_support, verbose, \ ...@@ -13,6 +12,11 @@ from test_all import db, dbshelve, test_support, verbose, \
if sys.version_info < (2, 4) :
from sets import Set as set
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# We want the objects to be comparable so we can test dbshelve.values # We want the objects to be comparable so we can test dbshelve.values
...@@ -29,8 +33,17 @@ class DataClass: ...@@ -29,8 +33,17 @@ class DataClass:
class DBShelveTestCase(unittest.TestCase): class DBShelveTestCase(unittest.TestCase):
if sys.version_info < (2, 4):
def assertTrue(self, expr, msg=None):
return self.failUnless(expr,msg=msg)
if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
(sys.version_info < (3, 2))) :
def assertIn(self, a, b, msg=None) :
return self.assertTrue(a in b, msg=msg)
def setUp(self): def setUp(self):
import sys
if sys.version_info[0] >= 3 : if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k from test_all import do_proxy_db_py3k
self._flag_proxy_db_py3k = do_proxy_db_py3k(False) self._flag_proxy_db_py3k = do_proxy_db_py3k(False)
...@@ -38,7 +51,6 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -38,7 +51,6 @@ class DBShelveTestCase(unittest.TestCase):
self.do_open() self.do_open()
def tearDown(self): def tearDown(self):
import sys
if sys.version_info[0] >= 3 : if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k from test_all import do_proxy_db_py3k
do_proxy_db_py3k(self._flag_proxy_db_py3k) do_proxy_db_py3k(self._flag_proxy_db_py3k)
...@@ -48,7 +60,6 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -48,7 +60,6 @@ class DBShelveTestCase(unittest.TestCase):
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
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
return key return key
else : else :
...@@ -118,11 +129,14 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -118,11 +129,14 @@ class DBShelveTestCase(unittest.TestCase):
dbvalues = d.values() dbvalues = d.values()
self.assertEqual(len(dbvalues), len(d.keys())) self.assertEqual(len(dbvalues), len(d.keys()))
with warnings.catch_warnings(): if sys.version_info < (2, 6) :
warnings.filterwarnings('ignore', values.sort()
'comparing unequal types not supported', dbvalues.sort()
DeprecationWarning) self.assertEqual(values, dbvalues)
self.assertEqual(sorted(values), sorted(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))
...@@ -197,10 +211,21 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -197,10 +211,21 @@ class DBShelveTestCase(unittest.TestCase):
self.d.append, 'unit test was here') self.d.append, 'unit test was here')
def test04_iterable(self) :
self.populateDB(self.d)
d = self.d
keys = d.keys()
keyset = set(keys)
self.assertEqual(len(keyset), len(keys))
for key in d :
self.assertIn(key, keyset)
keyset.remove(key)
self.assertEqual(len(keyset), 0)
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 sys.version_info[0] >= 3 :
if isinstance(key, bytes) : if isinstance(key, bytes) :
key = key.decode("iso8859-1") # 8 bits key = key.decode("iso8859-1") # 8 bits
...@@ -219,7 +244,6 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -219,7 +244,6 @@ class DBShelveTestCase(unittest.TestCase):
self.assertEqual(value, [x] * 10) self.assertEqual(value, [x] * 10)
elif key[0] == 'O': elif key[0] == 'O':
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
from types import InstanceType from types import InstanceType
self.assertEqual(type(value), InstanceType) self.assertEqual(type(value), InstanceType)
...@@ -287,7 +311,6 @@ class BasicEnvShelveTestCase(DBShelveTestCase): ...@@ -287,7 +311,6 @@ class BasicEnvShelveTestCase(DBShelveTestCase):
DBShelveTestCase.setUp(self) DBShelveTestCase.setUp(self)
def tearDown(self): def tearDown(self):
import sys
if sys.version_info[0] >= 3 : if sys.version_info[0] >= 3 :
from test_all import do_proxy_db_py3k from test_all import do_proxy_db_py3k
do_proxy_db_py3k(self._flag_proxy_db_py3k) do_proxy_db_py3k(self._flag_proxy_db_py3k)
......
...@@ -20,11 +20,15 @@ ...@@ -20,11 +20,15 @@
# #
# $Id$ # $Id$
import os, re import os, re, sys
try:
if sys.version_info[0] < 3 :
try:
import cPickle import cPickle
pickle = cPickle pickle = cPickle
except ImportError: except ImportError:
import pickle
else :
import pickle import pickle
import unittest import unittest
......
...@@ -37,7 +37,7 @@ class DBTxn_distributed(unittest.TestCase): ...@@ -37,7 +37,7 @@ class DBTxn_distributed(unittest.TestCase):
self.db = db.DB(self.dbenv) self.db = db.DB(self.dbenv)
self.db.set_re_len(db.DB_GID_SIZE) self.db.set_re_len(db.DB_GID_SIZE)
if must_open_db : if must_open_db :
if db.version() > (4,1) : if db.version() >= (4,2) :
txn=self.dbenv.txn_begin() txn=self.dbenv.txn_begin()
self.db.open(self.filename, self.db.open(self.filename,
db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0666, db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0666,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
is closed before its DB objects. is closed before its DB objects.
""" """
import os import os, sys
import unittest import unittest
from test_all import db, test_support, 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
...@@ -155,9 +155,6 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -155,9 +155,6 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
db.DB_INIT_LOG | db.DB_CREATE) db.DB_INIT_LOG | db.DB_CREATE)
d = db.DB(dbenv) d = db.DB(dbenv)
txn = dbenv.txn_begin() txn = dbenv.txn_begin()
if db.version() < (4,1) :
d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE)
else :
d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE, d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE,
txn=txn) txn=txn)
d.put("XXX", "yyy", txn=txn) d.put("XXX", "yyy", txn=txn)
...@@ -166,11 +163,35 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -166,11 +163,35 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
c1 = d.cursor(txn) c1 = d.cursor(txn)
c2 = c1.dup() c2 = c1.dup()
self.assertEquals(("XXX", "yyy"), c1.first()) self.assertEquals(("XXX", "yyy"), c1.first())
import warnings
# Not interested in warnings about implicit close. # Not interested in warnings about implicit close.
with warnings.catch_warnings(): import warnings
if sys.version_info < (2, 6) :
# Completely resetting the warning state is
# problematic with python >=2.6 with -3 (py3k warning),
# because some stdlib modules selectively ignores warnings.
warnings.simplefilter("ignore") warnings.simplefilter("ignore")
txn.commit() txn.commit()
warnings.resetwarnings()
else :
# When we drop support for python 2.3 and 2.4
# we could use: (in 2.5 we need a __future__ statement)
#
# with warnings.catch_warnings():
# warnings.simplefilter("ignore")
# txn.commit()
#
# We can not use "with" as is, because it would be invalid syntax
# in python 2.3, 2.4 and (with no __future__) 2.5.
# Here we simulate "with" following PEP 343 :
w = warnings.catch_warnings()
w.__enter__()
try :
warnings.simplefilter("ignore")
txn.commit()
finally :
w.__exit__()
self.assertRaises(db.DBCursorClosedError, c2.first) self.assertRaises(db.DBCursorClosedError, c2.first)
if db.version() > (4,3,0) : if db.version() > (4,3,0) :
......
...@@ -20,7 +20,7 @@ if have_threads : ...@@ -20,7 +20,7 @@ if have_threads :
class LockingTestCase(unittest.TestCase): class LockingTestCase(unittest.TestCase):
import sys import sys
if sys.version_info[:3] < (2, 4, 0): if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None): def assertTrue(self, expr, msg=None):
self.failUnless(expr,msg=msg) self.failUnless(expr,msg=msg)
...@@ -89,7 +89,18 @@ class LockingTestCase(unittest.TestCase): ...@@ -89,7 +89,18 @@ class LockingTestCase(unittest.TestCase):
for t in threads: for t in threads:
t.join() t.join()
if db.version() >= (4, 2) :
def test03_lock_timeout(self): def test03_lock_timeout(self):
self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT)
self.assertEqual(self.env.get_timeout(db.DB_SET_LOCK_TIMEOUT), 0)
self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT)
self.assertEqual(self.env.get_timeout(db.DB_SET_TXN_TIMEOUT), 0)
self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT)
self.assertEqual(self.env.get_timeout(db.DB_SET_LOCK_TIMEOUT), 123456)
self.env.set_timeout(7890123, db.DB_SET_TXN_TIMEOUT)
self.assertEqual(self.env.get_timeout(db.DB_SET_TXN_TIMEOUT), 7890123)
def test04_lock_timeout2(self):
self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT) self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT)
self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT) self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT)
self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT) self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT)
...@@ -124,6 +135,7 @@ class LockingTestCase(unittest.TestCase): ...@@ -124,6 +135,7 @@ class LockingTestCase(unittest.TestCase):
self.env.lock_get,anID2, "shared lock", db.DB_LOCK_READ) self.env.lock_get,anID2, "shared lock", db.DB_LOCK_READ)
end_time=time.time() end_time=time.time()
deadlock_detection.end=True deadlock_detection.end=True
# Floating point rounding
self.assertTrue((end_time-start_time) >= 0.0999) self.assertTrue((end_time-start_time) >= 0.0999)
self.env.lock_put(lock) self.env.lock_put(lock)
t.join() t.join()
......
"""Miscellaneous bsddb module test cases """Miscellaneous bsddb module test cases
""" """
import os import os, sys
import unittest import unittest
from test_all import db, dbshelve, hashopen, test_support, get_new_environment_path, get_new_database_path from test_all import db, dbshelve, hashopen, test_support, get_new_environment_path, get_new_database_path
...@@ -9,6 +9,13 @@ from test_all import db, dbshelve, hashopen, test_support, get_new_environment_p ...@@ -9,6 +9,13 @@ from test_all import db, dbshelve, hashopen, test_support, get_new_environment_p
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class MiscTestCase(unittest.TestCase): class MiscTestCase(unittest.TestCase):
if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None):
self.failUnless(expr, msg=msg)
def assertFalse(self, expr, msg=None):
self.failIf(expr, msg=msg)
def setUp(self): def setUp(self):
self.filename = get_new_database_path() self.filename = get_new_database_path()
self.homeDir = get_new_environment_path() self.homeDir = get_new_environment_path()
...@@ -27,7 +34,6 @@ class MiscTestCase(unittest.TestCase): ...@@ -27,7 +34,6 @@ 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)
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
self.assertEqual(self.homeDir, env.db_home) self.assertEqual(self.homeDir, env.db_home)
else : else :
...@@ -119,6 +125,19 @@ class MiscTestCase(unittest.TestCase): ...@@ -119,6 +125,19 @@ class MiscTestCase(unittest.TestCase):
test_support.unlink(self.filename) test_support.unlink(self.filename)
def test08_ExceptionTypes(self) :
self.assertTrue(issubclass(db.DBError, Exception))
for i, j in db.__dict__.items() :
if i.startswith("DB") and i.endswith("Error") :
self.assertTrue(issubclass(j, db.DBError), msg=i)
if i not in ("DBKeyEmptyError", "DBNotFoundError") :
self.assertFalse(issubclass(j, KeyError), msg=i)
# This two exceptions have two bases
self.assertTrue(issubclass(db.DBKeyEmptyError, KeyError))
self.assertTrue(issubclass(db.DBNotFoundError, KeyError))
#---------------------------------------------------------------------- #----------------------------------------------------------------------
......
import os import os
import pickle import pickle
try: import sys
if sys.version_info[0] < 3 :
try:
import cPickle import cPickle
except ImportError: except ImportError:
cPickle = None cPickle = None
else :
cPickle = None
import unittest import unittest
from test_all import db, test_support, get_new_environment_path, get_new_database_path from test_all import db, test_support, get_new_environment_path, get_new_database_path
......
"""TestCases for exercising a Recno DB. """TestCases for exercising a Recno DB.
""" """
import os import os, sys
import errno import errno
from pprint import pprint from pprint import pprint
import unittest import unittest
...@@ -14,10 +14,19 @@ letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ...@@ -14,10 +14,19 @@ letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class SimpleRecnoTestCase(unittest.TestCase): class SimpleRecnoTestCase(unittest.TestCase):
import sys if sys.version_info < (2, 4) :
if sys.version_info[:3] < (2, 4, 0): def assertFalse(self, expr, msg=None) :
def assertFalse(self, expr, msg=None): return self.failIf(expr,msg=msg)
self.failIf(expr,msg=msg) def assertTrue(self, expr, msg=None) :
return self.assert_(expr, msg=msg)
if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
(sys.version_info < (3, 2))) :
def assertIsInstance(self, obj, datatype, msg=None) :
return self.assertEqual(type(obj), datatype, msg=msg)
def assertGreaterEqual(self, a, b, msg=None) :
return self.assertTrue(a>=b, msg=msg)
def setUp(self): def setUp(self):
self.filename = get_new_database_path() self.filename = get_new_database_path()
...@@ -60,6 +69,9 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -60,6 +69,9 @@ 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:
if sys.version_info < (2, 6) :
self.assertEqual(val[0], db.EINVAL)
else :
self.assertEqual(val.args[0], db.EINVAL) self.assertEqual(val.args[0], db.EINVAL)
if verbose: print val if verbose: print val
else: else:
...@@ -177,6 +189,9 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -177,6 +189,9 @@ class SimpleRecnoTestCase(unittest.TestCase):
if get_returns_none: if get_returns_none:
self.fail("unexpected DBKeyEmptyError exception") self.fail("unexpected DBKeyEmptyError exception")
else: else:
if sys.version_info < (2, 6) :
self.assertEqual(val[0], db.DB_KEYEMPTY)
else :
self.assertEqual(val.args[0], db.DB_KEYEMPTY) self.assertEqual(val.args[0], db.DB_KEYEMPTY)
if verbose: print val if verbose: print val
else: else:
...@@ -265,6 +280,9 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -265,6 +280,9 @@ 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:
if sys.version_info < (2, 6) :
self.assertEqual(val[0], db.EINVAL)
else :
self.assertEqual(val.args[0], db.EINVAL) self.assertEqual(val.args[0], db.EINVAL)
if verbose: print val if verbose: print val
else: else:
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import os import os
import time import time
import unittest import unittest
import weakref
from test_all import db, test_support, have_threads, verbose, \ from test_all import db, test_support, have_threads, verbose, \
get_new_environment_path, get_new_database_path get_new_environment_path, get_new_database_path
...@@ -12,9 +11,9 @@ from test_all import db, test_support, have_threads, verbose, \ ...@@ -12,9 +11,9 @@ from test_all import db, test_support, have_threads, verbose, \
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class DBReplicationManager(unittest.TestCase): class DBReplication(unittest.TestCase) :
import sys import sys
if sys.version_info[:3] < (2, 4, 0): if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None): def assertTrue(self, expr, msg=None):
self.failUnless(expr,msg=msg) self.failUnless(expr,msg=msg)
...@@ -35,16 +34,13 @@ class DBReplicationManager(unittest.TestCase): ...@@ -35,16 +34,13 @@ class DBReplicationManager(unittest.TestCase):
| db.DB_INIT_LOG | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | | db.DB_INIT_LOG | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
db.DB_INIT_REP | db.DB_RECOVER | db.DB_THREAD, 0666) db.DB_INIT_REP | db.DB_RECOVER | db.DB_THREAD, 0666)
wr = weakref.ref(self)
self.confirmed_master=self.client_startupdone=False self.confirmed_master=self.client_startupdone=False
def confirmed_master(a,b,c) : def confirmed_master(a,b,c) :
if b==db.DB_EVENT_REP_MASTER : if b==db.DB_EVENT_REP_MASTER :
self = wr()
self.confirmed_master=True self.confirmed_master=True
def client_startupdone(a,b,c) : def client_startupdone(a,b,c) :
if b==db.DB_EVENT_REP_STARTUPDONE : if b==db.DB_EVENT_REP_STARTUPDONE :
self = wr()
self.client_startupdone=True self.client_startupdone=True
self.dbenvMaster.set_event_notify(confirmed_master) self.dbenvMaster.set_event_notify(confirmed_master)
...@@ -63,11 +59,21 @@ class DBReplicationManager(unittest.TestCase): ...@@ -63,11 +59,21 @@ class DBReplicationManager(unittest.TestCase):
self.dbClient.close() self.dbClient.close()
if self.dbMaster : if self.dbMaster :
self.dbMaster.close() self.dbMaster.close()
# Here we assign dummy event handlers to allow GC of the test object.
# Since the dummy handler doesn't use any outer scope variable, it
# doesn't keep any reference to the test object.
def dummy(*args) :
pass
self.dbenvMaster.set_event_notify(dummy)
self.dbenvClient.set_event_notify(dummy)
self.dbenvClient.close() self.dbenvClient.close()
self.dbenvMaster.close() self.dbenvMaster.close()
test_support.rmtree(self.homeDirClient) test_support.rmtree(self.homeDirClient)
test_support.rmtree(self.homeDirMaster) test_support.rmtree(self.homeDirMaster)
class DBReplicationManager(DBReplication) :
def test01_basic_replication(self) : def test01_basic_replication(self) :
master_port = test_support.find_unused_port() master_port = test_support.find_unused_port()
self.dbenvMaster.repmgr_set_local_site("127.0.0.1", master_port) self.dbenvMaster.repmgr_set_local_site("127.0.0.1", master_port)
...@@ -216,18 +222,15 @@ class DBReplicationManager(unittest.TestCase): ...@@ -216,18 +222,15 @@ class DBReplicationManager(unittest.TestCase):
self.assertTrue(time.time()<timeout) self.assertTrue(time.time()<timeout)
self.assertEquals(None, v) self.assertEquals(None, v)
class DBBaseReplication(DBReplicationManager): class DBBaseReplication(DBReplication) :
def setUp(self) : def setUp(self) :
DBReplicationManager.setUp(self) DBReplication.setUp(self)
wr = weakref.ref(self)
def confirmed_master(a,b,c) : def confirmed_master(a,b,c) :
if (b == db.DB_EVENT_REP_MASTER) or (b == db.DB_EVENT_REP_ELECTED) : if (b == db.DB_EVENT_REP_MASTER) or (b == db.DB_EVENT_REP_ELECTED) :
self = wr()
self.confirmed_master = True self.confirmed_master = True
def client_startupdone(a,b,c) : def client_startupdone(a,b,c) :
if b == db.DB_EVENT_REP_STARTUPDONE : if b == db.DB_EVENT_REP_STARTUPDONE :
self = wr()
self.client_startupdone = True self.client_startupdone = True
self.dbenvMaster.set_event_notify(confirmed_master) self.dbenvMaster.set_event_notify(confirmed_master)
...@@ -240,11 +243,9 @@ class DBBaseReplication(DBReplicationManager): ...@@ -240,11 +243,9 @@ class DBBaseReplication(DBReplicationManager):
# There are only two nodes, so we don't need to # There are only two nodes, so we don't need to
# do any routing decision # do any routing decision
def m2c(dbenv, control, rec, lsnp, envid, flags) : def m2c(dbenv, control, rec, lsnp, envid, flags) :
self = wr()
self.m2c.put((control, rec)) self.m2c.put((control, rec))
def c2m(dbenv, control, rec, lsnp, envid, flags) : def c2m(dbenv, control, rec, lsnp, envid, flags) :
self = wr()
self.c2m.put((control, rec)) self.c2m.put((control, rec))
self.dbenvMaster.rep_set_transport(13,m2c) self.dbenvMaster.rep_set_transport(13,m2c)
...@@ -261,12 +262,10 @@ class DBBaseReplication(DBReplicationManager): ...@@ -261,12 +262,10 @@ class DBBaseReplication(DBReplicationManager):
#self.dbenvClient.set_verbose(db.DB_VERB_FILEOPS_ALL, True) #self.dbenvClient.set_verbose(db.DB_VERB_FILEOPS_ALL, True)
def thread_master() : def thread_master() :
self = wr()
return self.thread_do(self.dbenvMaster, self.c2m, 3, return self.thread_do(self.dbenvMaster, self.c2m, 3,
self.master_doing_election, True) self.master_doing_election, True)
def thread_client() : def thread_client() :
self = wr()
return self.thread_do(self.dbenvClient, self.m2c, 13, return self.thread_do(self.dbenvClient, self.m2c, 13,
self.client_doing_election, False) self.client_doing_election, False)
...@@ -299,6 +298,17 @@ class DBBaseReplication(DBReplicationManager): ...@@ -299,6 +298,17 @@ class DBBaseReplication(DBReplicationManager):
self.c2m.put(None) self.c2m.put(None)
self.t_m.join() self.t_m.join()
self.t_c.join() self.t_c.join()
# Here we assign dummy event handlers to allow GC of the test object.
# Since the dummy handler doesn't use any outer scope variable, it
# doesn't keep any reference to the test object.
def dummy(*args) :
pass
self.dbenvMaster.set_event_notify(dummy)
self.dbenvClient.set_event_notify(dummy)
self.dbenvMaster.rep_set_transport(13,dummy)
self.dbenvClient.rep_set_transport(3,dummy)
self.dbenvClient.close() self.dbenvClient.close()
self.dbenvMaster.close() self.dbenvMaster.close()
test_support.rmtree(self.homeDirClient) test_support.rmtree(self.homeDirClient)
...@@ -358,6 +368,9 @@ class DBBaseReplication(DBReplicationManager): ...@@ -358,6 +368,9 @@ class DBBaseReplication(DBReplicationManager):
txn.commit() txn.commit()
break break
d = self.dbenvMaster.rep_stat(flags=db.DB_STAT_CLEAR);
self.assertTrue("master_changes" in d)
txn=self.dbenvMaster.txn_begin() txn=self.dbenvMaster.txn_begin()
self.dbMaster.put("ABC", "123", txn=txn) self.dbMaster.put("ABC", "123", txn=txn)
txn.commit() txn.commit()
...@@ -419,7 +432,6 @@ class DBBaseReplication(DBReplicationManager): ...@@ -419,7 +432,6 @@ class DBBaseReplication(DBReplicationManager):
break break
except db.DBRepUnavailError : except db.DBRepUnavailError :
pass pass
if not election_status[0] and not self.confirmed_master : if not election_status[0] and not self.confirmed_master :
from threading import Thread from threading import Thread
election_status[0] = True election_status[0] = True
...@@ -449,6 +461,14 @@ class DBBaseReplication(DBReplicationManager): ...@@ -449,6 +461,14 @@ class DBBaseReplication(DBReplicationManager):
self.assertTrue(self.confirmed_master) self.assertTrue(self.confirmed_master)
if db.version() >= (4,7) :
def test04_test_clockskew(self) :
fast, slow = 1234, 1230
self.dbenvMaster.rep_set_clockskew(fast, slow)
self.assertEqual((fast, slow),
self.dbenvMaster.rep_get_clockskew())
self.basic_rep_threading()
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def test_suite(): def test_suite():
......
...@@ -6,7 +6,7 @@ from test_all import db, test_support, get_new_environment_path, get_new_databas ...@@ -6,7 +6,7 @@ from test_all import db, test_support, get_new_environment_path, get_new_databas
class DBSequenceTest(unittest.TestCase): class DBSequenceTest(unittest.TestCase):
import sys import sys
if sys.version_info[:3] < (2, 4, 0): if sys.version_info < (2, 4) :
def assertTrue(self, expr, msg=None): def assertTrue(self, expr, msg=None):
self.failUnless(expr,msg=msg) self.failUnless(expr,msg=msg)
...@@ -37,7 +37,7 @@ class DBSequenceTest(unittest.TestCase): ...@@ -37,7 +37,7 @@ class DBSequenceTest(unittest.TestCase):
self.seq = db.DBSequence(self.d, flags=0) self.seq = db.DBSequence(self.d, flags=0)
start_value = 10 * self.int_32_max start_value = 10 * self.int_32_max
self.assertEqual(0xA00000000, start_value) self.assertEqual(0xA00000000, start_value)
self.assertEquals(None, self.seq.init_value(start_value)) self.assertEquals(None, self.seq.initial_value(start_value))
self.assertEquals(None, self.seq.open(key='id', txn=None, flags=db.DB_CREATE)) self.assertEquals(None, self.seq.open(key='id', txn=None, flags=db.DB_CREATE))
self.assertEquals(start_value, self.seq.get(5)) self.assertEquals(start_value, self.seq.get(5))
self.assertEquals(start_value + 5, self.seq.get()) self.assertEquals(start_value + 5, self.seq.get())
...@@ -77,7 +77,7 @@ class DBSequenceTest(unittest.TestCase): ...@@ -77,7 +77,7 @@ class DBSequenceTest(unittest.TestCase):
self.seq = db.DBSequence(self.d, flags=0) self.seq = db.DBSequence(self.d, flags=0)
seq_range = (10 * self.int_32_max, 11 * self.int_32_max - 1) seq_range = (10 * self.int_32_max, 11 * self.int_32_max - 1)
self.assertEquals(None, self.seq.set_range(seq_range)) self.assertEquals(None, self.seq.set_range(seq_range))
self.seq.init_value(seq_range[0]) self.seq.initial_value(seq_range[0])
self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE)) self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE))
self.assertEquals(seq_range, self.seq.get_range()) self.assertEquals(seq_range, self.seq.get_range())
...@@ -110,7 +110,7 @@ class DBSequenceTest(unittest.TestCase): ...@@ -110,7 +110,7 @@ class DBSequenceTest(unittest.TestCase):
value_minus=(-1L<<63)+1 # Two complement value_minus=(-1L<<63)+1 # Two complement
self.assertEquals(-9223372036854775807L,value_minus) self.assertEquals(-9223372036854775807L,value_minus)
self.seq = db.DBSequence(self.d, flags=0) self.seq = db.DBSequence(self.d, flags=0)
self.assertEquals(None, self.seq.init_value(value_plus-1)) self.assertEquals(None, self.seq.initial_value(value_plus-1))
self.assertEquals(None, self.seq.open(key='id', txn=None, self.assertEquals(None, self.seq.open(key='id', txn=None,
flags=db.DB_CREATE)) flags=db.DB_CREATE))
self.assertEquals(value_plus-1, self.seq.get(1)) self.assertEquals(value_plus-1, self.seq.get(1))
...@@ -119,7 +119,7 @@ class DBSequenceTest(unittest.TestCase): ...@@ -119,7 +119,7 @@ class DBSequenceTest(unittest.TestCase):
self.seq.remove(txn=None, flags=0) self.seq.remove(txn=None, flags=0)
self.seq = db.DBSequence(self.d, flags=0) self.seq = db.DBSequence(self.d, flags=0)
self.assertEquals(None, self.seq.init_value(value_minus)) self.assertEquals(None, self.seq.initial_value(value_minus))
self.assertEquals(None, self.seq.open(key='id', txn=None, self.assertEquals(None, self.seq.open(key='id', txn=None,
flags=db.DB_CREATE)) flags=db.DB_CREATE))
self.assertEquals(value_minus, self.seq.get(1)) self.assertEquals(value_minus, self.seq.get(1))
......
...@@ -21,7 +21,6 @@ from test_all import db, dbutils, test_support, verbose, have_threads, \ ...@@ -21,7 +21,6 @@ from test_all import db, dbutils, test_support, verbose, have_threads, \
if have_threads : if have_threads :
from threading import Thread from threading import Thread
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
from threading import currentThread from threading import currentThread
else : else :
...@@ -36,8 +35,7 @@ class BaseThreadedTestCase(unittest.TestCase): ...@@ -36,8 +35,7 @@ class BaseThreadedTestCase(unittest.TestCase):
dbsetflags = 0 dbsetflags = 0
envflags = 0 envflags = 0
import sys if sys.version_info < (2, 4) :
if sys.version_info[:3] < (2, 4, 0):
def assertTrue(self, expr, msg=None): def assertTrue(self, expr, msg=None):
self.failUnless(expr,msg=msg) self.failUnless(expr,msg=msg)
...@@ -99,7 +97,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -99,7 +97,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
rt.setDaemon(True) rt.setDaemon(True)
else : else :
...@@ -118,7 +115,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -118,7 +115,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
for t in writers: for t in writers:
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
t.setDaemon(True) t.setDaemon(True)
else : else :
...@@ -131,7 +127,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -131,7 +127,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
t.join() t.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -161,7 +156,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -161,7 +156,6 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -231,7 +225,6 @@ class SimpleThreadedBase(BaseThreadedTestCase): ...@@ -231,7 +225,6 @@ class SimpleThreadedBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
rt.setDaemon(True) rt.setDaemon(True)
else : else :
...@@ -250,7 +243,6 @@ class SimpleThreadedBase(BaseThreadedTestCase): ...@@ -250,7 +243,6 @@ class SimpleThreadedBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
for t in writers: for t in writers:
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
t.setDaemon(True) t.setDaemon(True)
else : else :
...@@ -263,7 +255,6 @@ class SimpleThreadedBase(BaseThreadedTestCase): ...@@ -263,7 +255,6 @@ class SimpleThreadedBase(BaseThreadedTestCase):
t.join() t.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -290,7 +281,6 @@ class SimpleThreadedBase(BaseThreadedTestCase): ...@@ -290,7 +281,6 @@ class SimpleThreadedBase(BaseThreadedTestCase):
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -361,7 +351,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -361,7 +351,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
args = (self.d, x), args = (self.d, x),
name = 'reader %d' % x, name = 'reader %d' % x,
)#verbose = verbose) )#verbose = verbose)
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
rt.setDaemon(True) rt.setDaemon(True)
else : else :
...@@ -379,7 +368,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -379,7 +368,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
writers.append(wt) writers.append(wt)
dt = Thread(target = self.deadlockThread) dt = Thread(target = self.deadlockThread)
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
dt.setDaemon(True) dt.setDaemon(True)
else : else :
...@@ -387,7 +375,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -387,7 +375,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
dt.start() dt.start()
for t in writers: for t in writers:
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
t.setDaemon(True) t.setDaemon(True)
else : else :
...@@ -403,7 +390,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -403,7 +390,6 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
dt.join() dt.join()
def writerThread(self, d, keys, readers): def writerThread(self, d, keys, readers):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -424,14 +410,17 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -424,14 +410,17 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
readers.pop().start() readers.pop().start()
except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val: except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val:
if verbose: if verbose:
print "%s: Aborting transaction (%s)" % (name, val.args[1]) if sys.version_info < (2, 6) :
print "%s: Aborting transaction (%s)" % (name, val[1])
else :
print "%s: Aborting transaction (%s)" % (name,
val.args[1])
txn.abort() txn.abort()
if verbose: if verbose:
print "%s: thread finished" % name print "%s: thread finished" % name
def readerThread(self, d, readerNum): def readerThread(self, d, readerNum):
import sys
if sys.version_info[0] < 3 : if sys.version_info[0] < 3 :
name = currentThread().getName() name = currentThread().getName()
else : else :
...@@ -455,7 +444,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -455,7 +444,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
finished = True finished = True
except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val: except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val:
if verbose: if verbose:
print "%s: Aborting transaction (%s)" % (name, val.args[1]) if sys.version_info < (2, 6) :
print "%s: Aborting transaction (%s)" % (name, val[1])
else :
print "%s: Aborting transaction (%s)" % (name,
val.args[1])
c.close() c.close()
txn.abort() txn.abort()
......
...@@ -81,7 +81,9 @@ Extension Modules ...@@ -81,7 +81,9 @@ Extension Modules
- Issue #1039, #8154: Fix os.execlp() crash with missing 2nd argument. - Issue #1039, #8154: Fix os.execlp() crash with missing 2nd argument.
- Issue #6949: Allow the _bsddb extension to be built with db-4.8.x. - Issue #8156: bsddb module updated to version 4.8.4.
http://www.jcea.es/programacion/pybsddb.htm#bsddb3-4.8.4.
This update drops support for Berkeley DB 4.0, and adds support for 4.8.
- Issue #8142: Update libffi to the 3.0.9 release. - Issue #8142: Update libffi to the 3.0.9 release.
......
This diff is collapsed.
...@@ -70,6 +70,10 @@ ...@@ -70,6 +70,10 @@
* DBLock (A lock handle) * DBLock (A lock handle)
* DBSequence (Sequence) * DBSequence (Sequence)
* *
* New datatypes:
*
* DBLogCursor (Log Cursor)
*
*/ */
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
...@@ -105,7 +109,7 @@ ...@@ -105,7 +109,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.3" #define PY_BSDDB_VERSION "4.8.4"
/* Python object definitions */ /* Python object definitions */
...@@ -122,6 +126,7 @@ struct behaviourFlags { ...@@ -122,6 +126,7 @@ struct behaviourFlags {
struct DBObject; /* Forward declaration */ struct DBObject; /* Forward declaration */
struct DBCursorObject; /* Forward declaration */ struct DBCursorObject; /* Forward declaration */
struct DBLogCursorObject; /* Forward declaration */
struct DBTxnObject; /* Forward declaration */ struct DBTxnObject; /* Forward declaration */
struct DBSequenceObject; /* Forward declaration */ struct DBSequenceObject; /* Forward declaration */
...@@ -134,6 +139,7 @@ typedef struct { ...@@ -134,6 +139,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;
struct DBLogCursorObject *children_logcursors;
PyObject *private_obj; PyObject *private_obj;
PyObject *rep_transport; PyObject *rep_transport;
PyObject *in_weakreflist; /* List of weak references */ PyObject *in_weakreflist; /* List of weak references */
...@@ -145,7 +151,6 @@ typedef struct DBObject { ...@@ -145,7 +151,6 @@ typedef struct DBObject {
DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */ DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
u_int32_t flags; /* saved flags from open() */ u_int32_t flags; /* saved flags from open() */
u_int32_t setflags; /* saved flags from set_flags() */ u_int32_t setflags; /* saved flags from set_flags() */
int haveStat;
struct behaviourFlags moduleFlags; struct behaviourFlags moduleFlags;
struct DBTxnObject *txn; struct DBTxnObject *txn;
struct DBCursorObject *children_cursors; struct DBCursorObject *children_cursors;
...@@ -193,9 +198,20 @@ typedef struct DBTxnObject { ...@@ -193,9 +198,20 @@ typedef struct DBTxnObject {
} DBTxnObject; } DBTxnObject;
typedef struct DBLogCursorObject {
PyObject_HEAD
DB_LOGC* logc;
DBEnvObject* env;
struct DBLogCursorObject **sibling_prev_p;
struct DBLogCursorObject *sibling_next;
PyObject *in_weakreflist; /* List of weak references */
} DBLogCursorObject;
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
DB_LOCK lock; DB_LOCK lock;
int lock_initialized; /* Signal if we actually have a lock */
PyObject *in_weakreflist; /* List of weak references */ PyObject *in_weakreflist; /* List of weak references */
} DBLockObject; } DBLockObject;
...@@ -220,6 +236,7 @@ typedef struct DBSequenceObject { ...@@ -220,6 +236,7 @@ typedef struct DBSequenceObject {
/* To access the structure from an external module, use code like the /* To access the structure from an external module, use code like the
following (error checking missed out for clarity): following (error checking missed out for clarity):
// If you are using Python before 3.2:
BSDDB_api* bsddb_api; BSDDB_api* bsddb_api;
PyObject* mod; PyObject* mod;
PyObject* cobj; PyObject* cobj;
...@@ -231,6 +248,15 @@ typedef struct DBSequenceObject { ...@@ -231,6 +248,15 @@ typedef struct DBSequenceObject {
Py_DECREF(cobj); Py_DECREF(cobj);
Py_DECREF(mod); Py_DECREF(mod);
// If you are using Python 3.2 or up:
BSDDB_api* bsddb_api;
// Use "bsddb3._pybsddb.api" if you're using
// the standalone pybsddb add-on.
bsddb_api = (void **)PyCapsule_Import("bsddb._bsddb.api", 1);
The structure's members must not be changed. The structure's members must not be changed.
*/ */
...@@ -238,6 +264,7 @@ typedef struct { ...@@ -238,6 +264,7 @@ typedef struct {
/* Type objects */ /* Type objects */
PyTypeObject* db_type; PyTypeObject* db_type;
PyTypeObject* dbcursor_type; PyTypeObject* dbcursor_type;
PyTypeObject* dblogcursor_type;
PyTypeObject* dbenv_type; PyTypeObject* dbenv_type;
PyTypeObject* dbtxn_type; PyTypeObject* dbtxn_type;
PyTypeObject* dblock_type; PyTypeObject* dblock_type;
...@@ -247,7 +274,6 @@ typedef struct { ...@@ -247,7 +274,6 @@ typedef struct {
/* Functions */ /* Functions */
int (*makeDBError)(int err); int (*makeDBError)(int err);
} BSDDB_api; } BSDDB_api;
......
...@@ -708,7 +708,7 @@ class PyBuildExt(build_ext): ...@@ -708,7 +708,7 @@ class PyBuildExt(build_ext):
# versions of BerkeleyDB already installed. # versions of BerkeleyDB already installed.
max_db_ver = (4, 8) max_db_ver = (4, 8)
min_db_ver = (3, 3) min_db_ver = (4, 1)
db_setup_debug = False # verbose debug prints from this script? db_setup_debug = False # verbose debug prints from this script?
def allow_db_ver(db_ver): def allow_db_ver(db_ver):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment