diff options
author | Jim Fulton <jim@zope.com> | 2002-07-11 18:21:37 +0000 |
---|---|---|
committer | Jim Fulton <jim@zope.com> | 2002-07-11 18:21:37 +0000 |
commit | caf4bf056d6837c5e03bf1ead6637b5df58d9928 (patch) | |
tree | 8fa9e12ebe96d6bb948b6bd19b8ea0e84d15396a | |
parent | dc9c587bfee2359d89fcf29022170f2d361ec6db (diff) | |
download | zope-traversing-caf4bf056d6837c5e03bf1ead6637b5df58d9928.tar.gz |
Reimplemented service managers to be package based. Service managers
are no longer containers. They have a packages subobject (not a
packages service) that contains packages. TTW components are created
in packages. To register a component, create the appropriate component
directive objects (these should be called configuration objects).
This should be viewed as a prototype to illustrate the idea of
packages. Lots of things can change (especially UI) and many things
aren't done (e.g. visiting created directives).
In the course of this, I fixed a bunch of bugs and problems in
traversal machinery.
I also renamed Zope.ComponentArchitecture.IServiceManager back to
IServiceService, since this interface doesn't actually specify any
management.
-rw-r--r-- | EtcNamespace.py | 4 | ||||
-rw-r--r-- | IContainmentRoot.py | 24 | ||||
-rw-r--r-- | IPhysicallyLocatable.py | 32 | ||||
-rw-r--r-- | ITraverser.py | 17 | ||||
-rw-r--r-- | ObjectName.py | 6 | ||||
-rw-r--r-- | PhysicalLocationAdapters.py | 75 | ||||
-rw-r--r-- | Traverser.py | 43 | ||||
-rw-r--r-- | __init__.py | 28 | ||||
-rw-r--r-- | configure.zcml | 15 | ||||
-rw-r--r-- | tests/testConvenienceFunctions.py | 32 | ||||
-rw-r--r-- | tests/testPhysicalLocationAdapters.py | 64 | ||||
-rw-r--r-- | tests/testTraverser.py | 36 |
12 files changed, 289 insertions, 87 deletions
diff --git a/EtcNamespace.py b/EtcNamespace.py index 1c77801..0c0f917 100644 --- a/EtcNamespace.py +++ b/EtcNamespace.py @@ -13,7 +13,7 @@ ############################################################################## """ -$Id: EtcNamespace.py,v 1.2 2002/06/10 23:28:17 jim Exp $ +$Id: EtcNamespace.py,v 1.3 2002/07/11 18:21:34 jim Exp $ """ from Zope.App.OFS.ApplicationControl.ApplicationControl \ import ApplicationController @@ -47,7 +47,7 @@ def etc(name, parameters, pname, ob, request): method_name = "getServiceManager" method = getattr(ob, method_name, None) if method is None: - raise NotFound(ob, pname, request) + raise NotFoundError(ob, pname, request) return method() diff --git a/IContainmentRoot.py b/IContainmentRoot.py new file mode 100644 index 0000000..37e8fc5 --- /dev/null +++ b/IContainmentRoot.py @@ -0,0 +1,24 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +""" +$Id: IContainmentRoot.py,v 1.1 2002/07/11 18:21:34 jim Exp $ +""" + +from Interface import Interface + +class IContainmentRoot(Interface): + """Marker interface to designate root objects + """ + +__doc__ = IContainmentRoot.__doc__ + __doc__ diff --git a/IPhysicallyLocatable.py b/IPhysicallyLocatable.py new file mode 100644 index 0000000..11ce464 --- /dev/null +++ b/IPhysicallyLocatable.py @@ -0,0 +1,32 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +""" +$Id: IPhysicallyLocatable.py,v 1.1 2002/07/11 18:21:34 jim Exp $ +""" + +from Interface import Interface + +class IPhysicallyLocatable(Interface): + """Objects that have a physical location in a containment hierarchy. + """ + + def getPhysicalRoot(): + """Return the physical root object + """ + + def getPhysicalPath(): + """Return the physical path to the object as a sequence of names. + """ + +__doc__ = IPhysicallyLocatable.__doc__ + __doc__ diff --git a/ITraverser.py b/ITraverser.py index f02d72b..6754dc0 100644 --- a/ITraverser.py +++ b/ITraverser.py @@ -13,7 +13,7 @@ ############################################################################## """ -$Id: ITraverser.py,v 1.2 2002/06/10 23:28:17 jim Exp $ +$Id: ITraverser.py,v 1.3 2002/07/11 18:21:34 jim Exp $ """ import Interface @@ -22,21 +22,6 @@ _RAISE_KEYERROR=[] class ITraverser(Interface.Base): """Provide traverse features""" - - def getPhysicalRoot(): - """ - Returns the top-level Application object, or the base object if it is - unwrapped. - """ - - def getPhysicalPath(): - """ - Returns a path (an immutable sequence of strings) from the root. - - This path can be used to access this object again later, for example - in a copy/paste operation. Returns an empty tuple if the base object - is not wrapped. - """ def traverse(path, default=_RAISE_KEYERROR): """ diff --git a/ObjectName.py b/ObjectName.py index be245db..e86d6c9 100644 --- a/ObjectName.py +++ b/ObjectName.py @@ -14,9 +14,9 @@ """ Revision information: -$Id: ObjectName.py,v 1.1 2002/06/15 20:38:17 stevea Exp $ +$Id: ObjectName.py,v 1.2 2002/07/11 18:21:34 jim Exp $ """ -from Zope.Proxy.ContextWrapper import getWrapperData +from Zope.Proxy.ContextWrapper import getInnerWrapperData from Interface import Interface @@ -42,7 +42,7 @@ class ObjectName(object): self.context = context def __str__(self): - dict = getWrapperData(self.context) + dict = getInnerWrapperData(self.context) name = dict and dict.get('name') or None if name is None: raise TypeError, \ diff --git a/PhysicalLocationAdapters.py b/PhysicalLocationAdapters.py new file mode 100644 index 0000000..06b0ac3 --- /dev/null +++ b/PhysicalLocationAdapters.py @@ -0,0 +1,75 @@ +############################################################################## +# +# Copyright (c) 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""XXX short summary goes here. + +XXX longer description goes here. + +$Id: PhysicalLocationAdapters.py,v 1.1 2002/07/11 18:21:34 jim Exp $ +""" +__metaclass__ = type + +from Zope.App.Traversing.IPhysicallyLocatable import IPhysicallyLocatable +from Zope.App.Traversing.IContainmentRoot import IContainmentRoot +from Zope.ComponentArchitecture import getAdapter +from Zope.Proxy.ContextWrapper import getInnerWrapperData, getWrapperContainer + +class WrapperPhysicallyLocatable: + __doc__ = IPhysicallyLocatable.__doc__ + + __implements__ = IPhysicallyLocatable + + def __init__(self, context): + self.context = context + + def getPhysicalRoot(self): + "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable" + container = getWrapperContainer(self.context) + if container is None: + raise TypeError("Not enough context to determine location root") + return getAdapter(container, IPhysicallyLocatable).getPhysicalRoot() + + def getPhysicalPath(self): + "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable" + context = self.context + container = getWrapperContainer(context) + if container is None: + raise TypeError("Not enough context to determine location") + name = getInnerWrapperData(context)['name'] + + container = getAdapter(container, IPhysicallyLocatable) + container_path = container.getPhysicalPath() + + return container_path + (name, ) + + +class RootPhysicallyLocatable: + __doc__ = IPhysicallyLocatable.__doc__ + + __implements__ = IPhysicallyLocatable + + __used_for__ = IContainmentRoot + + def __init__(self, context): + self.context = context + + def getPhysicalPath(self): + "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable" + return ('', ) + + def getPhysicalRoot(self): + "See Zope.App.Traversing.IPhysicallyLocatable.IPhysicallyLocatable" + return self.context + + + diff --git a/Traverser.py b/Traverser.py index 011d7c2..0d584e0 100644 --- a/Traverser.py +++ b/Traverser.py @@ -13,13 +13,12 @@ ############################################################################## """Default implementation of ITraverser. -$Id: Traverser.py,v 1.2 2002/06/10 23:28:17 jim Exp $ +$Id: Traverser.py,v 1.3 2002/07/11 18:21:34 jim Exp $ """ -from ITraverser import ITraverser -from ITraversable import ITraversable +from Zope.ComponentArchitecture import getAdapter from Zope.ContextWrapper.IWrapper import IWrapper -from Zope.Proxy.ContextWrapper import getWrapperContext, getWrapperData +from Zope.Proxy.ContextWrapper import getWrapperContainer, getInnerWrapperData from Zope.Proxy.ContextWrapper import ContextWrapper from Zope.ComponentArchitecture import queryAdapter from Zope.Exceptions import NotFoundError, Unauthorized @@ -27,6 +26,10 @@ from Namespaces import namespaceLookup from ParameterParsing import parameterizedNameParse from Zope.Security.SecurityManagement import getSecurityManager +from IPhysicallyLocatable import IPhysicallyLocatable +from ITraverser import ITraverser +from ITraversable import ITraversable + from types import StringTypes from __future__ import generators @@ -35,7 +38,7 @@ from __future__ import generators def WrapperChain(w): while w is not None: yield w - w = getWrapperContext(w) + w = getWrapperContainer(w) _marker = object() @@ -47,27 +50,11 @@ class Traverser: # This adapter can be used for any object. def __init__(self, wrapper): - self._wrapper = wrapper - - def getPhysicalRoot(self): - # Loop over all wrappers until the last one, which is the root. - for w in WrapperChain(self._wrapper): - pass - return w - - def getPhysicalPath(self): - path = [] - - for w in WrapperChain(self._wrapper): - d = getWrapperData(w) - if d: - path.insert(0, d['name']) - - return tuple(path) + self.context = wrapper def traverse(self, path, default=_marker, request=None): if not path: - return self._wrapper + return self.context if isinstance(path, StringTypes): path = path.split('/') @@ -80,11 +67,12 @@ class Traverser: path.reverse() pop = path.pop - curr = self._wrapper + curr = self.context if not path[-1]: # Start at the root pop() - curr = self.getPhysicalRoot() + curr = getAdapter(self.context, IPhysicallyLocatable + ).getPhysicalRoot() try: while path: name = pop() @@ -93,7 +81,7 @@ class Traverser: continue if name == '..': - curr = getWrapperContext(curr) or curr + curr = getWrapperContainer(curr) or curr continue @@ -109,7 +97,8 @@ class Traverser: traversable = queryAdapter(curr, ITraversable, None) if traversable is None: - raise NotFoundError, 'No traversable adapter found' + raise NotFoundError( + 'No traversable adapter found', curr) next = traversable.traverse(nm, parms, name, path) curr = ContextWrapper(next, curr, name=name) diff --git a/__init__.py b/__init__.py index eb01c62..91d5fdb 100644 --- a/__init__.py +++ b/__init__.py @@ -18,7 +18,9 @@ Traversing the object tree. from Zope.ComponentArchitecture import getAdapter as _getAdapter from ObjectName import IObjectName as _IObjectName from ITraverser import ITraverser as _ITraverser +from IPhysicallyLocatable import IPhysicallyLocatable as _IPhysicallyLocatable from Traverser import WrapperChain as _WrapperChain +from Traverser import Traverser as _Traverser from Zope.Proxy.ContextWrapper import getWrapperContext as _getWrapperContext from Zope.Proxy.ContextWrapper import isWrapper as _isWrapper from types import StringTypes @@ -41,9 +43,10 @@ def traverse(place, path, default=_marker, request=None): code unexpectedly. Consider using traverseName instead. """ - if not _isWrapper(place): - raise TypeError, "Not enough context information to traverse" - traverser = _getAdapter(place, _ITraverser) + # XXX This made no sense. It would mean you couldn't traverse from root + #if not _isWrapper(place): + # raise TypeError, "Not enough context information to traverse" + traverser = _Traverser(place) if default is _marker: return traverser.traverse(path, request=request) else: @@ -92,15 +95,26 @@ def getParents(obj): return [p for p in iterator] def getPhysicalPath(obj): - """Returns a tuple of names representing the physical path to the - given object. + """Returns a tuple of names representing the physical path to the object. Raises TypeError if the given object is not context wrapped """ if not _isWrapper(obj): raise TypeError, "Not enough context information to traverse" - return _getAdapter(obj, _ITraverser).getPhysicalPath() + return _getAdapter(obj, _IPhysicallyLocatable).getPhysicalPath() + +def getPhysicalPathString(obj): + """Returns a string representing the physical path to the object. + + Raises TypeError if the given object is not context wrapped + """ + if not _isWrapper(obj): + raise TypeError, "Not enough context information to traverse" + + path = _getAdapter(obj, _IPhysicallyLocatable).getPhysicalPath() + return '/'.join(path) + def getPhysicalRoot(obj): """Returns the root of the traversal for the given object. @@ -110,7 +124,7 @@ def getPhysicalRoot(obj): if not _isWrapper(obj): raise TypeError, "Not enough context information to traverse" - return _getAdapter(obj, _ITraverser).getPhysicalRoot() + return _getAdapter(obj, _IPhysicallyLocatable).getPhysicalRoot() def locationAsTuple(location): """Given a location as a unicode or ascii string or as a tuple of diff --git a/configure.zcml b/configure.zcml index 584215c..ce032df 100644 --- a/configure.zcml +++ b/configure.zcml @@ -17,14 +17,25 @@ factory=".ObjectName." provides=".ObjectName.IObjectName" permission='Zope.Public' -/> + /> <adapter factory=".ObjectName.SiteObjectName" provides=".ObjectName.IObjectName" for="Zope.App.OFS.Content.Folder.RootFolder.IRootFolder" permission='Zope.Public' -/> + /> + +<adapter + provides=".IPhysicallyLocatable." + factory=".PhysicalLocationAdapters.WrapperPhysicallyLocatable" + /> + +<adapter + provides=".IPhysicallyLocatable." + for=".IContainmentRoot." + factory=".PhysicalLocationAdapters.RootPhysicallyLocatable" + /> </zopeConfigure> diff --git a/tests/testConvenienceFunctions.py b/tests/testConvenienceFunctions.py index 477396c..44912f5 100644 --- a/tests/testConvenienceFunctions.py +++ b/tests/testConvenienceFunctions.py @@ -13,7 +13,7 @@ ############################################################################## """ -$Id: testConvenienceFunctions.py,v 1.3 2002/06/25 12:38:12 stevea Exp $ +$Id: testConvenienceFunctions.py,v 1.4 2002/07/11 18:21:34 jim Exp $ """ from unittest import TestCase, TestSuite, main, makeSuite from Zope.App.OFS.Services.ServiceManager.tests.PlacefulSetup \ @@ -21,10 +21,18 @@ from Zope.App.OFS.Services.ServiceManager.tests.PlacefulSetup \ from Zope.Proxy.ContextWrapper import ContextWrapper from Zope.App.Traversing.Traverser import Traverser from Zope.ComponentArchitecture import getService + from Zope.App.Traversing.ITraverser import ITraverser from Zope.App.Traversing.ITraversable import ITraversable from Zope.App.Traversing.DefaultTraversable import DefaultTraversable from Zope.App.Traversing.ObjectName import IObjectName, ObjectName + +from Zope.App.Traversing.IPhysicallyLocatable import IPhysicallyLocatable +from Zope.App.Traversing.IContainmentRoot import IContainmentRoot +from Zope.App.Traversing.PhysicalLocationAdapters \ + import WrapperPhysicallyLocatable, RootPhysicallyLocatable + + from Zope.Exceptions import NotFoundError class C: @@ -37,10 +45,11 @@ class Test(PlacefulSetup, TestCase): PlacefulSetup.setUp(self) # Build up a wrapper chain root = C('root') + root.__implements__ = IContainmentRoot folder = C('folder') item = C('item') - self.root = ContextWrapper(root, None, name='') + self.root = root self.folder = ContextWrapper(folder, self.root, name='folder') self.item = ContextWrapper(item, self.folder, name='item') self.unwrapped_item = item @@ -49,12 +58,16 @@ class Test(PlacefulSetup, TestCase): folder.item = item self.tr = Traverser(root) - getService(None,"Adapters").provideAdapter( + getService(None, "Adapters").provideAdapter( None, ITraverser, Traverser) - getService(None,"Adapters").provideAdapter( + getService(None, "Adapters").provideAdapter( None, ITraversable, DefaultTraversable) - getService(None,"Adapters").provideAdapter( + getService(None, "Adapters").provideAdapter( None, IObjectName, ObjectName) + getService(None, "Adapters").provideAdapter( + None, IPhysicallyLocatable, WrapperPhysicallyLocatable) + getService(None, "Adapters").provideAdapter( + IContainmentRoot, IPhysicallyLocatable, RootPhysicallyLocatable) def testTraverse(self): @@ -82,15 +95,6 @@ class Test(PlacefulSetup, TestCase): traverseName(self.item, '.'), self.tr.traverse('/folder/item') ) - - - def testTraverseNameUnwrapped(self): - from Zope.App.Traversing import traverseName - self.assertRaises( - TypeError, - traverseName, - self.unwrapped_item, 'item' - ) def testTraverseNameBadValue(self): from Zope.App.Traversing import traverseName diff --git a/tests/testPhysicalLocationAdapters.py b/tests/testPhysicalLocationAdapters.py new file mode 100644 index 0000000..c0e55c6 --- /dev/null +++ b/tests/testPhysicalLocationAdapters.py @@ -0,0 +1,64 @@ +############################################################################## +# +# Copyright (c) 2001, 2002 Zope Corporation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +""" +$Id: testPhysicalLocationAdapters.py,v 1.1 2002/07/11 18:21:34 jim Exp $ +""" + +from unittest import TestCase, TestSuite, main, makeSuite +from Zope.ComponentArchitecture.tests.PlacelessSetup import PlacelessSetup +from Zope.ComponentArchitecture.GlobalAdapterService import provideAdapter +from Zope.ComponentArchitecture import getAdapter + +from Zope.App.Traversing.IContainmentRoot import IContainmentRoot +from Zope.App.Traversing.IPhysicallyLocatable import IPhysicallyLocatable +from Zope.App.Traversing.PhysicalLocationAdapters \ + import WrapperPhysicallyLocatable, RootPhysicallyLocatable +from Zope.Proxy.ContextWrapper import ContextWrapper + +class Root: __implements__ = IContainmentRoot +class C: pass + +class Test(PlacelessSetup, TestCase): + + def test(self): + provideAdapter(None, IPhysicallyLocatable, WrapperPhysicallyLocatable) + provideAdapter(IContainmentRoot, IPhysicallyLocatable, + RootPhysicallyLocatable) + + root = Root() + 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 test_suite(): + return TestSuite(( + makeSuite(Test), + )) + +if __name__=='__main__': + main(defaultTest='test_suite') + + + + + diff --git a/tests/testTraverser.py b/tests/testTraverser.py index c44aa33..06d9b85 100644 --- a/tests/testTraverser.py +++ b/tests/testTraverser.py @@ -13,7 +13,7 @@ ############################################################################## """ -$Id: testTraverser.py,v 1.3 2002/06/15 20:38:18 stevea Exp $ +$Id: testTraverser.py,v 1.4 2002/07/11 18:21:34 jim Exp $ """ import unittest @@ -21,6 +21,12 @@ from Zope.App.Traversing.ITraverser import ITraverser from Zope.App.Traversing.ITraversable import ITraversable from Zope.App.Traversing.Traverser import Traverser from Zope.App.Traversing.DefaultTraversable import DefaultTraversable + +from Zope.App.Traversing.IPhysicallyLocatable import IPhysicallyLocatable +from Zope.App.Traversing.IContainmentRoot import IContainmentRoot +from Zope.App.Traversing.PhysicalLocationAdapters \ + import WrapperPhysicallyLocatable, RootPhysicallyLocatable + from Zope.Proxy.ContextWrapper import ContextWrapper from Zope.Exceptions import NotFoundError, Unauthorized from Zope.ComponentArchitecture import getService @@ -44,7 +50,7 @@ class TraverserTests(PlacefulSetup, unittest.TestCase): def setUp(self): PlacefulSetup.setUp(self) # Build up a wrapper chain - self.root = ContextWrapper(C('root'), None, name='') + self.root = C('root') self.folder = ContextWrapper(C('folder'), self.root, name='folder') self.item = ContextWrapper(C('item'), self.folder, name='item') self.tr = Traverser(self.item) @@ -56,22 +62,10 @@ class TraverserTests(PlacefulSetup, unittest.TestCase): for interface in instancesOfObjectImplements(Traverser): verifyClass(interface, Traverser) - def testPhysicalRoot(self): - self.failUnless(self.tr.getPhysicalRoot() is self.root) - - def testPhysicalPath(self): - self.assertEquals(self.tr.getPhysicalPath(), ('', 'folder', 'item')) - - def testUnwrapped(self): - # The feature should do the right thing for unwrapped objects too - unwrapped = C('unwrapped') - tr = Traverser(unwrapped) - self.assertEquals(tr.getPhysicalPath(), ()) - self.failUnless(tr.getPhysicalRoot() is unwrapped) - class UnrestrictedNoTraverseTests(unittest.TestCase): def setUp(self): self.root = root = C('root') + self.root.__implements__ = IContainmentRoot self.folder = folder = C('folder') self.item = item = C('item') @@ -89,10 +83,15 @@ class UnrestrictedTraverseTests(PlacefulSetup, unittest.TestCase): PlacefulSetup.setUp(self) # Build up a wrapper chain - getService(None,"Adapters").provideAdapter( + getService(None, "Adapters").provideAdapter( None, ITraversable, DefaultTraversable) + getService(None, "Adapters").provideAdapter( + None, IPhysicallyLocatable, WrapperPhysicallyLocatable) + getService(None, "Adapters").provideAdapter( + IContainmentRoot, IPhysicallyLocatable, RootPhysicallyLocatable) self.root = root = C('root') + self.root.__implements__ = IContainmentRoot self.folder = folder = C('folder') self.item = item = C('item') @@ -160,8 +159,13 @@ class RestrictedTraverseTests(PlacefulSetup, unittest.TestCase): getService(None,"Adapters").provideAdapter( None, ITraversable, DefaultTraversable) + getService(None, "Adapters").provideAdapter( + None, IPhysicallyLocatable, WrapperPhysicallyLocatable) + getService(None, "Adapters").provideAdapter( + IContainmentRoot, IPhysicallyLocatable, RootPhysicallyLocatable) self.root = root = C('root') + root.__implements__ = IContainmentRoot self.folder = folder = C('folder') self.item = item = C('item') |