<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<META NAME="Generator" CONTENT="MS Exchange Server version 6.5.7653.2">
<TITLE>Why does this useage of __setstate__ fail?</TITLE>
</HEAD>
<BODY>
<!-- Converted from text/rtf format -->

<P><FONT SIZE=2 FACE="Arial">Can someone explain why the test below&nbsp; (test_persistence) is failing?&nbsp; I am adding an attribute after object creation with __setstate__, but I can't get the new attribute to persist.</FONT></P>

<P><FONT SIZE=2 FACE="Arial">------------------------------------------------</FONT>

<BR><FONT SIZE=2 FACE="Arial">import transaction</FONT>

<BR><FONT SIZE=2 FACE="Arial">import unittest</FONT>

<BR><FONT SIZE=2 FACE="Arial">from persistent import Persistent</FONT>

<BR><FONT SIZE=2 FACE="Arial">from ZODB import FileStorage, DB</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">TMP_DB = 'zodb-test-filestorage.fs'</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">class User(Persistent):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def __init__(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def __setstate__(self, state):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Persistent.__setstate__(self, state)</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not hasattr(self, 'color'):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.color = 'blue'</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def getColor(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.color</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def setColor(self, color):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.color = color</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transaction.commit()</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">class ZODB_TestCase(unittest.TestCase):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def setUp(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; storage = FileStorage.FileStorage(TMP_DB)</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.db = DB(storage)</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn = self.db.open()</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbroot = conn.root()</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Ensure that a 'userdb' key is present</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # in the root</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if not dbroot.has_key('userdb'):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from BTrees.OOBTree import OOBTree</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbroot['userdb'] = OOBTree()</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.userdb = dbroot['userdb']</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.id = 'amk'</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def tearDown(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.db.close()</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def test_AddUser(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuser = User()</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuser.first_name = 'Andrew'; newuser.last_name = 'Kuchling'</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Add object to the BTree, keyed on the ID</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.userdb[self.id] = newuser</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Commit the change</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transaction.commit()</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # setstate is not called after the constructor</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assert not hasattr(newuser, 'color')</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def test_setstate(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuser = self.userdb[self.id]</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # setstate is called subsequently</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assert hasattr(newuser, 'color')</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assert newuser.color == 'blue'</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuser.setColor('red')</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assert newuser.color == 'red'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; def test_persistence(self):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newuser = self.userdb[self.id]</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assert newuser.color == 'red' # this fails!&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">if __name__ == '__main__':</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; import os</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; if os.path.exists(TMP_DB):</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.unlink(TMP_DB)</FONT>

<BR><FONT SIZE=2 FACE="Arial">&nbsp;&nbsp;&nbsp; unittest.main()</FONT>
</P>

<P><FONT SIZE=2 FACE="Arial">---------------------------------------------------------------------------------</FONT>

<BR><B><FONT SIZE=2 FACE="GE Inspira">David Mika, PhD</FONT></B>

<BR><FONT SIZE=2 FACE="GE Inspira">Material Systems Technologies</FONT>

<BR><FONT SIZE=2 FACE="GE Inspira">k1-mb 235</FONT>

<BR><FONT SIZE=2 FACE="GE Inspira">GE Research Center</FONT>

<BR><FONT SIZE=2 FACE="GE Inspira">Niskayuna, NY 12309</FONT>

<BR><FONT SIZE=2 FACE="GE Inspira">518 387 4223 (phone)</FONT>

<BR><FONT SIZE=2 FACE="GE Inspira">mika@crd.ge.com</FONT>
</P>
<BR>

</BODY>
</HTML>