[Zope-dev] __bobo_traverse__, restrictedTraverse and PageTemplates

Florent Guillaume fg@nuxeo.com
Tue, 2 Apr 2002 14:47:08 +0000 (UTC)


I'm using Zope 2.5.1b1, CMF from CVS.

I'm having a strange problem when trying to define a custom
__bobo_traverse__, where an Unauthorized exception is raised from
PageTemplates/Expressions.py/restrictedTraverse.

The object's __bobo_traverse__ is simply doing
    def __bobo_traverse__(self, REQUEST, name):
        """Traversal to get to the virtual documents."""
        target = getattr(self, name, None)
        if target is not None:
            return target
        #... other things that are never called ...

(The goal would be to make some objects appear to be under a given level
which isn't in fact a container but calls the catalog to display a
listing.)

With that code, if I try to view the object, I get:

  ...
  File .../lib/python/ZPublisher/Publish.py, line 39, in call_object
    (Object: foo)
  File .../Products/CMFCore/PortalContent.py, line 167, in __call__
    (Object: foo)
  File .../lib/python/Shared/DC/Scripts/Bindings.py, line 252, in __call__
    (Object: mylevel_view)
  File .../lib/python/Shared/DC/Scripts/Bindings.py, line 283, in _bindAndExec
    (Object: mylevel_view)
  File .../lib/python/Products/PageTemplates/Expressions.py, line 177, in _eval
  File .../lib/python/Products/PageTemplates/Expressions.py, line 134, in _eval
    (Info: here)
  File .../lib/python/Products/PageTemplates/Expressions.py, line 321, in restrictedTraverse
    (Object: foo)
    (Info: {'path': ['portal_url'], 'TraversalRequestNameStack': []})
Unauthorized: You are not allowed to access portal_url in this context

There error stems from the fact that the view calls here/portal_url, which
sould be ok.

If I remove the bobo_traverse, everything works fine and dandy of course.
I don't undersand the difference because my __bobo_traverse__ is just
doing standard stuff that traversal would do anyway.

If I look at Expressions.py/restrictedTraverse, there are discrepancies
I cannot explain.
The relevant parts in this case are (I commented the code that's not
executed, for display purposes):

        t=get(object, '__bobo_traverse__', N)
        if t is not N:
            o=t(REQUEST, name)
            container = None
            #if has(o, 'im_self'):
            #    container = o.im_self
            #elif (has(get(object, 'aq_base', object), name)
            #    and get(object, name) == o):
            #    container = object
            if not validate(object, container, name, o):
                raise Unauthorized, name   # line 321
        else:
            o=get(object, name, M)
            if o is not M:
                # Check security.
                if has(object, 'aq_acquire'):
                    object.aq_acquire(
                        name, validate2, validate)
                #else:
                #    if not validate(object, object, name, o):
                #        raise Unauthorized, name
            #else:
            #    try:
            #        o=object[name]
            #    except (AttributeError, TypeError):
            #        raise AttributeError, name
            #    if not validate(object, object, name, o):
            #        raise Unauthorized, name
        object = o


So I don't understand the different treatments, with bobo_traverse I get
a None container, which makes the validate fail, whereas standard
traversal calls ac_acquire with as a filter validate2, the filters
receives a container, and this validation suceeds.

If anybody has any lights on how I write do the __bobo_traverse__ I
need...


Thanks,


Florent

-- 
Florent Guillaume, Nuxeo (Paris, France)
+33 1 40 33 79 10  http://nuxeo.com  mailto:fg@nuxeo.com