[Zope-dev] External Method Missery

Steve Alexander steve@cat-box.net
Wed, 12 Jul 2000 11:35:41 +0100


Chris Withers wrote:
> 
> I think this is a bgu so I'll chuck it into the collector unless someone
> tells me otherwise...
> 
> I have an external method called navTree (dtml-tree was too broken to
> fix in the time frame :( ) with a spec as follows:
> 
> def navTree(self,start):
> 
> It's called in some DTML as:
> 
> <dtml-var "nav_tree(PARENTS[-2])">
> 
> which is fine, unless I call it with the following:
> 
> <dtml-var "nav_tree(start=PARENTS[-2])">
> 
> in which case I get:
> TypeError: not enough arguments; expected 2, got 0
> 
> which is not very helpful :(
> 
> Any ideas?

Ok.

I debugged this by creating an external method to see what it is
actually receiving:

  def navtree(*arg, **kw):
    print 'navtree'
    print 'arg= ', arg
    print 'kw=  ', kw
    print


For  <dtml-var "navtree(PARENTS[-1])"> we get:
navtree
 arg=  (<Application instance at 858ac40>,)
 kw=   {}

For <dtml-var "navtree(start=PARENTS[-1])"> we get:
navtree
 arg=  ()
 kw=   {'start': <Application instance at 858ac40>}

That is, no "self" argument is getting passed.

Now, I change the external method to have a "self" argument first:

  def navtree(self, *arg, **kw):
    print 'navtree'
    print 'self=', self
    print 'arg= ', arg
    print 'kw=  ', kw
    print


For  <dtml-var "navtree(PARENTS[-1])"> we get:
 navtree
 self= <Application instance at 858ac40>
 arg=  ()
 kw=   {}

For <dtml-var "navtree(start=PARENTS[-1])"> we get:
 navtree
 self= <Folder instance at 8589ea0>
 arg=  ()
 kw=   {'start': <Application instance at 858ac40>}

So, in the first case, you're not getting the current context passed in,
but you are getting it in the second case.


One more try:

  def navtree(self, **kw):
    print 'navtree'
    print 'self=', self
    print 'kw=  ', kw
    print

For <dtml-var "navtree(PARENTS[-1])"> we get:
 navtree
 self= <Application instance at 858ac40>
 kw=   {}

For <dtml-var "navtree(start=PARENTS[-1])"> we get:
 navtree
 self= <Folder instance at 8589ea0>
 kw=   {'start': <Application instance at 858ac40>}


Looks like it is assumed that the first non-keyword argument should be
passed as the client (ie "self"). 



So, you can fix your exception by giving "start" a default value:

  def navTree(self,start=''):

However, you'll have to always use the keyword form of calling it:

  <dtml-var "nav_tree(start=PARENTS[-2])">

Or otherwise, provide a client for it:

  <dtml-var "nav_tree(this(), PARENTS[-2])">


As for why this is the case... I have other things to do this morning,
so I won't go rooting around in the DTML source just now. [ Although, it
sure is tempting :-) ]

--
Steve Alexander
Software Engineer
Cat-Box limited
http://www.cat-box.net