[Zope-dev] Why does restrictedTraverse() in Zope 2 not respect IPublishTraverse adapters?
Laurence Rowe
l at lrowe.co.uk
Thu May 14 16:55:40 EDT 2009
Tres Seaver wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Martin Aspeli wrote:
>
>> There's currently a funny inconsistency in Zope's Traversable class. If
>> you have a URL like http://localhost:8080/path/to/@@aview/foo, and
>> @@aview implements IPublishTraverse (and, I presume, if there's a custom
>> IPublishTraverse adapter for any other path component), URL traversal
>> will work fine, but calling to.restrictedTraverse('@@aview/foo') or some
>> variant thereof will fail, because (un)restrictedTraverse() does not
>> respect custom IPublishTraverse adapters.
>
> 'restrictedTraverse' is not (and never has been) the same as URL
> traversal. For instance:
>
> - - URL traversal does no security checking until it finds the published
> object.
>
> - - URL traveresal manages the '__before_publishing_traverse__' hooks.
>
>
> If you want your adapter to be respected by *both*, it needs to
> implement the appropriate interfaces for both.
>
>> I can kind of see why it's done like this since it's called
>> I*Publish*Traverse, but it is a pain.
>>
>> Note that namespace traversal (like ++skin++) works fine with
>> restrictedTraverse().
>>
>> I don't think it'd be hard to implement this, but:
>>
>> - is this a bug?
>
> No.
>
>> - is there a reason not to do this?
>
> - -1 to adding any more majyk to the over-complicated Z3-style traversal
> dance inside Zope2, especially as it would involve a bunch of subtle
> behavior changes which would be hard to explain.
>
> For maximum portability across Z2 / Z3 / BFG, you could just do the same
> thing and implement __getitem__ on any object you want to be traversable
> by either the publisher or APIs like (un)restrictedTraverse, and forego
> the over-complicated component-laden traversal dance. ;)
Minimal example demonstrating this with a view in zope2:
>>> from zope.component import getSiteManager
>>> from Testing.makerequest import makerequest
>>> from zope.publisher.browser import IBrowserView
>>> from Acquisition import Explicit
>>> from zope.component import getSiteManager
>>> app = makerequest(app)
>>> smgr = getSiteManager()
>>> class Foo(Explicit):
... def __init__(self, context, request):
... self.context, self.request = context, request
... def __getitem__(self, key):
... return int(key)
...
>>> smgr.registerAdapter(Foo, (None, IRequest), IBrowserView, name='foo')
>>> app.unrestrictedTraverse('@@foo/12345')
12345
Laurence
More information about the Zope-Dev
mailing list