Log message for revision 78451: The existing two absolute_url adapter implementations are specifically geared towards OFS.Traversable and OFS.Application. Name them so. Introduce a more generic implementation that's very very close to the Zope 3 one and works on objects that don't inherit from OFS.Traversable or support acquisition (e.g. views, resources, etc.)
Changed: U Zope/branches/philikon-aq/lib/python/Products/Five/browser/absoluteurl.py U Zope/branches/philikon-aq/lib/python/Products/Five/browser/configure.zcml U Zope/branches/philikon-aq/lib/python/Products/Five/browser/tests/test_absoluteurl.py -=- Modified: Zope/branches/philikon-aq/lib/python/Products/Five/browser/absoluteurl.py =================================================================== --- Zope/branches/philikon-aq/lib/python/Products/Five/browser/absoluteurl.py 2007-07-29 00:43:22 UTC (rev 78450) +++ Zope/branches/philikon-aq/lib/python/Products/Five/browser/absoluteurl.py 2007-07-29 01:48:18 UTC (rev 78451) @@ -15,26 +15,89 @@ $Id$ """ +import urllib from Acquisition import aq_inner, aq_parent from OFS.interfaces import ITraversable from zope.interface import implements from zope.component import getMultiAdapter from zope.traversing.browser.interfaces import IAbsoluteURL +from zope.traversing.browser.absoluteurl import _insufficientContext, _safe from Products.Five.browser import BrowserView class AbsoluteURL(BrowserView): - """An adapter for Zope3-style absolute_url using Zope2 methods + """An absolute_url adapter for generic objects in Zope 2 that + aren't OFS.Traversable (e.g. views, resources, etc.). - (original: zope.traversing.browser.absoluteurl) + This is very close to the generic implementation from + zope.traversing.browser, but the Zope 2 request doesn't support + all the methods that it uses yet. """ implements(IAbsoluteURL) - def __init__(self, context, request): - self.context, self.request = context, request + def __unicode__(self): + return urllib.unquote(self.__str__()).decode('utf-8') def __str__(self): + context = self.context + request = self.request + + container = aq_parent(context) + if container is None: + raise TypeError(_insufficientContext) + + url = str(getMultiAdapter((container, request), name='absolute_url')) + name = self._getContextName(context) + if name is None: + raise TypeError(_insufficientContext) + + if name: + url += '/' + urllib.quote(name.encode('utf-8'), _safe) + + return url + + __call__ = __str__ + + def _getContextName(self, context): + if getattr(context, 'getId', None) is not None: + return context.getId() + getattr(context, '__name__', None) + + def breadcrumbs(self): + context = self.context + request = self.request + + # We do this here do maintain the rule that we must be wrapped + container = aq_parent(context) + if container is None: + raise TypeError(_insufficientContext) + + base = tuple(getMultiAdapter((container, request), + name='absolute_url').breadcrumbs()) + + name = self._getContextName(context) + if name is None: + raise TypeError(_insufficientContext) + + if name: + base += ({'name': name, + 'url': ("%s/%s" % (base[-1]['url'], + urllib.quote(name.encode('utf-8'), + _safe))) + }, ) + + return base + +class OFSTraversableAbsoluteURL(BrowserView): + """An absolute_url adapter for OFS.Traversable subclasses + """ + implements(IAbsoluteURL) + + def __unicode__(self): + return urllib.unquote(self.__str__()).decode('utf-8') + + def __str__(self): context = aq_inner(self.context) return context.absolute_url() @@ -47,10 +110,10 @@ name = context.getId() - if container is None or self._isVirtualHostRoot() \ - or not ITraversable.providedBy(container): - return ( - {'name': name, 'url': context.absolute_url()},) + if (container is None + or self._isVirtualHostRoot() + or not ITraversable.providedBy(container)): + return ({'name': name, 'url': context.absolute_url()},) view = getMultiAdapter((container, request), IAbsoluteURL) base = tuple(view.breadcrumbs()) @@ -66,15 +129,9 @@ context = aq_inner(self.context) return context.restrictedTraverse(virtualrootpath) == context -class SiteAbsoluteURL(AbsoluteURL): - """An adapter for Zope3-style absolute_url using Zope2 methods - - This one is just used to stop breadcrumbs from crumbing up - to the Zope root. - - (original: zope.traversing.browser.absoluteurl) +class RootAbsoluteURL(OFSTraversableAbsoluteURL): + """An absolute_url adapter for the root object (OFS.Application) """ - def breadcrumbs(self): context = self.context request = self.request Modified: Zope/branches/philikon-aq/lib/python/Products/Five/browser/configure.zcml =================================================================== --- Zope/branches/philikon-aq/lib/python/Products/Five/browser/configure.zcml 2007-07-29 00:43:22 UTC (rev 78450) +++ Zope/branches/philikon-aq/lib/python/Products/Five/browser/configure.zcml 2007-07-29 01:48:18 UTC (rev 78451) @@ -39,21 +39,37 @@ /> <browser:page - for="zope.traversing.interfaces.IContainmentRoot" + for="OFS.interfaces.ITraversable" name="absolute_url" - class=".absoluteurl.SiteAbsoluteURL" + class=".absoluteurl.OFSTraversableAbsoluteURL" permission="zope.Public" allowed_interface="zope.traversing.browser.interfaces.IAbsoluteURL" /> <view - for="zope.traversing.interfaces.IContainmentRoot" - factory=".absoluteurl.SiteAbsoluteURL" + for="OFS.interfaces.ITraversable" + factory=".absoluteurl.OFSTraversableAbsoluteURL" type="zope.publisher.interfaces.http.IHTTPRequest" permission="zope.Public" provides="zope.traversing.browser.interfaces.IAbsoluteURL" /> + <browser:page + for="OFS.interfaces.IApplication" + name="absolute_url" + class=".absoluteurl.RootAbsoluteURL" + permission="zope.Public" + allowed_interface="zope.traversing.browser.interfaces.IAbsoluteURL" + /> + + <view + for="OFS.interfaces.IApplication" + factory=".absoluteurl.RootAbsoluteURL" + type="zope.publisher.interfaces.http.IHTTPRequest" + permission="zope.Public" + provides="zope.traversing.browser.interfaces.IAbsoluteURL" + /> + <browser:view for="OFS.interfaces.IObjectManager" name="+" Modified: Zope/branches/philikon-aq/lib/python/Products/Five/browser/tests/test_absoluteurl.py =================================================================== --- Zope/branches/philikon-aq/lib/python/Products/Five/browser/tests/test_absoluteurl.py 2007-07-29 00:43:22 UTC (rev 78450) +++ Zope/branches/philikon-aq/lib/python/Products/Five/browser/tests/test_absoluteurl.py 2007-07-29 01:48:18 UTC (rev 78451) @@ -51,12 +51,11 @@ This test assures and demonstrates that the absolute url stops traversing through an object's parents when it has reached the - root object. In Zope 3 this is marked with the IContainmentRoot - interface: + root object. - >>> from zope.interface import directlyProvides, providedBy - >>> from zope.traversing.interfaces import IContainmentRoot - >>> directlyProvides(self.folder, IContainmentRoot) + >>> from zope.interface import alsoProvides, noLongerProvides + >>> from OFS.interfaces import IApplication + >>> alsoProvides(self.folder, IApplication) >>> for crumb in view.breadcrumbs(): ... info = crumb.items() @@ -65,8 +64,7 @@ [('name', 'test_folder_1_'), ('url', 'http://nohost/test_folder_1_')] [('name', 'testoid'), ('url', 'http://nohost/test_folder_1_/testoid')] - >>> directlyProvides(self.folder, - ... providedBy(self.folder) - IContainmentRoot) + >>> noLongerProvides(self.folder, IApplication) The absolute url view is obviously not affected by virtual hosting: _______________________________________________ Zope-Checkins maillist - Zope-Checkins@zope.org http://mail.zope.org/mailman/listinfo/zope-checkins