I have done work on a couple of products and one thing I've noticed is if you change what is done in the __init__ method of an object there isn't a good way to make the change so that it takes effect on old instances of the object. For example: def init(self): self.data.append('cow') becomes: def init(self): self.data.append('cow') self.data.append('horse') things created with the first constructor must be removed and recreated if 'horse' is to be added. Is there a way to go through and update old instances of a product to a newer version? Or should backwards compatibility be designed into the product? Thanks, --Brian
You either need to account for older-state objects in your code or you need to manually upgrade instances of your objects. There's no standard way to do the latter. ----- Original Message ----- From: "brian.r.brinegar.1" <brinegar@purdue.edu> To: <zope-dev@zope.org> Sent: Tuesday, January 22, 2002 5:37 PM Subject: [Zope-dev] Product upgrades
I have done work on a couple of products and one thing I've noticed is if you change what is done in the __init__ method of an object there isn't a good way to make the change so that it takes effect on old instances of the object. For example:
def init(self): self.data.append('cow')
becomes:
def init(self): self.data.append('cow') self.data.append('horse')
things created with the first constructor must be removed and recreated if 'horse' is to be added. Is there a way to go through and update old instances of a product to a newer version? Or should backwards compatibility be designed into the product?
Thanks, --Brian
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
...and, this is a good argument for hiding the data in your objects' attributes, and only accessing that data through method calls. Encapsulation and data hiding. Chris McDonough wrote:
You either need to account for older-state objects in your code or you need to manually upgrade instances of your objects. There's no standard way to do the latter.
----- Original Message ----- From: "brian.r.brinegar.1" <brinegar@purdue.edu> To: <zope-dev@zope.org> Sent: Tuesday, January 22, 2002 5:37 PM Subject: [Zope-dev] Product upgrades
I have done work on a couple of products and one thing I've noticed is if you change what is done in the __init__ method of an object there isn't a good way to make the change so that it takes effect on old instances of the object. For example:
def init(self): self.data.append('cow')
becomes:
def init(self): self.data.append('cow') self.data.append('horse')
things created with the first constructor must be removed and recreated if 'horse' is to be added. Is there a way to go through and update old instances of a product to a newer version? Or should backwards compatibility be designed into the product?
Thanks, --Brian
-- Steve Alexander
On Tue, 2002-01-22 at 21:20, Steve Alexander wrote:
...and, this is a good argument for hiding the data in your objects' attributes, and only accessing that data through method calls. Encapsulation and data hiding.
ComputedAttributes also help in this: it looks like an attribute, but is actually a method!! :-) Cheers, Leo
On 1/22/02 7:22 PM, "Leonardo Rochael Almeida" <leo@hiper.com.br> wrote:
On Tue, 2002-01-22 at 21:20, Steve Alexander wrote:
...and, this is a good argument for hiding the data in your objects' attributes, and only accessing that data through method calls. Encapsulation and data hiding.
ComputedAttributes also help in this: it looks like an attribute, but is actually a method!! :-)
And then there's the happy world of 'properties' in Python 2.2. Mmm. -- Jeffrey P Shell www.cuemedia.com Sent using the Entourage X Test Drive.
From: "Jeffrey P Shell" <jeffrey@cuemedia.com>
And then there's the happy world of 'properties' in Python 2.2. Mmm.
Ah! Lovely! Thats one thing I have really missed in python! I'm longing for Zope 2.5.0 so we can start porting our CMS system to it! 2.3.3 is starting to be a pain.
On Wed, 2002-01-23 at 11:55, Chris Withers wrote:
Jeffrey P Shell wrote:
And then there's the happy world of 'properties' in Python 2.2. Mmm.
?
Didn't hear about this... where can I read?
http://www.amk.ca/python/2.2/index.html#SECTION000340000000000000000 seb
Chris Withers wrote:
Jeffrey P Shell wrote:
And then there's the happy world of 'properties' in Python 2.2. Mmm.
?
Didn't hear about this... where can I read?
http://www.amk.ca/python/2.2/ section 2.4, Attributes -- Steve
...and, this is a good argument for hiding the data in your objects' attributes, and only accessing that data through method calls. Encapsulation and data hiding.
Steve, I don't suppose you could explain in a bit more detail what you mean here. I'm slightly struggling to get my head around the finer points of OO programming (it'd be fair to say I've only really used python in a procedural way so far). How does what you describe above help to get around the problem of an old instance being constructed with the old __init__ not having the same attributes as the new instances? Don't suppose you could give me an example? :-) cheers tim
On Wed, 2002-01-23 at 09:32, Tim Hicks wrote:
...and, this is a good argument for hiding the data in your objects' attributes, and only accessing that data through method calls. Encapsulation and data hiding.
Steve,
I don't suppose you could explain in a bit more detail what you mean here. I'm slightly struggling to get my head around the finer points of OO programming (it'd be fair to say I've only really used python in a procedural way so far). How does what you describe above help to get around the problem of an old instance being constructed with the old __init__ not having the same attributes as the new instances? Don't suppose you could give me an example? :-)
Basically, if you want to have a new attribute, say, myNewAttribute, instead of doing:: class SomeClass(...): def __init__(self,...): ... self.myNewAttribute = something... you do:: class SomeClass(...): _myNewAttribute = None def myNewAttribute(self): if self._myNewAttribute is None: self._myNewAttribute = something return self._myNewAttribute Of course this means that you can only access it as 'self.myNewAttribute()' instead of 'self.myNewAttribute', because you never know when it will already be initialized. Actually, you can know when it is not initialized, because it will be None, but resist the temptation and let myNewAttribute() do it for you. That's what encapsulation is for. You don't have to worry about updating old versions because, if the old instance doesn't have _myNewAttribute then it will be taken from the class. And the myNewAttribute() method will always be taken from the class anyway (even for old versions of your object). Cheers, Leo -- Ideas don't stay in some minds very long because they don't like solitary confinement.
<snip>
Basically, if you want to have a new attribute, say, myNewAttribute, instead of doing::
class SomeClass(...):
def __init__(self,...): ... self.myNewAttribute = something...
you do::
class SomeClass(...):
_myNewAttribute = None
def myNewAttribute(self):
if self._myNewAttribute is None: self._myNewAttribute = something
return self._myNewAttribute
Of course this means that you can only access it as 'self.myNewAttribute()' instead of 'self.myNewAttribute', because you never know when it will already be initialized. Actually, you can know when it is not initialized, because it will be None, but resist the temptation and let myNewAttribute() do it for you. That's what encapsulation is for.
You don't have to worry about updating old versions because, if the old instance doesn't have _myNewAttribute then it will be taken from the class. And the myNewAttribute() method will always be taken from the class anyway (even for old versions of your object).
Leo, thanks very much. That was just what I was after. much appreciated tim
Chris McDonough wrote:
You either need to account for older-state objects in your code or you need to manually upgrade instances of your objects. There's no standard way to do the latter.
Well, I did write something which makes it a bit easier: http://www.zope.org/Members/chrisw/UpdateSupport/ cheers, Chris
brian.r.brinegar.1 wrote: things created with the first constructor must be removed and recreated if 'horse' is to be added. Is there a way to go through and update old instances of a product to a newer version? Or should backwards compatibility be designed into the product? Generally Zope uses pickle to save the objects. And pickel will not save the methods, nor the class attributes:: class Person: meta_type = 'person' def __init__(self): self.name = 'Max Rasmussen' def hello(self, text): print 'hello %s' % text In this class '__init__()', 'hello()' and 'meta_type' will be automatically updated whenever you update you class, as they are shared globally. But the 'self.name' attribute is part if the object instance, not the class. So it will be saved in the ZODB. If you then want to change you object so that it has firstName and lastName attributes you must do it manually. Write an external script that walks through the objects one by one and then changes the attributes:: def updatePersons(self): # the ZopeFind() methods finds all of the objects with a given metatype # or other attributes. # It is defined in <zopesite>\lib\python\OFS\FindSupport.py persons = self.ZopeFind(self, obj_metatypes=['person'], search_sub=1) for person in persons: person.firstName = '' person.lastName = '' del(person.name) def updatePersons(self): # Or if you want to use the name value to create first and last name from from string import rfind persons = self.ZopeFind(self, obj_metatypes=['person'], search_sub=1) for person in persons: lastSpace = rfind(person.name, ' ') fName, lName = person.name[:lastSpace], person.name[lastSpace+1:] person.firstName = fName person.lastName = lName del(person.name) So as you can see, it is really hard to make a standard way of updating a product. But it is actually not hard to write a method to do it for you. But one thing that I wonder about is how do the rest of you make shure that you old products are updated? Shouldn't there be some kind of hook in Zope that calls an update method if it was present, and the version has changed? regards Max M
On Wed, 23 Jan 2002, Max M wrote:
Generally Zope uses pickle to save the objects. And pickel will not save the methods, nor the class attributes::
I'm surprised to have seen no mention of __setstate__ in this thread. Is doing simple upgrade-on-the-fly via __setstate__ now considered Bad Form? --RDM
participants (11)
-
brian.r.brinegar.1 -
Chris McDonough -
Chris Withers -
Jeffrey P Shell -
Lennart Regebro -
Leonardo Rochael Almeida -
Max M -
R. David Murray -
seb bacon -
Steve Alexander -
Tim Hicks