[Zodb-checkins] CVS: Zope3/src/zodb/btrees - interfaces.py:1.7.10.1 TreeSetTemplate.c:1.2.12.1 SetTemplate.c:1.2.12.1 SetOpTemplate.c:1.2.12.1 BucketTemplate.c:1.3.10.1 BTreeTemplate.c:1.2.12.1 BTreeModuleTemplate.c:1.2.12.1

Jeremy Hylton jeremy@zope.com
Wed, 12 Mar 2003 16:37:48 -0500


Update of /cvs-repository/Zope3/src/zodb/btrees
In directory cvs.zope.org:/tmp/cvs-serv27771/btrees

Modified Files:
      Tag: opaque-pickles-branch
	interfaces.py TreeSetTemplate.c SetTemplate.c SetOpTemplate.c 
	BucketTemplate.c BTreeTemplate.c BTreeModuleTemplate.c 
Log Message:
Update from trunk.


=== Zope3/src/zodb/btrees/interfaces.py 1.7 => 1.7.10.1 ===
--- Zope3/src/zodb/btrees/interfaces.py:1.7	Fri Jan 17 11:44:33 2003
+++ Zope3/src/zodb/btrees/interfaces.py	Wed Mar 12 16:37:41 2003
@@ -55,6 +55,9 @@
             # enough info to unlink an empty bucket from its containing
             # BTree correctly
             'Empty bucket from deleting all keys',
+
+            # 11; conflicting changes in an internal BTree node
+            'Conflicting changes in an internal BTree node',
             ]
 
     def __init__(self, p1, p2, p3, reason):
@@ -98,20 +101,26 @@
     def has_key(key):
         """Check whether the object has an item with the given key"""
 
-    def keys(min=None, max=None):
-        """Return an IReadSequence containing the keys in the collection
+    def keys(min=None, max=None, excludemin=False, excludemax=False):
+        """Return an IReadSequence containing the keys in the collection.
 
-        The type of the IReadSequence is not specified. It could be a
-        list or a tuple or some other type.
+        The type of the IReadSequence is not specified. It could be a list
+        or a tuple or some other type.
 
-        If a min is specified, then output is constrained to
-        items having keys greater than or equal to the given min.
-        A min value of None is ignored.
-
-        If a max is specified, then output is constrained to
-        items having keys less than or equal to the given min.
-        A max value of None is ignored.
-        """
+        All arguments are optional, and may be specified as keyword
+        arguments, or by position.
+
+        If a min is specified, then output is constrained to keys greater
+        than or equal to the given min, and, if excludemin is specified and
+        true, is further constrained to keys strictly greater than min.  A
+        min value of None is ignored.  If min is None or not specified, and
+        excludemin is true, the smallest key is excluded.
+
+        If a max is specified, then output is constrained to keys less than
+        or equal to the given max, and, if excludemax is specified and
+        true, is further constrained to keys strictly less than max.  A max
+        value of None is ignored.  If max is None or not specified, and
+        excludemax is true, the largest key is excluded. """
 
     def maxKey(key=None):
         """Return the maximum key
@@ -167,36 +176,54 @@
         key-value tuples.
         """
 
-    def values(min=None, max=None):
-        """Return a IReadSequence containing the values in the collection
-
-        The type of the IReadSequence is not specified. It could be a
-        list or a tuple or some other type.
-
-        If a min is specified, then output is constrained to
-        items having keys greater than or equal to the given min.
-        A min value of None is ignored.
-
-        If a max is specified, then output is constrained to
-        items having keys less than or equal to the given max.
-        A max value of None is ignored.
-        """
-
-    def items(min=None, max=None):
-        """Return a IReadSequence containing the items in the collection
-
-        An item is a key-value tuple.
+    def values(min=None, max=None, excludemin=False, excludemax=False):
+        """Return an IReadSequence containing the values in the collection.
 
-        The type of the IReadSequence is not specified. It could be a
-        list or a tuple or some other type.
+        The type of the IReadSequence is not specified. It could be a list
+        or a tuple or some other type.
 
