set update in 2.5

D

Duncan Smith

Hello,
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())
type(k[1])
s = set()
s.update(list(k))
type(iter(s).next())
s = set()
s.update(k)
type(iter(s).next())
s = set()
s.add(n)
type(iter(s).next())
hash(n) 1
 
P

Peter Otten

Duncan said:
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())
s = set()
s.update(list(k))
type(iter(s).next())
s = set()
s.update(k)
type(iter(s).next())
s = set()
s.add(n)
type(iter(s).next())
hash(n) 1

Is your KeyedSet derived from dict?

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

$ python2.4
[snip].... def __iter__(self): return self.itervalues()
....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
 
D

Duncan Smith

Peter said:
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())

type(k[1])

s = set()
s.update(list(k))
type(iter(s).next())

s = set()
s.update(k)
type(iter(s).next())

s = set()
s.add(n)
type(iter(s).next())


1

Is your KeyedSet derived from dict?

Thanks Peter. It is derived from dict.
$ python2.5
[snip]

... def __iter__(self): return self.itervalues()
...

set(['a', 'b'])


$ python2.4
[snip]

... def __iter__(self): return self.itervalues()
...

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

I will file a report. Cheers.

Duncan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top