Re: [Zope-dev] External Method Missery

2000-07-13 Thread Chris Withers

Shane Hathaway wrote:
 Here's the logic: ExternalMethod sets up func_* attributes so it can
 masquerade as a function.  The trick works well enough to convince
 ZPublisher's mapply() to pass in a "self" argument as the first
 argument when needed.

What 'self' does mapply pass? I always though it would be the object
being rendered (the one that would appear before PARENTS[0] in PARENTS
if such a thing were possible ;-) but it appears to in fact be
PARENTS[0].

...which seems silly

So, apparently I have to pass this() to my external method to find out
what object I'm working on, which is a shame :(

My code which prepares a list of object that are in the URL path (does
this mean the objects that have been traveresed?) now looks like:

def navTree(self,startlevel,this):
# strip off acquisition wrappers, reverse the list... yum yum ;-)
objects = map(lambda o : getattr(o, 'aq_base',
o),self.REQUEST.PARENTS[:-startlevel])
objects.reverse()
objects.append(getattr(this, 'aq_base', this))

...which doesn't give quite what I want
objects[-1] should be the object getting rendered, however, for folders
getting rendered where index_html is a DTML document, it is the
index_html document.

I guess what I'm asking is, from PARENTS and this(), is there any way I
can tell when I'm rendering folder/ as opposed to folder/index_html?

If I can't, then how should I do this?

cheers,

Chris

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




Re: [Zope-dev] External Method Missery

2000-07-13 Thread Chris Withers

Steve Alexander wrote:
 Ah... but are you calling the external method from a DTML method? These
 are all methods, and therefore you'd expect the "self" object to be the
 object the methods are subobjects of.

The exact turn of events is that index_html is a DTML method which shows
a DTML _document_ with dtml-var doc_name

The header, in which the navtree is rendered, is a DTML method that's
called from the doc_name DTML document with another dtml-var

navtree is a DTML method which calls the external method.

So unravel all that, and you can decide for yourself ;-)

See my reply to my own posting which poses another interesting question.

It'd be nice to have some way of finding whether the object being
rendered to the browser is the result of rendering a DTML method _on_
the object or just the object itself...

cheers,

Chris

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




[Zope-dev] External Method Missery

2000-07-12 Thread Chris Withers

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?

cheers,

Chris

PS:
Traceback (innermost last):
  File /mnt/data/2/zope/external/2-1-6/lib/python/ZPublisher/Publish.py,
line 214, in publish_module
  File /mnt/data/2/zope/external/2-1-6/lib/python/ZPublisher/Publish.py,
line 179, in publish
  File /mnt/data/2/zope/external/2-1-6/lib/python/Zope/__init__.py, line
202, in zpublisher_exception_hook
(Object: ElementWithAttributes)
  File /mnt/data/2/zope/external/2-1-6/lib/python/ZPublisher/Publish.py,
line 165, in publish
  File /mnt/data/2/zope/external/2-1-6/lib/python/ZPublisher/mapply.py,
line 160, in mapply
(Object: index_html)
  File /mnt/data/2/zope/external/2-1-6/lib/python/ZPublisher/Publish.py,
line 102, in call_object
(Object: index_html)
  File /mnt/data/2/zope/external/2-1-6/lib/python/OFS/DTMLMethod.py,
line 150, in __call__
(Object: index_html)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_String.py,
line 502, in __call__
(Object: index_html)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_Util.py,
line 335, in eval
(Object: _[REQUEST['lang']])
(Info: REQUEST)
  File lt;stringgt;, line 0, in ?
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_Util.py,
line 161, in careful_getitem
  File /mnt/data/2/zope/external/2-1-6/lib/python/OFS/DTMLDocument.py,
line 162, in __call__
(Object: en)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_String.py,
line 502, in __call__
(Object: en)
  File /mnt/data/2/zope/external/2-1-6/lib/python/OFS/DTMLMethod.py,
line 146, in __call__
(Object: standard_html_header)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_String.py,
line 502, in __call__
(Object: standard_html_header)
  File /mnt/data/2/zope/external/2-1-6/lib/python/OFS/DTMLMethod.py,
line 146, in __call__
(Object: left_menu)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_String.py,
line 502, in __call__
(Object: left_menu)
  File
/mnt/data/2/zope/external/2-1-6/lib/python/DocumentTemplate/DT_Util.py,
line 335, in eval
(Object: nav_tree(start=PARENTS[-2]))
(Info: PARENTS)
  File lt;stringgt;, line 0, in ?
  File
/mnt/data/2/zope/external/2-1-6/lib/python/Products/ExternalMethod/ExternalMethod.py,
line 248, in __call__
(Object: nav_tree)
(Info: ((), {'start': lt;Folder instance at 86d4de0gt;}, None))

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




Re: [Zope-dev] External Method Missery

2000-07-12 Thread Steve Alexander

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

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




Re: [Zope-dev] External Method Missery

2000-07-12 Thread Shane Hathaway

Steve Alexander wrote:
 
 Chris Withers wrote:
  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
 
 So, in the first case, you're not getting the current context passed in,
 but you are getting it in the second case.
 
 ...
 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 :-) ]

The problem is near the bottom of ExternalMethod.py.  The PythonMethod
product is based partly on ExternalMethod, so I'm now familiar with the
invocation mechanism.

Here's the logic: ExternalMethod sets up func_* attributes so it can
masquerade as a function.  The trick works well enough to convince
ZPublisher's mapply() to pass in a "self" argument as the first
argument when needed.

However, if you invoke the method directly (as you're doing here),
mapply is not part of the mechanism.  So you're supposed to provide the
"self" argument manually.  This is nonintuitive IMHO.

BUT if you don't provide the "self" argument, and ExternalMethod can
see that the method signature includes "self" as the first argument,
ExternalMethod will try to call the method again with the self argument
prepended.

So if you have arguments with defaults or use variable argument lists,
that last algorithm falls to pieces.  The solution is to always provide
the "self" argument.

Shane

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




Re: [Zope-dev] External Method Missery

2000-07-12 Thread Steve Alexander

Chris Withers wrote:
 
 Shane Hathaway wrote:
  that last algorithm falls to pieces.  The solution is to always provide
  the "self" argument.
 
 When calling or in the signature of your external method?

Both.

Declare it like this:

  def external_method(self, ...other args...):

Use it like this:
 
 dtml-var "external_method(this(),...other args..." ?

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

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )




Re: [Zope-dev] External Method Missery

2000-07-12 Thread Chris Withers

Steve Alexander wrote:
 Both.
   def external_method(self, ...other args...):
  dtml-var "external_method(this(),...other args..." ?

I'll go with this advice since I still can't make heads or tails which
of the two Shane thinks I need to do ;-)

Of course, it's not documented like this. I think the docs say just make
sure the def has self as the first argument...

Can someone from DC pick up the Issue I dropped in the collector
relating to this and solve the problem in some sensible way ;-)

cheers,

Chris

PS: Doing both proved to be an extremely bad idea :(
Suddenly I'm getting lots of key errors and the like.
I'm going back to what I was doing:

-self argument first in def
-call with dtml-var "nav_tree(PARENTS[-2])"

___
Zope-Dev maillist  -  [EMAIL PROTECTED]
http://lists.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
 http://lists.zope.org/mailman/listinfo/zope-announce
 http://lists.zope.org/mailman/listinfo/zope )