[Zope-Checkins] SVN: Zope/branches/wichert=request-modifier/ If a traversal step returns the same object do not call before-publish hooks again
Wichert Akkerman
wichert at wiggy.net
Sun Feb 21 16:12:32 EST 2010
Log message for revision 109226:
If a traversal step returns the same object do not call before-publish hooks again
Changed:
U Zope/branches/wichert=request-modifier/doc/CHANGES.rst
U Zope/branches/wichert=request-modifier/src/ZPublisher/BaseRequest.py
U Zope/branches/wichert=request-modifier/src/ZPublisher/tests/testBeforeTraverse.py
-=-
Modified: Zope/branches/wichert=request-modifier/doc/CHANGES.rst
===================================================================
--- Zope/branches/wichert=request-modifier/doc/CHANGES.rst 2010-02-21 20:44:15 UTC (rev 109225)
+++ Zope/branches/wichert=request-modifier/doc/CHANGES.rst 2010-02-21 21:12:32 UTC (rev 109226)
@@ -20,6 +20,9 @@
Bugs Fixed
++++++++++
+- If a traversal step returns the same object do not call before-publish hooks
+ again.
+
- Protect ZCTextIndex's clear method against storing Acquisition wrappers.
- LP #195761: fixed ZMI XML export / import and restored it to the UI.
Modified: Zope/branches/wichert=request-modifier/src/ZPublisher/BaseRequest.py
===================================================================
--- Zope/branches/wichert=request-modifier/src/ZPublisher/BaseRequest.py 2010-02-21 20:44:15 UTC (rev 109225)
+++ Zope/branches/wichert=request-modifier/src/ZPublisher/BaseRequest.py 2010-02-21 21:12:32 UTC (rev 109226)
@@ -36,6 +36,12 @@
# quote url path segments, but leave + and @ intact
return urllib_quote(text, '/+@')
+def _base(obj):
+ if IAcquirer.providedBy(obj):
+ return aq_base(obj)
+ return obj
+
+
try:
from ExtensionClass import Base
from ZPublisher.Converters import type_converters
@@ -428,10 +434,12 @@
try:
# We build parents in the wrong order, so we
# need to make sure we reverse it when we're done.
+ same_object = False
while 1:
- bpth = getattr(object, '__before_publishing_traverse__', None)
- if bpth is not None:
- bpth(object, self)
+ if not same_object:
+ bpth = getattr(object, '__before_publishing_traverse__', None)
+ if bpth is not None:
+ bpth(object, self)
path = request.path = request['TraversalRequestNameStack']
# Check for method:
@@ -505,6 +513,7 @@
self.roles = getRoles(
object, check_name, subobject,
self.roles)
+ same_object = _base(object) is _base(subobject)
object = subobject
except (KeyError, AttributeError):
if response.debug_mode:
Modified: Zope/branches/wichert=request-modifier/src/ZPublisher/tests/testBeforeTraverse.py
===================================================================
--- Zope/branches/wichert=request-modifier/src/ZPublisher/tests/testBeforeTraverse.py 2010-02-21 20:44:15 UTC (rev 109225)
+++ Zope/branches/wichert=request-modifier/src/ZPublisher/tests/testBeforeTraverse.py 2010-02-21 21:12:32 UTC (rev 109226)
@@ -1,10 +1,12 @@
import sys
import logging
+from zope.interface import implements
from Acquisition import Implicit
from ZPublisher import BeforeTraverse
from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.HTTPResponse import HTTPResponse
+from zope.publisher.interfaces import IPublishTraverse
def makeBaseRequest(root):
response = HTTPResponse()
@@ -133,6 +135,39 @@
"""
pass
+class CountHook:
+ counter = 0
+ def __call__(self, obj, request):
+ self.counter += 1
+
+
+class TraverseToSelfObject(Implicit):
+ implements(IPublishTraverse)
+ def publishTraverse(self, request, name):
+ return self
+
+def testNoMulitpleCalls(self):
+ """
+ Sometimes a traversal adapter is used which only modifies the
+ request, but does not do any real traversing. Skin traversal
+ adapters are a common example of this type of adapter. In this
+ case we do not want to call the before publish hooks for the
+ same object multiple times.
+
+ >>> root = DummyObjectBasic()
+ >>> request = makeBaseRequest(root)
+
+ >>> container = TraverseToSelfObject()
+ >>> root.container = container
+
+ >>> counter = CountHook()
+ >>> BeforeTraverse.registerBeforeTraverse(container, counter, 'count_hook')
+
+ >>> _ = request.traverse('container/traverser/obj')
+ >>> counter.counter
+ 1
+ """
+
from zope.testing import doctest
def test_suite():
More information about the Zope-Checkins
mailing list