[Zope] publishing a double-underscore method?

Paul Winkler pw_lists@slinkp.com
Wed, 7 May 2003 06:57:48 -0400


I'm glad to see you got it working using __bobo_traverse__
but i wanted to follow up on this, in case others following this
thread are still confused.

On Tue, May 06, 2003 at 04:21:49PM -0700, Dylan Reinhardt wrote:
> On Tue, 2003-05-06 at 11:45, Paul Winkler wrote:
> > >     if name == 'test':
> > >         return 'this is a test'
> > 
> > so you're visiting http://mysite/foo/test?
> 
> Yes.
> 
> > i guess the problem is that 'test' and/or 'this is a test'
> > do not have docstrings. i'm not sure which is the problem.
> 
> I'm not sure I see how either *could* have docstrings.  Am I missing
> something?

Yes - when you visit http://my_zope/foo/test, assuming there's an object
with the id "foo" in the zope root, ZPublisher tries to get "test" from
foo by doing getattr(foo, "test")
In your case, you've defined __getattr__ in such a way that it succeeds
even though there is no attribute foo.test. 
All well and good so far; the result is a string, "this is a test".

Here's where the problem is. Once the path has been resolved to an
object, ZPublisher DOES NOT send this object directly to the browser.
Instead, in lib/python/ZPublisher/BaseRequest.py, in
BaseRequest.traverse() (a really huge monster method),
it does several things to try to "publish" the object
(i.e. send something back to the browser).
Summarized:

0) check to see if the object has a __doc__ attribute.
   if not, stop raise an error - only objects with docstrings
   may be published.  In your case, this is as far as we got
   since strings don't have docstrings.

1) check to see if the object defines __browser_default__
   (which allows you to use something other than index_html).
   I don't know the details of __browser_default__ so we'll
   ignore that for now. :)

2) otherwise, try to get an index_html attribute from the
   object, call it, and send the result to the browser.

3) otherwise, try to call the object itself (i.e. its __call__ method)
   and send the result to the browser.


> I also did:
> 
> __getattr__(self, name):
>     if name == 'test':
>         return self.my_test()
> *and* tried
> 
> __getattr__(self, name):
>     if name == 'test':
>         return self.my_test().__of__(self)
> 
> for:
> 
> def my_test(self):
>     """ got a docstring here too """
>     return 'simple test completed'
> 
> Each of the above uses of my_test returned the same docstring error.

heh... that's because you're still giving zpublisher a string to
publish. If you gave it self.my_test instead of self.my_test(),
you'd be OK.  

BUT then you get into why it's tricky to overload __getattr__...
__getattr__ is already used heavily by zope for acquisition AND
security, and as soon as I tried doing funky things with __getattr__
i got all kinds of odd errors with very confusing tracebacks.
This is the reason we have __bobo_traverse__.

-- 

Paul Winkler
home:  http://www.slinkp.com
"Muppet Labs, where the future is made - today!"