Commit 3ca45ffc authored by Christian Theune's avatar Christian Theune

- Added Post Traversal Hook and corresponding tests

parent 830b6bd4
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
############################################################################## ##############################################################################
""" Basic ZPublisher request management. """ Basic ZPublisher request management.
$Id: BaseRequest.py,v 1.54 2003/11/28 16:46:47 jim Exp $ $Id: BaseRequest.py,v 1.55 2004/03/03 11:07:01 ctheune Exp $
""" """
from urllib import quote from urllib import quote
...@@ -252,6 +252,9 @@ class BaseRequest: ...@@ -252,6 +252,9 @@ class BaseRequest:
request['TraversalRequestNameStack'] = request.path = path request['TraversalRequestNameStack'] = request.path = path
# Set the posttraverse for duration of the traversal here
self._post_traverse = post_traverse = []
entry_name = '' entry_name = ''
try: try:
# We build parents in the wrong order, so we # We build parents in the wrong order, so we
...@@ -376,6 +379,9 @@ class BaseRequest: ...@@ -376,6 +379,9 @@ class BaseRequest:
steps.append(entry_name) steps.append(entry_name)
finally: finally:
parents.reverse() parents.reverse()
# After traversal post traversal hooks aren't available anymore
del self._post_traverse
request['PUBLISHED'] = parents.pop(0) request['PUBLISHED'] = parents.pop(0)
...@@ -449,8 +455,21 @@ class BaseRequest: ...@@ -449,8 +455,21 @@ class BaseRequest:
# Remove http request method from the URL. # Remove http request method from the URL.
request['URL']=URL request['URL']=URL
# Run post traversal hooks here
result = None
if post_traverse:
result = exec_callables(post_traverse)
if result is not None:
object = result
return object return object
def post_traverse(self, f, args=()):
"""Set a callable object and argument tuple to be combined if traversal succeeds."""
if hasattr(self, "_post_traverse"):
self._post_traverse.append((f, tuple(args)))
retry_count=0 retry_count=0
def supports_retry(self): return 0 def supports_retry(self): return 0
...@@ -459,8 +478,13 @@ class BaseRequest: ...@@ -459,8 +478,13 @@ class BaseRequest:
""" """
self._held=self._held+(object,) self._held=self._held+(object,)
def exec_callables(callables):
result = None
for (f, args) in callables:
# Don't catch exceptions here. And don't hide them anyway.
result = f(*args)
if result is not None:
return result
def old_validation(groups, request, auth, def old_validation(groups, request, auth,
roles=UNSPECIFIED_ROLES): roles=UNSPECIFIED_ROLES):
......
from unittest import TestCase, TestSuite, makeSuite, main
import Zope
Zope.startup()
from Acquisition import Implicit
from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.HTTPResponse import HTTPResponse
# Various post traversal methods
pt_simple_was_run = 0
def pt_simple():
global pt_simple_was_run
pt_simple_was_run = 1
pass
def pt_static_arg(request, b):
request.set('b', b)
pass
def pt_simple_redirect(a):
return a
def pt_chain_test(request, string):
request.set('a', request.get('a', '') + string)
class DummyObjectBasic(Implicit):
""" Dummy class with docstring.
"""
def _setObject(self, id, object):
setattr(self, id, object)
return getattr(self, id)
def view(self):
""" Attribute with docstring.
"""
return 'view content'
class DummyObjectWithPTHook(DummyObjectBasic):
""" Dummy class with docstring.
"""
traversal = []
def __before_publishing_traverse__(self, object, REQUEST):
for x in self.traversal:
REQUEST.post_traverse(*x)
class TestBaseRequestPT(TestCase):
def setUp(self):
self.root = DummyObjectBasic()
self.f1 = self.root._setObject('folder', DummyObjectBasic() )
self.f1._setObject('objBasic', DummyObjectWithPTHook() )
def makeBaseRequest(self):
response = HTTPResponse()
environment = { 'URL': '',
'PARENTS': [self.root],
'steps': [],
'_hacked_path': 0,
'_test_counter': 0,
'response': response }
return BaseRequest(environment)
def test_post_basic(self):
global pt_simple_was_run
pt_simple_was_run = 0
r = self.makeBaseRequest()
# Set hook
self.f1.objBasic.traversal = [(pt_simple,)]
x = r.traverse('folder/objBasic')
# Object should be self.f1.objBasic
self.assertEqual(x, self.f1.objBasic)
self.assertEqual(pt_simple_was_run, 1)
self.f1.objBasic.traversal = []
def test_post_arg(self):
r = self.makeBaseRequest()
b = 1
self.f1.objBasic.traversal = [(pt_static_arg, (r, b))]
x = r.traverse('folder/objBasic')
# Object should have been traversed normally
self.assertEqual(x, self.f1.objBasic)
self.assertEqual(r.get('b', 0), b)
self.f1.objBasic.traversal = []
def test_hook_chain(self):
r = self.makeBaseRequest()
self.f1.objBasic.traversal = [ (pt_chain_test, (r, 'a')),
(pt_chain_test, (r, 'b')),
(pt_chain_test, (r, 'c')),
(pt_chain_test, (r, 'd'))]
x = r.traverse('folder/objBasic')
self.assertEqual(r.get('a',''), 'abcd')
self.f1.objBasic.traversal = []
def test_hook_redirect(self):
r = self.makeBaseRequest()
check = []
self.f1.objBasic.traversal = [(pt_simple_redirect, (check,))]
x = r.traverse('folder/objBasic')
self.assertEqual(x, check)
def test_hook_chain_redirect(self):
r = self.makeBaseRequest()
check = []
self.f1.objBasic.traversal = [ (pt_chain_test, (r, 'a')),
(pt_chain_test, (r, 'b')),
(pt_chain_test, (r, 'c')),
(pt_simple_redirect, (check,)),
(pt_simple_redirect, (1,)),
(pt_chain_test, (r, 'd'))]
x = r.traverse('folder/objBasic')
self.assertEqual(r.get('a',''), 'abc')
self.assertEqual(x, check)
def test_suite():
return TestSuite( ( makeSuite(TestBaseRequestPT), ) )
if __name__ == '__main__':
main(defaultTest='test_suite')
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