-        If a min is specified, then output is constrained to
-        items having keys greater than or equal to the given min.
-        A min value of None is ignored.
+        All arguments are optional, and may be specified as keyword
+        arguments, or by position.
 
-        If a max is specified, then output is constrained to
-        items having keys less than or equal to the given max.
-        A max value of None is ignored.
+        If a min is specified, then output is constrained to values whose
+        keys are greater than or equal to the given min, and, if excludemin
+        is specified and true, is further constrained to values whose keys
+        are strictly greater than min.  A min value of None is ignored.  If
+        min is None or not specified, and excludemin is true, the value
+        corresponding to the smallest key is excluded.
+
+        If a max is specified, then output is constrained to values whose
+        keys are less than or equal to the given max, and, if excludemax is
+        specified and true, is further constrained to values whose keys are
+        strictly less than max.  A max value of None is ignored.  If max is
+        None or not specified, and excludemax is true, the value
+        corresponding to the largest key is excluded.
+        """
+
+    def items(min=None, max=None, excludemin=False, excludemax=False):
+        """Return an IReadSequence containing the items in the collection.
+
+        An item is a 2-tuple, a (key, value) pair.
+
+        The type of the IReadSequence is not specified.  It could be a list
+        or a tuple or some other type.
+
+        All arguments are optional, and may be specified as keyword
+        arguments, or by position.
+
+        If a min is specified, then output is constrained to items whose
+        keys are greater than or equal to the given min, and, if excludemin
+        is specified and true, is further constrained to items whose keys
+        are strictly greater than min.  A min value of None is ignored.  If
+        min is None or not specified, and excludemin is true, the item with
+        the smallest key is excluded.
+
+        If a max is specified, then output is constrained to items whose
+        keys are less than or equal to the given max, and, if excludemax is
+        specified and true, is further constrained to items whose keys are
+        strictly less than max.  A max value of None is ignored.  If max is
+        None or not specified, and excludemax is true, the item with the
+        largest key is excluded.
         """
 
     def byValue(minValue):


=== Zope3/src/zodb/btrees/TreeSetTemplate.c 1.2 => 1.2.12.1 ===
--- Zope3/src/zodb/btrees/TreeSetTemplate.c:1.2	Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/btrees/TreeSetTemplate.c	Wed Mar 12 16:37:41 2003
@@ -118,37 +118,49 @@
   {"__getstate__", (PyCFunction) BTree_getstate,	METH_NOARGS,
    "__getstate__() -> state\n\n"
    "Return the picklable state of the TreeSet."},
+
   {"__setstate__", (PyCFunction) TreeSet_setstate,	METH_VARARGS,
    "__setstate__(state)\n\n"
    "Set the state of the TreeSet."},
+
   {"has_key",	(PyCFunction) BTree_has_key,	METH_O,
    "has_key(key)\n\n"
    "Return true if the TreeSet contains the given key."},
-  {"keys",	(PyCFunction) BTree_keys,	METH_VARARGS,
+
+  {"keys",	(PyCFunction) BTree_keys,	METH_KEYWORDS,
    "keys([min, max]) -> list of keys\n\n"
    "Returns the keys of the TreeSet.  If min and max are supplied, only\n"
    "keys greater than min and less than max are returned."},
+
   {"maxKey", (PyCFunction) BTree_maxKey,	METH_VARARGS,
    "maxKey([max]) -> key\n\n"
    "Return the largest key in the BTree.  If max is specified, return\n"
    "the largest key <= max."},
+
   {"minKey", (PyCFunction) BTree_minKey,	METH_VARARGS,
    "minKey([mi]) -> key\n\n"
    "Return the smallest key in the BTree.  If min is specified, return\n"
    "the smallest key >= min."},
+
   {"clear",	(PyCFunction) BTree_clear,	METH_NOARGS,
    "clear()\n\nRemove all of the items from the BTree."},
+
   {"insert",	(PyCFunction)TreeSet_insert,	METH_VARARGS,
    "insert(id,[ignored]) -- Add an id to the set"},
+
   {"update",	(PyCFunction)TreeSet_update,	METH_VARARGS,
    "update(collection)\n\n Add the items from the given collection."},
+
   {"remove",	(PyCFunction)TreeSet_remove,	METH_VARARGS,
    "remove(id) -- Remove a key from the set"},
+
   {"_check", (PyCFunction) BTree_check,       METH_NOARGS,
    "Perform sanity check on TreeSet, and raise exception if flawed."},
+
 #ifdef PERSISTENT
   {"_p_resolveConflict", (PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
    "_p_resolveConflict() -- Reinitialize from a newly created copy"},
+
   {"_p_deactivate", (PyCFunction) BTree__p_deactivate,	METH_NOARGS,
    "_p_deactivate()\n\nReinitialize from a newly created copy."},
 #endif


=== Zope3/src/zodb/btrees/SetTemplate.c 1.2 => 1.2.12.1 ===
--- Zope3/src/zodb/btrees/SetTemplate.c:1.2	Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/btrees/SetTemplate.c	Wed Mar 12 16:37:41 2003
@@ -168,30 +168,41 @@
 static struct PyMethodDef Set_methods[] = {
   {"__getstate__", (PyCFunction) bucket_getstate,	METH_VARARGS,
    "__getstate__() -- Return the picklable state of the object"},
+
   {"__setstate__", (PyCFunction) set_setstate,	METH_VARARGS,
    "__setstate__() -- Set the state of the object"},
-  {"keys",	(PyCFunction) bucket_keys,	METH_VARARGS,
+
+  {"keys",	(PyCFunction) bucket_keys,	METH_KEYWORDS,
      "keys() -- Return the keys"},
+
   {"has_key",	(PyCFunction) bucket_has_key,	METH_O,
      "has_key(key) -- Test whether the bucket contains the given key"},
+
   {"clear",	(PyCFunction) bucket_clear,	METH_VARARGS,
    "clear() -- Remove all of the items from the bucket"},
+
   {"maxKey", (PyCFunction) Bucket_maxKey,	METH_VARARGS,
-   "maxKey([key]) -- Fine the maximum key\n\n"
+   "maxKey([key]) -- Find the maximum key\n\n"
    "If an argument is given, find the maximum <= the argument"},
+
   {"minKey", (PyCFunction) Bucket_minKey,	METH_VARARGS,
-   "minKey([key]) -- Fine the minimum key\n\n"
+   "minKey([key]) -- Find the minimum key\n\n"
    "If an argument is given, find the minimum >= the argument"},
+
 #ifdef PERSISTENT
   {"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
    "_p_resolveConflict() -- Reinitialize from a newly created copy"},
+
   {"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_VARARGS,
    "_p_deactivate() -- Reinitialize from a newly created copy"},
 #endif
+
   {"insert",	(PyCFunction)Set_insert,	METH_VARARGS,
    "insert(id,[ignored]) -- Add a key to the set"},
+
   {"update",	(PyCFunction)Set_update,	METH_VARARGS,
    "update(seq) -- Add the items from the given sequence to the set"},
+
   {"remove",	(PyCFunction)Set_remove,	METH_VARARGS,
    "remove(id) -- Remove an id from the set"},
 
@@ -222,11 +233,11 @@
 
   UNLESS (format) UNLESS (format=PyString_FromString(MOD_NAME_PREFIX "Set(%s)"))
     return NULL;
-  UNLESS (t=PyTuple_New(1)) return NULL;
-  UNLESS (r=bucket_keys(self,NULL)) goto err;
-  PyTuple_SET_ITEM(t,0,r);
-  r=t;
-  ASSIGN(r,PyString_Format(format,r));
+  UNLESS (t = PyTuple_New(1)) return NULL;
+  UNLESS (r = bucket_keys(self, NULL, NULL)) goto err;
+  PyTuple_SET_ITEM(t, 0, r);
+  r = t;
+  ASSIGN(r, PyString_Format(format, r));
   return r;
 err:
   Py_DECREF(t);


=== Zope3/src/zodb/btrees/SetOpTemplate.c 1.2 => 1.2.12.1 ===
--- Zope3/src/zodb/btrees/SetOpTemplate.c:1.2	Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/btrees/SetOpTemplate.c	Wed Mar 12 16:37:41 2003
@@ -124,7 +124,7 @@
     }
   else if (PyObject_IsInstance(s, (PyObject *)&BTreeType))
     {
-      i->set = BTree_rangeSearch(BTREE(s), NULL, 'i');
+      i->set = BTree_rangeSearch(BTREE(s), NULL, NULL, 'i');
       UNLESS(i->set) return -1;
 
       if (useValues)
@@ -137,7 +137,7 @@
     }
   else if (PyObject_IsInstance(s, (PyObject *)&TreeSetType))
     {
-      i->set = BTree_rangeSearch(BTREE(s), NULL, 'k');
+      i->set = BTree_rangeSearch(BTREE(s), NULL, NULL, 'k');
       UNLESS(i->set) return -1;
       i->next = nextTreeSetItems;
     }


=== Zope3/src/zodb/btrees/BucketTemplate.c 1.3 => 1.3.10.1 ===
--- Zope3/src/zodb/btrees/BucketTemplate.c:1.3	Sat Jan 11 01:35:04 2003
+++ Zope3/src/zodb/btrees/BucketTemplate.c	Wed Mar 12 16:37:41 2003
@@ -598,6 +598,9 @@
  Arguments:     self        The bucket
                 keyarg      The key to match against
                 low         Boolean; true for low end of range, false for high
+                exclude_equal  Boolean; if true, don't accept an exact match,
+                	       and if there is one then move right if low and
+                	       left if !low.
                 offset      The output offset
 
  If low true, *offset <- index of the smallest item >= key,
@@ -609,9 +612,9 @@
       1     The correct index was stored into *offset
      -1     Error
 
- Example:  Suppose the keys are [2, 4].  Searching for 2 sets *offset to 0 and
- returns 1 regardless of low.  Searching for 4 sets *offset to 1 and returns
- 1 regardless of low.
+ Example:  Suppose the keys are [2, 4], and exclude_equal is false.  Searching
+ for 2 sets *offset to 0 and returns 1 regardless of low.  Searching for 4
+ sets *offset to 1 and returns 1 regardless of low.
  Searching for 1:
      If low true, sets *offset to 0, returns 1.
      If low false, returns 0.
@@ -621,9 +624,12 @@
  Searching for 5:
      If low true, returns 0.
      If low false, sets *offset to 1, returns 1.
+
+ The 1, 3 and 5 examples are the same when exclude_equal is true.
  */
 static int
-Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int *offset)
+Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal,
+		    int *offset)
 {
     int i, cmp;
     int result = -1;    /* until proven innocent */
@@ -638,18 +644,24 @@
         return -1;
 
     BUCKET_SEARCH(i, cmp, self, key, goto Done);
-    if (cmp == 0)   /* exact match at index i */
-        result = 1;
-
-    /* Else keys[i-1] < key < keys[i], picturing infinities at OOB indices */
-    else if (low)   /* i has the smallest item > key, unless i is OOB */
-        result = i < self->len;
-
-    else {          /* i-1 has the largest item < key, unless i-1 is 0OB */
-        --i;
-        result = i >= 0;
+    if (cmp == 0) {
+    	/* exact match at index i */
+    	if (exclude_equal) {
+	    /* but we don't want an exact match */
+            if (low)
+                ++i;
+            else
+                --i;
+        }
     }
+    /* Else keys[i-1] < key < keys[i], picturing infinities at OOB indices,
+     * and i has the smallest item > key, which is correct for low.
+     */
+    else if (! low)
+        /* i-1 has the largest item < key (unless i-1 is 0OB) */
+        --i;
 
+    result = 0 <= i && i < self->len;
     if (result)
         *offset = i;
 
@@ -674,7 +686,7 @@
   /* Find the low range */
   if (key)
     {
-      if ((rc = Bucket_findRangeEnd(self, key, min, &offset)) <= 0)
+      if ((rc = Bucket_findRangeEnd(self, key, min, 0, &offset)) <= 0)
         {
           if (rc < 0) return NULL;
           goto empty;
@@ -709,45 +721,66 @@
 }
 
 static int
-Bucket_rangeSearch(Bucket *self, PyObject *args, int *low, int *high)
+Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
+		   int *low, int *high)
 {
-  PyObject *f=0, *l=0;
-  int rc;
-
-  if (args && ! PyArg_ParseTuple(args,"|OO",&f, &l)) return -1;
-
-  UNLESS (self->len) goto empty;
-
-  /* Find the low range */
-  if (f && f != Py_None)
-    {
-      UNLESS (rc = Bucket_findRangeEnd(self, f, 1, low))
-        {
-          if (rc < 0) return -1;
-          goto empty;
-        }
+    PyObject *min = Py_None;
+    PyObject *max = Py_None;
+    int excludemin = 0;
+    int excludemax = 0;
+    int rc;
+
+    if (args) {
+        if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
+        				  &min,
+        				  &max,
+        				  &excludemin,
+        				  &excludemax))
+	    return -1;
     }
-  else *low = 0;
 
-  /* Find the high range */
-  if (l && l != Py_None)
-    {
-      UNLESS (rc = Bucket_findRangeEnd(self, l, 0, high))
-        {
-          if (rc < 0) return -1;
-          goto empty;
+    UNLESS (self->len) goto empty;
+
+    /* Find the low range */
+    if (min != Py_None) {
+        UNLESS (rc = Bucket_findRangeEnd(self, min, 1, excludemin, low)) {
+            if (rc < 0) return -1;
+            goto empty;
         }
     }
-  else *high = self->len - 1;
-
-  /* If f < l to begin with, it's quite possible that low > high now. */
-  if (*low <= *high)
-    return 0;
+    else {
+    	*low = 0;
+    	if (excludemin) {
+    	    if (self->len < 2)
+    	    	goto empty;
+    	    ++*low;
+    	}
+    }
+
+    /* Find the high range */
+    if (max != Py_None) {
+        UNLESS (rc = Bucket_findRangeEnd(self, max, 0, excludemax, high)) {
+            if (rc < 0) return -1;
+            goto empty;
+	}
+    }
+    else {
+	*high = self->len - 1;
+	if (excludemax) {
+	    if (self->len < 2)
+	    	goto empty;
+	    --*high;
+	}
+    }
+
+    /* If min < max to begin with, it's quite possible that low > high now. */
+    if (*low <= *high)
+        return 0;
 
  empty:
-  *low = 0;
-  *high = -1;
-  return 0;
+    *low = 0;
+    *high = -1;
+    return 0;
 }
 
 /*
@@ -761,14 +794,14 @@
 ** Returns:	list of bucket keys
 */
 static PyObject *
-bucket_keys(Bucket *self, PyObject *args)
+bucket_keys(Bucket *self, PyObject *args, PyObject *kw)
 {
   PyObject *r = NULL, *key;
   int i, low, high;
 
   PER_USE_OR_RETURN(self, NULL);
 
-  if (Bucket_rangeSearch(self, args, &low, &high) < 0)
+  if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
       goto err;
 
   r = PyList_New(high-low+1);
@@ -803,14 +836,14 @@
 ** Returns	list of values
 */
 static PyObject *
-bucket_values(Bucket *self, PyObject *args)
+bucket_values(Bucket *self, PyObject *args, PyObject *kw)
 {
   PyObject *r=0, *v;
   int i, low, high;
 
   PER_USE_OR_RETURN(self, NULL);
 
-  if (Bucket_rangeSearch(self, args, &low, &high) < 0) goto err;
+  if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0) goto err;
 
   UNLESS (r=PyList_New(high-low+1)) goto err;
 
@@ -843,14 +876,14 @@
 ** Returns:	list of all items in the bucket
 */
 static PyObject *
-bucket_items(Bucket *self, PyObject *args)
+bucket_items(Bucket *self, PyObject *args, PyObject *kw)
 {
   PyObject *r=0, *o=0, *item=0;
   int i, low, high;
 
   PER_USE_OR_RETURN(self, NULL);
 
-  if (Bucket_rangeSearch(self, args, &low, &high) < 0) goto err;
+  if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0) goto err;
 
   UNLESS (r=PyList_New(high-low+1)) goto err;
 
@@ -992,7 +1025,7 @@
 static PyObject *
 bucket__p_deactivate(Bucket *self)
 {
-    if (self->po_state == UPTODATE && self->po_dm) {
+    if (self->po_state == UPTODATE && self->po_dm && self->po_oid) {
 	if (_bucket_clear(self) < 0)
 	    return NULL;
 	self->po_state = GHOST;
@@ -1246,14 +1279,15 @@
  * Returns a BTreeIter object, or NULL if error.
  */
 static PyObject *
-buildBucketIter(Bucket *self, PyObject *args, char kind)
+buildBucketIter(Bucket *self, PyObject *args, PyObject *kw, char kind)
 {
     BTreeItems *items;
     int lowoffset, highoffset;
     BTreeIter *result = NULL;
 
     PER_USE_OR_RETURN(self, NULL);
-    if (Bucket_rangeSearch(self, args, &lowoffset, &highoffset) < 0) goto Done;
+    if (Bucket_rangeSearch(self, args, kw, &lowoffset, &highoffset) < 0)
+        goto Done;
 
     items = (BTreeItems *)newBTreeItems(kind, self, lowoffset,
                                               self, highoffset);
@@ -1271,28 +1305,28 @@
 static PyObject *
 Bucket_getiter(Bucket *self)
 {
-    return buildBucketIter(self, NULL, 'k');
+    return buildBucketIter(self, NULL, NULL, 'k');
 }
 
 /* The implementation of Bucket.iterkeys(). */
 static PyObject *
-Bucket_iterkeys(Bucket *self, PyObject *args)
+Bucket_iterkeys(Bucket *self, PyObject *args, PyObject *kw)
 {
-    return buildBucketIter(self, args, 'k');
+    return buildBucketIter(self, args, kw, 'k');
 }
 
 /* The implementation of Bucket.itervalues(). */
 static PyObject *
-Bucket_itervalues(Bucket *self, PyObject *args)
+Bucket_itervalues(Bucket *self, PyObject *args, PyObject *kw)
 {
-    return buildBucketIter(self, args, 'v');
+    return buildBucketIter(self, args, kw, 'v');
 }
 
 /* The implementation of Bucket.iteritems(). */
 static PyObject *
-Bucket_iteritems(Bucket *self, PyObject *args)
+Bucket_iteritems(Bucket *self, PyObject *args, PyObject *kw)
 {
-    return buildBucketIter(self, args, 'i');
+    return buildBucketIter(self, args, kw, 'i');
 }
 
 /* End of iterator support. */
@@ -1378,42 +1412,58 @@
 static struct PyMethodDef Bucket_methods[] = {
     {"__getstate__", (PyCFunction) bucket_getstate,	METH_NOARGS,
      "__getstate__() -- Return the picklable state of the object"},
+
     {"__setstate__", (PyCFunction) bucket_setstate,	METH_O,
      "__setstate__() -- Set the state of the object"},
-    {"keys",	(PyCFunction) bucket_keys,	METH_VARARGS,
+
+    {"keys",	(PyCFunction) bucket_keys,	METH_KEYWORDS,
      "keys([min, max]) -- Return the keys"},
+
     {"has_key",	(PyCFunction) bucket_has_key,	METH_O,
      "has_key(key) -- Test whether the bucket contains the given key"},
+
     {"clear",	(PyCFunction) bucket_clear,	METH_VARARGS,
      "clear() -- Remove all of the items from the bucket"},
+
     {"update",	(PyCFunction) Mapping_update,	METH_O,
      "update(collection) -- Add the items from the given collection"},
+
     {"maxKey", (PyCFunction) Bucket_maxKey,	METH_VARARGS,
-     "maxKey([key]) -- Fine the maximum key\n\n"
+     "maxKey([key]) -- Find the maximum key\n\n"
      "If an argument is given, find the maximum <= the argument"},
+
     {"minKey", (PyCFunction) Bucket_minKey,	METH_VARARGS,
-     "minKey([key]) -- Fine the minimum key\n\n"
+     "minKey([key]) -- Find the minimum key\n\n"
      "If an argument is given, find the minimum >= the argument"},
-    {"values",	(PyCFunction) bucket_values,	METH_VARARGS,
+
+    {"values",	(PyCFunction) bucket_values,	METH_KEYWORDS,
      "values([min, max]) -- Return the values"},
-    {"items",	(PyCFunction) bucket_items,	METH_VARARGS,
+
+    {"items",	(PyCFunction) bucket_items,	METH_KEYWORDS,
      "items([min, max])) -- Return the items"},
+
     {"byValue",	(PyCFunction) bucket_byValue,	METH_O,
      "byValue(min) -- "
      "Return value-keys with values >= min and reverse sorted by values"},
+
     {"get",	(PyCFunction) bucket_getm,	METH_VARARGS,
      "get(key[,default]) -- Look up a value\n\n"
      "Return the default (or None) if the key is not found."},
-    {"iterkeys", (PyCFunction) Bucket_iterkeys,  METH_VARARGS,
+
+    {"iterkeys", (PyCFunction) Bucket_iterkeys,  METH_KEYWORDS,
      "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
-    {"itervalues", (PyCFunction) Bucket_itervalues,  METH_VARARGS,
+
+    {"itervalues", (PyCFunction) Bucket_itervalues,  METH_KEYWORDS,
      "B.itervalues([min[,max]]) -> an iterator over the values of B"},
-    {"iteritems", (PyCFunction) Bucket_iteritems,    METH_VARARGS,
+
+    {"iteritems", (PyCFunction) Bucket_iteritems,    METH_KEYWORDS,
      "B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"},
+
 #ifdef PERSISTENT
     {"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict,
      METH_VARARGS,
      "_p_resolveConflict() -- Reinitialize from a newly created copy"},
+
     {"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_NOARGS,
      "_p_deactivate() -- Reinitialize from a newly created copy"},
 #endif
@@ -1551,7 +1601,7 @@
     char repr[10000];
     int rv;
 
-    i = bucket_items(self, NULL);
+    i = bucket_items(self, NULL, NULL);
     if (!i)
 	return NULL;
     r = PyObject_Repr(i);


=== Zope3/src/zodb/btrees/BTreeTemplate.c 1.2 => 1.2.12.1 === (530/630 lines abridged)
--- Zope3/src/zodb/btrees/BTreeTemplate.c:1.2	Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/btrees/BTreeTemplate.c	Wed Mar 12 16:37:41 2003
@@ -814,7 +814,7 @@
 static PyObject *
 BTree__p_deactivate(BTree *self)
 {
-    if (self->po_state == UPTODATE && self->po_dm) {
+    if (self->po_state == UPTODATE && self->po_dm && self->po_oid) {
 	if (_BTree_clear(self) < 0)
 	    return NULL;
 	self->po_state = GHOST;
@@ -1049,74 +1049,97 @@
 
 #ifdef PERSISTENT
 
-/* Return the caar of a tuple, where caar means t[0][0].
-   If t or t[0] is None, return None.
-   If caar is not None or a tuple, raise TypeError and return NULL.
-   Otherwise, raise TypeError and return NULL.
+/* Recognize the special cases of a BTree that's empty or contains a single
+ * bucket.  In the former case, return a borrowed reference to Py_None.
+ * In this single-bucket case, the bucket state is embedded directly in the
+ * BTree state, like so:
+ *
+ *     (
+ *         (
+ *              thebucket.__getstate__(),
+ *         ),
+ *     )
+ *
+ * When this obtains, return a borrowed reference to thebucket.__getstate__().
+ * Else return NULL with an exception set.  The exception should always be
+ * ConflictError then, but may be TypeError if the state makes no sense at all
+ * for a BTree (corrupted or hostile state).
+ */
+PyObject *
+get_bucket_state(PyObject *t)
+{
+	if (t == Py_None)
+		return Py_None;		/* an empty BTree */
+	if (! PyTuple_Check(t)) {
+		PyErr_SetString(PyExc_TypeError,
+			"_p_resolveConflict: expected tuple or None for state");
+		return NULL;
+	}
 
-   Always returns a borrowed reference.
+	if (PyTuple_GET_SIZE(t) == 2) {
+		/* A non-degenerate BTree. */
+		return merge_error(-1, -1, -1, 11);

[-=- -=- -=- 530 lines omitted -=- -=- -=-]

      "opposite order."},
+
     {"get",	(PyCFunction) BTree_getm,	METH_VARARGS,
      "get(key[, default=None]) -> Value for key or default\n\n"
      "Return the value or the default if the key is not found."},
+
     {"maxKey", (PyCFunction) BTree_maxKey,	METH_VARARGS,
      "maxKey([max]) -> key\n\n"
      "Return the largest key in the BTree.  If max is specified, return\n"
      "the largest key <= max."},
+
     {"minKey", (PyCFunction) BTree_minKey,	METH_VARARGS,
      "minKey([mi]) -> key\n\n"
      "Return the smallest key in the BTree.  If min is specified, return\n"
      "the smallest key >= min."},
+
     {"clear",	(PyCFunction) BTree_clear,	METH_NOARGS,
      "clear()\n\nRemove all of the items from the BTree."},
+
     {"insert", (PyCFunction)BTree_addUnique, METH_VARARGS,
      "insert(key, value) -> 0 or 1\n\n"
      "Add an item if the key is not already used. Return 1 if the item was\n"
      "added, or 0 otherwise."},
+
     {"update",	(PyCFunction) Mapping_update,	METH_O,
      "update(collection)\n\n Add the items from the given collection."},
-    {"iterkeys", (PyCFunction) BTree_iterkeys,  METH_VARARGS,
+
+    {"iterkeys", (PyCFunction) BTree_iterkeys,  METH_KEYWORDS,
      "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
-    {"itervalues", (PyCFunction) BTree_itervalues,  METH_VARARGS,
+
+    {"itervalues", (PyCFunction) BTree_itervalues,  METH_KEYWORDS,
      "B.itervalues([min[,max]]) -> an iterator over the values of B"},
-    {"iteritems", (PyCFunction) BTree_iteritems,    METH_VARARGS,
+
+    {"iteritems", (PyCFunction) BTree_iteritems,    METH_KEYWORDS,
      "B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"},
+
     {"_check", (PyCFunction) BTree_check,       METH_NOARGS,
      "Perform sanity check on BTree, and raise exception if flawed."},
+
 #ifdef PERSISTENT
     {"_p_resolveConflict", (PyCFunction) BTree__p_resolveConflict,
      METH_VARARGS,
      "_p_resolveConflict() -- Reinitialize from a newly created copy"},
+
     {"_p_deactivate", (PyCFunction) BTree__p_deactivate,	METH_NOARGS,
      "_p_deactivate()\n\nReinitialize from a newly created copy."},
 #endif


=== Zope3/src/zodb/btrees/BTreeModuleTemplate.c 1.2 => 1.2.12.1 ===
--- Zope3/src/zodb/btrees/BTreeModuleTemplate.c:1.2	Wed Dec 25 09:12:16 2002
+++ Zope3/src/zodb/btrees/BTreeModuleTemplate.c	Wed Mar 12 16:37:41 2003
@@ -332,6 +332,13 @@
     return r;
 }
 
+/* Shared keyword-argument list for BTree/Bucket
+ * (iter)?(keys|values|items)
+ */
+static char *search_keywords[] = {"min", "max",
+				  "excludemin", "excludemax",
+				  0};
+
 #include "BTreeItemsTemplate.c"
 #include "BucketTemplate.c"
 #include "SetTemplate.c"