diff options
author | Martijn Faassen <faassen@startifact.com> | 2010-07-09 10:59:58 +0000 |
---|---|---|
committer | Martijn Faassen <faassen@startifact.com> | 2010-07-09 10:59:58 +0000 |
commit | c2088ddc969e4600b8fd92165f9ef7f6ac216aa7 (patch) | |
tree | 67c1dc844c6af55a901bf9bdef02031f33050128 /src/zope/traversing | |
parent | 625e13e8b81ce71ded483131b3fcf99cb9c486e9 (diff) | |
download | zope-traversing-c2088ddc969e4600b8fd92165f9ef7f6ac216aa7.tar.gz |
Fix behavior: now __parent__ is checked first before an ILocation
adapter lookup is performed.
Diffstat (limited to 'src/zope/traversing')
-rw-r--r-- | src/zope/traversing/browser/absoluteurl.py | 16 | ||||
-rw-r--r-- | src/zope/traversing/browser/tests.py | 50 |
2 files changed, 63 insertions, 3 deletions
diff --git a/src/zope/traversing/browser/absoluteurl.py b/src/zope/traversing/browser/absoluteurl.py index efef9c5..54602e2 100644 --- a/src/zope/traversing/browser/absoluteurl.py +++ b/src/zope/traversing/browser/absoluteurl.py @@ -49,8 +49,20 @@ class AbsoluteURL(BrowserView): or sameProxiedObjects(context, request.getVirtualHostRoot())): return request.getApplicationURL() - context = ILocation(context) - container = getattr(context, '__parent__', None) + # first try to get the __parent__ of the object, no matter whether + # it provides ILocation or not. If this fails, look up an ILocation + # adapter. This will always work, as a general ILocation adapter + # is registered for interface in zope.location (a LocationProxy) + # This proxy will return a parent of None, causing this to fail + # More specific ILocation adapters can be provided however. + try: + container = context.__parent__ + except AttributeError: + # we need to assign to context here so we can get + # __name__ from it below + context = ILocation(context) + container = context.__parent__ + if container is None: raise TypeError(_insufficientContext) diff --git a/src/zope/traversing/browser/tests.py b/src/zope/traversing/browser/tests.py index bc4a095..a52baf5 100644 --- a/src/zope/traversing/browser/tests.py +++ b/src/zope/traversing/browser/tests.py @@ -27,6 +27,7 @@ from zope.interface.verify import verifyObject from zope.publisher.browser import TestRequest from zope.publisher.http import IHTTPRequest, HTTPCharsets from zope.location.interfaces import ILocation +from zope.location.location import LocationProxy from zope.container.contained import contained @@ -39,6 +40,9 @@ class Root(object): class TrivialContent(object): """Trivial content object, used because instances of object are rocks.""" +class AdaptedContent(object): + """A simple content object that has an ILocation adapter for it.""" + class FooContent(object): """Class whose location will be provided by an adapter.""" @@ -70,7 +74,12 @@ class TestAbsoluteURL(PlacelessSetup, TestCase): zope.component.provideAdapter(FooLocation) zope.component.provideAdapter(HTTPCharsets, (IHTTPRequest,), IUserPreferredCharsets) - + # LocationProxy as set by zope.location + # this makes a default LocationProxy for all objects that + # don't define a more specific adapter + zope.component.provideAdapter(LocationProxy, (Interface,), + ILocation) + def tearDown(self): PlacelessSetup.tearDown(self) @@ -112,6 +121,27 @@ class TestAbsoluteURL(PlacelessSetup, TestCase): {'name': 'c', 'url': 'http://127.0.0.1/a/b/c'}, )) + + def testParentButNoLocation(self): + request = TestRequest() + + content1 = TrivialContent() + content1.__parent__ = Root() + content1.__name__ = 'a' + + content2 = TrivialContent() + content2.__parent__ = content1 + content2.__name__ = 'b' + + content3 = TrivialContent() + content3.__parent__ = content2 + content3.__name__ = 'c' + + view = getMultiAdapter((content3, request), name='absolute_url') + self.assertEqual(str(view), 'http://127.0.0.1/a/b/c') + self.assertEqual(absoluteURL(content3, request), + 'http://127.0.0.1/a/b/c') + def testAdaptedContext(self): request = TestRequest() @@ -128,6 +158,23 @@ class TestAbsoluteURL(PlacelessSetup, TestCase): {'name': 'foo', 'url': 'http://127.0.0.1/bar/foo'}, )) + def testParentTrumpsAdapter(self): + # if we have a location adapter for a content object but + # the object also has its own __parent__, this will trump the + # adapter + request = TestRequest() + + + content = FooContent() + content.__parent__ = Root() + content.__name__ = 'foo' + + view = getMultiAdapter((content, request), name='absolute_url') + self.assertEqual(str(view), 'http://127.0.0.1/foo') + self.assertEqual(absoluteURL(content, request), + 'http://127.0.0.1/foo') + + def testBasicContext_unicode(self): #Tests so that AbsoluteURL handle unicode names as well request = TestRequest() @@ -242,6 +289,7 @@ class TestAbsoluteURL(PlacelessSetup, TestCase): self.assertEqual(str(view), 'http://127.0.0.1') self.assertEqual(absoluteURL(None, request), 'http://127.0.0.1') + def testVirtualHostingWithoutContextInformation(self): request = TestRequest() request._vh_root = contained(TrivialContent(), Root(), name='a') |