[Zodb-checkins] SVN: ZODB/trunk/ Collector 1873.

Tim Peters tim.one at comcast.net
Fri Aug 26 16:35:38 EDT 2005


Log message for revision 38114:
  Collector 1873.
  
  update_from_seq():  If PySequence_Check(seq) returns true,
  go on to check for the existence of "iteritems" when deciding
  whether the input is or is not "a sequence".  Alas,
  PySequence_Check() does return true for PersistentMapping and
  PersistentDict instances, so that they couldn't be used as
  arguments to BTree/Bucket construction or update().
  
  This is nasty type-sniffing, but it was before too.  There's
  no way to make such stuff bulletproof, so I'm settling for
  incremental improvement.
  

Changed:
  U   ZODB/trunk/NEWS.txt
  U   ZODB/trunk/src/BTrees/BucketTemplate.c
  U   ZODB/trunk/src/BTrees/tests/testBTrees.py

-=-
Modified: ZODB/trunk/NEWS.txt
===================================================================
--- ZODB/trunk/NEWS.txt	2005-08-26 20:27:15 UTC (rev 38113)
+++ ZODB/trunk/NEWS.txt	2005-08-26 20:35:38 UTC (rev 38114)
@@ -183,11 +183,15 @@
 BTrees
 ------
 
-- (3.5.a5) Collector 1843.  When a non-integer was passed to a method like
+- (3.5a5) Collector 1843.  When a non-integer was passed to a method like
   ``keys()`` of a Bucket or Set with integer keys, an internal error code
   was overlooked, leading to everything from "delayed errors" to segfaults.
   Such cases raise TypeError now, as intended.
 
+- (3.5a9) Collector 1873.  It wasn't possible to construct a BTree or Bucket
+  from, or apply their update() methods to, a PersistentMapping or
+  PersistentDict.  This works now.
+
 - (3.5a4) Collector 1831.  The BTree ``minKey()`` and ``maxKey()`` methods
   gave a misleading message if no key satisfying the constraints existed in a
   non-empty tree.

Modified: ZODB/trunk/src/BTrees/BucketTemplate.c
===================================================================
--- ZODB/trunk/src/BTrees/BucketTemplate.c	2005-08-26 20:27:15 UTC (rev 38113)
+++ ZODB/trunk/src/BTrees/BucketTemplate.c	2005-08-26 20:35:38 UTC (rev 38114)
@@ -457,7 +457,12 @@
        INCREF of the seq argument.  So seq must always be DECREFed on
        the way out.
      */
-    if (!PySequence_Check(seq)) {
+    /* Use items() if it's not a sequence.  Alas, PySequence_Check()
+     * returns true for a PeristentMapping or PersistentDict, and we
+     * want to use items() in those cases too.
+     */
+    if (!PySequence_Check(seq) || /* or it "looks like a dict" */
+          PyObject_HasAttrString(seq, "iteritems")) {
 	PyObject *items;
 	items = PyObject_GetAttrString(seq, "items");
 	if (items == NULL)
@@ -466,7 +471,8 @@
 	Py_DECREF(items);
 	if (seq == NULL)
 	    return -1;
-    } else
+    }
+    else
 	Py_INCREF(seq);
 
     iter = PyObject_GetIter(seq);

Modified: ZODB/trunk/src/BTrees/tests/testBTrees.py
===================================================================
--- ZODB/trunk/src/BTrees/tests/testBTrees.py	2005-08-26 20:27:15 UTC (rev 38113)
+++ ZODB/trunk/src/BTrees/tests/testBTrees.py	2005-08-26 20:35:38 UTC (rev 38114)
@@ -345,6 +345,18 @@
         self.t.update(l)
         self.assertEqual(list(self.t.items()), items)
 
+    # Before ZODB 3.4.2, update/construction from PersistentMapping failed.
+    def testUpdateFromPersistentMapping(self):
+        from persistent.mapping import PersistentMapping
+
+        pm = PersistentMapping({1: 2})
+        self.t.update(pm)
+        self.assertEqual(list(self.t.items()), [(1, 2)])
+
+        # Construction goes thru the same internals as .update().
+        t = self.t.__class__(pm)
+        self.assertEqual(list(t.items()), [(1, 2)])
+
     def testEmptyRangeSearches(self):
         t = self.t
         t.update([(1,1), (5,5), (9,9)])



More information about the Zodb-checkins mailing list