[Zope] Re: [Zope-CMF] Persistent dictionaries
Tres Seaver
tseaver@palladion.com
Fri, 24 Aug 2001 07:53:04 -0400
Thomas Olsen wrote:
> Hi
>
> I'm working on a CMF Product which is based on PortalFolder and
> PortalContent. This Folderish object contains some items which inherits from
> OFS.SimpleItem.Item, Persistence.Persistent and Aquisition.Implicit.
> These items have (had) some properties which are speciel to their class. In
> order to get around the problem with adding new attributes and having
> instantiated objects which doesn't have the attributes I decided to keep the
> attributes in a dictionary. So in my base class I did:
>
> ---snip--------------------------------------------
> class AbstractElement(Persistent, Item, Implicit):
> """ Abstract base class for Element objects. """
> _attributes = PersistentMapping()
>
> def __getattr__(self, name):
> if self._attributes.has_key(name):
> return self._attributes[name]
> else:
> raise AttributeError, name
> ---snip--------------------------------------------
Note that this spelling make '_attributes' a "shared instance
attribute" (all instances of the class, or ony class derived
from it, will share the mapping. Normally, I would expect to
see the '_attibutes' assigned either in the initializer::
def __init__( self ):
self._attributes = PersistentMapping()
or else "lazily"::
_attributes = None;
def __getattr__( self, name ):
if self._attributes is None:
self._attributes = PersistentMapping()
if self._attributes.has_key( name ): #...
> and my derived classes look something like this:
>
> ---snip--------------------------------------------
> class TextElement(AbstractElement):
> """
> text element.
> """
> meta_type = 'Text Element'
>
> def __init__(self, id):
> self.id = id
> self._attributes = {'value':'','html':'','alignment':''}
>
> def edit(self, value, html, alignment):
> """ Update the properties """
> self._attributes['alignment'] = str(alignment)
> self._attributes['value'] = str(value)
> self._attributes['html'] = utils._format_stx(self.value)
> ---snip--------------------------------------------
>
> It works great - until the object gets unloaded from the memory :-(
>
> What am I doing wrong?
Note as well that plaing with '__getattr__' in the presence of
the acquisition machinery could be classifieds as Deep Voodoo (tm);
The canonical solution to your problem is to set a "shared" value
for the new attribute on the class, with an appropriate default;
instances which don't have the attribute in their own '__dict__'
will find it in the class. Where that solution is infeasible,
the pickling machinery offers the '__setstate__' hook, which is
called immediately on unpickling; you would *really* prefer not
to use this hook, but it is available.
Tres.
--
===============================================================
Tres Seaver tseaver@zope.com
Zope Corporation "Zope Dealers" http://www.zope.com