def testImplementsITraverser(self): self.failUnless(ITraverser.providedBy(self.tr))
def __bobo_traverse__(self, REQUEST, name): """Hook for Zope 2 traversal This method is called by Zope 2's ZPublisher upon traversal. It allows us to trick it into faking the Zope 3 traversal system by using an ITraverser adapter. """ # We are trying to be compatible with Zope 2 and 3 traversal # behaviour as much as possible. Therefore the first part of # this method is based on BaseRequest.traverse's behaviour: # 1. If an object has __bobo_traverse__, use it. # 2. Otherwise do attribute look-up or, if that doesn't work, # key item lookup. result = _marker if hasattr(self, '__fallback_traverse__'): try: return self.__fallback_traverse__(REQUEST, name) except (AttributeError, KeyError): pass except NotFound: # OFS.Application.__bobo_traverse__ calls # REQUEST.RESPONSE.notFoundError which sets the HTTP # status code to 404 try: REQUEST.RESPONSE.setStatus(200) except AttributeError: pass else: # See if the object itself has the attribute, try acquisition # later if getattr(aq_base(self), name, _marker) is not _marker: return getattr(self, name) try: # item access should never acquire result = self[name] # WebDAV requests will always return something, # sometimes it's a NullResource, which we will ignore # and return later if necessary if not isinstance(result, NullResource): return result except (KeyError, IndexError, TypeError, AttributeError): pass # This is the part Five adds: # 3. If neither __bobo_traverse__ nor attribute/key look-up # work, we try to find a Zope 3-style view. # For that we need to make sure we have a good request # (sometimes __bobo_traverse__ gets a stub request) if not IBrowserRequest.providedBy(REQUEST): # Try to get the REQUEST by acquisition REQUEST = getattr(self, 'REQUEST', None) if not IBrowserRequest.providedBy(REQUEST): REQUEST = FakeRequest() setDefaultSkin(REQUEST) # Con Zope 3 into using Zope 2's checkPermission Products.Five.security.newInteraction() # Use the ITraverser adapter (which in turn uses ITraversable # adapters) to traverse to a view. Note that we're mixing # object-graph and object-publishing traversal here, but Zope # 2 has no way to tell us when to use which... # TODO Perhaps we can decide on object-graph vs. # object-publishing traversal depending on whether REQUEST is # a stub or not? try: return ITraverser(self).traverse( path=[name], request=REQUEST).__of__(self) except (ComponentLookupError, LookupError, AttributeError, KeyError, NotFound): pass # Fallback on acquisition, let it raise an AttributeError if it must try: return getattr(self, name) except AttributeError: if result is not _marker: return result raise
def __bobo_traverse__(self, REQUEST, name): """Hook for Zope 2 traversal This method is called by Zope 2's ZPublisher upon traversal. It allows us to trick it into faking the Zope 3 traversal system by using an ITraverser adapter. """ # We are trying to be compatible with Zope 2 and 3 traversal # behaviour as much as possible. Therefore the first part of # this method is based on BaseRequest.traverse's behaviour: # 1. If an object has __bobo_traverse__, use it. # 2. Otherwise do attribute look-up or, if that doesn't work, # key item lookup. if zope.deprecation.__show__(): warnings.warn("The view lookup done by Traversable." \ "__bobo_traverse__ is now done by the standard " \ "traversal. This class is no longer needed and " "will be removed in Zope 2.12.", DeprecationWarning, 2) if hasattr(self, '__fallback_traverse__'): try: return self.__fallback_traverse__(REQUEST, name) except (AttributeError, KeyError): pass except NotFound: # OFS.Application.__bobo_traverse__ calls # REQUEST.RESPONSE.notFoundError which sets the HTTP # status code to 404 try: REQUEST.RESPONSE.setStatus(200) except AttributeError: pass else: try: return getattr(self, name) except AttributeError: pass try: return self[name] except (KeyError, IndexError, TypeError, AttributeError): pass # This is the part Five adds: # 3. If neither __bobo_traverse__ nor attribute/key look-up # work, we try to find a Zope 3-style view. # For that we need to make sure we have a good request # (sometimes __bobo_traverse__ gets a stub request) if not IBrowserRequest.providedBy(REQUEST): # Try to get the REQUEST by acquisition REQUEST = getattr(self, 'REQUEST', None) if not IBrowserRequest.providedBy(REQUEST): REQUEST = FakeRequest() setDefaultSkin(REQUEST) # Con Zope 3 into using Zope 2's checkPermission Products.Five.security.newInteraction() # Use the ITraverser adapter (which in turn uses ITraversable # adapters) to traverse to a view. Note that we're mixing # object-graph and object-publishing traversal here, but Zope # 2 has no way to tell us when to use which... # TODO Perhaps we can decide on object-graph vs. # object-publishing traversal depending on whether REQUEST is # a stub or not? try: return ITraverser(self).traverse( path=[name], request=REQUEST).__of__(self) except (ComponentLookupError, LookupError, AttributeError, KeyError, NotFound): pass raise AttributeError(name)