summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Fulton <jim@zope.com>2002-07-13 14:18:37 +0000
committerJim Fulton <jim@zope.com>2002-07-13 14:18:37 +0000
commit33cc9b96bc66a62ff8120b3ad6091d658ead52dd (patch)
tree819e7f437cf53528ad8037a142d7d44df1a246cb
parent15dd1d76d172b8c7782ba4c350e0892370d80881 (diff)
downloadzope-traversing-33cc9b96bc66a62ff8120b3ad6091d658ead52dd.tar.gz
Fixed bug in context management when uri segments that produce only
side effects (e.g. ++skin++ZopeTop) are used. Fixed up absolute url bread crumbs to not show side-effect steps in bread crumbs, while retaining them in the breadcrumb urls. Refactored side-effect handling slightly (changed context data names) in absolute url and physical path code. Added tests for side effect handling for absolute url, physical path, and namespace handling code.
-rw-r--r--Namespaces.py33
-rw-r--r--SkinNamespace.py9
-rw-r--r--Traverser.py3
-rw-r--r--tests/testNamespaceTrversal.py22
-rw-r--r--tests/testPhysicalLocationAdapters.py45
5 files changed, 104 insertions, 8 deletions
diff --git a/Namespaces.py b/Namespaces.py
index 166e82b..ea831c8 100644
--- a/Namespaces.py
+++ b/Namespaces.py
@@ -13,11 +13,11 @@
##############################################################################
"""
-$Id: Namespaces.py,v 1.4 2002/07/12 19:28:32 jim Exp $
+$Id: Namespaces.py,v 1.5 2002/07/13 14:18:36 jim Exp $
"""
from Zope.Exceptions import NotFoundError
-from Zope.Proxy.ContextWrapper import ContextWrapper
+from Zope.Proxy.ContextWrapper import ContextWrapper, getWrapperObject
from Zope.Configuration.Action import Action
_namespace_handlers = {}
@@ -39,11 +39,36 @@ def namespaceLookup(name, ns, qname, parameters, object, request=None):
name -- the original name
ns -- The namespace
qname -- The name without any parameters
+
+ The resulting object is returned in the context of the original.
+ This means that the caller should *not* wrap the result.
"""
handler = _namespace_handlers.get(ns)
if handler is None:
raise NotFoundError(name)
- new = ContextWrapper(handler(qname, parameters, name, object, request),
- object, name=name)
+
+ new = handler(qname, parameters, name, object, request)
+ if new is object:
+ # The handler had a side effect only and didn't look up a
+ # different object. We want to retain the side-effect name
+ # for things like URLs.
+
+ # But wait, there's more. The object may be wrapped. If the
+ # object is already wrapped and we return the object in the
+ # context of itself, the containment context will be wrong,
+ # because the inner wrapper will be the original object, so
+ # our added layer with the name we want to preserve will be
+ # ignored when searching containment.
+
+ # For this reason, we'll remove a layer of wrapping from new
+ # before we put it in context.
+
+ new = getWrapperObject(new)
+
+ new = ContextWrapper(new, object, name='.', side_effect_name=name)
+
+ else:
+ new = ContextWrapper(new, object, name=name)
+
return new
diff --git a/SkinNamespace.py b/SkinNamespace.py
index d23cb08..64b29c6 100644
--- a/SkinNamespace.py
+++ b/SkinNamespace.py
@@ -13,7 +13,7 @@
##############################################################################
"""
-$Id: SkinNamespace.py,v 1.1 2002/07/12 19:28:32 jim Exp $
+$Id: SkinNamespace.py,v 1.2 2002/07/13 14:18:36 jim Exp $
"""
from Zope.App.OFS.ApplicationControl.ApplicationControl \
@@ -22,11 +22,18 @@ from Namespaces import provideNamespaceHandler
from Exceptions import UnexpectedParameters
from Zope.Exceptions import NotFoundError
+class NoRequest(NotFoundError):
+ """Atempt to access a presentation component outside of a request context
+ """
+
def skin(name, parameters, pname, ob, request):
if parameters:
raise UnexpectedParameters(parameters)
+ if not request:
+ raise NoRequest(pname)
+
request.setViewSkin(name)
return ob
diff --git a/Traverser.py b/Traverser.py
index 0d584e0..592f97b 100644
--- a/Traverser.py
+++ b/Traverser.py
@@ -13,7 +13,7 @@
##############################################################################
"""Default implementation of ITraverser.
-$Id: Traverser.py,v 1.3 2002/07/11 18:21:34 jim Exp $
+$Id: Traverser.py,v 1.4 2002/07/13 14:18:36 jim Exp $
"""
from Zope.ComponentArchitecture import getAdapter
@@ -81,6 +81,7 @@ class Traverser:
continue
if name == '..':
+ # XXX This doesn't look right. Why fall back to curr?
curr = getWrapperContainer(curr) or curr
continue
diff --git a/tests/testNamespaceTrversal.py b/tests/testNamespaceTrversal.py
index f490d2e..2380bf8 100644
--- a/tests/testNamespaceTrversal.py
+++ b/tests/testNamespaceTrversal.py
@@ -14,7 +14,7 @@
"""
Revision information:
-$Id: testNamespaceTrversal.py,v 1.3 2002/07/12 19:28:33 jim Exp $
+$Id: testNamespaceTrversal.py,v 1.4 2002/07/13 14:18:36 jim Exp $
"""
from unittest import TestCase, TestSuite, main, makeSuite
@@ -32,8 +32,10 @@ class Test(CleanUp, TestCase):
def setUp(self):
from Zope.App.Traversing.Namespaces import provideNamespaceHandler
from Zope.App.Traversing.AttrItemNamespaces import attr, item
+ from Zope.App.Traversing.SkinNamespace import skin
provideNamespaceHandler('attribute', attr)
provideNamespaceHandler('item', item)
+ provideNamespaceHandler('skin', skin)
def testAttr(self):
@@ -47,6 +49,24 @@ class Test(CleanUp, TestCase):
traverser = Traverser(c)
v = traverser.traverse('++item++a')
self.assertEqual(v, 'avalue')
+
+ def testSideEffectsContextDetail(self):
+ """Check to make sure that when we traverse something in context,
+ that we get the right context for the result."""
+ from Zope.Proxy.ContextWrapper \
+ import ContextWrapper, getWrapperContainer
+ from Zope.App.Traversing.Traverser import Traverser
+ from Zope.Publisher.Browser.BrowserRequest import TestRequest
+
+ c1 = C()
+ c2 = C()
+ c2c1 = ContextWrapper(c2, c1)
+
+ traverser = Traverser(c2c1)
+ v = traverser.traverse('++skin++ZopeTop', request=TestRequest())
+ self.assertEqual(v, c2)
+ self.failUnless(getWrapperContainer(v) is c2c1)
+
diff --git a/tests/testPhysicalLocationAdapters.py b/tests/testPhysicalLocationAdapters.py
index c0e55c6..5242d76 100644
--- a/tests/testPhysicalLocationAdapters.py
+++ b/tests/testPhysicalLocationAdapters.py
@@ -12,7 +12,7 @@
#
##############################################################################
"""
-$Id: testPhysicalLocationAdapters.py,v 1.1 2002/07/11 18:21:34 jim Exp $
+$Id: testPhysicalLocationAdapters.py,v 1.2 2002/07/13 14:18:36 jim Exp $
"""
from unittest import TestCase, TestSuite, main, makeSuite
@@ -50,6 +50,49 @@ class Test(PlacelessSetup, TestCase):
self.assertRaises(TypeError, adapter.getPhysicalPath)
self.assertRaises(TypeError, adapter.getPhysicalRoot)
+ def testWSideEffectDataInFront(self):
+ provideAdapter(None, IPhysicallyLocatable, WrapperPhysicallyLocatable)
+ provideAdapter(IContainmentRoot, IPhysicallyLocatable,
+ RootPhysicallyLocatable)
+
+ root = Root()
+ root = ContextWrapper(root, root, name='.',
+ side_effect_name="++skin++ZopeTop")
+ f1 = ContextWrapper(C(), root, name='f1')
+ f2 = ContextWrapper(C(), f1, name='f2')
+ f3 = ContextWrapper(C(), f2, name='f3')
+
+ adapter = getAdapter(f3, IPhysicallyLocatable)
+
+ self.assertEqual(adapter.getPhysicalPath(), ('', 'f1', 'f2', 'f3'))
+ self.assertEqual(adapter.getPhysicalRoot(), root)
+
+ adapter = getAdapter(C(), IPhysicallyLocatable)
+ self.assertRaises(TypeError, adapter.getPhysicalPath)
+ self.assertRaises(TypeError, adapter.getPhysicalRoot)
+
+ def testWSideEffectDataInMiddle(self):
+ provideAdapter(None, IPhysicallyLocatable, WrapperPhysicallyLocatable)
+ provideAdapter(IContainmentRoot, IPhysicallyLocatable,
+ RootPhysicallyLocatable)
+
+ root = Root()
+ c = C()
+ f1 = ContextWrapper(c, root, name='f1')
+ f1 = ContextWrapper(c, f1, name='.',
+ side_effect_name="++skin++ZopeTop")
+ f2 = ContextWrapper(C(), f1, name='f2')
+ f3 = ContextWrapper(C(), f2, name='f3')
+
+ adapter = getAdapter(f3, IPhysicallyLocatable)
+
+ self.assertEqual(adapter.getPhysicalPath(), ('', 'f1', 'f2', 'f3'))
+ self.assertEqual(adapter.getPhysicalRoot(), root)
+
+ adapter = getAdapter(C(), IPhysicallyLocatable)
+ self.assertRaises(TypeError, adapter.getPhysicalPath)
+ self.assertRaises(TypeError, adapter.getPhysicalRoot)
+
def test_suite():
return TestSuite((
makeSuite(Test),