[Zope] Bug with External Methods and default params?

Martijn Faassen M.Faassen@vet.uu.nl
Tue, 23 Feb 1999 10:24:58 +0100


amos wrote:
> 
> Paul Everitt wrote:
> >
> > Martijn Faassen wrote:
> > >
> > > Martijn Faassen wrote:
> > > >
> > > > Stefan Franke wrote:
> > > [description of weird behavior/bug with default parameters in external
> > > methods]
> 
> I believe your questions are:
> 
> 1. Why is it tricky to call External Methods with variable expressions
> from DTML?

It's definitely tricky, but I'm not quite sure what I don't understand.
:)

> 2. Why do some REQUESTs have AUTHENTICATED_USERs and some don't?

No, this wasn't my question, but this did come up in a thread somewhere
involving REQUEST, to which I replied.

> 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'.

Are you sure? The external method:

def test4(self, foo, bar):
    return "%s %s" % (foo, bar)

Returns 'one two' when I call it like this:

<!--#var "test4('one', 'two')"-->

Also, this one:

def test1(self, foo):
    return "%s %s" % (self.REQUEST, foo)

when called with:
<!--#var "test1('bar')"-->

Returns a whole slew of REQUEST info, and then 'bar'.

I'm now even more confused. :)

However:

def test0(self, foo="foo"):
    return "%s %s" % (self.REQUEST, foo)

Gives an error when called like that. The page won't load at all:

<!--
 Error type:  
 Error value: read-only buffer, class
 -->

> Instead you should do this:
> 
> <!--#var "myMethod(foo='foo',bar='bar')"-->

Okay, this explains at least something, though I'm even more confused
why the previous *did* work as expected (except in the default argument
case):

<!--#var "test0()"-->

gives me a mess of REQUEST data and 'foo'.

while:

<!--#var "test0(foo="bar")-->

gives me the same and then 'bar'.

But 'self' is still definitely being passed, right?

> 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')"-->

But self was already passed just fine automatically, I thought...

From my (limited) perspective it still looks as if all works just as
expected (in the Python sense), *except* when I use default parameters
in the external methods, and only then when I don't use the explicit
"foo='bar'" method of parameter passing. Am I wrong in expecting it
should all work in a Pythonic way? 

> The answer to question 2 is that AUTHENTICATED_USER object is only
> present in the REQUEST object when the ORB puts it there. The ORB only
> puts it there when it has to perform authentication to publish the
> requested object. So if you are publishing a Document that is publicly
> viewable, the AUTHENTICATED_USER will not be set. As for the identity of
> the REQUEST as passed by the ORB when publishing a method, versus the
> acquired request (self.REQUEST) versus the REQUEST available in DTML,
> they should all be the same.

I *thought* this didn't confuse me, but now I am..Is AUTHENTICATED_USER
never set by documents that are publicly viewable? But, this trick seems
to work in publicly viewable docs:

<!--#call
"REQUEST.set('isManager',AUTHENTICATED_USER.hasRole(_.None,['Manager']))"-->

When one views (public) docs after having logged in as a manager now,
one can make the doc respond differently, such as:

<!--#if "isManager"-->
<p>I know you're the manager!</p>
<!--#/if-->

Does this mean AUTHENTICATED_USER is just not set in the *REQUEST*
object, but it is in the document itself?
 
> I hope this clears things up a bit.

Thank you for your reply, but no, it doesn't, really... I'm far more
confused now. :)

Perhaps I'm just bothered by my Python induced sense of how it *ought*
to work, but my tests seem to partially contradict what you explained..
(or at least show there is more going on than your explanation
indicates)

In any case, my 'typical user confusion' will hopefully enable you guys
to improve the documentation. :)

Regards,

Martijn