[Zodb-checkins] SVN: ZODB/branches/alienoid-btrees_pop/src/BTrees/ Added pop method implementation.

Ruslan Spivak rspivak at nuxeo.com
Tue Aug 30 16:42:14 EDT 2005


Log message for revision 38165:
  Added pop method implementation.

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

-=-
Modified: ZODB/branches/alienoid-btrees_pop/src/BTrees/BTreeTemplate.c
===================================================================
--- ZODB/branches/alienoid-btrees_pop/src/BTrees/BTreeTemplate.c	2005-08-30 20:38:50 UTC (rev 38164)
+++ ZODB/branches/alienoid-btrees_pop/src/BTrees/BTreeTemplate.c	2005-08-30 20:42:14 UTC (rev 38165)
@@ -1729,7 +1729,60 @@
     return value;
 }
 
+/* forward declaration */
+static int
+BTree_length_or_nonzero(BTree *self, int nonzero);
 
+static PyObject *
+BTree_pop(BTree *self, PyObject *args)
+{
+    PyObject *key;
+    PyObject *failobj = NULL; /* default */
+    PyObject *value;          /* return value */
+
+    if (! PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj))
+    	return NULL;
+
+    value = _BTree_get(self, key, 0);
+    if (value != NULL) {
+        if (_BTree_set(self, key, 0, 0, 0) < 0) {
+            Py_DECREF(value);
+            return NULL;;
+        }
+        return value;
+    }
+
+    /* 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;
+
+    int nonzero = 1;
+    int res = BTree_length_or_nonzero(self, nonzero);
+    if (res < 0) {
+        return NULL;
+    } else if (!res) {
+        /* btree is empty */
+        if (failobj == NULL) {
+            PyErr_SetString(PyExc_KeyError, "pop(): dictionary is empty");
+            return NULL;
+        }
+        PyErr_Clear();
+        Py_INCREF(failobj);
+        return failobj;
+    }
+
+    /* btree is not empty */
+    if (failobj == NULL)
+        return NULL;
+
+    PyErr_Clear();
+    Py_INCREF(failobj);
+    return failobj;
+}
+
+
 /* Search BTree self for key.  This is the sq_contains slot of the
  * PySequenceMethods.
  *
@@ -1873,6 +1926,10 @@
      "Return the value like get() except that if key is missing, d is both\n"
      "returned and inserted into the BTree as the value of k."},
 
+    {"pop", (PyCFunction) BTree_pop, METH_VARARGS,
+     "D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n\n"
+     "If key is not found, d is returned if given, otherwise KeyError is raised."},
+
     {"maxKey", (PyCFunction) BTree_maxKey,	METH_VARARGS,
      "maxKey([max]) -> key\n\n"
      "Return the largest key in the BTree.  If max is specified, return\n"

Modified: ZODB/branches/alienoid-btrees_pop/src/BTrees/BucketTemplate.c
===================================================================
--- ZODB/branches/alienoid-btrees_pop/src/BTrees/BucketTemplate.c	2005-08-30 20:38:50 UTC (rev 38164)
+++ ZODB/branches/alienoid-btrees_pop/src/BTrees/BucketTemplate.c	2005-08-30 20:42:14 UTC (rev 38165)
@@ -1287,6 +1287,61 @@
     return value;
 }
 
+
+/* forward declaration */
+static int
+Bucket_length(Bucket *self);
+
+static PyObject *
+bucket_pop(Bucket *self, PyObject *args)
+{
+    PyObject *key;
+    PyObject *failobj = NULL; /* default */
+    PyObject *value;          /* return value */
+    int dummy_changed;        /* in order to call _bucket_set */
+
+    if (! PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj))
+    	return NULL;
+
+    value = _bucket_get(self, key, 0);
+    if (value != NULL) {
+        if (_bucket_set(self, key, 0, 0, 0, &dummy_changed) < 0) {
+            Py_DECREF(value);
+            return NULL;;
+        }
+        return value;
+    }
+
+    /* The key isn't in the bucket.  If that's not due to a KeyError exception,
+     * pass back the unexpected exception.
+     */
+    if (! PyErr_ExceptionMatches(PyExc_KeyError))
+        return NULL;
+
+    int res = Bucket_length(self);
+    if (res < 0) {
+        return NULL;
+    } else if (!res) {
+        /* bucket is empty */
+        if (failobj == NULL) {
+            PyErr_SetString(PyExc_KeyError, "pop(): dictionary is empty");
+            return NULL;
+        }
+        PyErr_Clear();
+        Py_INCREF(failobj);
+        return failobj;
+    }
+
+    /* bucket is not empty */
+    if (failobj == NULL)
+        return NULL;
+
+    PyErr_Clear();
+    Py_INCREF(failobj);
+    return failobj;
+}
+
+
 /* Search bucket self for key.  This is the sq_contains slot of the
  * PySequenceMethods.
  *
@@ -1515,6 +1570,10 @@
      "Return the value like get() except that if key is missing, d is both\n"
      "returned and inserted into the bucket as the value of k."},
 
+    {"pop", (PyCFunction) bucket_pop, METH_VARARGS,
+     "D.pop(k[,d]) -> v, remove specified key and return the corresponding value.\n\n"
+     "If key is not found, d is returned if given, otherwise KeyError is raised."},
+
     {"iterkeys", (PyCFunction) Bucket_iterkeys,  METH_KEYWORDS,
      "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
 

Modified: ZODB/branches/alienoid-btrees_pop/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/branches/alienoid-btrees_pop/src/BTrees/tests/testBTrees.py	2005-08-30 20:38:50 UTC (rev 38164)
+++ ZODB/branches/alienoid-btrees_pop/src/BTrees/tests/testBTrees.py	2005-08-30 20:42:14 UTC (rev 38165)
@@ -628,6 +628,21 @@
         # Too many arguments.
         self.assertRaises(TypeError, t.setdefault, 1, 2, 3)
 
+
+    def testPop(self):
+        t = self.t
+
+        # KeyError when container is empty
+        self.assertRaises(KeyError, t.pop, 1)
+
+        t[1] = 3
+        self.assertRaises(KeyError, t.pop, 5)
+        self.assertEqual(t.pop(1), 3)
+        self.assertEqual(len(t), 0)
+
+        self.assertEqual(t.pop(1, 3), 3)
+
+
 class NormalSetTests(Base):
     """ Test common to all set types """
 



More information about the Zodb-checkins mailing list