]> granicus.if.org Git - python/commitdiff
pybsddb 4.3.2:
authorGregory P. Smith <greg@mad-scientist.com>
Sat, 4 Jun 2005 06:46:59 +0000 (06:46 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Sat, 4 Jun 2005 06:46:59 +0000 (06:46 +0000)
 * the has_key() method was not raising a DBError when a database error
   had occurred. [SF patch id 1212590]
 * added a wrapper for the DBEnv.set_lg_regionmax method [SF patch id 1212590]
 * DBKeyEmptyError now derives from KeyError just like DBNotFoundError.
 * internally everywhere DB_NOTFOUND was checked for has been updated
   to also check for DB_KEYEMPTY.  This fixes the semantics of a couple
   operations on recno and queue databases to be more intuitive and results
   in less unexpected DBKeyEmptyError exceptions being raised.

Lib/bsddb/test/test_basics.py
Lib/bsddb/test/test_recno.py
Modules/_bsddb.c

index 155705df1d9e03b62d896d2021c3412c1c3cbde9..d3bbb4f67068226447aecef2adb9e1ae14f7615d 100644 (file)
@@ -397,10 +397,14 @@ class BasicTestCase(unittest.TestCase):
         try:
             rec = c.current()
         except db.DBKeyEmptyError, val:
-            assert val[0] == db.DB_KEYEMPTY
-            if verbose: print val
+           if get_raises_error:
+               assert val[0] == db.DB_KEYEMPTY
+               if verbose: print val
+           else:
+               self.fail("unexpected DBKeyEmptyError")
         else:
-            self.fail('exception expected')
+           if get_raises_error:
+               self.fail('DBKeyEmptyError exception expected')
 
         c.next()
         c2 = c.dup(db.DB_POSITION)
@@ -612,7 +616,6 @@ class BasicTransactionTestCase(BasicTestCase):
         self.txn = self.env.txn_begin()
 
 
-
     def test06_Transactions(self):
         d = self.d
         if verbose:
index 56a79c776e671749b82cb3f8ca10da46c956574c..a46a0c5a02d0d580a4c110c6a210ebaa758b006d 100644 (file)
@@ -34,6 +34,10 @@ class SimpleRecnoTestCase(unittest.TestCase):
 
     def test01_basic(self):
         d = db.DB()
+
+       get_returns_none = d.set_get_returns_none(2)
+       d.set_get_returns_none(get_returns_none)
+
         d.open(self.filename, db.DB_RECNO, db.DB_CREATE)
 
         for x in letters:
@@ -65,6 +69,14 @@ class SimpleRecnoTestCase(unittest.TestCase):
         else:
             self.fail("expected exception")
 
+       # test that has_key raises DB exceptions (fixed in pybsddb 4.3.2)
+       try:
+           d.has_key(0)
+       except db.DBError, val:
+           pass
+       else:
+           self.fail("has_key did not raise a proper exception")
+
         try:
             data = d[100]
         except KeyError:
@@ -72,8 +84,13 @@ class SimpleRecnoTestCase(unittest.TestCase):
         else:
             self.fail("expected exception")
 
-        data = d.get(100)
-        assert data == None
+       try:
+           data = d.get(100)
+       except db.DBNotFoundError, val:
+           if get_returns_none:
+               self.fail("unexpected exception")
+       else:
+           assert data == None
 
         keys = d.keys()
         if verbose:
@@ -161,10 +178,14 @@ class SimpleRecnoTestCase(unittest.TestCase):
         try:
             d.get(99)
         except db.DBKeyEmptyError, val:
-            assert val[0] == db.DB_KEYEMPTY
-            if verbose: print val
+           if get_returns_none:
+               self.fail("unexpected DBKeyEmptyError exception")
+           else:
+               assert val[0] == db.DB_KEYEMPTY
+               if verbose: print val
         else:
-            self.fail("expected exception")
+           if not get_returns_none:
+               self.fail("expected exception")
 
         rec = c.set(40)
         while rec:
index 6a39d859349087a0ab6b77143e860b9a369d94fd..3858e26a2433c80cdc9c399c96bc3abf1ef600ab 100644 (file)
@@ -97,7 +97,7 @@
 #error "eek! DBVER can't handle minor versions > 9"
 #endif
 
-#define PY_BSDDB_VERSION "4.3.1"
+#define PY_BSDDB_VERSION "4.3.2"
 static char *rcs_id = "$Id$";
 
 
@@ -153,7 +153,7 @@ static PyInterpreterState* _db_interpreterState = NULL;
 
 static PyObject* DBError;               /* Base class, all others derive from this */
 static PyObject* DBCursorClosedError;   /* raised when trying to use a closed cursor object */
-static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY */
+static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY: also derives from KeyError */
 static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
 static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
@@ -212,10 +212,10 @@ static PyObject* DBPermissionsError;    /* EPERM  */
 
 struct behaviourFlags {
     /* What is the default behaviour when DB->get or DBCursor->get returns a
-       DB_NOTFOUND error?  Return None or raise an exception? */
+       DB_NOTFOUND || DB_KEYEMPTY error?  Return None or raise an exception? */
     unsigned int getReturnsNone : 1;
     /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
-     * returns a DB_NOTFOUND error?  Return None or raise an exception? */
+     * returns a DB_NOTFOUND || DB_KEYEMPTY  error?  Return None or raise? */
     unsigned int cursorSetReturnsNone : 1;
 };
 
@@ -673,7 +673,8 @@ static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
     err = self->dbc->c_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.getReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -1285,7 +1286,8 @@ _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
     err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->moduleFlags.getReturnsNone) {
         err = 0;
         Py_INCREF(Py_None);
         retval = Py_None;
@@ -1430,12 +1432,13 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
     err = self->db->get(self->db, txn, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
         err = 0;
         Py_INCREF(dfltobj);
         retval = dfltobj;
     }
-    else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
+    else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+            && self->moduleFlags.getReturnsNone) {
         err = 0;
         Py_INCREF(Py_None);
         retval = Py_None;
@@ -1499,12 +1502,13 @@ DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
     err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
         err = 0;
         Py_INCREF(dfltobj);
         retval = dfltobj;
     }
