[Zope-CMF] __setattr__ in a persistent class

Chris Withers chrisw@nipltd.com
Thu, 31 Jul 2003 15:05:25 +0100


Gregoire Weber wrote:
> Hi all!
> 
> Q: Somebody on the list, knowing how to intercept attribute 
>    setting and getting with __setattr__ and __getattr__ in 
>    a persistent subclass?

A: Don't do this, explain what your problem is and fidn a better solution :-)


> What I like to do:
> 
>    I created a CMF content type named TransBag (a (semi) 
>    transparent bag holding another content object) that 
>    should hold other content object. 
> 
>    This should allow selective access (read and write) to 
>    attributes of the content object (like title, description, 
>    etc) and to the bag (like portal_type, workflow_history).
> 
>    This selective access should be totally transparent for 
>    existing CMF tools like portal_metadata etc.
> 
>    I need this concept for the next versions of CMFCollection.

Can you explain why? Not sure what CMFCollection does and don't quite grok the 
stuff above...

>    I've stepped through the code with the pdb and recognized 
>    that setting self._p_changed = 1 doesn't help. It seems 
>    that self._p_changed is some kind of write protected. 
>    Resulting in 0 (zero) after the write!

don't trust that. self._p_changed=1 definitely works, but is likely highyl 'magic'.

see inserts below...


>     def __setattr__(self, name, value):
>         """Intercept attribute setting.
>         """
>         if self._isDirectAccessAllowed(name): # '_blah' etc.
>             # set attribute to TransBag object
>             self.__dict__[name] = value

               self._p_changed = 1

>         else:
>             # set attribute to '_attrs' dictionary to be able 
>             # to intercept attribute reading with '__getattr__'
>             self.__dict__['_attrs'][name] = value
>             self._p_changed = 1

               self.__dict__['_attrs']._p_changed = 1

>     def __getattr__(self, name):
>         """Intercept attribute getting.
> 
>         Called if attribute does not exist on the object
>         (because intercepted in __setattr__ or aquired)
>         """
>         if name in self._attrs.keys():
>             return self._attrs[name]
>         
>         # without this aquisition would not work
>         raise AttributeError

           raise AttributeError,name

Hmmm... that said, I don't really understand what you're trying to do, so the 
above suggestions may be bogus...

Chris