_p_changed, was RE: [ZODB-Dev] Excellent overview of ODBMS and my take on ZODB

Jeremy Hylton jeremy@alum.mit.edu
Tue, 26 Feb 2002 18:14:29 -0500


> So what does this mean concretely. I don't modify
> objects in __getattr__, and I don't override
> __delattr__. Is it as simple as putting
>
> self._p_changed = 1
>
> in __setattr__ ? (I realize that I don't need to set it if
> the object isn't actually changed in __setattr__.)
>
> Is this all I need to think about? (Well, on this issue I
> mean.)

I haven't followed the whole thread, but I think this is not right.  The
__getattr__() and __setattr__() methods in the Persistence base class
already track access to individual attributes.  The __setattr__() hook will
set _p_changed for you.

The problem comes when an object has a reference to another non-persistent
object.  If you modify a non-persistent subobject, you need to explicitly
notify the persistent parent that its child changed.  For example:

class Menu(Persistent):
    def __init__(self):
        self.dishes = []

If you write a method that modifies the dishes attribute, __setattr__()
won't be called.  The modification is handled entirely by the list object.
So you need to set _p_changed explicitly.

    def addDish(self, dish):
        self.dishes.append(dish)
        self._p_changed = 1

Jeremy