[Zope-CMF] __setattr__ in a persistent class
Gregoire Weber
gregweb@gmx.ch
Wed, 30 Jul 2003 01:55:15 +0200
Hi all!
Q: Somebody on the list, knowing how to intercept attribute=20
setting and getting with __setattr__ and __getattr__ in=20
a persistent subclass?
What I like to do:
I created a CMF content type named TransBag (a (semi)=20
transparent bag holding another content object) that=20
should hold other content object.=20
This should allow selective access (read and write) to=20
attributes of the content object (like title, description,=20
etc) and to the bag (like portal_type, workflow_history).
This selective access should be totally transparent for=20
existing CMF tools like portal_metadata etc.
I need this concept for the next versions of CMFCollection.
Some background about my investigations:
I searched all possible zope mailing list archives. Some=20
messages said, that it is extremly hard to do that (years=20
1999 and 2000 as I remember), others said that it is=20
possible to do that in some manner (from Zope 2.2 on, but=20
without info about how to do it). There were messages=20
stating that I should trigger the persistence mechanism=20
by setting self._p_changed =3D 1.
Unfortunately this doesn't seem to work fro persistent=20
objects.
I've stepped through the code with the pdb and recognized=20
that setting self._p_changed =3D 1 doesn't help. It seems=20
that self._p_changed is some kind of write protected.=20
Resulting in 0 (zero) after the write!
So writing is not persistent! arrrgh!
I'm totally stuck. I'm not a low level ZODB guru.
Can somebody point me in the right direction?=20
Alternative concepts to achieve the above goal?
Help and pointers would be apreciated! Thanks.
Sorry for the long e-mail. Below a simplified code snippet.
Gregoire
-------------------------------------------------------------
class TransBag(PortalContent, DefaultDublinCoreImpl):
"""Transparent Bag
**simplified code version**
Holds any arbitrary cmf content object. Allows attribute=20
specific read and write access policies.
"""
def __init__(self):
self.__dict__['_attrs'] =3D {}
# other stuff
def __setattr__(self, name, value):
"""Intercept attribute setting.
"""
if self._isDirectAccessAllowed(name): # '_blah' etc.
# set attribute to TransBag object
self.__dict__[name] =3D value
else:
# set attribute to '_attrs' dictionary to be able=20
# to intercept attribute reading with '__getattr__'
self.__dict__['_attrs'][name] =3D value
self._p_changed =3D 1=20
# also tried self.__dict__['_p_changed'] =3D 1
# --- reading _p_changed in pdb results in 0 ---
### tried also this: didn't work neither!
#attrs =3D self._attrs
#attrs[name] =3D value
#self.__dict__['_attrs'] =3D attrs
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]
=20
# without this aquisition would not work
raise AttributeError
# etc.
_____________________________________
Gr=E9goire Weber
mailto:gregoire.weber@switzerland.org