Commit 72795b10 authored by Tim Peters's avatar Tim Peters

Merge rev 38114 from trunk.

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.
parent 652c3a5f
......@@ -28,6 +28,13 @@ PersistentMapping
a list containing ``x``'s keys, ``iter(x)`` creates an iterator for
``x``'s keys, and so on.
BTrees
------
- (3.4.2a1) 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.
What's new in ZODB3 3.4.1?
==========================
......
......@@ -457,7 +457,12 @@ update_from_seq(PyObject *map, PyObject *seq)
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 @@ update_from_seq(PyObject *map, PyObject *seq)
Py_DECREF(items);
if (seq == NULL)
return -1;
} else
}
else
Py_INCREF(seq);
iter = PyObject_GetIter(seq);
......
......@@ -345,6 +345,18 @@ class MappingBase(Base):
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)])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment