This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author alexandre.vassalotti
Recipients alexandre.vassalotti, collinwinter, edonmyder, swiftcoder
Date 2009-05-25.21:14:04
SpamBayes Score 1.2652102e-12
Marked as misclassified No
Message-id <1243286047.84.0.482284899773.issue1761028@psf.upfronthosting.co.za>
In-reply-to
Content
Checked this out more throughly and I came to the conclusion this cannot
be fixed without a considerable amount of work.

The problem is pickle adds an Node instance stub in the next_nodes set
before its attributes are ready. Since the stub doesn't have any
attribute at the time its added to the set, the __hash__ method fails
with an AttributeError exception.

To fix this, pickle would need to detect cyclic objects with a custom
__hash__ method; and when it would see one, it would need to emit POP
opcodes to revert the parts of the object already pickled. And then,
pickle would have to re-pickle the cyclic object using a special
procedure that would delay the use of __hash__ until all the attributes
of the object are ready to be used.

I do not believe the bug arises frequently enough to justify adding more
tricky code to pickle. So, I will not fix this myself (feel free to
write a patch, however).

Finally, you can workaround the bug using the __getstate__/__setstate__
mechanism as follow:

class Node(object):
  def __init__(self, i):
    self.i = i
    self.next_nodes = set()
  def __cmp__(self, other):
	return cmp(self.i, other.i)
  def __hash__(self):
    return hash(self.i)
  def __getstate__(self):
    next_nodes = self.next_nodes.copy()
    next_nodes.discard(self)
    return {'i': self.i,
            'self_in_next_nodes': self in self.next_nodes,
            'next_nodes': next_nodes}
  def __setstate__(self, state):
    if state.pop('self_in_next_nodes'):
        self.__dict__.update(state)
        state['next_nodes'].add(self)
    else:
        self.__dict__.update(state)

n = Node(12)
n.next_nodes = set([n])
History
Date User Action Args
2009-05-25 21:14:08alexandre.vassalottisetrecipients: + alexandre.vassalotti, collinwinter, edonmyder, swiftcoder
2009-05-25 21:14:07alexandre.vassalottisetmessageid: <1243286047.84.0.482284899773.issue1761028@psf.upfronthosting.co.za>
2009-05-25 21:14:06alexandre.vassalottilinkissue1761028 messages
2009-05-25 21:14:04alexandre.vassalotticreate