[Python-Dev] Bug in Pickle protocol involving __setstate__

2008-03-18 Thread Greg Kochanski
If we have a hierarchy of classes, and we use
__getstate__/__setstate__, the wrong version
of __setstate__ gets called.

Possibly, this is a documentation problem, but here goes:

Take two classes, A and B, where B is the child of A.

Construct a B.   Pickle it.   Unpickle it, and you find
that the __setstate__ function for A is called with the result
produced by B.__getstate__().

This is wrong.


An example follows:

import pickle as P


class A(object):
 def __init__(self, a):
 print 'A.__init__'
 self.a = a

 def __getstate__(self):
 print 'A.__getstate'
 return self.a

 def __setstate__(self, upstate):
 print 'A.__setstate', upstate
 self.a = upstate

class B(A):
 def __init__(self, a, b):
 print 'B.__init__'
 A.__init__(self, a)
 self.b = b

 def __getstate__(self):
 print 'B.__getstate'
 return (A.__getstate__(self), self.b)

 def __setstate(self, upstate):
# This never gets called!
 print 'B.__setstate', upstate
 A.__setstate__(self, upstate[0])
 self.b = upstate[1]


 def __repr__(self):
 return 'B a=%d b=%d' % (self.a, self.b)


q = B(1,2)
print '---'
r = P.loads(P.dumps(q, 0))
print 'q=', q
print 'r=', r


Now, run it:

$ python foo.py
B.__init__
A.__init__
---
B.__getstate
A.__getstate
A.__setstate (1, 2)
q= B a=1 b=2, h=46912504218064
r= Traceback (most recent call last):
   File foo.py, line 44, in module
 print 'r=', r
   File foo.py, line 37, in __repr__
 return 'B a=%d b=%d' % (self.a, self.b)
AttributeError: 'B' object has no attribute 'b'
$
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Bug in Pickle protocol involving __setstate__

2008-03-18 Thread Thomas Wouters
On Mon, Mar 3, 2008 at 8:00 AM, Greg Kochanski [EMAIL PROTECTED]
wrote:

 If we have a hierarchy of classes, and we use
 __getstate__/__setstate__, the wrong version
 of __setstate__ gets called.

 Possibly, this is a documentation problem, but here goes:


No, it's a typo error :)



 Take two classes, A and B, where B is the child of A.

 Construct a B.   Pickle it.   Unpickle it, and you find
 that the __setstate__ function for A is called with the result
 produced by B.__getstate__().

 This is wrong.


 An example follows:

 import pickle as P


 class A(object):
 def __init__(self, a):
 print 'A.__init__'
 self.a = a

 def __getstate__(self):
 print 'A.__getstate'
 return self.a

 def __setstate__(self, upstate):
 print 'A.__setstate', upstate
 self.a = upstate

 class B(A):
 def __init__(self, a, b):
 print 'B.__init__'
 A.__init__(self, a)
 self.b = b

 def __getstate__(self):
 print 'B.__getstate'
 return (A.__getstate__(self), self.b)

 def __setstate(self, upstate):


Try actually calling this method '__setstate__' instead.


# This never gets called!
 print 'B.__setstate', upstate
 A.__setstate__(self, upstate[0])
 self.b = upstate[1]


 def __repr__(self):
 return 'B a=%d b=%d' % (self.a, self.b)


 q = B(1,2)
 print '---'
 r = P.loads(P.dumps(q, 0))
 print 'q=', q
 print 'r=', r


 Now, run it:

 $ python foo.py
 B.__init__
 A.__init__
 ---
 B.__getstate
 A.__getstate
 A.__setstate (1, 2)
 q= B a=1 b=2, h=46912504218064
 r= Traceback (most recent call last):
   File foo.py, line 44, in module
 print 'r=', r
   File foo.py, line 37, in __repr__
 return 'B a=%d b=%d' % (self.a, self.b)
 AttributeError: 'B' object has no attribute 'b'
 $
 ___
 Python-Dev mailing list
 Python-Dev@python.org
 http://mail.python.org/mailman/listinfo/python-dev
 Unsubscribe:
 http://mail.python.org/mailman/options/python-dev/thomas%40python.org




-- 
Thomas Wouters [EMAIL PROTECTED]

Hi! I'm a .signature virus! copy me into your .signature file to help me
spread!
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com