[Zodb-checkins] SVN: ZODB/branches/alienoid-btrees_setdefault/src/BTrees/ BTree_setdefault(): Rewrote to look more like Python's

Tim Peters tim.one at comcast.net
Mon Aug 29 15:29:28 EDT 2005


Log message for revision 38146:
  BTree_setdefault():  Rewrote to look more like Python's
  dict.setdefault implementation, and to use 4-space indents
  like the rest of the file.  This fixes some endcase bugs too.
  
  Alas, treating the default "key missing value" of None
  correctly reveals that this isn't a sane policy for
  II, OI, or IF BTrees:  they can't have None as a value.
  
  testSetdefault():  Rewrote to reflect correct treatment of
  a missing default, and added an XXX noting that the repaired
  test fails now for II, OI, and IF trees.
  
  Note:  Buckets need to grow a setdefault() implementation
  too.
  

Changed:
  U   ZODB/branches/alienoid-btrees_setdefault/src/BTrees/BTreeTemplate.c
  U   ZODB/branches/alienoid-btrees_setdefault/src/BTrees/tests/testBTrees.py

-=-
Modified: ZODB/branches/alienoid-btrees_setdefault/src/BTrees/BTreeTemplate.c
===================================================================
--- ZODB/branches/alienoid-btrees_setdefault/src/BTrees/BTreeTemplate.c	2005-08-29 17:18:41 UTC (rev 38145)
+++ ZODB/branches/alienoid-btrees_setdefault/src/BTrees/BTreeTemplate.c	2005-08-29 19:29:27 UTC (rev 38146)
@@ -1703,23 +1703,30 @@
 static PyObject *
 BTree_setdefault(BTree *self, PyObject *args)
 {
-        PyObject *key, *d = Py_None, *r;
+    PyObject *key;
+    PyObject *failobj = Py_None;  /* default */
+    PyObject *value;  /* return value */
 
-        UNLESS (PyArg_ParseTuple(args, "O|O", &key, &d)) return NULL;
-        if ((r = _BTree_get(self, key, 0)))
-                return r;
-        UNLESS (PyErr_ExceptionMatches(PyExc_KeyError)) return NULL;
-        PyErr_Clear();
+    if (! PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
+    	return NULL;
 
-        Py_INCREF(d);
-        if (d == Py_None)
-                return d;
+    value = _BTree_get(self, key, 0);
+    if (value != NULL)
+        return value;
 
-        if (_BTree_set(self, key, d, 0, 0) < 0) {
-                Py_DECREF(d);
-                return NULL;
-        }
-        return d;
+    /* The key isn't in the tree.  If that's not due to a KeyError exception,
+     * pass back the unexpected exception.
+     */
+    if (! PyErr_ExceptionMatches(PyExc_KeyError))
+        return NULL;
+    PyErr_Clear();
+
+    /* Associate `key` with `failobj` in the tree, and return `failobj`. */
+    value = failobj;
+    if (_BTree_set(self, key, failobj, 0, 0) < 0)
+        value = NULL;
+    Py_XINCREF(value);
+    return value;
 }
 
 

Modified: ZODB/branches/alienoid-btrees_setdefault/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/branches/alienoid-btrees_setdefault/src/BTrees/tests/testBTrees.py	2005-08-29 17:18:41 UTC (rev 38145)
+++ ZODB/branches/alienoid-btrees_setdefault/src/BTrees/tests/testBTrees.py	2005-08-29 19:29:27 UTC (rev 38146)
@@ -1092,12 +1092,21 @@
 
     def testSetdefault(self):
         t = self.t
+
+        # XXX This test fails for II, OI, and IF trees:  they can't have
+        # XXX None as a value.
         self.assert_(t.setdefault(1) is None)
-        self.assertEqual(t.setdefault(1, 5), 5)
-        self.assert_(t[1] == 5)
-        self.assertEqual(t.setdefault(1, 3), 5)
+        # That should also have associated 1 with None in the tree.
+        self.assert_(t[1] is None)
+        # And trying to change it again should have no effect.
+        self.assert_(t.setdefault(1, 666) is None)
 
+        # Same thing, but with an explicit default.
+        self.assertEqual(t.setdefault(2, 5), 5)
+        self.assertEqual(t[2], 5)
+        self.assertEqual(t.setdefault(2, 666), 5)
 
+
 # tests of various type errors
 
 class TypeTest(TestCase):



More information about the Zodb-checkins mailing list