From: Jan Engelhardt <jengelh@inai.de>
Date: 2013-07-06 16:07:31.146616589 +0200

This patch was partially autogenerated:
 - copying python-bsddb3-6.0.0 sources into the python-2.7.5 tree
 - creating a diff -w against the unmodified python-2.7.5
 - stripped all hunks that pertained to module renaming
 - manually added db6 searching to setup.py

---
 Lib/bsddb/test/test_all.py         |   15 +++--
 Lib/bsddb/test/test_misc.py        |    5 +
 Lib/bsddb/test/test_replication.py |   25 +-------
 Modules/_bsddb.c                   |  108 +++++++++++++++++++++++++++++++++----
 Modules/bsddb.h                    |    2 
 setup.py                           |    6 +-
 6 files changed, 120 insertions(+), 41 deletions(-)

--- a/Lib/bsddb/test/test_all.py
+++ b/Lib/bsddb/test/test_all.py
@@ -74,8 +74,9 @@ if sys.version_info[0] >= 3 :
                 key = key.decode(charset)
             return (key, value.decode(charset))
 
-        def __next__(self) :
-            v = getattr(self._dbcursor, "next")()
+        def __next__(self, flags=0, dlen=-1, doff=-1) :
+            v = getattr(self._dbcursor, "next")(flags=flags, dlen=dlen,
+                    doff=doff)
             return self._fix(v)
 
         next = __next__
@@ -128,8 +129,8 @@ if sys.version_info[0] >= 3 :
             v = self._dbcursor.current(flags=flags, dlen=dlen, doff=doff)
             return self._fix(v)
 
-        def first(self) :
-            v = self._dbcursor.first()
+        def first(self, flags=0, dlen=-1, doff=-1) :
+            v = self._dbcursor.first(flags=flags, dlen=dlen, doff=doff)
             return self._fix(v)
 
         def pget(self, key=None, data=None, flags=0) :
@@ -489,7 +490,11 @@ def print_versions():
     print 'py module:            %s' % getattr(bsddb, "__file"+suffix)
     print 'extension module:     %s' % getattr(bsddb, "__file"+suffix)
 
-    print 'python version:       %s' % sys.version
+    print 'Test working dir:     %s' % get_test_path_prefix()
+    import platform
+    print 'python version:       %s %s' % \
+            (sys.version.replace("\r", "").replace("\n", ""), \
+            platform.architecture()[0])
     print 'My pid:               %s' % os.getpid()
     print '-=' * 38
 
--- a/Lib/bsddb/test/test_misc.py
+++ b/Lib/bsddb/test/test_misc.py
@@ -46,8 +46,9 @@ class MiscTestCase(unittest.TestCase):
             d[repr(i)] = repr(100*i)
         db.close()
         db = hashopen(self.filename)
-        rp = repr(db)
-        self.assertEqual(rp, repr(d))
+        rp = repr(sorted(db.items()))
+        rd = repr(sorted(d.items()))
+        self.assertEqual(rp, rd)
         db.close()
 
     # http://sourceforge.net/tracker/index.php?func=detail&aid=1708868&group_id=13900&atid=313900
