set update in 2.5

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Duncan Smith

    #1

    set update in 2.5

    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())
    <class 'graphItems.Nod e'>
    >>type(k[1])
    <class 'graphItems.Nod e'>
    >>s = set()
    >>s.update(list (k))
    >>type(iter(s). next())
    <class 'graphItems.Nod e'>
    >>s = set()
    >>s.update(k)
    >>type(iter(s). next())
    <type 'int'>
    >>s = set()
    >>s.add(n)
    >>type(iter(s). next())
    <class 'graphItems.Nod e'>
    >>hash(n)
    1
    >>>
  • Peter Otten

    #2
    Re: set update in 2.5

    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.Nod e'>
    >>>type(k[1])
    <class 'graphItems.Nod e'>
    >>>s = set()
    >>>s.update(lis t(k))
    >>>type(iter(s) .next())
    <class 'graphItems.Nod e'>
    >>>s = set()
    >>>s.update(k )
    >>>type(iter(s) .next())
    <type 'int'>
    >>>s = set()
    >>>s.add(n)
    >>>type(iter(s) .next())
    <class 'graphItems.Nod e'>
    >>>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.000000 000 +0200
    +++ setobject_new.c 2007-01-28 10:02:24.071688 248 +0100
    @@ -854,7 +854,7 @@
    if (PyAnySet_Check (other))
    return set_merge(so, other);

    - if (PyDict_Check(o ther)) {
    + if (PyDict_CheckEx act(other)) {
    PyObject *value;
    Py_ssize_t pos = 0;
    while (PyDict_Next(ot her, &pos, &key, &value)) {

    Peter

    Comment

    • Duncan Smith

      #3
      Re: set update in 2.5

      Peter Otten wrote:
      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.Nod e'>
      >>
      >>>>>type(k[1])
      >>
      >><class 'graphItems.Nod e'>
      >>
      >>>>>s = set()
      >>>>>s.update(l ist(k))
      >>>>>type(iter( s).next())
      >>
      >><class 'graphItems.Nod e'>
      >>
      >>>>>s = set()
      >>>>>s.update(k )
      >>>>>type(iter( s).next())
      >>
      >><type 'int'>
      >>
      >>>>>s = set()
      >>>>>s.add(n)
      >>>>>type(iter( s).next())
      >>
      >><class 'graphItems.Nod e'>
      >>
      >>>>>hash(n)
      >>
      >>1
      >>
      >
      Is your KeyedSet derived from dict?
      >
      Thanks Peter. It is 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.000000 000 +0200
      +++ setobject_new.c 2007-01-28 10:02:24.071688 248 +0100
      @@ -854,7 +854,7 @@
      if (PyAnySet_Check (other))
      return set_merge(so, other);
      >
      - if (PyDict_Check(o ther)) {
      + if (PyDict_CheckEx act(other)) {
      PyObject *value;
      Py_ssize_t pos = 0;
      while (PyDict_Next(ot her, &pos, &key, &value)) {
      >
      Peter
      I will file a report. Cheers.

      Duncan

      Comment

      Working...