mò ,á¸Ec@s›dkZdkZdklZdklZdklZdkl Z d„Z defd„ƒYZ dfd „ƒYZ d „Z d klZd „ZdS( N(sImplicit(sBeforeTraverse(s BaseRequest(s HTTPResponsecCsRtƒ}hdd<d|g<dg<dd<dd<d|<}t|ƒS( NtURLttPARENTStstepst _hacked_pathit _test_countertresponse(t HTTPResponseRtroott environmentt BaseRequest(RR R((tB/data/zmath/zope/lib/python/ZPublisher/tests/testBeforeTraverse.pytmakeBaseRequest s ?tDummyObjectBasiccBstZdZRS(s! Dummy class with docstring. (t__name__t __module__t__doc__(((R R s t BrokenHookcBstZd„ZRS(NcGs"|iiGdGHt|ii‚dS(Ntcalled(tselft __class__Rt TypeError(Rtargs((R t__call__s(RRR(((R RscCsdS(sÿ Zope supports a 'before traverse' hook that is used for several features, including 'Site Access Rules'. It is implemented using a special API for registering hooks, and the hooks themselves are called during traversal by ZPublisher. >>> root = DummyObjectBasic() >>> request = makeBaseRequest(root) >>> container = DummyObjectBasic() >>> root.container = container >>> obj = DummyObjectBasic() >>> container.obj = obj Setup a broken hook as the before traverse hook for the container. That will create a 'MultiHook' object: >>> BeforeTraverse.registerBeforeTraverse(container, BrokenHook(), ... 'broken_hook') >>> container.__before_publishing_traverse__ >>> container.__before_traverse__ {(99, 'broken_hook'): } Setup logging so we can see the actual exception being logged: >>> logger = logging.getLogger('ZPublisher') >>> level = logger.level >>> handlers = logger.handlers[:] >>> logger.addHandler(logging.StreamHandler(sys.stdout)) >>> logger.setLevel(logging.ERROR) Now do the actual traversal: >>> _ = request.traverse('container/obj') BrokenHook called '__before_publishing_traverse__' call ... failed. Traceback (most recent call last): ... TypeError: BrokenHook Unregister the borken hook: >>> _ = BeforeTraverse.unregisterBeforeTraverse(container, 'broken_hook') The list of 'before traverse' hooks is empty: >>> container.__before_traverse__ {} But the 'MultiHook' is not removed: >>> container.__before_publishing_traverse__ If you have an object in the same container that you want to call during traversal you can register a 'NameCaller' as the hook instead, and it will delegate to the callable by looking it up as an attribute of the container: >>> container.broken_callable = BrokenHook() >>> BeforeTraverse.registerBeforeTraverse(container, ... BeforeTraverse.NameCaller('broken_callable'), ... 'broken_callable') >>> container.__before_traverse__ {(99, 'broken_callable'): } Now do the actual traversal: >>> _ = request.traverse('container/obj') BrokenHook called BeforeTraverse: Error while invoking hook: "broken_callable" Traceback (most recent call last): ... TypeError: BrokenHook Unregister the borken hook: >>> _ = BeforeTraverse.unregisterBeforeTraverse(container, 'broken_callable') The list of 'before traverse' hooks is empty: >>> container.__before_traverse__ {} But the 'MultiHook' is not removed: >>> container.__before_publishing_traverse__ Finally, restore the logger state: >>> logger.setLevel(level) >>> logger.handlers = handlers[:] N((R((R ttestBeforeTraverse se(sdoctestcCstidtiƒS(Nt optionflags(tdoctestt DocTestSuitetELLIPSIS(((R t test_suiteŠs(tsystloggingt AcquisitiontImplicitt ZPublishertBeforeTraversetZPublisher.BaseRequestR tZPublisher.HTTPResponseRR R RRt zope.testingRR( RRR RR!RR#RR RRR ((R t?s        h