[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!"