<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=us-ascii">
<META content="MSHTML 6.00.2900.3243" name=GENERATOR></HEAD>
<BODY
style="WORD-WRAP: break-word; webkit-nbsp-mode: space; webkit-line-break: after-white-space">
<DIV dir=ltr align=left><FONT face=Arial color=#0000ff size=2><SPAN
class=884500616-17012008>Thanks David, you are correct. I now am testing
in the correct order, and everything works as expected for a simple
attribute. Where I have been runing awry is when the the attribute is a
class. I have assembled another example below. Thanks also to Tres
Sever who suggested the following with the first example I
sent:</SPAN></FONT></DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2></FONT></SPAN></FONT> </DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2>You are mutating the object *inside* your __setstate__: the
ZODB persistence machinery clears the '_p_changed' flag after you *exit*
from<SPAN class=884500616-17012008> </SPAN>'__setstate__': the protocol is not
intended to support a persistent "write-on-read".</FONT></SPAN></FONT></DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2></FONT></SPAN></FONT> </DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2>I can accept this, but after returning from the
__setstate__, I further modify the object and commit the transaction (see
test_2_setstate). This should persist as I understand it. Why does
it not? The reason I am persisting with this is the __setstate__ offers an
elegant way to upgrade existing objects--something I find myself doing
often.</FONT></SPAN></FONT></DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2></FONT></SPAN></FONT> </DIV>
<DIV dir=ltr align=left><FONT><SPAN class=884500616-17012008><FONT face=Arial
color=#0000ff size=2>---------------------------------------------</DIV>
<DIV></FONT></SPAN></FONT><FONT face=Arial color=#0000ff size=2>import
transaction<BR>import unittest<BR>from persistent import Persistent<BR>from ZODB
import FileStorage, DB</FONT></DIV>
<DIV><FONT face=Arial color=#0000ff size=2></FONT> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2>TMP_DB =
'zodb-test-filestorage.fs'</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2>class
Color(Persistent):<BR> def
__init__(self):<BR> self.color =
'blue'<BR> def setColor(self,
color):<BR> self.color =
color</FONT></DIV>
<DIV><SPAN class=884500616-17012008></SPAN><FONT face=Arial color=#0000ff
size=2> <SPAN
class=884500616-17012008> transaction.commit()</SPAN><BR>
def getColor(self):<BR> return
self.color</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2>class
User(Persistent):<BR> def
__init__(self):<BR>
pass<BR> def __setstate__(self,
state):<BR>
Persistent.__setstate__(self,
state)<BR> if not hasattr(self,
'color'):<BR>
print 'adding
color'<BR>
self.color = Color()<BR> def
getColor(self):<BR> return
self.color.getColor()<BR> def setColor(self,
color):<BR>
self.color.setColor(color)<BR>
transaction.commit()</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2>class
ZODB_TestCase(unittest.TestCase):<BR> def
setUp(self):<BR> storage =
FileStorage.FileStorage(TMP_DB)<BR>
self.db = DB(storage)<BR> conn =
self.db.open()<BR> dbroot =
conn.root()<BR> # Ensure that a
'userdb' key is present<BR> # in the
root<BR> if not
dbroot.has_key('userdb'):<BR>
from BTrees.OOBTree import
OOBTree<BR>
dbroot['userdb'] = OOBTree()<BR>
self.userdb = dbroot['userdb']</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff
size=2> self.id = 'amk'</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2> def
tearDown(self):<BR>
self.db.close()</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2> def
test_1_AddUser(self):<BR> print 'in
test1'<BR> newuser =
User()<BR> newuser.first_name =
'Andrew'; newuser.last_name =
'Kuchling'<BR> # Add object to the
BTree, keyed on the ID<BR>
self.userdb[self.id] = newuser<BR> #
Commit the change<BR>
transaction.commit()</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff
size=2> # setstate is not called after
the constructor<BR> assert not
hasattr(newuser, 'color')</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2> def
test_2_setstate(self):<BR> print 'in
test2'<BR> newuser =
self.userdb[self.id]<BR> # setstate is
called subsequently<BR> assert
hasattr(newuser, 'color')<BR> assert
newuser.getColor() == 'blue'<BR>
newuser.setColor('red')<BR> assert
newuser.getColor() == 'red'
</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2> def
test_3_persistence(self):<BR> print
'in test3'<BR> newuser =
self.userdb[self.id]<BR> assert
newuser.getColor() == 'red'</FONT></DIV>
<DIV> </DIV>
<DIV><FONT face=Arial color=#0000ff size=2>if __name__ ==
'__main__':<BR> import os<BR> if
os.path.exists(TMP_DB):<BR>
os.unlink(TMP_DB)<BR> unittest.main()</FONT></DIV>
<DIV> </DIV>
<DIV><SPAN class=884500616-17012008></SPAN><FONT face=Arial><FONT
color=#0000ff><FONT size=2>-<SPAN
class=884500616-17012008>------------------------------------------------------</SPAN></FONT></FONT></FONT><BR></DIV>
<DIV class=OutlookMessageHeader lang=en-us dir=ltr align=left>
<HR tabIndex=-1>
</DIV>
<DIV></DIV>
<DIV>Hi David,</DIV>
<DIV><FONT face=Arial color=#0000ff size=2></FONT><BR
class=webkit-block-placeholder></DIV>
<DIV>It looks like you might be assuming that the tests run in the order</DIV>
<DIV>you wrote them. The test_persistence() function actually gets called</DIV>
<DIV>before the test_setstate(), so there is no chance for the color
to be 'red'.</DIV>
<DIV><FONT face=Arial color=#0000ff size=2></FONT><BR></DIV>
<DIV>I don't think the failure of this particular test has anything to do
with </DIV>
<DIV>your __setstate__() method. When I write __setstate__()
methods,</DIV>
<DIV>though, I modify the state dictionary and then call
Persistent.__setstate__. </DIV>
<DIV>This avoids triggering the persistent attribute machinery at
all.</DIV>
<DIV><FONT face=Arial color=#0000ff size=2></FONT><BR></DIV>
<DIV>David Binger</DIV>
<DIV><FONT face=Arial color=#0000ff size=2></FONT><BR></DIV>
<DIV>
<DIV><FONT face=Arial color=#0000ff
size=2></FONT> </DIV></DIV></BODY></HTML>