Hi, Most of the time when someone complains about DTML syntax or the learning curve and so on, the answer is we should code our logic in python if we know this language. That's what I am trying to do because I love Python. However, many times I don't know how to import my logic in Zope. example: I wrote a very simple module MyTest.py: ################################## class SuperClass: def __init__(self): self.a='This is a in SuperClass' class MyClass(SuperClass): def __init__(self): SuperClass.__init__(self) self.b='This is b in Myclass' ################################## In the python interpreter I do the following things:
import MyTest import MyTest.MyClass t=MyTest.MyClass.MyClass() t.a 'This is a in SuperClass' t.b 'This is b in Myclass'
That's what I expected. Now I intall the package in zope. I make a ZClass which only Base class in MyClass. Its metatype is MyClassClass, so it appears on the popup menu near the Add button. But when I try to add an instance I get the following message: Error Type: TypeError Error Value: unbound method must be called with class instance 1st argument I guess that the problem is the line SuperClass.__init__(self) ==>however I don't understand why it works fine with the python interpreter and why not in Zope. Others behaviors of Zope: suppose i add the following line in the MyClass __init__ function: self.d='I am d' No problem when I run it with the interpreter: >>>t.d 'I am d' In zope: <dtml-var "MyClassInstance.d"> renders: Error Type: AttributeError Error Value: d I get the right value of d only with the new instances of MyClass. On the other hand if MyClass has a property sheet, all the instances are updated if change the property sheet. ==>So again, why these differences in the behavior of ZClass instances depending of which part we modify (the python Base Class or the Zope ZClass)? I really love Zope but I prefer code in python. However I hit often the wall when I try to put the pieces together. I think that speaking about documentation : clear API docs would be, for me the most important. What behavior could I expect from the differents parts of Zope. Example of docs I find useful with other 'languages': Python Library Reference Java API documentation
From: "Oscar Picasso" <picasso@videotron.ca>
Hi,
Most of the time when someone complains about DTML syntax or the learning curve and so on, the answer is we should code our logic in python if we know this language. That's what I am trying to do because I love Python.
However, many times I don't know how to import my logic in Zope.
example:
I wrote a very simple module MyTest.py: ################################## class SuperClass: def __init__(self): self.a='This is a in SuperClass'
class MyClass(SuperClass): def __init__(self): SuperClass.__init__(self) self.b='This is b in Myclass' ################################## In the python interpreter I do the following things:
import MyTest import MyTest.MyClass t=MyTest.MyClass.MyClass() t.a 'This is a in SuperClass' t.b 'This is b in Myclass'
That's what I expected. Now I intall the package in zope. I make a ZClass which only Base class in MyClass. Its metatype is MyClassClass, so it appears on the popup menu near the Add button.
But when I try to add an instance I get the following message:
Error Type: TypeError Error Value: unbound method must be called with class instance 1st argument
I guess that the problem is the line SuperClass.__init__(self)
==>however I don't understand why it works fine with the python interpreter and why not in Zope.
This is a side effect of using Extension Classes. From ExtensionClass.stx: Overriding methods inherited from Python base classes A problem occurs when trying to overide methods inherited from Python base classes. Consider the following example:: from ExtensionClass import Base class Spam: def __init__(self, name): self.name=name class ECSpam(Base, Spam): def __init__(self, name, favorite_color): Spam.__init__(self,name) self.favorite_color=favorite_color This implementation will fail when an 'ECSpam' object is instantiated. The problem is that 'ECSpam.__init__' calls 'Spam.__init__', and 'Spam.__init__' can only be called with a Python instance (an object of type '"instance"') as the first argument. The first argument passed to 'Spam.__init__' will be an 'ECSpam' instance (an object of type 'ECSPam'). To overcome this problem, extension classes provide a class method 'inheritedAttribute' that can be used to obtain an inherited attribute that is suitable for calling with an extension class instance. Using the 'inheritedAttribute' method, the above example can be rewritten as:: from ExtensionClass import Base class Spam: def __init__(self, name): self.name=name class ECSpam(Base, Spam): def __init__(self, name, favorite_color): ECSpam.inheritedAttribute('__init__')(self,name) self.favorite_color=favorite_color This isn't as pretty but does provide the desired result. -- Another way, and I used this, is by bypassing the method binding, by accessing the unbound method. The above example could also be: def __init__(self, name, favorite_color): ECSpam.__init__.im_func(self, name) self.favorite_color=favorite_color
Others behaviors of Zope: suppose i add the following line in the MyClass __init__ function: self.d='I am d'
No problem when I run it with the interpreter:
t.d 'I am d'
In zope: <dtml-var "MyClassInstance.d"> renders: Error Type: AttributeError Error Value: d
I get the right value of d only with the new instances of MyClass. On the other hand if MyClass has a property sheet, all the instances are updated if change the property sheet.
==>So again, why these differences in the behavior of ZClass instances depending of which part we modify (the python Base Class or the Zope ZClass)?
The propertysheet variables become class variables, which are persisted as well. So when you retrieve an instance, the persisted class that described the behaviour of that instance is taken from the ZODB, and the new persisted class has the .d attribute there. In your python class however, .d is a instance variable, it gets set when a new instance is created and __init__ is called. And exisiting instances don't get __init__ called again, after all they were initialized already. They only get their current state restored, and that state never included the d attribute. Only on new instances, where __init__ is called, does d get set. You could get around this by making d a class variable, by adding d='I am d' to you class definition. Alternatively, you could use the __setstate__ method, it is called when the instance is retrieved from the ZODB. It revives the state of the object, and you'll have to remember to call Persitant.__setstate__ as well: def __setstate__(self, state): Persistent.__setstate__(self, state) if not hasattr(self, 'd'): self.d = 'I am d'
I really love Zope but I prefer code in python. However I hit often the
wall
when I try to put the pieces together. I think that speaking about documentation : clear API docs would be, for me the most important. What behavior could I expect from the differents parts of Zope.
Example of docs I find useful with other 'languages': Python Library Reference Java API documentation
We are working on this. Two projects that will work towards solving this: http://www.zope.org/Members/Amos/Documentation/Plan http://www.zope.org/Members/michel/Projects/Interfaces/FrontPage Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ | The Open Source Web Application Server ---------------------------------------------
participants (2)
-
Martijn Pieters -
Oscar Picasso