-    else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
+    else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+            && self->moduleFlags.getReturnsNone) {
         err = 0;
         Py_INCREF(Py_None);
         retval = Py_None;
@@ -1629,7 +1633,8 @@ DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
     err = self->db->get(self->db, txn, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->moduleFlags.getReturnsNone) {
         err = 0;
         Py_INCREF(Py_None);
         retval = Py_None;
@@ -2745,7 +2750,15 @@ DB_has_key(DBObject* self, PyObject* args)
     err = self->db->get(self->db, txn, &key, &data, 0);
     MYDB_END_ALLOW_THREADS;
     FREE_DBT(key);
-    return PyInt_FromLong((err == DB_BUFFER_SMALL) || (err == 0));
+
+    if (err == DB_BUFFER_SMALL || err == 0) {
+        return PyInt_FromLong(1);
+    } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
+        return PyInt_FromLong(0);
+    }
+
+    makeDBError(err);
+    return NULL;
 }
 
 
@@ -2843,8 +2856,8 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
         Py_DECREF(item);
     }
 
-    /* DB_NOTFOUND is okay, it just means we got to the end */
-    if (err != DB_NOTFOUND && makeDBError(err)) {
+    /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
+    if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
         Py_DECREF(list);
         list = NULL;
     }
@@ -3051,7 +3064,8 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
     err = self->dbc->c_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.getReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3138,7 +3152,8 @@ DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
     err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.getReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3305,7 +3320,8 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
     MYDB_END_ALLOW_THREADS;
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.cursorSetReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3377,7 +3393,8 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
     MYDB_END_ALLOW_THREADS;
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.cursorSetReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3432,7 +3449,7 @@ _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
     MYDB_END_ALLOW_THREADS;
-    if ((err == DB_NOTFOUND) && returnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3572,7 +3589,8 @@ DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
     MYDB_END_ALLOW_THREADS;
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.cursorSetReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3640,7 +3658,8 @@ DBC_join_item(DBCursorObject* self, PyObject* args)
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
     MYDB_END_ALLOW_THREADS;
-    if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
+    if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
+           && self->mydb->moduleFlags.getReturnsNone) {
         Py_INCREF(Py_None);
         retval = Py_None;
     }
@@ -3941,6 +3960,23 @@ DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
 }
 
 
+static PyObject*
+DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
+{
+    int err, lg_max;
+
+    if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+
 static PyObject*
 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
 {
@@ -4651,6 +4687,7 @@ static PyMethodDef DBEnv_methods[] = {
     {"set_lg_bsize",    (PyCFunction)DBEnv_set_lg_bsize,     METH_VARARGS},
     {"set_lg_dir",      (PyCFunction)DBEnv_set_lg_dir,       METH_VARARGS},
     {"set_lg_max",      (PyCFunction)DBEnv_set_lg_max,       METH_VARARGS},
+    {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
     {"set_lk_detect",   (PyCFunction)DBEnv_set_lk_detect,    METH_VARARGS},
     {"set_lk_max",      (PyCFunction)DBEnv_set_lk_max,       METH_VARARGS},
 #if (DBVER >= 32)
@@ -5279,12 +5316,15 @@ DL_EXPORT(void) init_bsddb(void)
     DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
     PyDict_SetItemString(d, "DBError", DBError);
 
-    /* Some magic to make DBNotFoundError derive from both DBError and
-       KeyError, since the API only supports using one base class. */
+    /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
+     * from both DBError and KeyError, since the API only supports
+     * using one base class. */
     PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
-    PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
+    PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
+                "class DBKeyEmptyError(DBError, KeyError): pass",
                  Py_file_input, d, d);
     DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
+    DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
     PyDict_DelItemString(d, "KeyError");