--- a/Lib/bsddb/test/test_replication.py
+++ b/Lib/bsddb/test/test_replication.py
@@ -165,21 +165,10 @@ class DBReplicationManager(DBReplication
         # is not generated if the master has no new transactions.
         # This is solved in BDB 4.6 (#15542).
         import time
-        timeout = time.time()+60
+        timeout = time.time()+10
         while (time.time()<timeout) and not (self.confirmed_master and self.client_startupdone) :
             time.sleep(0.02)
-        # self.client_startupdone does not always get set to True within
-        # the timeout.  On windows this may be a deep issue, on other
-        # platforms it is likely just a timing issue, especially on slow
-        # virthost buildbots (see issue 3892 for more).  Even though
-        # the timeout triggers, the rest of this test method usually passes
-        # (but not all of it always, see below).  So we just note the
-        # timeout on stderr and keep soldering on.
-        if time.time()>timeout:
-            import sys
-            print >> sys.stderr, ("XXX: timeout happened before"
-                "startup was confirmed - see issue 3892")
-            startup_timeout = True
+        self.assertTrue(time.time()<timeout)
 
         d = self.dbenvMaster.repmgr_site_list()
         self.assertEqual(len(d), 1)
@@ -237,14 +226,6 @@ class DBReplicationManager(DBReplication
             txn.commit()
             if v is None :
                 time.sleep(0.02)
-        # If startup did not happen before the timeout above, then this test
-        # sometimes fails.  This happens randomly, which causes buildbot
-        # instability, but all the other bsddb tests pass.  Since bsddb3 in the
-        # stdlib is currently not getting active maintenance, and is gone in
-        # py3k, we just skip the end of the test in that case.
-        if time.time()>=timeout and startup_timeout:
-            self.skipTest("replication test skipped due to random failure, "
-                "see issue 3892")
         self.assertLess(time.time(), timeout)
         self.assertEqual("123", v)
 
@@ -375,7 +356,7 @@ class DBBaseReplication(DBReplication) :
         # is not generated if the master has no new transactions.
         # This is solved in BDB 4.6 (#15542).
         import time
-        timeout = time.time()+60
+        timeout = time.time()+10
         while (time.time()<timeout) and not (self.confirmed_master and
                 self.client_startupdone) :
             time.sleep(0.02)
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -124,10 +124,14 @@ typedef int Py_ssize_t;
 #define NUMBER_Check    PyLong_Check
 #define NUMBER_AsLong   PyLong_AsLong
 #define NUMBER_FromLong PyLong_FromLong
+#define NUMBER_FromUnsignedLong PyLong_FromUnsignedLong
 #else
 #define NUMBER_Check    PyInt_Check
 #define NUMBER_AsLong   PyInt_AsLong
 #define NUMBER_FromLong PyInt_FromLong
+#if (PY_VERSION_HEX >= 0x02050000)
+#define NUMBER_FromUnsignedLong PyInt_FromSize_t
+#endif
 #endif
 
 #ifdef WITH_THREAD
@@ -853,6 +857,18 @@ static void _addIntToDict(PyObject* dict
     Py_XDECREF(v);
 }
 
+#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000)
+/* add an unsigned integer to a dictionary using the given name as a key */
+static void _addUnsignedIntToDict(PyObject* dict, char *name, unsigned int value)
+{
+    PyObject* v = NUMBER_FromUnsignedLong((unsigned long) value);
+    if (!v || PyDict_SetItemString(dict, name, v))
+        PyErr_Clear();
+
+    Py_XDECREF(v);
+}
+#endif
+
 /* The same, when the value is a time_t */
 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
 {
@@ -2677,13 +2693,21 @@ _default_cmp(const DBT *leftKey,
 static int
 _db_compareCallback(DB* db,
                     const DBT *leftKey,
-                    const DBT *rightKey)
+            const DBT *rightKey
+#if (DBVER >= 60)
+          , size_t *locp
+#endif
+            )
 {
     int res = 0;
     PyObject *args;
     PyObject *result = NULL;
     DBObject *self = (DBObject *)db->app_private;
 
+# if (DBVER >= 60)
+    locp = NULL;  /* As required by documentation */
+#endif
+
     if (self == NULL || self->btCompareCallback == NULL) {
         MYDB_BEGIN_BLOCK_THREADS;
         PyErr_SetString(PyExc_TypeError,
@@ -2791,13 +2815,21 @@ DB_set_bt_compare(DBObject* self, PyObje
 static int
 _db_dupCompareCallback(DB* db,
 		    const DBT *leftKey,
-		    const DBT *rightKey)
+            const DBT *rightKey
+#if (DBVER >= 60)
+          , size_t *locp
+#endif
+        )
 {
     int res = 0;
     PyObject *args;
     PyObject *result = NULL;
     DBObject *self = (DBObject *)db->app_private;
 
+#if (DBVER >= 60)
+    locp = NULL;  /* As required by documentation */
+#endif
+
     if (self == NULL || self->dupCompareCallback == NULL) {
 	MYDB_BEGIN_BLOCK_THREADS;
 	PyErr_SetString(PyExc_TypeError,
@@ -3576,13 +3608,14 @@ Py_ssize_t DB_length(PyObject* _self)
     err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0);
     MYDB_END_ALLOW_THREADS;
 
+    if (makeDBError(err)) {
+        return -1;
+    }
+
     /* All the stat structures have matching fields upto the ndata field,
        so we can use any of them for the type cast */
     size = ((DB_BTREE_STAT*)sp)->bt_ndata;
 
-    if (err)
-        return -1;
-
     free(sp);
     return size;
 }
@@ -8420,12 +8453,22 @@ static PyObject*
 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
 {
     int err, flags = 0;
+#if (DBVER >= 60)
+    unsigned
+#endif
     int delta = 1;
     db_seq_t value;
     PyObject *txnobj = NULL;
     DB_TXN *txn = NULL;
     static char* kwnames[] = {"delta", "txn", "flags", NULL };
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+#if (DBVER >=60)
+            "|IOi:get",
+#else
+            "|iOi:get",
+#endif
+            kwnames, &delta, &txnobj, &flags))
         return NULL;
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
@@ -8555,8 +8598,19 @@ DBSequence_remove(DBSequenceObject* self
 static PyObject*
 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
 {
-    int err, size;
-    if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
+    int err;
+#if (DBVER >= 60)
+    unsigned
+#endif
+    int size;
+
+    if (!PyArg_ParseTuple(args,
+#if (DBVER >= 60)
+            "I:set_cachesize",
+#else
+            "i:set_cachesize",
+#endif
+            &size))
         return NULL;
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
@@ -8571,7 +8625,11 @@ DBSequence_set_cachesize(DBSequenceObjec
 static PyObject*
 DBSequence_get_cachesize(DBSequenceObject* self)
 {
-    int err, size;
+    int err;
+#if (DBVER >= 60)
+    unsigned
+#endif
+    int size;
 
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
@@ -8700,6 +8758,9 @@ DBSequence_stat(DBSequenceObject* self,
 
 
 #define MAKE_INT_ENTRY(name)  _addIntToDict(dict_stat, #name, sp->st_##name)
+#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000)
+#define MAKE_UNSIGNED_INT_ENTRY(name)   _addUnsignedIntToDict(dict_stat, #name, sp->st_##name)
+#endif
 #define MAKE_LONG_LONG_ENTRY(name)  _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
 
     MAKE_INT_ENTRY(wait);
@@ -8709,10 +8770,15 @@ DBSequence_stat(DBSequenceObject* self,
     MAKE_LONG_LONG_ENTRY(last_value);
     MAKE_LONG_LONG_ENTRY(min);
     MAKE_LONG_LONG_ENTRY(max);
+#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000)
+    MAKE_UNSIGNED_INT_ENTRY(cache_size);
+#else
     MAKE_INT_ENTRY(cache_size);
+#endif
     MAKE_INT_ENTRY(flags);
 
 #undef MAKE_INT_ENTRY
+#undef MAKE_UNSIGNED_INT_ENTRY
 #undef MAKE_LONG_LONG_ENTRY
 
     free(sp);
@@ -9014,7 +9080,7 @@ static PyMethodDef DBEnv_methods[] = {
     {"txn_recover",     (PyCFunction)DBEnv_txn_recover,     METH_NOARGS},
 #if (DBVER < 48)
     {"set_rpc_server",  (PyCFunction)DBEnv_set_rpc_server,
-        METH_VARARGS|METH_KEYWORDS},
+        METH_VARARGS||METH_KEYWORDS},
 #endif
     {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS},
     {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS},
@@ -9986,6 +10052,10 @@ PyMODINIT_FUNC  PyInit__bsddb(void)    /
     ADD_INT(d, DB_LOG_ZERO);
 #endif
 
+#if (DBVER >= 60)
+    ADD_INT(d, DB_LOG_BLOB);
+#endif
+
 #if (DBVER >= 44)
     ADD_INT(d, DB_DSYNC_DB);
 #endif
@@ -10046,6 +10116,10 @@ PyMODINIT_FUNC  PyInit__bsddb(void)    /
     ADD_INT(d, DB_EVENT_REG_PANIC);
 #endif
 
+#if (DBVER >= 60)
+    ADD_INT(d, DB_EVENT_REP_AUTOTAKEOVER_FAILED);
+#endif
+
 #if (DBVER >=52)
     ADD_INT(d, DB_EVENT_REP_SITE_ADDED);
     ADD_INT(d, DB_EVENT_REP_SITE_REMOVED);
@@ -10150,6 +10224,20 @@ PyMODINIT_FUNC  PyInit__bsddb(void)    /
     ADD_INT(d, DB_REP_CONF_INMEM);
 #endif
 
+#if (DBVER >= 60)
+    ADD_INT(d, DB_REPMGR_ISVIEW);
+#endif
+
+#if (DBVER >= 60)
+    ADD_INT(d, DB_DBT_BLOB);
+#endif
+
+#if (DBVER >= 60)
+    ADD_INT(d, DB_STREAM_READ);
+    ADD_INT(d, DB_STREAM_WRITE);
+    ADD_INT(d, DB_STREAM_SYNC_WRITE);
+#endif
+
     ADD_INT(d, DB_TIMEOUT);
 
 #if (DBVER >= 50)
--- a/Modules/bsddb.h
+++ b/Modules/bsddb.h
@@ -110,7 +110,7 @@
 #error "eek! DBVER can't handle minor versions > 9"
 #endif
 
-#define PY_BSDDB_VERSION "5.3.0"
+#define PY_BSDDB_VERSION "6.0.0"
 
 /* Python object definitions */
 
--- a/setup.py
+++ b/setup.py
@@ -951,7 +951,7 @@ class PyBuildExt(build_ext):
         # a release.  Most open source OSes come with one or more
         # versions of BerkeleyDB already installed.
 
-        max_db_ver = (5, 3)
+        max_db_ver = (6, 0)
         min_db_ver = (4, 3)
         db_setup_debug = False   # verbose debug prints from this script?
 
@@ -991,6 +991,7 @@ class PyBuildExt(build_ext):
         # construct a list of paths to look for the header file in on
         # top of the normal inc_dirs.
         db_inc_paths = [
+            '/usr/include/db6',
             '/usr/include/db4',
             '/usr/local/include/db4',
             '/opt/sfw/include/db4',
@@ -1030,6 +1031,7 @@ class PyBuildExt(build_ext):
         for dn in inc_dirs:
             std_variants.append(os.path.join(dn, 'db3'))
             std_variants.append(os.path.join(dn, 'db4'))
+            std_variants.append(os.path.join(dn, 'db6'))
             for x in gen_db_minor_ver_nums(4):
                 std_variants.append(os.path.join(dn, "db4%d"%x))
                 std_variants.append(os.path.join(dn, "db4.%d"%x))
