odd behavior when External Method calls DTML Method
I am experiencing some kind of acquisition problem when calling DTML Methods from External Methods In a nutshell, I have a dtml method: ---------------------(test1_dtml)--- <dtml-var URL> ------------------------------------ ...which renders fine when I view it using a web browser. When I test an external method which calls this DTML method, however, I get this traceback: Traceback (innermost last): File /usr/local/Zope-2.5.0-linux2-x86/lib/python/ZPublisher/Publish.py, line 150, in publish_module File /usr/local/Zope-2.5.0-linux2-x86/lib/python/ZPublisher/Publish.py, line 114, in publish File /usr/local/Zope-2.5.0-linux2-x86/lib/python/Zope/__init__.py, line 158, in zpublisher_exception_hook (Object: Test) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/ZPublisher/Publish.py, line 98, in publish File /usr/local/Zope-2.5.0-linux2-x86/lib/python/ZPublisher/mapply.py, line 88, in mapply (Object: test1) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/ZPublisher/Publish.py, line 39, in call_object (Object: test1) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/Products/ExternalMethod/External Method.py, line 202, in __call__ (Object: test1) (Info: ((<Folder instance at 89f8ac8>,), {}, None)) File /home/zope/2-5-0/lib/python/Products/Model/Extensions/XmlRpc.py, line 66, in Test_test1 (Object: Test) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/OFS/DTMLMethod.py, line 127, in __call__ (Object: test1_dtml) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/DocumentTemplate/DT_String.py, line 473, in __call__ (Object: test1_dtml) KeyError: URL This is the module containing the function for my External Method: --------------------(myModule.py)--- def test1( self ): return self.Test.test1_dtml( self ) ------------------------------------ Curiously, though my DTML Method '''<dtml-var URL>''' does not work, if I change it to '''<dtml-var "REQUEST.get('URL')">''' it works fine. ????? Thanks to any Acquisition Gurus who can explain this. Brian Withun ------------
[Brian Withun]
I am experiencing some kind of acquisition problem when calling DTML
Methods
from External Methods
In a nutshell, I have a dtml method:
---------------------(test1_dtml)--- <dtml-var URL> ------------------------------------
... File /usr/local/Zope-2.5.0-linux2-x86/lib/python/OFS/DTMLMethod.py, line 127, in __call__ (Object: test1_dtml) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/DocumentTemplate/DT_String.py, line 473, in __call__ (Object: test1_dtml) KeyError: URL
This is the module containing the function for my External Method:
--------------------(myModule.py)--- def test1( self ): return self.Test.test1_dtml( self ) ------------------------------------
Curiously, though my DTML Method '''<dtml-var URL>''' does not work, if I change it to '''<dtml-var "REQUEST.get('URL')">''' it works fine. ?????
This is not the correct way to write an external method. First of all, Python does not have a "self" parameter or property. The name is used, by convention, in defining classes, and has nothing to do with function definitions. Even though you may call it "self", it is just a parameter to be passed in like any other. You need to figure out what object reference to send to the external method. Remember, when you modify the external method, you have to save it again in the "properties" tab for the page of that method, otherwise Zope won't know about your changes. But you aren't passing any argument to the function - none is passed by default to an external method. So you should see an error "not enough arguments", which you don't. I can't say why "URL" is not being found - is that really the id of the external method? If it were defined in the parent page of the dtml method, that might explain why it wasn't found. If <dtml-var "REQUEST.get('URL')"> succeeds, as you say, it indicates that your REQUEST object has a 'URL' property, and has nothing to do with the external method. I would name your external method something else to be on the safe side - "URL" seems like it would be likely to have name collisions. Cheers, Tom P
I would name your external method something else to be on the safe side - "URL" seems like it would be likely to have name collisions.
There's no collision because I'm expecting to use the built-in REQUEST.URL. I tried to come up with a minimal reproducible example illustrating the error I am experiencing. I chose 'URL' specifically because it is ALWAYS available in the REQUEST object. It is not a method or object of my creation. Perhaps it would have been clearer if I chose a more obvious REQUEST attribute such as SERVER_URL... I think my question is better asked, "how do I call a DTML Method from an External Method?" Here is another attempt to illustrate my problem. I'm using REQUEST.SERVER_URL rather than REQUEST.URL, but it's the same behavior. ----------------------------(DMTL Method at /Test/test_dtml) <p> <dtml-var SERVER_URL> : <dtml-try> <dtml-var SERVER_URL> <dtml-except KeyError> didn't work - KeyError </dtml-try> </p> <p> <dtml-var "_['SERVER_URL']"> : <dtml-try> <dtml-var "_['SERVER_URL']"> <dtml-except KeyError> didn't work - KeyError </dtml-try> </p> <p> <dtml-var "REQUEST.SERVER_URL"> : <dtml-try> <dtml-var "REQUEST.SERVER_URL"> <dtml-except KeyError> didn't work - KeyError </dtml-try> </p> ----------------------------(end DTML Method) When I browse to http://myserver.com/Test/test_dtml, I see this: (as expected) <dtml-var SERVER_URL> : http://myserver.com <dtml-var "_['SERVER_URL']"> : http://myserver.com <dtml-var "REQUEST.SERVER_URL"> : http://myserver.com But when I browse to http://myserver.com/Test/test_method, I see this (unexplained) <dtml-var SERVER_URL> : didn't work - KeyError <dtml-var "_['SERVER_URL']"> : didn't work - KeyError <dtml-var "REQUEST.SERVER_URL"> : http://myserver.com Why does only the third expression syntax work? test_method is just an External Method which calls the same DTML Method: -------------------------(External Method at /Test/test_method) def Test_test1( self ): return self.Test.test1_dtml( self.XmlRpc.Test,self ) -------------------------(end External Method) ASIDE: It is my understanding that, when zope executes an External Method, the first argument is implicitly "self", which represents the Zope namespace. In my case, my external method is called with no arguments (via a browser), yet receives one implicit argument; the Zope. This allows the called External Method to access elements inside of Zope which it would otherwise not be able to do. So I call a DTML Method inside of the Zope (from the External Method) by accessing self.Test.test1_dtml. "self" represents the zope application and ".Test" represents the Test folder, and ".test1_dtml" represents my DTML Method within that folder. Once there, however, Zope doesn't seem to be traversing the _existing_ REQUEST object for names. I get a KeyError while accessing a variable that I _know_ is in the REQUEST. The sample code above pretty much proves that (at least to me). Why does <dtml-var "REQUEST.SERVER_URL"> work when <dtml-var SERVER_URL> does not? I hope I've made it more clear this time :-) Brian Withun AIM: BHWITHUN Y! Messenger: BHWITHUN -----Original Message----- From: zope-admin@zope.org [mailto:zope-admin@zope.org]On Behalf Of Thomas B. Passin Sent: Wednesday, April 17, 2002 11:36 AM To: Zope mailing list Subject: Re: [Zope] odd behavior when External Method calls DTML Method [Brian Withun]
I am experiencing some kind of acquisition problem when calling DTML
Methods
from External Methods
In a nutshell, I have a dtml method:
---------------------(test1_dtml)--- <dtml-var URL> ------------------------------------
... File /usr/local/Zope-2.5.0-linux2-x86/lib/python/OFS/DTMLMethod.py, line 127, in __call__ (Object: test1_dtml) File /usr/local/Zope-2.5.0-linux2-x86/lib/python/DocumentTemplate/DT_String.py, line 473, in __call__ (Object: test1_dtml) KeyError: URL
This is the module containing the function for my External Method:
--------------------(myModule.py)--- def test1( self ): return self.Test.test1_dtml( self ) ------------------------------------
Curiously, though my DTML Method '''<dtml-var URL>''' does not work, if I change it to '''<dtml-var "REQUEST.get('URL')">''' it works fine. ?????
This is not the correct way to write an external method. First of all, Python does not have a "self" parameter or property. The name is used, by convention, in defining classes, and has nothing to do with function definitions. Even though you may call it "self", it is just a parameter to be passed in like any other. You need to figure out what object reference to send to the external method. Remember, when you modify the external method, you have to save it again in the "properties" tab for the page of that method, otherwise Zope won't know about your changes. But you aren't passing any argument to the function - none is passed by default to an external method. So you should see an error "not enough arguments", which you don't. I can't say why "URL" is not being found - is that really the id of the external method? If it were defined in the parent page of the dtml method, that might explain why it wasn't found. If <dtml-var "REQUEST.get('URL')"> succeeds, as you say, it indicates that your REQUEST object has a 'URL' property, and has nothing to do with the external method. I would name your external method something else to be on the safe side - "URL" seems like it would be likely to have name collisions. Cheers, Tom P _______________________________________________ Zope maillist - Zope@zope.org http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )
Thomas B. Passin writes:
def ExternalMethod(self): .... This is not the correct way to write an external method. First of all, Python does not have a "self" parameter or property. The name is used, by convention, in defining classes, and has nothing to do with function definitions. Even though you may call it "self", it is just a parameter to be passed in like any other. What you say is right for normal Python function but *wrong* for External Methods!
External Methods have some calling magic that depends on the name of the first parameter. It must be "self" for the magic to apply. You find a description in the "External Method" section of <http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html>
.... I can't say why "URL" is not being found ... It because the DTML object has only one of its two positional arguments. "self.request" should be the second.
Explanation in the "Calling DTML objects" of <http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html> Dieter
[Dieter Maurer]
Thomas B. Passin writes:
def ExternalMethod(self): .... This is not the correct way to write an external method. First of all, Python does not have a "self" parameter or property. The name is used, by convention, in defining classes, and has nothing to do with function definitions. Even though you may call it "self", it is just a parameter to be passed in like any other. What you say is right for normal Python function but *wrong* for External Methods!
External Methods have some calling magic that depends on the name of the first parameter. It must be "self" for the magic to apply.
Yes, I went and looked at the description after posting my reply. It was clear from his reply that the original poster knew it, too - at least he wasn't expecting normal Python behavior for a function def, which is what I had originally assumed he was thinking.
You find a description in the "External Method" section of
<http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html>
Even the help material that comes with Zope talks about it. Tom P
Brian Withun writes:
I am experiencing some kind of acquisition problem when calling DTML Methods from External Methods
In a nutshell, I have a dtml method:
---------------------(test1_dtml)--- <dtml-var URL> ------------------------------------
...which renders fine when I view it using a web browser. When I test an external method which calls this DTML method, however, I get this traceback:
Traceback (innermost last): .... line 473, in __call__ (Object: test1_dtml) KeyError: URL
This is the module containing the function for my External Method:
--------------------(myModule.py)--- def test1( self ): return self.Test.test1_dtml( self ) ------------------------------------
Please read "Calling DTML objects" in <http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html> The second parameter "self.REQUEST" is missing... Dieter
participants (3)
-
Brian Withun -
Dieter Maurer -
Thomas B. Passin