Port BerkeleyDB 4.1 support from the pybsddb project.  bsddb is now at
version 4.1.1 and works with up to BerkeleyDB 4.1.25.
diff --git a/Lib/bsddb/test/test_basics.py b/Lib/bsddb/test/test_basics.py
index f2ccb8a..37f4d11 100644
--- a/Lib/bsddb/test/test_basics.py
+++ b/Lib/bsddb/test/test_basics.py
@@ -3,14 +3,20 @@
 various DB flags, etc.
 """
 
-import sys, os, string
+import os
+import sys
+import errno
+import shutil
+import string
 import tempfile
 from pprint import pprint
 import unittest
 
 from bsddb import db
 
-from test.test_support import verbose
+from test_all import verbose
+
+DASH = '-'
 
 
 #----------------------------------------------------------------------
@@ -23,7 +29,8 @@
             print 'bsddb.db.version(): %s' % (info, )
             print db.DB_VERSION_STRING
             print '-=' * 20
-        assert info == (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR, db.DB_VERSION_PATCH)
+        assert info == (db.DB_VERSION_MAJOR, db.DB_VERSION_MINOR,
+                        db.DB_VERSION_PATCH)
 
 #----------------------------------------------------------------------
 
@@ -35,19 +42,30 @@
     dbname       = None
     useEnv       = 0
     envflags     = 0
+    envsetflags  = 0
 
     def setUp(self):
         if self.useEnv:
             homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home')
-            try: os.mkdir(homeDir)
-            except os.error: pass
-            self.env = db.DBEnv()
-            self.env.set_lg_max(1024*1024)
-            self.env.open(homeDir, self.envflags | db.DB_CREATE)
-            tempfile.tempdir = homeDir
-            self.filename = os.path.split(tempfile.mktemp())[1]
-            tempfile.tempdir = None
             self.homeDir = homeDir
+            try:
+                shutil.rmtree(homeDir)
+            except OSError, e:
+                # unix returns ENOENT, windows returns ESRCH
+                if e.errno not in (errno.ENOENT, errno.ESRCH): raise
+            os.mkdir(homeDir)
+            try:
+                self.env = db.DBEnv()
+                self.env.set_lg_max(1024*1024)
+                self.env.set_flags(self.envsetflags, 1)
+                self.env.open(homeDir, self.envflags | db.DB_CREATE)
+                tempfile.tempdir = homeDir
+                self.filename = os.path.split(tempfile.mktemp())[1]
+                tempfile.tempdir = None
+            # Yes, a bare except is intended, since we're re-raising the exc.
+            except:
+                shutil.rmtree(homeDir)
+                raise
         else:
             self.env = None
             self.filename = tempfile.mktemp()
@@ -61,7 +79,8 @@
         else:
             self.d.open(self.filename,   # try out keyword args
                         mode = self.dbmode,
-                        dbtype = self.dbtype, flags = self.dbopenflags|db.DB_CREATE)
+                        dbtype = self.dbtype,
+                        flags = self.dbopenflags|db.DB_CREATE)
 
         self.populateDB()
 
@@ -70,19 +89,13 @@
         self.d.close()
         if self.env is not None:
             self.env.close()
-
-            import glob
-            files = glob.glob(os.path.join(self.homeDir, '*'))
-            for file in files:
-                os.remove(file)
-
+            shutil.rmtree(self.homeDir)
             ## Make a new DBEnv to remove the env files from the home dir.
             ## (It can't be done while the env is open, nor after it has been
             ## closed, so we make a new one to do it.)
             #e = db.DBEnv()
             #e.remove(self.homeDir)
             #os.remove(os.path.join(self.homeDir, self.filename))
-
         else:
             os.remove(self.filename)
 
@@ -106,7 +119,7 @@
 
 
     def makeData(self, key):
-        return string.join([key] * 5, '-')
+        return DASH.join([key] * 5)
 
 
 
@@ -209,7 +222,8 @@
 
         if verbose:
             print '\n', '-=' * 30
-            print "Running %s.test02_DictionaryMethods..." % self.__class__.__name__
+            print "Running %s.test02_DictionaryMethods..." % \
+                  self.__class__.__name__
 
         for key in ['0002', '0101', '0401', '0701', '0998']:
             data = d[key]
@@ -266,10 +280,14 @@
     def test03_SimpleCursorStuff(self):
         if verbose:
             print '\n', '-=' * 30
-            print "Running %s.test03_SimpleCursorStuff..." % self.__class__.__name__
+            print "Running %s.test03_SimpleCursorStuff..." % \
+                  self.__class__.__name__
 
-        c = self.d.cursor()
-
+        if self.env and self.dbopenflags & db.DB_AUTO_COMMIT:
+            txn = self.env.txn_begin()
+        else:
+            txn = None
+        c = self.d.cursor(txn=txn)
 
         rec = c.first()
         count = 0
@@ -350,6 +368,8 @@
 
         c.close()
         c2.close()
+        if txn:
+            txn.commit()
 
         # time to abuse the closed cursors and hope we don't crash
         methods_to_test = {
@@ -367,14 +387,16 @@
         for method, args in methods_to_test.items():
             try:
                 if verbose:
-                    print "attempting to use a closed cursor's %s method" % method
+                    print "attempting to use a closed cursor's %s method" % \
+                          method
                 # a bug may cause a NULL pointer dereference...
                 apply(getattr(c, method), args)
             except db.DBError, val:
                 assert val[0] == 0
                 if verbose: print val
             else:
-                self.fail("no exception raised when using a buggy cursor's %s method" % method)
+                self.fail("no exception raised when using a buggy cursor's"
+                          "%s method" % method)
 
     #----------------------------------------
 
@@ -382,7 +404,8 @@
         d = self.d
         if verbose:
             print '\n', '-=' * 30
-            print "Running %s.test04_PartialGetAndPut..." % self.__class__.__name__
+            print "Running %s.test04_PartialGetAndPut..." % \
+                  self.__class__.__name__
 
         key = "partialTest"
         data = "1" * 1000 + "2" * 1000
@@ -393,7 +416,8 @@
         d.put("partialtest2", ("1" * 30000) + "robin" )
         assert d.get("partialtest2", dlen=5, doff=30000) == "robin"
 
-        # There seems to be a bug in DB here...  Commented out the test for now.
+        # There seems to be a bug in DB here...  Commented out the test for
+        # now.
         ##assert d.get("partialtest2", dlen=5, doff=30010) == ""
 
         if self.dbsetflags != db.DB_DUP:
@@ -423,6 +447,10 @@
     #----------------------------------------
 
     def test06_Truncate(self):
+        if db.version() < (3,3):
+            # truncate is a feature of BerkeleyDB 3.3 and above
+            return
+
         d = self.d
         if verbose:
             print '\n', '-=' * 30
@@ -472,9 +500,11 @@
 #----------------------------------------------------------------------
 
 class BasicTransactionTestCase(BasicTestCase):
-    dbopenflags = db.DB_THREAD
+    dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
     useEnv = 1
-    envflags = db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK | db.DB_INIT_TXN
+    envflags = (db.DB_THREAD | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
+                db.DB_INIT_TXN)
+    envsetflags = db.DB_AUTO_COMMIT
 
 
     def tearDown(self):
@@ -557,6 +587,10 @@
     #----------------------------------------
 
     def test07_TxnTruncate(self):
+        if db.version() < (3,3):
+            # truncate is a feature of BerkeleyDB 3.3 and above
+            return
+
         d = self.d
         if verbose:
             print '\n', '-=' * 30
@@ -624,10 +658,11 @@
         d = self.d
         if verbose:
             print '\n', '-=' * 30
-            print "Running %s.test08_DuplicateKeys..." % self.__class__.__name__
+            print "Running %s.test08_DuplicateKeys..." % \
+                  self.__class__.__name__
 
         d.put("dup0", "before")
-        for x in string.split("The quick brown fox jumped over the lazy dog."):
+        for x in "The quick brown fox jumped over the lazy dog.".split():
             d.put("dup1", x)
         d.put("dup2", "after")
 
@@ -699,11 +734,13 @@
             print "Running %s.test09_MultiDB..." % self.__class__.__name__
 
         d2 = db.DB(self.env)
-        d2.open(self.filename, "second", self.dbtype, self.dbopenflags|db.DB_CREATE)
+        d2.open(self.filename, "second", self.dbtype,
+                self.dbopenflags|db.DB_CREATE)
         d3 = db.DB(self.env)
-        d3.open(self.filename, "third", self.otherType(), self.dbopenflags|db.DB_CREATE)
+        d3.open(self.filename, "third", self.otherType(),
+                self.dbopenflags|db.DB_CREATE)
 
-        for x in string.split("The quick brown fox jumped over the lazy dog"):
+        for x in "The quick brown fox jumped over the lazy dog".split():
             d2.put(x, self.makeData(x))
 
         for x in string.letters:
@@ -785,29 +822,29 @@
 #----------------------------------------------------------------------
 #----------------------------------------------------------------------
 
-def suite():
-    theSuite = unittest.TestSuite()
+def test_suite():
+    suite = unittest.TestSuite()
 
-    theSuite.addTest(unittest.makeSuite(VersionTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicBTreeTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicHashTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicBTreeWithThreadFlagTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicHashWithThreadFlagTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicBTreeWithEnvTestCase))
-    theSuite.addTest(unittest.makeSuite(BasicHashWithEnvTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeTransactionTestCase))
-    theSuite.addTest(unittest.makeSuite(HashTransactionTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeRecnoTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeRecnoWithThreadFlagTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeDUPTestCase))
-    theSuite.addTest(unittest.makeSuite(HashDUPTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeDUPWithThreadTestCase))
-    theSuite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase))
-    theSuite.addTest(unittest.makeSuite(BTreeMultiDBTestCase))
-    theSuite.addTest(unittest.makeSuite(HashMultiDBTestCase))
+    suite.addTest(unittest.makeSuite(VersionTestCase))
+    suite.addTest(unittest.makeSuite(BasicBTreeTestCase))
+    suite.addTest(unittest.makeSuite(BasicHashTestCase))
+    suite.addTest(unittest.makeSuite(BasicBTreeWithThreadFlagTestCase))
+    suite.addTest(unittest.makeSuite(BasicHashWithThreadFlagTestCase))
+    suite.addTest(unittest.makeSuite(BasicBTreeWithEnvTestCase))
+    suite.addTest(unittest.makeSuite(BasicHashWithEnvTestCase))
+    suite.addTest(unittest.makeSuite(BTreeTransactionTestCase))
+    suite.addTest(unittest.makeSuite(HashTransactionTestCase))
+    suite.addTest(unittest.makeSuite(BTreeRecnoTestCase))
+    suite.addTest(unittest.makeSuite(BTreeRecnoWithThreadFlagTestCase))
+    suite.addTest(unittest.makeSuite(BTreeDUPTestCase))
+    suite.addTest(unittest.makeSuite(HashDUPTestCase))
+    suite.addTest(unittest.makeSuite(BTreeDUPWithThreadTestCase))
+    suite.addTest(unittest.makeSuite(HashDUPWithThreadTestCase))
+    suite.addTest(unittest.makeSuite(BTreeMultiDBTestCase))
+    suite.addTest(unittest.makeSuite(HashMultiDBTestCase))
 
-    return theSuite
+    return suite
 
 
 if __name__ == '__main__':
-    unittest.main( defaultTest='suite' )
+    unittest.main(defaultTest='test_suite')