[Zope] Bug with External Methods and default params?

Martijn Faassen M.Faassen@vet.uu.nl
Tue, 23 Feb 1999 16:56:56 +0100


amos wrote:

I did some research and also installed Zope 1.10; the DTML Documents
that support properties have my special interest here. So, another
reply:

> The answer to question 1 is that External Methods are slightly weird
> methods which when called from variable expressions in DTML need to
> explicitly be passed the self argument if they define one. For example:
> 
> def myMethod(self, foo, bar):
>   "blah blah"
>   ...
> 
> will not work correctly is called like so:
> 
> <!--#var "myMethod('foo','bar')"-->
> because this assigns 'foo' to self and 'bar' to foo and nothing to
> 'bar'.

This doesn't appear to be the case? See below.

> Instead you should do this:
> 
> <!--#var "myMethod(foo='foo',bar='bar')"-->
> 
> Or if you really want to pass self, you can choose a Zope object to pass
> (such as the parent Folder in the case of DTML methods or 'this()' in
> the case of other Zope objects.) For example here's one way to
> explicitly pass the self argument:
> 
> <!--#var "myMethod(this(),'foo','bar')"-->


I did some research with the following external method:

def blah(self, id):
    if hasattr(self, id):
        return "We know %s" % id
    else:
        return "We don't know %s" % id

Is this use of hasattr allowed, or discouraged? It seemed to work at
first, but now it's starting to confuse me to now end.

I made a folder. I defined the property 'prop_in_folder' in it. Then I
put a DTML method in it: 

  <!--#var standard_html_header-->

  <p><!--#var "blah('prop_in_folder')"--></p>
  <p><!--#var "blah(this(), 'prop_in_folder')"--></p>

  <!--#var standard_html_footer-->

The output of this DTML method is this:

  We know prop_in_folder

  We know prop_in_folder

My analysis: 'self' appears to be passed automatically; 'prop_in_folder'
is not assigned to 'self'. Alternatively passing this() works fine too.
Both ways pass as self the containing folder.

Then I made a DTML Document (as opposed to DTML method) in the same
folder. I also defined a property in the document, called 'prop_in_doc'.
The DTML of the DTML Document is the following:

  <!--#var standard_html_header-->

  <p><!--#var "blah('prop_in_doc')"--></p>
  <p><!--#var "blah('prop_in_folder')"--></p>
  <p><!--#var "blah(this(), 'prop_in_doc')"--></p>
  <p><!--#var "blah(this(), 'prop_in_folder')"--></p>

  <!--#var standard_html_footer-->

It gives the following output:

  We don't know prop_in_doc

  We know prop_in_folder

  We know prop_in_doc

  We don't know prop_in_folder

This is where confusion starts to get me. Apparently in the first cases
(when 'this()' is not passed, the self that is passed is the surrounding
Folder. In the second case, this() seems to pass the Document itself,
but somehow the Folder's property is not seen. This is odd, as folder
properties do propagate to DTML methods as well as subfolders (I just
tested this, yup, they do, both with and without passing this()). 

But apparently properties in surrounding folders *are* seen by DTML
Documents, as evidenced by this:

  <p><!--#var prop_in_folder--></p>

This works in a DTML document and gives me the (string) value of
'prop_in_folder'.

An added complication:

If I use explicit parameter naming in the DTML that calls blah(), like
this:

  <!--#var "blah('id=prop_in_doc')"-->

it results in an error message.

Yet another complication is the use of default parameters in the
external method (as mentioned earlier).

It would be useful if there was some explanation for all this behavior.
It is confusing me a lot. :)

The behavior I think I expect is (I'm not sure if I *want* this
behavior; there are probably caveats which make it impossible?):

If the external method has as first parameter 'self', then, pass 'self'
(either the document or the surrounding folder) silently and
automatically. For both documents and folders, this 'self' should
propagate properties etc the same way. In summary, it all works the same
way as Python methods do, and documents and folders are in the
equivalent of an inheritance tree so that 'self' always shares the
attributes of its containing folders.

If the external method doesn't use the parameter 'self', then treat it
as a Python function.

Anyway, I'm waiting eagerly for explanations. Even a "Martijn, you
missed the blindingly obvious, and the obvious is X and X explains
everything like thus!" is welcome. :)

Regards,

Martijn