Fix a bug in the traversal code regarding IBrowserPublisher.browserDefault.

browserDefault implementations that were returning object_thats_not_self, ()
didnt' work.
parent 3420457b
...@@ -427,7 +427,7 @@ class BaseRequest: ...@@ -427,7 +427,7 @@ class BaseRequest:
else: else:
# If we have reached the end of the path, we look to see # If we have reached the end of the path, we look to see
# if we can find IBrowserPublisher.browserDefault. If so, # if we can find IBrowserPublisher.browserDefault. If so,
# we call it to let the object tell us how to publish it # we call it to let the object tell us how to publish it.
# BrowserDefault returns the object to be published # BrowserDefault returns the object to be published
# (usually self) and a sequence of names to traverse to # (usually self) and a sequence of names to traverse to
# find the method to be published. # find the method to be published.
...@@ -440,7 +440,8 @@ class BaseRequest: ...@@ -440,7 +440,8 @@ class BaseRequest:
not hasattr(object,'__bobo_traverse__')): not hasattr(object,'__bobo_traverse__')):
if object.aq_parent is not object.aq_inner.aq_parent: if object.aq_parent is not object.aq_inner.aq_parent:
from webdav.NullResource import NullResource from webdav.NullResource import NullResource
object = NullResource(parents[-2], object.getId(), self).__of__(parents[-2]) object = NullResource(parents[-2], object.getId(),
self).__of__(parents[-2])
if IBrowserPublisher.providedBy(object): if IBrowserPublisher.providedBy(object):
adapter = object adapter = object
...@@ -451,10 +452,9 @@ class BaseRequest: ...@@ -451,10 +452,9 @@ class BaseRequest:
# Zope2 doesn't set up its own adapters in a lot # Zope2 doesn't set up its own adapters in a lot
# of cases so we will just use a default adapter. # of cases so we will just use a default adapter.
adapter = DefaultPublishTraverse(object, self) adapter = DefaultPublishTraverse(object, self)
newobject, default_path = adapter.browserDefault(self) object, default_path = adapter.browserDefault(self)
if default_path or newobject is not object: if default_path:
object = newobject
request._hacked_path=1 request._hacked_path=1
if len(default_path) > 1: if len(default_path) > 1:
path = list(default_path) path = list(default_path)
......
...@@ -264,11 +264,11 @@ import zope.interface ...@@ -264,11 +264,11 @@ import zope.interface
import zope.component import zope.component
import zope.testing.cleanup import zope.testing.cleanup
import zope.traversing.namespace import zope.traversing.namespace
import zope.publisher.browser
from zope.publisher.browser import IBrowserRequest from zope.publisher.browser import IBrowserRequest
from zope.publisher.browser import IDefaultBrowserLayer from zope.publisher.browser import IDefaultBrowserLayer
from zope.traversing.interfaces import ITraversable from zope.traversing.interfaces import ITraversable
class IDummy(zope.interface.Interface): class IDummy(zope.interface.Interface):
"""IDummy""" """IDummy"""
...@@ -292,6 +292,33 @@ class DummyView(Implicit): ...@@ -292,6 +292,33 @@ class DummyView(Implicit):
def __call__(self): def __call__(self):
return 'view on %s' % (self.content.name) return 'view on %s' % (self.content.name)
class DummyPage(zope.publisher.browser.BrowserPage):
# BrowserPage is an IBrowserPublisher with a browserDefault that
# returns self, () so that __call__ is invoked by the publisher.
def __call__(self):
return 'Test page'
class DummyPage2(zope.publisher.browser.BrowserPage):
def browserDefault(self, request):
# intentionally return something that's not self
return DummyPage(self.context, request), ()
# __call__ remains unimplemented, baseclass raises NotImplementedError
class DummyPage3(zope.publisher.browser.BrowserPage):
def browserDefault(self, request):
# intentionally return a method here
return self.foo, ()
def foo(self):
return 'Test page'
# __call__ remains unimplemented, baseclass raises NotImplementedError
class TestBaseRequestZope3Views(TestCase): class TestBaseRequestZope3Views(TestCase):
def setUp(self): def setUp(self):
...@@ -309,9 +336,15 @@ class TestBaseRequestZope3Views(TestCase): ...@@ -309,9 +336,15 @@ class TestBaseRequestZope3Views(TestCase):
# The request needs to implement the proper interface # The request needs to implement the proper interface
zope.interface.classImplements(BaseRequest, IDefaultBrowserLayer) zope.interface.classImplements(BaseRequest, IDefaultBrowserLayer)
# Define our 'meth' view # Define the views
gsm.registerAdapter(DummyView, (IDummy, IDefaultBrowserLayer), None, gsm.registerAdapter(DummyView, (IDummy, IDefaultBrowserLayer),
'meth') zope.interface.Interface, 'meth')
gsm.registerAdapter(DummyPage, (IDummy, IDefaultBrowserLayer),
zope.interface.Interface, 'page')
gsm.registerAdapter(DummyPage2, (IDummy, IDefaultBrowserLayer),
zope.interface.Interface, 'page2')
gsm.registerAdapter(DummyPage3, (IDummy, IDefaultBrowserLayer),
zope.interface.Interface, 'page3')
# Bind the 'view' namespace (for @@ traversal) # Bind the 'view' namespace (for @@ traversal)
gsm.registerAdapter(zope.traversing.namespace.view, gsm.registerAdapter(zope.traversing.namespace.view,
...@@ -407,6 +440,16 @@ class TestBaseRequestZope3Views(TestCase): ...@@ -407,6 +440,16 @@ class TestBaseRequestZope3Views(TestCase):
r.traverse('folder/obj/++view++meth') r.traverse('folder/obj/++view++meth')
self.assertEqual(r['URL'], '/folder/obj/++view++meth') self.assertEqual(r['URL'], '/folder/obj/++view++meth')
def test_browserDefault(self):
# Test that browserDefault returning self, () works
r = self.makeBaseRequest()
ob = r.traverse('folder/obj/page')
self.assertEqual(ob(), 'Test page')
r = self.makeBaseRequest()
ob = r.traverse('folder/obj/page2')
self.assertEqual(ob(), 'Test page')
def test_suite(): def test_suite():
return TestSuite( ( makeSuite(TestBaseRequest), return TestSuite( ( makeSuite(TestBaseRequest),
makeSuite(TestBaseRequestZope3Views), makeSuite(TestBaseRequestZope3Views),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment