set update in 2.5

Peter Otten __peter__ at web.de
Sun Jan 28 04:15:39 EST 2007


Duncan Smith wrote:

>      In moving from 2.4 to 2.5 I find that some of my unit tests are now
> failing.  I've worked out that the problem relates to the set update
> method.  In 2.4 I could update a set with an iterable type derived from
> dict as the argument.  I now find that the set is updated with the hash
> values of the items in my iterable, rather than the items themselves.
> Converting to a list first gets round the problem.
> 
> My iterable type has the same API as 'set' but requires items to have
> hashable 'uid' attributes, so they can also be looked up by uid.  I hope
> this, and the fact that this worked fine in 2.4 will be enough to track
> down the issue without me having to paste reams of code (other than the
> following, pasted from IDLE).  Any ideas?  Cheers.
> 
> Duncan
> 
> 
>>>> from graphItems import Node
>>>> from keyed_sets import KeyedSet
>>>> n = Node(1)
>>>> n.uid
> 1
>>>> k = KeyedSet([n])
>>>> k
> KeyedSet([1])
>>>> type(iter(k).next())
> <class 'graphItems.Node'>
>>>> type(k[1])
> <class 'graphItems.Node'>
>>>> s = set()
>>>> s.update(list(k))
>>>> type(iter(s).next())
> <class 'graphItems.Node'>
>>>> s = set()
>>>> s.update(k)
>>>> type(iter(s).next())
> <type 'int'>
>>>> s = set()
>>>> s.add(n)
>>>> type(iter(s).next())
> <class 'graphItems.Node'>
>>>> hash(n)
> 1
>>>>

Is your KeyedSet derived from dict?

$ python2.5
[snip]
>>> class D(dict):
...     def __iter__(self): return self.itervalues()
...
>>> d = D(a=1, b=2)
>>> set(d)
set(['a', 'b'])
>>>

$ python2.4
[snip]
>>> class D(dict):
...     def __iter__(self): return self.itervalues()
...
>>> d = D(a=1, b=2)
>>> set(d)
set([1, 2])


I think you should file a bug report. The fix is probably

--- setobject.c 2006-09-08 08:02:26.000000000 +0200
+++ setobject_new.c     2007-01-28 10:02:24.071688248 +0100
@@ -854,7 +854,7 @@
        if (PyAnySet_Check(other))
                return set_merge(so, other);

-       if (PyDict_Check(other)) {
+       if (PyDict_CheckExact(other)) {
                PyObject *value;
                Py_ssize_t pos = 0;
                while (PyDict_Next(other, &pos, &key, &value)) {

Peter



More information about the Python-list mailing list