[ZODB-Dev] Persistent sub-objects: noob question

Steve Alexander steve at z3u.com
Sat Jan 24 12:58:37 EST 2004


> class Foo(Persistent):
>     def __init__(self):
>         self.bar = OOBTree()
> 
>     def store(self, key, value):
>         self.bar[value] = key
>         self._p_changed = 1  # redundant

Let's say you have a dict instead. In this case, you will need to prod 
_p_changed. However, you should do it before mutating the object, not 
afterwards. So, you'd get something like this:


  class Foo(Persistent):
      def __init__(self):
          self.bar = {}

      def store(self, key, value):
          self._p_changed = 1
          self.bar[value] = key


The reason to set _p_changed before mutating the object is because if 
there is an exception raised after a mutation but before setting 
_p_changed, your persistnent object might stay around in the cache. That 
is, it would not be reloaded with fresh state.

Consider this example:

      def storeMany(self, keys, values):
          for key, value in zip(keys, values):
              self.bar[key] = value
          self._p_changed = 1  # This is too late!

What happens if I call the method as below?

   obj.storeMany(['fish', {}, 'fluid'], [6, 28, 496])

The method will raise a TypeError because dicts are unhashable. However, 
the entry 'fish': 6 will have been added to the dict. The ZODB will not 
realize that the object has effectively changed, so the object can stick 
around in the cache.


--
Steve Alexander




More information about the ZODB-Dev mailing list