[Zope] update existing instances of a class?

Paul Winkler pw_lists at slinkp.com
Sun Sep 12 16:10:59 EDT 2004


On Sat, Sep 11, 2004 at 06:06:55PM -0700, John Schinnerer wrote:
> For example:
> I have updated my python product code by adding properties to a class.
> I have refreshed the product via the ZMI.
> If I then go to an instance of the class created *before* the property
> additions and refresh, and click on the Properties tab, I get an
> attribute error.
> The error is generated in PropertyManager.py, on a call to getProperty.
> The error value is the name of the first property that is *not* present
> in the "old" instance of the class (any instance created before adding
> properties to the product and refreshing).
> 
> So it doesn't appear to me that "old" instances automagically get the
> new properties, since they generate an attribute error when trying to
> access the first of the new properties.

If it was just a vanilla attribute and not a Property, you could
get away with having a default immutable value in the class,
e.g.

class Foo:
    new_property_id = 0
    ...

But there are two things the PropertyManager implementation does
when you add a property:
1) it sets an attribute with the property's id.
2) it adds an entry to the instance's _properties dictionary (which
is a mapping of property id to type).

If _properties does not contain this entry, then getProperty(foo)
will raise an error as you've noticed.

This means that you really do need to touch all instances
if you want them all to get a new property.
 
> That is my question - is there any way to 'touch' the old instances so
> that they get the new properties?

There are two:

1) write some lazy auto-updating code in one of your class methods.
e.g. (pseudocode):

    def getProperty(self, id, default=None):
        """ get the property"""
        if id in [list of the properties i'm adding]:
            if not self.hasProperty(id):
                self.setProperty(id, some_default_value)
        return PropertyManager.getProperty(self, 

The nice thing about this code is that it works "on demand".
The problem is that you can never get rid of it unless you
are sure you have asked for all relevant properties from all
existing instances. In which case you might as well go to 
option 2.

2) write a Script that uses ZopeFind to find all instances
of your class and call setProperty() on each of them.
Run this script once and you're done.
This is what I've always done.
I think there are examples on zopelabs.com.

-- 

Paul Winkler
http://www.slinkp.com


More information about the Zope mailing list