<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Hi David,</div><div><br class="webkit-block-placeholder"></div><div>It&nbsp;looks&nbsp;like&nbsp;you&nbsp;might&nbsp;be&nbsp;assuming&nbsp;that&nbsp;the&nbsp;tests&nbsp;run&nbsp;in&nbsp;the&nbsp;order</div><div>you&nbsp;wrote&nbsp;them.&nbsp;&nbsp;The&nbsp;test_persistence()&nbsp;function&nbsp;actually&nbsp;gets&nbsp;called</div><div>before&nbsp;the&nbsp;test_setstate(), so there is no chance for the color to be 'red'.</div><div><br></div><div>I don't think the failure of this particular test has anything to do with&nbsp;</div><div>your __setstate__() method. &nbsp;When I write __setstate__() methods,</div><div>though, &nbsp;I modify the state dictionary and then call Persistent.__setstate__. &nbsp;</div><div>This&nbsp;avoids triggering the persistent attribute machinery at all.</div><div><br></div><div>David Binger</div><div><br></div><div><div><div>On Jan 16, 2008, at 9:43 PM, Mika, David P (GE, Research) wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"> <div> <!-- 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"><a href="mailto:mika@crd.ge.com">mika@crd.ge.com</a></font> </p> <br> </div> _______________________________________________<br>For more information about ZODB, see the ZODB Wiki:<br><a href="http://www.zope.org/Wikis/ZODB/">http://www.zope.org/Wikis/ZODB/</a><br><br>ZODB-Dev mailing list &nbsp;- &nbsp;ZODB-Dev@zope.org<br>http://mail.zope.org/mailman/listinfo/zodb-dev<br></blockquote></div><br></div></body></html>