I have a Python Product that I'm developing. During the course of development, I want to add a new attribute. All new instances get this attribute, as it is defined with a default value in the constructor.
In addition, all instances that get edited via the web get the attribute, as the edit-processing method is defined to have a default value for this attribute.
Is there any way of interacting with the ZODB persistence machinery to add the default attribute to all instances as they are brought out of persistent storage -- so that I can just restart Zope, and have all of my instances updated as I use them ?
I can't find the right method or whatever in the ZODB on-line docs, or in the source.
Steve, The "best way" to do this is to define the new attribute (with its default value) as a class attribute. That way when you ask for the attribute on old instances you'll get the default value found in the class. If you change the attribute (through the web or whatever), the changed attribute will be saved *in the instance*. That way you don't even have to bother setting a default in the constructor (though it won't really hurt anything to do so). For example: # old class class Spam: """A spam object""" def cook(self): return 'cooked!' # new class - we want to add a 'color' attribute that defaults # to 'pink' and to be able to change the color, but we need old # instances to support this too. class Spam: """A spam object""" def cook(self): return 'cooked!' # class attribute - doing a getattr on 'color' will find # this for old instances. color='pink' def setColor(self, color='green'): # if this is called, the color attr will be saved in the # *instance*. The class default will not change. self.color=color Note that there is one caveat to this approach - if the attr that you want a default for is a _mutable_ Python object (like a dict or list), then you have to be careful not to modify the class attribute directly. In those cases you need to do a little more work: class Spam: """A spam object""" # A dict of spam flavors. flavors={} def addFlavor(self, name, desc): # We have to be careful here. We can't just say # 'self.flavors[name]=desc', because if we are an old # instance then self.flavors will give us the 'flavors' # *class attribute*. We don't want to mutate that, what # we really want to do is create flavors as an instance # attribute if we are getting the default. # set dict to either the 'flavors' from the _instance_ or # a fresh new dictionary. dict=self.__dict__.get('flavors', {}) # add the entry dict[name]=desc # this is important - the Zope persistence machinery can't # automatically know about changes to mutable builtin Python # types like dictionaries, so we have do a setattr on self # to make sure the changes to the dictionary are saved! self.flavors=dict Hope this helps! Brian Lloyd brian@digicool.com Software Engineer 540.371.6909 Digital Creations http://www.digicool.com